Service_NSSM/CC_SDK/Include/Module/Comm/WebSocket/CCWebSocket.h

553 lines
17 KiB
C
Raw Normal View History

2025-09-27 14:24:18 +08:00
#ifndef CC_WEBSOCKET_H
#define CC_WEBSOCKET_H
#include <bio.h>
#include <buffer.h>
#include <CCThreadPool.h>
#include "CCEpoll.h"
#include "CC.h"
#include <ws_packet.h>
#include <string>
#include <random>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include "CCTimer.h"
// WebSocket 类格式的回调函数宏定义
#define CC_WSFunClass(Fun) [this](auto && PH1) { Fun(std::forward<decltype(PH1)>(PH1)); }
// WebSocket 普通函数格式的回调函数宏定义
#define CC_WSFun(Fun) Fun
namespace CTL{
/**
* WebSocket
* WebSocket
*/
class WebSocketInfo {
WebSocketPacket m_packet; // WebSocket 数据包
CTL::Socket m_sock; // Socket 连接
ByteArray m_buffer; // 数据缓冲区
bool Con_Flag = false; // 连接标志
int ID = -1; // 客户端 ID
int m_count = 0;
String URL_Path = "/";
public:
/**
* WebSocket
* @return WebSocket
*/
WebSocketPacket& GetPacket();
/**
* Socket
* @return Socket
*/
CTL::Socket& GetSock();
/**
* WebSocket
* @return WebSocket
*/
[[nodiscard]] const WebSocketPacket& GetPacket() const;
/**
* WebSocket
* @param packet WebSocket
*/
void SetPacket(const WebSocketPacket& packet);
/**
* Socket
* @param socket Socket
*/
void SetSock(const CTL::Socket& socket);
/**
*
* @param buffer
*/
void SetBuffer(ByteBuffer& buffer);
/**
*
* @return
*/
ByteArray& GetBuffer();
/**
*
* @return
*/
[[nodiscard]] bool GetConnectFlag() const;
/**
*
* @param F
*/
void SetConnectFlag(bool F);
/**
* ID
* @param ID ID
*/
void SetID(int ID);
SSL* ssl = nullptr; // SSL 对象指针
/**
* ID
* @return ID
*/
[[nodiscard]] int GetID() const;
/**
*
* @param data
* @param size
* @return
*/
bool Write(const char* data, size_t size);
/**
*
* @param text
* @return
*/
bool SendText(const CTL::String& text);
/**
*
* @param binaryData
* @return
*/
bool SendBinary(const ByteArray& binaryData);
/**
* Ping二进制数据
* @param binaryData
* @return
*/
bool SendPing(const ByteArray& binaryData);
/**
* Pong二进制数据
* @param binaryData
* @return
*/
bool SendPong(const ByteArray& binaryData);
/**
* SSL
* @param ssl SSL
* @param buffer
* @param size
* @return
*/
static bool WriteSSLResponse(SSL* ssl, const char* buffer, size_t size);
/**
*
* @param statusCode
* @param reason
*/
void CloseConnection(uint16_t statusCode = 1000, const CTL::String& reason = "");
/**
* Ping心跳内收到一个Ping消息就更新连接状态
*/
void StatusUpdate();
/**
* Ping心跳内收到一个Ping消息就更新连接状态
*/
void StateReset();
/**
*
* @return Ping心跳个数
*/
int GetStatus() const;
/**
*
* @return Ping心跳个数
*/
int GetStatus();
/**
*
* @param path
*/
void SetURLPath(const String& path);
/**
*
* @return
*/
String GetURLPath();
};
/**
* WebSocket
* WebSocket
*/
class WebSocket {
public:
// 请求处理函数类型
using RequestFunc = std::function<void(WebSocketInfo&)>;
/**
* WebSocket
* @param ip IP
* @param port
* @param ChokeUp
* @return
*/
bool Init(const CTL::String& ip,int port,bool ChokeUp = true);
/**
* WebSocket
* @param ws WebSocket
* @param ssl_ctx SSL
* @return
*/
bool Init(const WebSocket& ws,SSL_CTX* ssl_ctx = nullptr);
/**
* WebSocket
* @return
*/
int Running();
/**
*
* @param URL
* @param OnOpenFun
* @param OnCloseFun
* @param OnMessageFun
* @param OnErrorFun
* @param OnPingFun Ping
* @param OnPongFun Pong
*/
void OnBind(const CTL::String& URL,const RequestFunc& OnOpenFun = nullptr,const RequestFunc& OnCloseFun = nullptr,
const RequestFunc& OnMessageFun = nullptr,const RequestFunc& OnErrorFun = nullptr,
const RequestFunc& OnPingFun = nullptr,const RequestFunc& OnPongFun = nullptr);
/**
*
* @param client Socket
* @param ev
* @param Data
* @param ssl SSL
*/
void ProcessingClientRequests(CTL::Socket& client,CC_EP_EV &ev,const CTL::String& Data,SSL* ssl = nullptr);
/**
*
* @return
*/
CCMap<int,WebSocketInfo> GetClientAll();
/**
*
* @return
*/
CCList<WebSocketInfo> GetClientListAll();
/**
* ID
* @param ID ID
* @return WebSocketInfo
*/
WebSocketInfo GetClient(int ID);
/**
* SSL
* @return
*/
bool InitSSL();
/**
* SSL
* @param CertPath
* @return
*/
bool LoadSSLCertificate(const CTL::String& CertPath) const;
/**
* SSL
* @param KeyPath
* @param Passwd
* @return
*/
bool LoadSSLKey(const CTL::String &KeyPath, const CTL::String &Passwd) const;
/**
* SSL
* @param CA_Path
* @return
*/
bool LoadSSLVerify(const CTL::String& CA_Path) const;
/**
* WebSocket
* */
void Stop();
/**
* sec-websocket-key
* @return sec-websocket-key
*/
static std::string generate_sec_websocket_key();
/**
*
* @param str
* @return
*/
static std::string& trim(std::string& str);
/**
*
* @param ssl SSL
* @param client Socket
* @param buf
* @param size
* @return
*/
static ByteHander ReadBuffer(SSL* ssl,CTL::Socket& client,char* buf,ByteHander size);
/**
* Ping心跳间隔
* @param Seconds
*/
void SetTimingTime(const unsigned long Seconds) {
m_timer_count = Seconds;
}
/**
*
* @return Ping心跳间隔
*/
unsigned long GetTimingTime() const {
return m_timer_count;
}
/**
*
* @return Ping心跳间隔
*/
unsigned long GetTimingTime() {
return m_timer_count;
}
/**
* Ping心跳开关
* @param PingUp Ping心跳开关
*/
void SettingPing(const bool PingUp) {
Tick_m = PingUp;
}
protected:
CTL::Socket m_sock; // 服务器 Socket
Epoll m_epoll; // Epoll 对象
CC_EP_EV events[MAX_EVENTS]{}; // 事件数组
bool ServerFlag = true,Client = false,ClientOK = false,Tick_m = true; // 标志位
ThreadPool M_S_POOl{}; // 线程池
size_t M_Pool_Size = 128,M_Pool_Max = 1024; // 线程池参数
int M_Pool_KeepAliveTime = 1000; // 线程池保活时间
CCMap<CTL::String,RequestFunc> URLOpenFun; // URL 打开回调函数映射
CCMap<CTL::String,RequestFunc> URLCloseFun; // URL 关闭回调函数映射
CCMap<CTL::String,RequestFunc> URLMessageFun; // URL 消息回调函数映射
CCMap<CTL::String,RequestFunc> URL_ERROR_Fun; // URL 错误回调函数映射
CCMap<CTL::String,RequestFunc> URL_Ping_Fun; // URL Ping回调函数映射
CCMap<CTL::String,RequestFunc> URL_Pong_Fun; // URL Pong回调函数映射
CCMap<CTL::String,bool> URLS; // URL 标志位映射
CCMap<int,WebSocketInfo> Clients; // 客户端信息映射
CCMutex m_mutex; // 共享互斥锁
SSL_CTX* ssl_ctx = nullptr; // SSL 上下文
Timer m_timer; // 定时器
unsigned long m_timer_count = 60;
private:
// 接受客户端连接
void AcceptingClient();
/**
*
* @param client Socket
* @param ssl SSL
* @return
*/
CTL::String GetRequest(CTL::Socket& client,SSL* ssl = nullptr);
/**
*
* @param str
*/
void MessagePrint(const CTL::String& str);
/**
* ID
* @return ID
*/
int AllocationID();
/**
*
* @param ws WebSocketInfo
*/
void AddClient(const WebSocketInfo &ws);
/**
*
* @param ws
*/
void UpClient(const WebSocketInfo &ws);
/**
*
* @param ws WebSocketInfo
*/
void DeleteClient(const WebSocketInfo &ws);
/**
* SSL
* @param client Socket
* @return SSL
*/
SSL* NewSSL(const CTL::Socket& client) const;
/**
*
*/
void Tick();
};
class WebSocketClient {
// 请求处理函数类型
using RequestFunc = std::function<void(WebSocketInfo&)>;
WebSocketInfo LocalClientInfo;// 客户端连接信息
/**
* WebSocket
* WebSocket
*/
struct WebSocketClient_Info {
CTL::String IP; // 客户端 IP 地址
int Prot = 0; // 客户端端口号
CTL::String Path; // 请求路径
CTL::String Protocol; // 使用的协议
};
ByteBuffer ClientBuffer; // 客户端缓冲区
RequestFunc OnErrorFun,OnOpenFun,OnCloseFun,OnMessageFun,OnPingFun,OnPongFun; // 回调函数
String ClientKey;
bool ServerFlag = true,Client = false,ClientOK = false; // 标志位
Socket m_sock;
SSL_CTX* ssl_ctx = nullptr; // SSL 上下文
public:
/**
* WebSocket
* @param ip IP
* @param port
* @param URL
* @return
*/
bool Connect(const CTL::String& ip,int port,const String& URL);
/**
* WebSocket
* @param WsURL WebSocket URL
* @return
*/
bool Connect(const CTL::String& WsURL);
/**
*
* @param OnOpenFun
* @param OnCloseFun
* @param OnMessageFun
* @param OnErrorFun
* @param OnPingFun Ping
* @param OnPongFun Pong
*/
void OnBind(const RequestFunc& OnOpenFun = nullptr,const RequestFunc& OnCloseFun = nullptr,
const RequestFunc& OnMessageFun = nullptr,const RequestFunc& OnErrorFun = nullptr,
const RequestFunc& OnPingFun = nullptr,const RequestFunc& OnPongFun = nullptr);
/**
* WebSocket
*/
int Running();
/**
* WebSocket
*/
void Stop();
/**
* @param data
* @return
*/
bool SendBinary(const ByteArray& data);
/**
* @param text
* @return
*/
bool SendText(const String& text);
/**
* SSL
* @return
*/
bool InitSSL();
/**
* SSL
* @param CertPath
* @return
*/
bool LoadSSLCertificate(const CTL::String& CertPath) const;
/**
* SSL
* @param KeyPath
* @param Passwd
* @return
*/
bool LoadSSLKey(const CTL::String &KeyPath, const CTL::String &Passwd) const;
/**
* SSL
* @param CA_Path
* @return
*/
bool LoadSSLVerify(const CTL::String& CA_Path) const;
private:
/**
* WebSocket
* @param url WebSocket URL
* @return WebSocketClient
*/
static WebSocketClient_Info ParsingLink(const std::string& url);
/**
*
* @param ip_ IP
* @param port_
* @param Path
* @param ssh
* @return
*/
[[nodiscard]] bool Send_Handshake(const String &ip_, int port_,const String& Path, const String &ssh) const;
/**
*
* @return
*/
bool Recv_Handshake();
};
}
#endif