增加websocket支持

This commit is contained in:
xx
2024-06-19 03:01:08 +08:00
parent d5818c3299
commit ec4df79c9e
8 changed files with 336 additions and 3 deletions

View File

@@ -9,7 +9,7 @@
#define DEBUG_MEM 0
#define USE_OPENSSL 0
#define USE_OPENSSL 1
using namespace ylib;

View File

@@ -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

View 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

View File

@@ -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);

View File

@@ -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
View 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());
}

View File

@@ -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

View File

@@ -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);