diff --git a/API.cpp b/API.cpp index d8e95d3..350f81c 100644 --- a/API.cpp +++ b/API.cpp @@ -8,6 +8,7 @@ # define _WINSOCK_DEPRECATED_NO_WARNINGS #endif #include "API.h" +#include "plugin.h" #include "dependencies/webby/webby.c" @@ -101,12 +102,11 @@ int TS3_API::onHttpRequest(struct WebbyConnection* connection) { read_len = sizeof(buf) - 1; if (WebbyRead(connection, buf, read_len)) return 1; - return Instance().sendAllInfo(connection); + Instance().sendAllInfo(connection); + return 0; } int TS3_API::onWebsocketConnection(struct WebbyConnection* connection) { - onLogMessage("onWebsocketConnection unsupported"); - connection->user_data = (void*)1; - return 0; // Not supported atm + return 0; // Allow all } int TS3_API::writeJson(struct WebbyConnection* connection, std::string& message) { WebbyHeader headers[1] = { {"Content-Type","application/json"} }; @@ -126,13 +126,11 @@ bool TS3_API::isWebsocketConnection(struct WebbyConnection* connection) { } int TS3_API::write(struct WebbyConnection* connection, const char* response, struct WebbyHeader* headers, int header_count) { size_t response_len = strlen(response); - if (isWebsocketConnection(connection)) { - if (WebbyBeginSocketFrame(connection, WEBBY_WS_OP_TEXT_FRAME)) - return 1; - int ok = WebbyWrite(connection, response, response_len); - //int ok = WebbyPrintf(connection, "%s", response); + if (is_websocket_request(connection)) { + WebbyBeginSocketFrame(connection, WEBBY_WS_OP_TEXT_FRAME); + WebbyPrintf(connection, "%s\r\n", response); WebbyEndSocketFrame(connection); - return ok; + return 0; } else { size_t response_len = strlen(response); @@ -272,7 +270,7 @@ int TS3_API::sendAllInfo(struct WebbyConnection* connection) { std::lock_guard guard(mutex); nlohmann::json jsonClients; nlohmann::json jsonBody; - for (auto it : clients) { + for (auto& it : clients) { TS3User* client = it.second; if (!client) continue; nlohmann::json clientJson; @@ -369,6 +367,13 @@ void TS3_API::update() { std::lock_guard guard(mutex); if (ws_server) WebbyServerUpdate(ws_server); + static clock_t last_update = 0; + if (!last_update) + last_update = clock(); + if (clock() - last_update > 2 * CLOCKS_PER_SEC) { + last_update = clock(); + refreshAll(); + } } TS3_API::TS3User* TS3_API::getUser(anyID clientId) { std::lock_guard guard(mutex); diff --git a/API.h b/API.h index ddcdfee..7b749f3 100644 --- a/API.h +++ b/API.h @@ -1,4 +1,6 @@ #pragma once + + #include #include @@ -79,6 +81,7 @@ class TS3_API { int writeJson(struct WebbyConnection* connection, nlohmann::json & json); // Write out to a connection int write(struct WebbyConnection* connection, const char* response, struct WebbyHeader* headers = nullptr, int header_count = 0); + int writeHttp(struct WebbyConnection* connection, const char* response, struct WebbyHeader* headers = nullptr, int header_count = 0); bool isWebsocketConnection(struct WebbyConnection* connection); public: static TS3_API& Instance() { diff --git a/dependencies/webby/webby.c b/dependencies/webby/webby.c index 7a0b134..2d55ff3 100644 --- a/dependencies/webby/webby.c +++ b/dependencies/webby/webby.c @@ -891,13 +891,13 @@ static int is_websocket_request(struct WebbyConnection* conn) if (NULL == (hdr = WebbyFindHeader(conn, "Connection"))) return 0; - if (0 != strcasecmp(hdr, "Upgrade")) + if (NULL == strstr(hdr, "Upgrade")) return 0; if (NULL == (hdr = WebbyFindHeader(conn, "Upgrade"))) return 0; - if (0 != strcasecmp(hdr, "websocket")) + if (NULL == strstr(hdr, "websocket")) return 0; return 1; diff --git a/dependencies/webby/webby.h b/dependencies/webby/webby.h index a7bed72..96c7b56 100644 --- a/dependencies/webby/webby.h +++ b/dependencies/webby/webby.h @@ -165,6 +165,8 @@ WebbyServerMemoryNeeded(const struct WebbyServerConfig *config); struct WebbyServer* WebbyServerInit(struct WebbyServerConfig *config, void *memory, size_t memory_size); +int is_websocket_request(struct WebbyConnection* conn); + /* Update the server. Call frequently (at least once per frame). */ void WebbyServerUpdate(struct WebbyServer *srv); diff --git a/plugin.cpp b/plugin.cpp index 14a0353..58dc926 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -47,6 +47,8 @@ static struct TS3Functions ts3Functions; static char* pluginID = NULL; +static UINT WM_TEAMSPEAK3_JSON_API_STARTED = 0; + /*********************************** Required functions ************************************/ /* * If any of these required functions is not implemented, TS3 will refuse to load the plugin @@ -123,18 +125,19 @@ int refreshAll() { int ret = ERROR_ok; if (!is_connected()) { // Not fully connected; make sure client and server vars are flushed - if (instance.server.id) { + if (instance.server.host) { instance.resetServerVariables(); instance.sendAllInfo(); } - instance.server.id = 0; + instance.server.host[0] = 0; return 0; } - bool new_connection = !instance.server.id; + bool new_connection = !instance.server.host; + need_to_send |= new_connection; char* s; if ((ret = ts3Functions.getServerVariableAsString(serverConnectionHandlerID, VIRTUALSERVER_NAME, &s)) != ERROR_ok) { API::onLogMessage("Failed to get server name, code 0x%04x", ret); - return 1; + goto send_if_needed; } if (strcmp(s, server.name) != 0) { need_to_send = true; @@ -145,11 +148,11 @@ int refreshAll() { // Get server info if ((ret = ts3Functions.getServerConnectInfo(serverConnectionHandlerID, server.host, &server.port, server.password, sizeof(server.password))) != ERROR_ok) { API::onLogMessage("Failed to get getServerConnectInfo, code 0x%04x", ret); - return 1; + goto send_if_needed; } if ((ret = ts3Functions.getServerVariableAsString(serverConnectionHandlerID, VIRTUALSERVER_NAME, &s)) != ERROR_ok) { API::onLogMessage("Failed to get server name, code 0x%04x", ret); - return 1; + goto send_if_needed; } strncpy_s(server.name, s, sizeof(server.name) - 1); ts3Functions.freeMemory(s); @@ -160,13 +163,13 @@ int refreshAll() { if ((ret = ts3Functions.getClientID(serverConnectionHandlerID, &server.my_client_id)) != ERROR_ok) { API::onLogMessage("Failed to get my id, code 0x%04x", ret); - return 1; + goto send_if_needed; } // Update all connected users anyID* clientIDs; if ((ret = ts3Functions.getClientList(serverConnectionHandlerID, &clientIDs)) != ERROR_ok) { API::onLogMessage("Failed to get getClientList, code 0x%04x", ret); - return 1; + goto send_if_needed; } bool has_changed = false; @@ -175,24 +178,24 @@ int refreshAll() { need_to_send |= has_changed; } ts3Functions.freeMemory(clientIDs); - +send_if_needed: if (need_to_send) { instance.sendAllInfo(); } - return 0; + return ret; } int ts3plugin_updateAPIServer() { return refreshAll(); } - - /* * Custom code called right after loading the plugin. Returns 0 on success, 1 on failure. * If the function returns 1 on failure, the plugin will be unloaded again. */ int ts3plugin_init() { TS3_API::Instance(); + WM_TEAMSPEAK3_JSON_API_STARTED = RegisterWindowMessageW(L"WM_TEAMSPEAK3_JSON_API_STARTED"); + SendNotifyMessageW(HWND_BROADCAST, WM_TEAMSPEAK3_JSON_API_STARTED, NULL, NULL); return 0; } /* Custom code called right before the plugin is unloaded */ diff --git a/plugin.h b/plugin.h index 9c0a548..7ace764 100644 --- a/plugin.h +++ b/plugin.h @@ -18,6 +18,9 @@ extern "C" { #endif + +PLUGINS_EXPORTDLL uint64 is_connected(); +PLUGINS_EXPORTDLL int refreshAll(); /* Required functions */ PLUGINS_EXPORTDLL const char* ts3plugin_name(); PLUGINS_EXPORTDLL const char* ts3plugin_version(); @@ -38,23 +41,14 @@ PLUGINS_EXPORTDLL void ts3plugin_onConnectStatusChangeEvent(uint64 serverConnect PLUGINS_EXPORTDLL void ts3plugin_onUpdateChannelEvent(uint64 serverConnectionHandlerID, uint64 channelID); PLUGINS_EXPORTDLL void ts3plugin_onUpdateChannelEditedEvent(uint64 serverConnectionHandlerID, uint64 channelID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier); PLUGINS_EXPORTDLL void ts3plugin_onUpdateClientEvent(uint64 serverConnectionHandlerID, anyID clientID, anyID invokerID, const char* invokerName, const char* invokerUniqueIdentifier); -PLUGINS_EXPORTDLL void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage); -PLUGINS_EXPORTDLL void ts3plugin_onClientMoveSubscriptionEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility); -PLUGINS_EXPORTDLL void ts3plugin_onClientMoveTimeoutEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* timeoutMessage); -PLUGINS_EXPORTDLL void ts3plugin_onClientMoveMovedEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID moverID, const char* moverName, const char* moverUniqueIdentifier, const char* moveMessage); -PLUGINS_EXPORTDLL void ts3plugin_onClientKickFromChannelEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID kickerID, const char* kickerName, const char* kickerUniqueIdentifier, const char* kickMessage); +PLUGINS_EXPORTDLL void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage);PLUGINS_EXPORTDLL void ts3plugin_onClientKickFromChannelEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID kickerID, const char* kickerName, const char* kickerUniqueIdentifier, const char* kickMessage); PLUGINS_EXPORTDLL void ts3plugin_onClientKickFromServerEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, anyID kickerID, const char* kickerName, const char* kickerUniqueIdentifier, const char* kickMessage); -PLUGINS_EXPORTDLL void ts3plugin_onClientIDsEvent(uint64 serverConnectionHandlerID, const char* uniqueClientIdentifier, anyID clientID, const char* clientName); -PLUGINS_EXPORTDLL void ts3plugin_onClientIDsFinishedEvent(uint64 serverConnectionHandlerID); PLUGINS_EXPORTDLL void ts3plugin_onServerEditedEvent(uint64 serverConnectionHandlerID, anyID editerID, const char* editerName, const char* editerUniqueIdentifier); -PLUGINS_EXPORTDLL void ts3plugin_onServerUpdatedEvent(uint64 serverConnectionHandlerID); -PLUGINS_EXPORTDLL int ts3plugin_onServerErrorEvent(uint64 serverConnectionHandlerID, const char* errorMessage, unsigned int error, const char* returnCode, const char* extraMessage); PLUGINS_EXPORTDLL void ts3plugin_onServerStopEvent(uint64 serverConnectionHandlerID, const char* shutdownMessage); PLUGINS_EXPORTDLL int ts3plugin_onTextMessageEvent(uint64 serverConnectionHandlerID, anyID targetMode, anyID toID, anyID fromID, const char* fromName, const char* fromUniqueIdentifier, const char* message, int ffIgnored); PLUGINS_EXPORTDLL void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int status, int isReceivedWhisper, anyID clientID); /* Clientlib rare */ -PLUGINS_EXPORTDLL void ts3plugin_onClientSelfVariableUpdateEvent(uint64 serverConnectionHandlerID, int flag, const char* oldValue, const char* newValue); PLUGINS_EXPORTDLL void ts3plugin_onClientChannelGroupChangedEvent(uint64 serverConnectionHandlerID, uint64 channelGroupID, uint64 channelID, anyID clientID, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity); PLUGINS_EXPORTDLL void ts3plugin_onServerGroupClientAddedEvent(uint64 serverConnectionHandlerID, anyID clientID, const char* clientName, const char* clientUniqueIdentity, uint64 serverGroupID, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity); PLUGINS_EXPORTDLL void ts3plugin_onServerGroupClientDeletedEvent(uint64 serverConnectionHandlerID, anyID clientID, const char* clientName, const char* clientUniqueIdentity, uint64 serverGroupID, anyID invokerClientID, const char* invokerName, const char* invokerUniqueIdentity);