mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-15 01:10:52 +08:00
9697f95b8f
This reverts commit 15d999759e
.
205 lines
4.6 KiB
C++
205 lines
4.6 KiB
C++
#include "stdafx.h"
|
|
#include "WebsocketServlet_impl.h"
|
|
|
|
WebsocketServlet_impl::WebsocketServlet_impl(acl::redis_client_cluster& cluster,
|
|
size_t max_conns)
|
|
{
|
|
// 创建 session 存储对象
|
|
session_ = new acl::redis_session(cluster, max_conns);
|
|
step_ = 0;
|
|
}
|
|
|
|
WebsocketServlet_impl::~WebsocketServlet_impl(void)
|
|
{
|
|
delete session_;
|
|
}
|
|
|
|
bool WebsocketServlet_impl::doUnknown(acl::HttpServletRequest&,
|
|
acl::HttpServletResponse& res)
|
|
{
|
|
res.setStatus(400);
|
|
res.setContentType("text/html; charset=");
|
|
// 发送 http 响应头
|
|
if (res.sendHeader() == false)
|
|
return false;
|
|
// 发送 http 响应体
|
|
acl::string buf("<root error='unkown request method' />\r\n");
|
|
(void) res.getOutputStream().write(buf);
|
|
return false;
|
|
}
|
|
|
|
bool WebsocketServlet_impl::doGet(acl::HttpServletRequest& req,
|
|
acl::HttpServletResponse& res)
|
|
{
|
|
return doPost(req, res);
|
|
}
|
|
|
|
bool WebsocketServlet_impl::doPost(acl::HttpServletRequest& req,
|
|
acl::HttpServletResponse& res)
|
|
{
|
|
res.setContentType("text/html; charset=utf-8") // 设置响应字符集
|
|
.setContentEncoding(false) // 设置是否压缩数据
|
|
.setChunkedTransferEncoding(true); // 采用 chunk 传输方式
|
|
|
|
const char* ip = req.getLocalAddr();
|
|
if (ip == NULL || *ip == 0) {
|
|
logger_error("getLocalAddr error");
|
|
return false;
|
|
}
|
|
unsigned short port = req.getLocalPort();
|
|
if (port == 0) {
|
|
logger_error("getLocalPort error");
|
|
return false;
|
|
}
|
|
|
|
acl::string local_addr;
|
|
local_addr << ip << ":" << port;
|
|
|
|
printf("getLocalAddr: %s\r\n", local_addr.c_str());
|
|
|
|
acl::string html_file;
|
|
html_file << "www/upload.html";
|
|
acl::string buf;
|
|
if (acl::ifstream::load(html_file, &buf) == false) {
|
|
logger_error("load %s error %s",
|
|
html_file.c_str(), acl::last_serror());
|
|
return doError(req, res);
|
|
}
|
|
|
|
buf << "<script>g_url='ws://" << local_addr << "/'</script>";
|
|
|
|
// 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次
|
|
// res.write 且两个参数均为 0 以表示 chunk 传输数据结束
|
|
return res.write(buf) && res.write(NULL, 0);
|
|
}
|
|
|
|
bool WebsocketServlet_impl::onPing(unsigned long long, bool)
|
|
{
|
|
return sendPong();
|
|
}
|
|
|
|
|
|
bool WebsocketServlet_impl::onPong(unsigned long long, bool)
|
|
{
|
|
return sendPing();
|
|
}
|
|
|
|
bool WebsocketServlet_impl::onMessage(unsigned long long payload_len,
|
|
bool text, bool finish)
|
|
{
|
|
(void) text;
|
|
(void) finish;
|
|
|
|
switch (step_) {
|
|
case 0:
|
|
step_++;
|
|
return getFilename(payload_len);
|
|
case 1:
|
|
step_++;
|
|
if (getFilesize(payload_len) == false) {
|
|
fp_.close();
|
|
return false;
|
|
}
|
|
return true;
|
|
case 2:
|
|
if (saveFile(payload_len) == false) {
|
|
fp_.close();
|
|
return false;
|
|
}
|
|
return true;
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool WebsocketServlet_impl::getFilename(unsigned long long payload_len)
|
|
{
|
|
if (readData(payload_len, filename_) == false) {
|
|
printf("read filename error\r\n");
|
|
return false;
|
|
}
|
|
|
|
printf("get filename=%s\r\n", filename_.c_str());
|
|
if (fp_.open_trunc(filename_) == false) {
|
|
printf("open %s error %s\r\n", filename_.c_str(),
|
|
acl::last_serror());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool WebsocketServlet_impl::getFilesize(unsigned long long payload_len)
|
|
{
|
|
acl::string buf;
|
|
if (readData(payload_len, buf) == false) {
|
|
printf("read filesize error\r\n");
|
|
fp_.close();
|
|
return false;
|
|
}
|
|
filesize_ = atoll(buf.c_str());
|
|
nread_ = 0;
|
|
printf("get filesize=%lld\r\n", filesize_);
|
|
if (filesize_ <= 0) {
|
|
fp_.close();
|
|
}
|
|
|
|
return filesize_ > 0;
|
|
}
|
|
|
|
bool WebsocketServlet_impl::readData(unsigned long long len, acl::string& path)
|
|
{
|
|
char buf[8192];
|
|
while (len > 0) {
|
|
size_t n = len > sizeof(buf) ? sizeof(buf) : len;
|
|
int ret = readPayload(buf, n);
|
|
if (ret == -1) {
|
|
printf("readPayload error\r\n");
|
|
return false;
|
|
}
|
|
path.append(buf, ret);
|
|
len -= ret;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool WebsocketServlet_impl::saveFile(unsigned long long len)
|
|
{
|
|
char buf[8192];
|
|
while (nread_ < filesize_) {
|
|
size_t left = (size_t) (filesize_ - nread_);
|
|
size_t n = left > sizeof(buf) ? sizeof(buf) : left;
|
|
int ret = readPayload(buf, n);
|
|
if (ret == -1) {
|
|
printf("readPayload error\r\n");
|
|
return false;
|
|
}
|
|
if (ret == 0) {
|
|
break;
|
|
}
|
|
|
|
nread_ += ret;
|
|
if (fp_.write(buf, ret) == -1) {
|
|
printf("write data to %s error %s\r\n",
|
|
filename_.c_str(), acl::last_serror());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
printf("file=%s, payload_len=%llu, filesize_=%lld, nread_=%lld\r\n",
|
|
filename_.c_str(), len, filesize_, nread_);
|
|
|
|
if (nread_ == filesize_) {
|
|
printf("READ OVER FOR FILE %s\r\n", filename_.c_str());
|
|
|
|
step_ = 0;
|
|
filesize_ = 0;
|
|
nread_ = 0;
|
|
filename_.clear();
|
|
fp_.close();
|
|
return sendText("+ok");
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|