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

558 lines
17 KiB
C
Raw Permalink 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"
2025-09-30 16:24:15 +08:00
#include "TL/Map.h"
#include "TL/Queue.h"
2025-09-27 14:24:18 +08:00
// 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 = "/";
2025-09-30 16:24:15 +08:00
bool m_status = false;
mutable std::mutex m_mutex_id;
2025-09-27 14:24:18 +08:00
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
2025-09-30 16:24:15 +08:00
* @return
2025-09-27 14:24:18 +08:00
*/
2025-09-30 16:24:15 +08:00
static int WriteSSLResponse(SSL* ssl, const char* buffer, size_t size);
2025-09-27 14:24:18 +08:00
/**
*
* @param statusCode
* @param reason
*/
void CloseConnection(uint16_t statusCode = 1000, const CTL::String& reason = "");
/**
* Ping心跳内收到一个Ping消息就更新连接状态
*/
void StatusUpdate();
/**
* Ping心跳内收到一个Ping消息就更新连接状态
*/
void StateReset();
/**
2025-09-30 16:24:15 +08:00
*
2025-09-27 14:24:18 +08:00
* @return Ping心跳个数
*/
int GetStatus() const;
/**
*
* @param path
*/
void SetURLPath(const String& path);
/**
*
* @return
*/
String GetURLPath();
2025-09-30 16:24:15 +08:00
/**
*
* @return
*/
bool GetSendStatus() const;
2025-09-27 14:24:18 +08:00
};
/**
* WebSocket
* WebSocket
*/
2025-09-30 16:24:15 +08:00
using RequestFunc = std::function<void(WebSocketInfo&)>;
class WebSocketBind {
public:
WebSocketBind() = default;
CTL::String URL = "";
RequestFunc OnOpenFun;
RequestFunc OnCloseFun;
RequestFunc OnMessageFun;
RequestFunc OnPingFun;
RequestFunc OnPongFun;
RequestFunc OnErrorFun;
};
2025-09-27 14:24:18 +08:00
class WebSocket {
2025-09-30 16:24:15 +08:00
mutable std::shared_mutex m_mutex_t;
2025-09-27 14:24:18 +08:00
public:
/**
* WebSocket
* @param ip IP
* @param port
* @param ChokeUp
* @return
*/
bool Init(const CTL::String& ip,int port,bool ChokeUp = true);
/**
* WebSocket
2025-09-30 16:24:15 +08:00
* @param bind
2025-09-27 14:24:18 +08:00
* @return
*/
2025-09-30 16:24:15 +08:00
bool Init(const WebSocketBind& bind);
/**
* SSL
* @param ssl_ctx_t SSL_CTX
*/
void SetSSL(SSL_CTX* ssl_ctx_t);
2025-09-27 14:24:18 +08:00
/**
* 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);
/**
2025-09-30 16:24:15 +08:00
* ID列表
* @return ID的列表
2025-09-27 14:24:18 +08:00
*/
2025-09-30 16:24:15 +08:00
CCVector<int> GetClientListAll();
2025-09-27 14:24:18 +08:00
/**
* ID
* @param ID ID
* @return WebSocketInfo
*/
2025-09-30 16:24:15 +08:00
WebSocketInfo* GetClient(int ID);
2025-09-27 14:24:18 +08:00
/**
* 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心跳间隔
*/
2025-09-30 16:24:15 +08:00
unsigned long GetTimingTime() const {
2025-09-27 14:24:18 +08:00
return m_timer_count;
}
/**
* Ping心跳开关
* @param PingUp Ping心跳开关
*/
void SettingPing(const bool PingUp) {
Tick_m = PingUp;
}
2025-09-30 16:24:15 +08:00
/**
* WebSocket服务
*/
void InitService();
2025-09-27 14:24:18 +08:00
protected:
CTL::Socket m_sock; // 服务器 Socket
2025-09-30 16:24:15 +08:00
Epoll m_epoll; // Epoll 对象
2025-09-27 14:24:18 +08:00
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 标志位映射
2025-09-30 16:24:15 +08:00
Map<int,WebSocketInfo*> Clients; // 客户端信息映射
// CCMutex m_mutex; // 共享互斥锁
2025-09-27 14:24:18 +08:00
SSL_CTX* ssl_ctx = nullptr; // SSL 上下文
Timer m_timer; // 定时器
2025-09-30 16:24:15 +08:00
unsigned long m_timer_count = 120;
2025-09-27 14:24:18 +08:00
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
*/
2025-09-30 16:24:15 +08:00
void AddClient(WebSocketInfo* ws);
2025-09-27 14:24:18 +08:00
/**
*
* @param ws WebSocketInfo
*/
2025-09-30 16:24:15 +08:00
void DeleteClient(const int ID);
2025-09-27 14:24:18 +08:00
/**
* 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