diff --git a/scripting/include/websocket/ws.inc b/scripting/include/websocket/ws.inc index 66af284..e0cd96d 100755 --- a/scripting/include/websocket/ws.inc +++ b/scripting/include/websocket/ws.inc @@ -302,6 +302,22 @@ 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); + + /** + * 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 993ed0c..a3d1c60 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]); @@ -250,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[] = @@ -265,6 +316,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;