diff --git a/.gitignore b/.gitignore
index c406d65..23db8d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,203 @@
/.vs
/3rdparty/HP-Socket
-/out
\ No newline at end of file
+/out
+build/cmake_install.cmake
+build/CMakeCache.txt
+build/install_manifest.txt
+build/Makefile
+build/3rdparty/sqlite3/cmake_install.cmake
+build/3rdparty/sqlite3/Makefile
+build/3rdparty/sqlite3/CMakeFiles/CMakeDirectoryInformation.cmake
+build/3rdparty/sqlite3/CMakeFiles/progress.marks
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/build.make
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/cmake_clean_target.cmake
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/cmake_clean.cmake
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/compiler_depend.internal
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/compiler_depend.make
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/compiler_depend.ts
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/depend.make
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/DependInfo.cmake
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/flags.make
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/link.txt
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/progress.make
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/shell.c.o
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/shell.c.o.d
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.o
+build/3rdparty/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.o.d
+build/CMakeFiles/cmake.check_cache
+build/CMakeFiles/CMakeDirectoryInformation.cmake
+build/CMakeFiles/CMakeOutput.log
+build/CMakeFiles/Makefile.cmake
+build/CMakeFiles/Makefile2
+build/CMakeFiles/progress.marks
+build/CMakeFiles/TargetDirectories.txt
+build/CMakeFiles/3.22.1/CMakeCCompiler.cmake
+build/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake
+build/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_C.bin
+build/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin
+build/CMakeFiles/3.22.1/CMakeSystem.cmake
+build/CMakeFiles/3.22.1/CompilerIdC/a.out
+build/CMakeFiles/3.22.1/CompilerIdC/CMakeCCompilerId.c
+build/CMakeFiles/3.22.1/CompilerIdCXX/a.out
+build/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp
+build/lib/libsqlite3_d.a
+build/lib/libylib_d.a
+build/src/cmake_install.cmake
+build/src/Makefile
+build/src/CMakeFiles/CMakeDirectoryInformation.cmake
+build/src/CMakeFiles/progress.marks
+build/src/CMakeFiles/ylib.dir/build.make
+build/src/CMakeFiles/ylib.dir/cmake_clean_target.cmake
+build/src/CMakeFiles/ylib.dir/cmake_clean.cmake
+build/src/CMakeFiles/ylib.dir/compiler_depend.internal
+build/src/CMakeFiles/ylib.dir/compiler_depend.make
+build/src/CMakeFiles/ylib.dir/compiler_depend.ts
+build/src/CMakeFiles/ylib.dir/depend.make
+build/src/CMakeFiles/ylib.dir/DependInfo.cmake
+build/src/CMakeFiles/ylib.dir/flags.make
+build/src/CMakeFiles/ylib.dir/link.txt
+build/src/CMakeFiles/ylib.dir/progress.make
+build/src/CMakeFiles/ylib.dir/base/buffer.cpp.o
+build/src/CMakeFiles/ylib.dir/base/buffer.cpp.o.d
+build/src/CMakeFiles/ylib.dir/base/conversion.cpp.o
+build/src/CMakeFiles/ylib.dir/base/conversion.cpp.o.d
+build/src/CMakeFiles/ylib.dir/base/environment.cpp.o
+build/src/CMakeFiles/ylib.dir/base/environment.cpp.o.d
+build/src/CMakeFiles/ylib.dir/base/error.cpp.o
+build/src/CMakeFiles/ylib.dir/base/error.cpp.o.d
+build/src/CMakeFiles/ylib.dir/base/exception.cpp.o
+build/src/CMakeFiles/ylib.dir/base/exception.cpp.o.d
+build/src/CMakeFiles/ylib.dir/base/log4.cpp.o
+build/src/CMakeFiles/ylib.dir/base/log4.cpp.o.d
+build/src/CMakeFiles/ylib.dir/db/mssql.cpp.o
+build/src/CMakeFiles/ylib.dir/db/mssql.cpp.o.d
+build/src/CMakeFiles/ylib.dir/db/mysql.cpp.o
+build/src/CMakeFiles/ylib.dir/db/mysql.cpp.o.d
+build/src/CMakeFiles/ylib.dir/db/sqler.cpp.o
+build/src/CMakeFiles/ylib.dir/db/sqler.cpp.o.d
+build/src/CMakeFiles/ylib.dir/db/sqlite.cpp.o
+build/src/CMakeFiles/ylib.dir/db/sqlite.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/ftp_client.cpp.o
+build/src/CMakeFiles/ylib.dir/net/ftp_client.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_agent.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_agent.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_cache.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_cache.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_cdn.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_cdn.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_center.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_center.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_client_cache.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_client_cache.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_client_plus.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_client_plus.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_controller.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_controller.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_cookie.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_cookie.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_header.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_header.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_host.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_host.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_interceptor.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_interceptor.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_interface.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_interface.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_reqpack.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_reqpack.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_request.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_request.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_response.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_response.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_router.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_router.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_server_lst.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_server_lst.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_server.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_server.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_session.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_session.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_ssl.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_ssl.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_subscribe.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_subscribe.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_website.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_website.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/http_wsserver.cpp.o
+build/src/CMakeFiles/ylib.dir/net/http_wsserver.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/make_form.cpp.o
+build/src/CMakeFiles/ylib.dir/net/make_form.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_agent_lst.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_agent_lst.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_agent.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_agent.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_client_lst.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_client_lst.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_client.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_client.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_forward.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_forward.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_server_lst.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_server_lst.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp_server.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp_server.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/tcp2tcp.cpp.o
+build/src/CMakeFiles/ylib.dir/net/tcp2tcp.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/ttu_client.cpp.o
+build/src/CMakeFiles/ylib.dir/net/ttu_client.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/udp_node_lst.cpp.o
+build/src/CMakeFiles/ylib.dir/net/udp_node_lst.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/udp_node.cpp.o
+build/src/CMakeFiles/ylib.dir/net/udp_node.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/util.cpp.o
+build/src/CMakeFiles/ylib.dir/net/util.cpp.o.d
+build/src/CMakeFiles/ylib.dir/net/utt_server.cpp.o
+build/src/CMakeFiles/ylib.dir/net/utt_server.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/cache.cpp.o
+build/src/CMakeFiles/ylib.dir/util/cache.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/codec_des3.cpp.o
+build/src/CMakeFiles/ylib.dir/util/codec_des3.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/codec.cpp.o
+build/src/CMakeFiles/ylib.dir/util/codec.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/coroution.cpp.o
+build/src/CMakeFiles/ylib.dir/util/coroution.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/debug.cpp.o
+build/src/CMakeFiles/ylib.dir/util/debug.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/desktop.cpp.o
+build/src/CMakeFiles/ylib.dir/util/desktop.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/file.cpp.o
+build/src/CMakeFiles/ylib.dir/util/file.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/img.cpp.o
+build/src/CMakeFiles/ylib.dir/util/img.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/ini.cpp.o
+build/src/CMakeFiles/ylib.dir/util/ini.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/json.cpp.o
+build/src/CMakeFiles/ylib.dir/util/json.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/localstorage.cpp.o
+build/src/CMakeFiles/ylib.dir/util/localstorage.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/md5.cpp.o
+build/src/CMakeFiles/ylib.dir/util/md5.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/mem.cpp.o
+build/src/CMakeFiles/ylib.dir/util/mem.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/package.cpp.o
+build/src/CMakeFiles/ylib.dir/util/package.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/print.cpp.o
+build/src/CMakeFiles/ylib.dir/util/print.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/process.cpp.o
+build/src/CMakeFiles/ylib.dir/util/process.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/sharedmem.cpp.o
+build/src/CMakeFiles/ylib.dir/util/sharedmem.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/sqlite3.cpp.o
+build/src/CMakeFiles/ylib.dir/util/sqlite3.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/strutils.cpp.o
+build/src/CMakeFiles/ylib.dir/util/strutils.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/system.cpp.o
+build/src/CMakeFiles/ylib.dir/util/system.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/thread.cpp.o
+build/src/CMakeFiles/ylib.dir/util/thread.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/time.cpp.o
+build/src/CMakeFiles/ylib.dir/util/time.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/timeout.cpp.o
+build/src/CMakeFiles/ylib.dir/util/timeout.cpp.o.d
+build/src/CMakeFiles/ylib.dir/util/window.cpp.o
+build/src/CMakeFiles/ylib.dir/util/window.cpp.o.d
diff --git a/include/net/http_define.h b/include/net/http_define.h
index 4723008..ae0c652 100644
--- a/include/net/http_define.h
+++ b/include/net/http_define.h
@@ -34,12 +34,64 @@
#define HTTP_INTERCEPTOR_PRINT 0
// http lua 引擎
//#define HTTP_LUA_ENGINE 0
+
+
+
+
namespace ylib
{
namespace network
{
namespace http
{
+ ///
+ /// 消息类型
+ ///
+ ///
+
+ enum message_type {
+ // 普通
+ HTTP_SERVER_MESSAGE_TYPE_NORMAL = 0,
+ // WebSocket
+ HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET = 1,
+ };
+ enum ws_type {
+ // 升级
+ HTTP_SERVER_WEBSOCKET_TYPE_UPGRADE = 0,
+ // 消息头
+ HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_HEADER = 1,
+ // 消息包
+ HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_BODY = 2,
+ // 关闭
+ HTTP_SERVER_WEBSOCKET_TYPE_CLOSE = 3,
+ };
+ struct websocket_message {
+ struct ws_header {
+ // 是否结束帧
+ bool _final = false;
+ // 帧操作码
+ // 0x0 连续帧
+ // 0x1 文本帧
+ // 0x2 二进制帧
+ // 0x3-7 为非控制帧保留
+ // 0x8 连接关闭
+ // 0x9 ping
+ // 0xA pong
+ // 0xB-F 为控制帧保留
+ int opcode = 0x00;
+ // 是否使用掩码
+ uchar mask[4] = {0};
+ // 长度
+ uint64 length = 0;
+ };
+
+ ws_type type;
+ ws_header header;
+
+ std::string sec_websocket_key;
+ std::string filepath;
+ uint64 connid = 0;
+ };
///
/// 服务端缓存
///
@@ -187,6 +239,8 @@ namespace ylib
std::map cert;
// 最大上传大小限制
uint64 max_upload_size = 0;
+ // 支持WebSocket
+ bool websocket_enable = false;
};
class agent;
@@ -221,6 +275,12 @@ namespace ylib
std::string host;
// 缓存路径
ylib::file_io cache_file;
+ // WS自定义数据
+ std::string ws_filepath;
+ // 是WS
+ bool is_ws = false;
+ // WS消息
+ websocket_message ws_msg;
};
// 代理
struct proxy
@@ -270,6 +330,9 @@ namespace ylib
size_t offset = 0;
size_t length = 0;
};
+
+
+
}
}
diff --git a/include/net/http_reqpack.h b/include/net/http_reqpack.h
index b67c85a..59c266e 100644
--- a/include/net/http_reqpack.h
+++ b/include/net/http_reqpack.h
@@ -31,7 +31,9 @@ namespace ylib
///
///
///
- reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server,network::http::website* website);
+ ///
+ ///
+ reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server,network::http::website* website, network::http::message_type msg_type, std::shared_ptr ws_msg = nullptr);
~reqpack();
///
/// 请求对象
@@ -78,11 +80,30 @@ namespace ylib
///
///
ylib::json& extra() { return m_extra; }
+ ///
+ /// 消息类型
+ ///
+ ///
+ network::http::message_type msg_type() { return m_msg_type; }
+ ///
+ /// WebSocket消息
+ ///
+ ///
+ const std::shared_ptr& ws_msg() { return m_ws_msg; }
+
+
+ ///
+ /// 设置为关闭连接包
+ ///
+ void set_close() { m_is_close = true; }
+ bool is_close() { return m_is_close; }
private:
// 请求
std::shared_ptr m_request;
// 回复
std::shared_ptr m_response;
+ // WebSocket消息
+ std::shared_ptr m_ws_msg;
// httpserver
network::http::server* m_server = nullptr;
// 请求地址
@@ -97,6 +118,11 @@ namespace ylib
uint64 m_connid = 0;
// 附加数据
ylib::json m_extra;
+ // 消息类型
+ network::http::message_type m_msg_type = HTTP_SERVER_MESSAGE_TYPE_NORMAL;
+ // 是否为关闭连接包
+ bool m_is_close = false;
+
};
}
}
diff --git a/include/net/http_request.h b/include/net/http_request.h
index beb669e..8f5f775 100644
--- a/include/net/http_request.h
+++ b/include/net/http_request.h
@@ -84,7 +84,6 @@ namespace ylib
///
///
ylib::buffer& body();
-
private:
// reqpack
diff --git a/include/net/http_response.h b/include/net/http_response.h
index aa7df13..edbb461 100644
--- a/include/net/http_response.h
+++ b/include/net/http_response.h
@@ -20,6 +20,9 @@ namespace ylib
public:
response(network::http::reqpack* reqpack);
~response();
+ bool send_header(ushort stateNum, const std::string& stateDesc = "OK");
+ /// 发送 WebSocket 帧。opcode 默认 0x1 文本;0x2二进制 0x8关闭 0xA pong
+ bool send_ws(const char* buf, size_t buf_len, int opcode = 0x1);
bool send(const char* buf, size_t buf_len, ushort stateNum = 200, const std::string& stateDesc = "OK");
bool send(const ylib::buffer& value, ushort stateNum = 200, const std::string& stateDesc = "OK");
bool send(const std::string& value, ushort stateNum = 200, const std::string& stateDesc = "OK");
@@ -28,7 +31,10 @@ namespace ylib
std::map* headers();
bool redirect(const std::string& filepath, bool MovedPermanently = false);
bool forward(const std::string& filepath);
- public:
+
+ void response_done(){m_response = true;}
+ bool is_response_done(){return m_response;}
+ public:
ylib::json sjson;
private:
bool filecache(const uint64& last_modify_time);
diff --git a/include/net/http_router.h b/include/net/http_router.h
index 1f2ffe5..f63b5f5 100644
--- a/include/net/http_router.h
+++ b/include/net/http_router.h
@@ -64,11 +64,16 @@ namespace ylib
* param
* callback : 触发回调
******************************************************************/
- void other(std::function callback);
+ void other(std::function callback);
/******************************************************************
* function:数据接收后回调
******************************************************************/
void on_recved(std::function callback);
+
+ /******************************************************************
+ * function:关闭回调
+ ******************************************************************/
+ void on_close(std::function callback);
/******************************************************************
* function:数据发送前回调
* desc:不支持大文件断点传输方式
@@ -90,6 +95,8 @@ namespace ylib
private:
// 添加任务
void push(reqpack* rp);
+ // 添加连接断开任务
+ void push_close(uint64 connid,std::shared_ptr ws_msg);
// 是否为代理任务
bool is_proxy(reqpack* rp);
// 是否为CDN服务
@@ -102,11 +109,13 @@ namespace ylib
// 线程池
IHPThreadPool* m_threadpool;
// [回调] 未订阅请求
- std::function m_callback_other;
+ std::function m_callback_other;
// [回调] 接收后
std::function m_callback_recved;
// [回调] 发送前
std::function m_callback_sendbefore;
+ // [回调] 关闭
+ std::function m_callback_close;
// 拦截器
std::unique_ptr m_interceptor;
// 订阅器
diff --git a/include/net/http_server_lst.h b/include/net/http_server_lst.h
index 1745ce0..889baae 100644
--- a/include/net/http_server_lst.h
+++ b/include/net/http_server_lst.h
@@ -44,6 +44,8 @@ namespace ylib
EnHandleResult OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen);
EnHandleResult OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
EnHandleResult OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID);
+ private:
+ bool _MessageComplete(IHttpServer* pSender,CONNID dwConnID,message_type msg_type,std::shared_ptr ws_msg = nullptr);
private:
// HPSERVER 指针
network::http::server* m_server;
diff --git a/include/net/http_subscribe.h b/include/net/http_subscribe.h
index fb36b72..8158b60 100644
--- a/include/net/http_subscribe.h
+++ b/include/net/http_subscribe.h
@@ -19,8 +19,8 @@ namespace ylib
std::regex regex;
std::string pattern;
std::string extra;
- std::function callback;
- std::function callback2;
+ std::function callback;
+ std::function callback2;
};
/******************************************************
* class:订阅器
@@ -30,7 +30,7 @@ namespace ylib
public:
subscribe();
~subscribe();
- bool add(const std::string& pattern,const std::string& extra,std::function callback);
+ bool add(const std::string& pattern,const std::string& extra,std::function callback);
bool remove(const std::string& pattern);
bool exist(const std::string& pattern);
bool trigger(const std::string& url, network::http::reqpack* rp);
diff --git a/src/net/http_reqpack.cpp b/src/net/http_reqpack.cpp
index 91fab20..5490c65 100644
--- a/src/net/http_reqpack.cpp
+++ b/src/net/http_reqpack.cpp
@@ -23,19 +23,23 @@ If you have any questions, please contact us: 1585346868@qq.com Or visit our web
#include "net/http_response.h"
#include "util/time.h"
#define HPSERVER
-ylib::network::http::reqpack::reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server, network::http::website* website)
+ylib::network::http::reqpack::reqpack(const std::string& url, const std::string& host, const ylib::buffer& data, uint64 connid, network::http::server* server, network::http::website* website, network::http::message_type msg_type, std::shared_ptr ws_msg)
:m_url(url)
,m_host(host)
,m_data(data)
,m_connid(connid)
,m_server(server)
+ ,m_msg_type(msg_type)
+ ,m_ws_msg(ws_msg)
{
this->website(website);
-
- m_filepath = strutils::F(((IHttpServer*)m_server->hpserver())->GetUrlField((CONNID)m_connid, HUF_PATH));
+ if(m_msg_type == network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET){
+ m_filepath = url;
+ }else{
+ m_filepath = strutils::F(((IHttpServer*)m_server->hpserver())->GetUrlField((CONNID)m_connid, HUF_PATH));
+ }
// 防止访问上级目录
m_filepath = strutils::remove(m_filepath, "..");
-
}
ylib::network::http::reqpack::~reqpack()
{
@@ -59,4 +63,5 @@ const std::shared_ptr& network::http::reqpack::response
}
return m_response;
}
+
#endif
diff --git a/src/net/http_response.cpp b/src/net/http_response.cpp
index 4d20fa0..5be92ec 100644
--- a/src/net/http_response.cpp
+++ b/src/net/http_response.cpp
@@ -58,6 +58,14 @@ ylib::network::http::response::~response()
send((std::string)"The server does not return any data to the browser", 500, "Internal Server Error");
}
}
+
+bool ylib::network::http::response::send_ws(const char* buf, size_t buf_len, int opcode)
+{
+ // 异步入队后 GetWSMessageState 可能已失效,由调用方指定 opcode
+ // 必须标记已响应,否则析构会再发 HTTP 500,把 WebSocket 连接打断
+ m_response = true;
+ return (bool)HPSERVER->SendWSMessage((CONNID)m_reqpack->connid(), TRUE, 0, (BYTE)opcode, (const BYTE*)buf, (int)buf_len);
+}
bool ylib::network::http::response::send(const char* buf, size_t buf_len, ushort stateNum, const std::string& stateDesc)
{
@@ -85,10 +93,11 @@ bool ylib::network::http::response::send(const char* buf, size_t buf_len, ushort
m_response = true;
//合成THeader
//Content-Type
+ if(view.length() > 0)
{
HEADER_SET("Content-Type", "text/html");
HEADER_SET("Content-Length", std::to_string((uint64)view.length()));
- // 设置默认编码
+ // 设置默认编码
{
std::string value;
auto iter = m_headers.find("Content-Type");
@@ -113,13 +122,22 @@ bool ylib::network::http::response::send(const char* buf, size_t buf_len, ushort
idx++;
}
this->m_reqpack->server()->qps()->response(view.length());
- bool result = (bool)HPSERVER->SendResponse((CONNID)m_reqpack->connid(), stateNum, stateDesc.c_str(), headers, (int32)m_headers.size(), (const BYTE*)view.data(),(int)view.length());
+ bool result = false;
+ if(view.length() > 0){
+ result = (bool)HPSERVER->SendResponse((CONNID)m_reqpack->connid(), stateNum, stateDesc.c_str(), headers, (int32)m_headers.size(), (const BYTE*)view.data(),(int)view.length());
+ }else{
+ result = (bool)HPSERVER->SendResponse((CONNID)m_reqpack->connid(), stateNum, stateDesc.c_str(), headers, (int32)m_headers.size());
+ }
+
delete[] headers;
return result;
}
}
-
+bool ylib::network::http::response::send_header(ushort stateNum, const std::string& stateDesc)
+{
+ return send(NULL, 0, stateNum, stateDesc);
+}
bool ylib::network::http::response::send(const ylib::buffer& value, ushort stateNum, const std::string& stateDesc)
{
return send(value.data(), value.length(), stateNum, stateDesc);
@@ -378,7 +396,7 @@ bool ylib::network::http::response::forward(const std::string& filepath)
if(m_response == true)
return false;
m_response = true;
- network::http::reqpack* reqpack = new network::http::reqpack(filepath,m_reqpack->host(),m_reqpack->body(),m_reqpack->connid(), m_reqpack->server(), m_reqpack->website());
+ network::http::reqpack* reqpack = new network::http::reqpack(filepath,m_reqpack->host(),m_reqpack->body(),m_reqpack->connid(), m_reqpack->server(), m_reqpack->website(), m_reqpack->msg_type(), m_reqpack->ws_msg());
reqpack->extra() = m_reqpack->extra();
m_reqpack->website()->router()->push(reqpack);
diff --git a/src/net/http_router.cpp b/src/net/http_router.cpp
index 854d002..2611e7a 100644
--- a/src/net/http_router.cpp
+++ b/src/net/http_router.cpp
@@ -97,10 +97,14 @@ network::http::subscribe* ylib::network::http::router::subscribe()
m_subscribe->center(center());
return m_subscribe.get();
}
-void network::http::router::other(std::function callback)
+void network::http::router::other(std::function callback)
{
this->m_callback_other = callback;
}
+void ylib::network::http::router::on_close(std::function callback)
+{
+ m_callback_close = callback;
+}
void ylib::network::http::router::on_recved(std::function callback)
{
m_callback_recved = callback;
@@ -119,7 +123,12 @@ VOID __HP_CALL TaskProc_function(PVOID pvArg)
}
void ylib::network::http::router::__thread_callback(reqpack* rp)
{
-
+ if(rp->is_close()){
+ if(m_callback_close != nullptr){
+ m_callback_close((uint64)rp->connid(), rp->ws_msg().get());
+ }
+ return;
+ }
/*======== ======CDN服务==============*/
if (is_cdn(rp))
return;
@@ -150,7 +159,7 @@ void ylib::network::http::router::__thread_callback(reqpack* rp)
// 其它
if (m_callback_other != nullptr)
- m_callback_other(rp->request().get(), rp->response().get());
+ m_callback_other(rp->request().get(), rp->response().get(), rp->ws_msg().get());
}
catch (const std::exception& e)
{
@@ -165,7 +174,14 @@ void ylib::network::http::router::push(reqpack *rp)
{
m_handle_queue.push(rp);
}
-
+void ylib::network::http::router::push_close(uint64 connid,std::shared_ptr ws_msg)
+{
+ // url/host 必须是合法 string;传 0/nullptr 会按 const char* 构造 std::string 直接 logic_error
+ std::string url = (ws_msg != nullptr) ? ws_msg->filepath : std::string();
+ reqpack* rp = new reqpack(url, std::string(), ylib::buffer(), connid, nullptr, nullptr, network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET, ws_msg);
+ rp->set_close();
+ m_handle_queue.push(rp);
+}
bool ylib::network::http::router::is_cdn(reqpack* rp)
{
diff --git a/src/net/http_server_lst.cpp b/src/net/http_server_lst.cpp
index ed4ff5c..492dc00 100644
--- a/src/net/http_server_lst.cpp
+++ b/src/net/http_server_lst.cpp
@@ -31,8 +31,6 @@ If you have any questions, please contact us: 1585346868@qq.com Or visit our web
#include "net/util.h"
#include "net/http_cache.h"
#include "util/codec.h"
-
-#define BARE_HP 0
ylib::network::http::http_server_lst::http_server_lst(server* server)
{
@@ -41,7 +39,7 @@ ylib::network::http::http_server_lst::http_server_lst(server* server)
ylib::network::http::http_server_lst::~http_server_lst()
{
-}
+}
EnHandleResult ylib::network::http::http_server_lst::OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
{
@@ -51,9 +49,7 @@ EnHandleResult ylib::network::http::http_server_lst::OnPrepareListen(ITcpServer*
EnHandleResult ylib::network::http::http_server_lst::OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
{
//std::cout << "[OnAccept] HttpServerConnect:" << pSender->GetConnectionCount() << std::endl;
-#if BARE_HP == 0
pSender->SetConnectionExtra(dwConnID, (PVOID)new temp_recv);
-#endif
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnAccept ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
@@ -116,7 +112,6 @@ EnHandleResult ylib::network::http::http_server_lst::OnClose(ITcpServer* pSender
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnClose ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
-#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
@@ -129,11 +124,26 @@ EnHandleResult ylib::network::http::http_server_lst::OnClose(ITcpServer* pSender
m_server->agent()->disconnect(tr->agent_ssl,tr->agent_connid);
}
#endif
+ if(tr->is_ws){
+ auto website = m_server->center()->website(tr->host);
+ if (website != nullptr)
+ {
+ std::shared_ptr ws_msg = std::make_shared();
+ ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_CLOSE;
+ ws_msg->filepath = tr->ws_filepath;
+ website->router()->push_close((uint64)dwConnID,ws_msg);
+ }
+ }
+
+
delete tr;
}
}
-#endif
+
+
+
+
return HR_OK;
}
@@ -142,7 +152,7 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageBegin(IHttpServ
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnMessageBegin ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
-#if BARE_HP == 0
+
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
@@ -151,7 +161,7 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageBegin(IHttpServ
((temp_recv*)extra)->data.clear();
}
}
-#endif
+
return HPR_OK;
}
@@ -161,16 +171,15 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnRequestLine(IHttpServe
// ylib::log->info("OnRequestLine ("+nstring::from((uint64)dwConnID)+")","http_server");
//#endif
-#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
if (extra != 0)
{
((temp_recv*)extra)->url = lpszUrl;
- }
+ ((temp_recv*)extra)->ws_filepath = std::string(lpszUrl);
+ }
}
-#endif
return HPR_OK;
}
@@ -188,7 +197,6 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnHeader(IHttpServer* pS
#if HTTP_SERVER_DEBUG_PRINT == 1
ylib::log->info("OnHeader ("+std::to_string((uint64)dwConnID)+")"+lpszName+":"+lpszValue,"http_server");
#endif
-#if BARE_HP == 0
if(strcmp(lpszName,"Host") == 0){
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
@@ -200,7 +208,6 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnHeader(IHttpServer* pS
}
}
-#endif
return HPR_OK;
}
@@ -232,6 +239,53 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnUpgrade(IHttpServer* p
ylib::log->info("OnUpgrade ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
+ if (m_server->center()->config().websocket_enable)
+ {
+ if (enUpgradeType == HUT_WEB_SOCKET)
+ {
+
+
+ PVOID extra = 0;
+ if (pSender->GetConnectionExtra(dwConnID, &extra))
+ {
+ if (extra != 0)
+ {
+ ((temp_recv*)extra)->is_ws = true;
+ }
+ }
+
+
+ LPCSTR lpszValue = nullptr;
+ if (pSender->GetHeader(dwConnID,"Sec-WebSocket-Key", &lpszValue) == false)
+ return HPR_ERROR;
+
+ // std::string value = std::string(lpszValue)+ "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
+ // std::string accept_value = codec::base64::en(codec::sha1(value));
+
+
+
+ // THeader headers[3];
+ // headers[0].name = "Connection";
+ // headers[0].value = "Upgrade";
+ // headers[1].name = "Upgrade";
+ // headers[1].value = "WebSocket";
+ // headers[2].name = "Sec-WebSocket-Accept";
+ // headers[2].value = accept_value.c_str();
+ // pSender->SendResponse(dwConnID, 101, "Switching Protocols", headers,3);
+
+ std::shared_ptr ws_msg = std::make_shared();
+ ws_msg->sec_websocket_key = std::string(lpszValue);
+ ws_msg->connid = (uint64)dwConnID;
+ ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_UPGRADE;
+ if (_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET,ws_msg))
+ return HPR_OK;
+ return HPR_ERROR;
+ }
+ else
+ return HPR_ERROR;
+ }
+
return HPR_OK;
}
@@ -241,7 +295,6 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnBody(IHttpServer* pSen
ylib::log->info("OnBody ("+std::to_string((uint64)dwConnID)+")","http_server");
#endif
-#if BARE_HP == 0
PVOID extra = 0;
if (pSender->GetConnectionExtra(dwConnID, &extra))
{
@@ -257,20 +310,11 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnBody(IHttpServer* pSen
}
}
}
-#endif
return HPR_OK;
}
-
-EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
+bool ylib::network::http::http_server_lst::_MessageComplete(IHttpServer* pSender,CONNID dwConnID,network::http::message_type msg_type,std::shared_ptr ws_msg)
{
-#if HTTP_SERVER_DEBUG_PRINT == 1
- ylib::log->info("OnMessageComplete ("+std::to_string((uint64)dwConnID)+")","http_server");
-#endif
-#if BARE_HP == 1
- pSender->SendResponse(dwConnID, 200, "OK", nullptr, 0, (const BYTE*)"ONLY_HP_OK", 3);
- return HPR_OK;
-#endif
- network::http::reqpack* rp = nullptr;
+ network::http::reqpack* rp = nullptr;
temp_recv* tr = nullptr;
{
@@ -280,10 +324,10 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpS
if (extra != 0)
tr = (temp_recv*)extra;
else
- return HPR_OK;
+ return true;
}
else
- return HPR_OK;
+ return true;
}
// QPS记录
@@ -294,10 +338,16 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpS
{
pSender->SendResponse(dwConnID, 404, "Not Found", nullptr, 0, (const BYTE*)"No fount site", 12);
delete rp;
- return HPR_OK;
+ return false;
}
// 创建请求包
- rp = new network::http::reqpack(tr->url, tr->host, tr->data, (uint64)dwConnID, m_server, website);
+ std::string url;
+ if(msg_type == network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET){
+ url = tr->ws_filepath;
+ }else{
+ url = tr->url;
+ }
+ rp = new network::http::reqpack(url, tr->host, tr->data, (uint64)dwConnID, m_server, website, msg_type, ws_msg);
// 开始前处理请求包
{
@@ -310,13 +360,19 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpS
rp->body() = end_data;
}
}
-
-
// 追加置路由
website->router()->push(rp);
- return HPR_OK;
-
+ return true;
+}
+EnHttpParseResult ylib::network::http::http_server_lst::OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
+{
+#if HTTP_SERVER_DEBUG_PRINT == 1
+ ylib::log->info("OnMessageComplete ("+std::to_string((uint64)dwConnID)+")","http_server");
+#endif
+ if (_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_NORMAL,nullptr))
+ return HPR_OK;
+ return HPR_ERROR;
}
EnHttpParseResult ylib::network::http::http_server_lst::OnParseError(IHttpServer* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
@@ -339,16 +395,74 @@ EnHttpParseResult ylib::network::http::http_server_lst::OnParseError(IHttpServer
EnHandleResult ylib::network::http::http_server_lst::OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
{
- return HR_OK;
+
+ if(iReserved != 0)
+ return HR_ERROR; // 服务器不支持扩展
+
+
+ std::shared_ptr ws_msg = std::make_shared();
+ ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_HEADER;
+ ws_msg->connid = (uint64)dwConnID;
+ ws_msg->header._final = bFinal;
+ ws_msg->header.opcode = iOperationCode;
+ ws_msg->header.mask[0] = lpszMask[0];
+ ws_msg->header.mask[1] = lpszMask[1];
+ ws_msg->header.mask[2] = lpszMask[2];
+ ws_msg->header.mask[3] = lpszMask[3];
+ ws_msg->header.length = ullBodyLen;
+
+
+
+ PVOID extra = 0;
+ if (pSender->GetConnectionExtra(dwConnID, &extra))
+ {
+ if (extra != 0)
+ {
+ ((temp_recv*)extra)->data.clear();
+ ((temp_recv*)extra)->ws_msg = *ws_msg.get();
+ }
+ }
+
+
+ if (_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET,ws_msg))
+ return HR_OK;
+ return HR_ERROR;
}
EnHandleResult ylib::network::http::http_server_lst::OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
+ PVOID extra = 0;
+ if (pSender->GetConnectionExtra(dwConnID, &extra))
+ {
+ if (extra != 0)
+ {
+ ((temp_recv*)extra)->data.append((char*)pData, iLength);
+ }
+ }
return HR_OK;
}
EnHandleResult ylib::network::http::http_server_lst::OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID)
{
- return HR_OK;
+
+ std::shared_ptr ws_msg = std::make_shared();
+
+ PVOID extra = 0;
+ if (pSender->GetConnectionExtra(dwConnID, &extra))
+ {
+ if (extra != 0)
+ {
+ // 先带上 HEADER 缓存的 opcode 等信息;不要在这里 clear data,
+ // 否则 _MessageComplete 拷贝到 reqpack 的 body 会是空的
+ *ws_msg.get() = ((temp_recv*)extra)->ws_msg;
+ }
+ }
+ ws_msg->type = network::http::HTTP_SERVER_WEBSOCKET_TYPE_MESSAGE_BODY;
+ ws_msg->connid = (uint64)dwConnID;
+ if(_MessageComplete(pSender,dwConnID,network::http::HTTP_SERVER_MESSAGE_TYPE_WEBSOCKET,ws_msg))
+ {
+ return HR_OK;
+ }
+ return HR_ERROR;
}
#endif
diff --git a/src/net/http_subscribe.cpp b/src/net/http_subscribe.cpp
index abc536d..a777fde 100644
--- a/src/net/http_subscribe.cpp
+++ b/src/net/http_subscribe.cpp
@@ -30,7 +30,7 @@ network::http::subscribe::~subscribe()
{
clear();
}
-bool network::http::subscribe::add(const std::string& pattern, const std::string& extra, std::function callback)
+bool network::http::subscribe::add(const std::string& pattern, const std::string& extra, std::function callback)
{
std::unique_lock lock(m_rw_mutex);
// 判断是否存在
@@ -81,7 +81,7 @@ bool network::http::subscribe::trigger(const std::string& url, network::http::re
for (size_t i = 0; i < m_list.size(); i++)
{
if (std::regex_match(url.c_str(), m_list[i].regex)) {
- m_list[i].callback(rp->request().get(), rp->response().get(), m_list[i].pattern, m_list[i].extra);
+ m_list[i].callback(rp->request().get(), rp->response().get(), rp->ws_msg().get(), m_list[i].pattern, m_list[i].extra);
return true;
}
}