From dc16934da0162bf273e6eec366e6db5c5d5912a7 Mon Sep 17 00:00:00 2001 From: Verity <83372423+VerityIncorporated@users.noreply.github.com> Date: Tue, 25 Mar 2025 18:28:36 +0000 Subject: [PATCH 1/2] Forcibly disconnect client Allows you to disconnect clients who are connected to your websocket server. --- scripting/include/websocket/ws.inc | 7 +++++++ src/ws_natives_server.cpp | 16 ++++++++++++++++ src/ws_server.cpp | 13 +++++++++++++ src/ws_server.h | 1 + 4 files changed, 37 insertions(+) diff --git a/scripting/include/websocket/ws.inc b/scripting/include/websocket/ws.inc index 66af284..9d50170 100755 --- a/scripting/include/websocket/ws.inc +++ b/scripting/include/websocket/ws.inc @@ -302,6 +302,13 @@ methodmap WebSocketServer < Handle */ public native bool SendMessageToClient(const char[] clientId, const char[] message); + /** + * Forcibly disconnect client from websocket + * + * @param clientId client id + */ + public native bool DisconnectClient(const char[] clientId); + /** * Start the WebSocket server */ diff --git a/src/ws_natives_server.cpp b/src/ws_natives_server.cpp index 993ed0c..5ce374a 100644 --- a/src/ws_natives_server.cpp +++ b/src/ws_natives_server.cpp @@ -171,6 +171,21 @@ static cell_t ws_SendMessageToClient(IPluginContext *pContext, const cell_t *par return pWebsocketServer->sendToClient(clientId, msg); } +static cell_t ws_DisconnectClient(IPluginContext *pContext, const cell_t *params) +{ + WebSocketServer* pWebsocketServer = GetWsServerPointer(pContext, params[1]); + + if (!pWebsocketServer) + { + return 0; + } + + char *clientId; + pContext->LocalToString(params[2], &clientId); + + return pWebsocketServer->disconnectClient(clientId); +} + static cell_t ws_BroadcastMessage(IPluginContext *pContext, const cell_t *params) { WebSocketServer* pWebsocketServer = GetWsServerPointer(pContext, params[1]); @@ -265,6 +280,7 @@ const sp_nativeinfo_t ws_natives_server[] = {"WebSocketServer.Stop", ws_Stop}, {"WebSocketServer.BroadcastMessage", ws_BroadcastMessage}, {"WebSocketServer.SendMessageToClient", ws_SendMessageToClient}, + {"WebSocketServer.DisconnectClient", ws_DisconnectClient}, {"WebSocketServer.ClientsCount.get", ws_GetClientsCount}, {"WebSocketServer.EnablePong.get", ws_SetOrGetPongEnable}, {"WebSocketServer.EnablePong.set", ws_SetOrGetPongEnable}, diff --git a/src/ws_server.cpp b/src/ws_server.cpp index a973ba3..f8b3308 100644 --- a/src/ws_server.cpp +++ b/src/ws_server.cpp @@ -146,4 +146,17 @@ bool WebSocketServer::sendToClient(const std::string& clientId, const std::strin } } return false; +} + +bool WebSocketServer::disconnectClient(const std::string& clientId) { + auto clients = m_webSocketServer.getClients(); + + for (const auto& client : clients) + { + if (client.second == clientId) { + client.first->stop(); + return true; + } + } + return false; } \ No newline at end of file diff --git a/src/ws_server.h b/src/ws_server.h index e7be21f..25a98da 100644 --- a/src/ws_server.h +++ b/src/ws_server.h @@ -14,6 +14,7 @@ class WebSocketServer void OnError(ix::WebSocketErrorInfo errorInfo, std::shared_ptr connectionState); void broadcastMessage(const std::string& message); bool sendToClient(const std::string& clientId, const std::string& message); + bool disconnectClient(const std::string& clientId); ix::WebSocketServer m_webSocketServer; Handle_t m_webSocketServer_handle = BAD_HANDLE; From e0fa603af3a5c9cbbd08bcbeed60594070e7407c Mon Sep 17 00:00:00 2001 From: Verity <83372423+VerityIncorporated@users.noreply.github.com> Date: Wed, 26 Mar 2025 17:44:38 +0000 Subject: [PATCH 2/2] Implement GetClients and bump SMEXT_CONF_VERSION to 1.0.4 --- scripting/include/websocket/ws.inc | 9 +++++++ src/smsdk_config.h | 2 +- src/ws_natives_server.cpp | 40 ++++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/scripting/include/websocket/ws.inc b/scripting/include/websocket/ws.inc index 9d50170..e0cd96d 100755 --- a/scripting/include/websocket/ws.inc +++ b/scripting/include/websocket/ws.inc @@ -309,6 +309,15 @@ methodmap WebSocketServer < Handle */ public native bool DisconnectClient(const char[] clientId); + /** + * Get handles for all connected clients + * + * @param buffer Array to store client handles + * @param maxSize Maximum size of the array + * @return Number of handles stored + */ + public native int GetClients(WebSocket[] buffer, int maxSize); + /** * Start the WebSocket server */ diff --git a/src/smsdk_config.h b/src/smsdk_config.h index a724ae4..3702f1d 100755 --- a/src/smsdk_config.h +++ b/src/smsdk_config.h @@ -3,7 +3,7 @@ #define SMEXT_CONF_NAME "SourceMod WebSocket Extension" #define SMEXT_CONF_DESCRIPTION "Provide JSON and WebSocket Native" -#define SMEXT_CONF_VERSION "1.0.3" +#define SMEXT_CONF_VERSION "1.0.4" #define SMEXT_CONF_AUTHOR "ProjectSky" #define SMEXT_CONF_URL "https://github.com/ProjectSky/sm-ext-websocket" #define SMEXT_CONF_LOGTAG "websocket" diff --git a/src/ws_natives_server.cpp b/src/ws_natives_server.cpp index 5ce374a..a3d1c60 100644 --- a/src/ws_natives_server.cpp +++ b/src/ws_natives_server.cpp @@ -265,8 +265,44 @@ static cell_t ws_IsDeflateEnabled(IPluginContext *pContext, const cell_t *params static cell_t ws_GetClients(IPluginContext *pContext, const cell_t *params) { - // TODO: Implement - return 1; + WebSocketServer *pWebsocketServer = GetWsServerPointer(pContext, params[1]); + + if (!pWebsocketServer) + { + return 0; + } + + cell_t *outputArray; + pContext->LocalToPhysAddr(params[2], &outputArray); + cell_t maxSize = params[3]; + + auto clients = pWebsocketServer->m_webSocketServer.getClients(); + size_t count = 0; + + HandleSecurity sec(nullptr, myself->GetIdentity()); + + for (const auto &client : clients) + { + if (count >= maxSize) + break; + + WebSocketClient *pClient = new WebSocketClient(client.first.get()); + HandleError err; + Handle_t handle = handlesys->CreateHandleEx(g_htWsClient, pClient, &sec, nullptr, &err); + + if (handle != BAD_HANDLE) + { + pClient->m_websocket_handle = handle; + pClient->m_keepConnecting = true; + outputArray[count++] = handle; + } + else + { + delete pClient; + } + } + + return count; } const sp_nativeinfo_t ws_natives_server[] =