增加websocket支持
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
#define DEBUG_MEM 0
|
||||
|
||||
|
||||
#define USE_OPENSSL 0
|
||||
#define USE_OPENSSL 1
|
||||
|
||||
using namespace ylib;
|
||||
|
||||
|
||||
@@ -35,11 +35,13 @@
|
||||
#define USE_NET_HTTP_CLIENT 1
|
||||
#define USE_NET_HTTP_UTIL 1
|
||||
#define USE_NET_HTTP_AGENT 0
|
||||
#define USE_NET_HTTP_WS 1
|
||||
#else
|
||||
#define USE_NET_HTTP_WEBSITE 0
|
||||
#define USE_NET_HTTP_CLIENT 0
|
||||
#define USE_NET_HTTP_UTIL 0
|
||||
#define USE_NET_HTTP_AGENT 0
|
||||
#define USE_NET_HTTP_WS 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
70
include/net/http_wsserver.h
Normal file
70
include/net/http_wsserver.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "http_define.h"
|
||||
#if USE_NET_HTTP_WS == 1
|
||||
#include <functional>
|
||||
#include "base/define.h"
|
||||
#include "base/error.h"
|
||||
class wsserver_lst;
|
||||
namespace ylib
|
||||
{
|
||||
namespace network
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// WebSocket服务器
|
||||
/// </summary>
|
||||
class wsserver:public ylib::error_base {
|
||||
public:
|
||||
wsserver();
|
||||
~wsserver();
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="ssl"></param>
|
||||
/// <param name="ssl_key"></param>
|
||||
/// <param name="ssl_pem"></param>
|
||||
/// <returns></returns>
|
||||
bool start(ushort port, bool ssl = false,const std::string& ssl_key = "", const std::string& ssl_pem = "");
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
void stop();
|
||||
/// <summary>
|
||||
/// 发送
|
||||
/// </summary>
|
||||
bool send(int64 conn, std::string_view value);
|
||||
|
||||
void on_accept(std::function<bool(int64)> callback) { m_callback_accept = callback; }
|
||||
void on_recv(std::function<bool(int64,const char* data, int len)> callback) { m_callback_recv = callback; }
|
||||
void on_close(std::function<void(int64)> callback) { m_callback_close = callback; }
|
||||
|
||||
friend class wsserver_lst;
|
||||
private:
|
||||
// 端口
|
||||
ushort m_port = 0;
|
||||
// 是否为SSL
|
||||
bool m_ssl = false;
|
||||
// SSL-KEY
|
||||
std::string m_ssl_key;
|
||||
// SSL-PEM
|
||||
std::string m_ssl_pem;
|
||||
// 监听器
|
||||
wsserver_lst* m_listener = nullptr;
|
||||
// HPServer
|
||||
void* m_server = nullptr;
|
||||
|
||||
std::function<bool(int64)> m_callback_accept;
|
||||
std::function<bool(int64,const char* data, int len)> m_callback_recv;
|
||||
std::function<void(int64)> m_callback_close;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,7 @@ namespace ylib
|
||||
{
|
||||
namespace codec
|
||||
{
|
||||
ylib::buffer sha1(const ylib::buffer& data);
|
||||
std::string md5(const ylib::buffer& data);
|
||||
std::string to_utf8(const std::string& gbk);
|
||||
std::string to_gbk(const std::string& utf8);
|
||||
|
||||
@@ -12,8 +12,9 @@ file(GLOB_RECURSE HEADER_FILES
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
#set(MYSQL_CPPCONN_INCLUDE CACHE PATH "mysql-connector include")
|
||||
set(MYSQL_CPPCONN_INCLUDE "$ENV{USERPROFILE}/MySQL/MySQL Connector C++ 8.2.0/include/jdbc")
|
||||
set(OPENSSL_INCLUDE "D:/3rdparty/OpenSSL-Win64/include")
|
||||
include_directories(${OPENSSL_INCLUDE})
|
||||
include_directories(${MYSQL_CPPCONN_INCLUDE})
|
||||
include_directories(${PROJECT_SOURCE_DIR}/3rdparty/HP-Socket/Windows/Include)
|
||||
endif()
|
||||
|
||||
240
src/net/http_wsserver.cpp
Normal file
240
src/net/http_wsserver.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
#include "net/http_wsserver.h"
|
||||
//#include "HPSocket/HPSocket.h"
|
||||
#include "HPSocket/HPSocket-SSL.h"
|
||||
#include "util/codec.h"
|
||||
|
||||
class wsserver_lst : public IHttpServerListener
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
wsserver_lst(network::http::wsserver* server) :m_server(server) {}
|
||||
~wsserver_lst() {}
|
||||
private:
|
||||
EnHandleResult OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
|
||||
{
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
|
||||
{
|
||||
pSender->SetConnectionExtra(dwConnID, new ylib::buffer());
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnHandShake(ITcpServer* pSender, CONNID dwConnID)
|
||||
{
|
||||
if (m_server->m_callback_accept != nullptr)
|
||||
{
|
||||
if (m_server->m_callback_accept(dwConnID) == false)
|
||||
return HR_ERROR;
|
||||
}
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength)
|
||||
{
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
|
||||
{
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
|
||||
{
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnShutdown(ITcpServer* pSender)
|
||||
{
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
|
||||
{
|
||||
PVOID extra = nullptr;
|
||||
if (pSender->GetConnectionExtra(dwConnID, &extra))
|
||||
{
|
||||
delete static_cast<ylib::buffer*>(extra);
|
||||
}
|
||||
if (m_server->m_callback_close != nullptr)
|
||||
{
|
||||
m_server->m_callback_close(dwConnID);
|
||||
}
|
||||
return HR_OK;
|
||||
}
|
||||
|
||||
EnHttpParseResult OnMessageBegin(IHttpServer* pSender, CONNID dwConnID)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnRequestLine(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnStatusLine(IHttpServer* pSender, CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnHeader(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnHeadersComplete(IHttpServer* pSender, CONNID dwConnID)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnChunkHeader(IHttpServer* pSender, CONNID dwConnID, int iLength)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnChunkComplete(IHttpServer* pSender, CONNID dwConnID)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnUpgrade(IHttpServer* pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
|
||||
{
|
||||
if (enUpgradeType == HUT_WEB_SOCKET)
|
||||
{
|
||||
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);
|
||||
return HPR_OK;
|
||||
}
|
||||
else
|
||||
return HPR_ERROR;
|
||||
}
|
||||
EnHttpParseResult OnBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
EnHttpParseResult OnParseError(IHttpServer* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
|
||||
{
|
||||
return HPR_OK;
|
||||
}
|
||||
|
||||
EnHandleResult OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
|
||||
{
|
||||
PVOID extra = nullptr;
|
||||
if (pSender->GetConnectionExtra(dwConnID, &extra))
|
||||
{
|
||||
static_cast<ylib::buffer*>(extra)->clear();
|
||||
}
|
||||
|
||||
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
|
||||
{
|
||||
|
||||
PVOID extra = nullptr;
|
||||
if (pSender->GetConnectionExtra(dwConnID, &extra))
|
||||
{
|
||||
static_cast<ylib::buffer*>(extra)->append((const char*)pData, iLength);
|
||||
}
|
||||
|
||||
|
||||
return HR_OK;
|
||||
}
|
||||
EnHandleResult OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID)
|
||||
{
|
||||
PVOID extra = nullptr;
|
||||
ylib::buffer* data = nullptr;
|
||||
pSender->GetConnectionExtra(dwConnID, &extra);
|
||||
data = static_cast<ylib::buffer*>(extra);
|
||||
|
||||
if (m_server->m_callback_recv != nullptr)
|
||||
{
|
||||
if (m_server->m_callback_recv(dwConnID, (const char*)data->data(), data->length()) == false)
|
||||
return HR_ERROR;
|
||||
}
|
||||
return HR_OK;
|
||||
}
|
||||
private:
|
||||
// HPSERVER 指针
|
||||
network::http::wsserver* m_server = nullptr;
|
||||
};
|
||||
#define HPSERVER static_cast<::IHttpServer*>(m_server)
|
||||
ylib::network::http::wsserver::wsserver()
|
||||
{
|
||||
}
|
||||
|
||||
ylib::network::http::wsserver::~wsserver()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
bool ylib::network::http::wsserver::start(ushort port, bool ssl, const std::string& ssl_key, const std::string& ssl_pem)
|
||||
{
|
||||
stop();
|
||||
m_listener = new wsserver_lst(this);
|
||||
m_ssl = ssl;
|
||||
m_port = port;
|
||||
m_ssl_key = ssl_key;
|
||||
m_ssl_pem = ssl_pem;
|
||||
if (ssl)
|
||||
{
|
||||
m_server = HP_Create_HttpsServer(m_listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_server = HP_Create_HttpServer(m_listener);
|
||||
}
|
||||
if (HPSERVER->Start("0.0.0.0",m_port) == false)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
this->m_lastErrorDesc = "start failed, error code:" + std::string(SYS_GetLastErrorStr());
|
||||
#else
|
||||
this->m_lastErrorDesc = "start failed, error code:" + std::to_string((uint32)SYS_GetLastError());
|
||||
#endif
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ylib::network::http::wsserver::stop()
|
||||
{
|
||||
if (m_server == nullptr)
|
||||
return;
|
||||
//关闭HP HTTPSERVER
|
||||
if (HPSERVER->GetState() != SS_STOPPED)
|
||||
{
|
||||
if (HPSERVER->Stop())
|
||||
HPSERVER->Wait(-1);
|
||||
}
|
||||
//销毁释放
|
||||
if (m_ssl)
|
||||
HP_Destroy_HttpsServer(HPSERVER);
|
||||
else
|
||||
HP_Destroy_HttpServer(HPSERVER);
|
||||
if(m_listener != nullptr)
|
||||
delete m_listener;
|
||||
m_server = nullptr;
|
||||
m_listener = nullptr;
|
||||
m_callback_accept = nullptr;
|
||||
m_callback_close = nullptr;
|
||||
m_callback_recv = nullptr;
|
||||
}
|
||||
|
||||
bool ylib::network::http::wsserver::send(int64 conn, std::string_view value)
|
||||
{
|
||||
BOOL bFinal;
|
||||
BYTE iReserved;
|
||||
BYTE iOperationCode;
|
||||
if (HPSERVER->GetWSMessageState(conn,&bFinal,&iReserved,&iOperationCode,nullptr,nullptr,nullptr) == false)
|
||||
return false;
|
||||
return HPSERVER->SendWSMessage(conn,bFinal,iReserved,iOperationCode,(const BYTE*)value.data(),value.length());
|
||||
}
|
||||
@@ -25,14 +25,31 @@ If you have any questions, please contact us: 1585346868@qq.com Or visit our web
|
||||
#include "HPSocket/HPSocket.h"
|
||||
#if USE_OPENSSL== 1
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
#if USE_OPENSSL== 1
|
||||
ylib::buffer ylib::codec::sha1(const ylib::buffer& data)
|
||||
{
|
||||
ylib::buffer result;
|
||||
result.resize(20);
|
||||
SHA_CTX sha1;
|
||||
SHA1_Init(&sha1);
|
||||
SHA1_Update(&sha1, data.data(), data.size());
|
||||
SHA1_Final((unsigned char*)result.data(), &sha1);
|
||||
|
||||
|
||||
return result;
|
||||
//std::stringstream ss;
|
||||
//for (int i = 0; i < SHA_DIGEST_LENGTH; i++) {
|
||||
// ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
|
||||
//}
|
||||
//return ss.str();
|
||||
}
|
||||
#endif
|
||||
std::string ylib::codec::to_utf8(const std::string &gbk)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -19,6 +19,7 @@ If you have any questions, please contact us: 1585346868@qq.com Or visit our web
|
||||
/* system implementation headers */
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include "util/codec.h"
|
||||
|
||||
|
||||
// Constants for MD5Transform routine.
|
||||
@@ -353,6 +354,7 @@ namespace ylib
|
||||
{
|
||||
namespace codec
|
||||
{
|
||||
|
||||
std::string md5(const ylib::buffer& data)
|
||||
{
|
||||
MD5 md5 = MD5(data);
|
||||
|
||||
Reference in New Issue
Block a user