From aaea9b9339384350a1b53d966e0000e901444732 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Mon, 27 Jan 2020 02:21:39 +0100 Subject: [PATCH] A lot of updates --- music | 2 +- server/CMakeLists.txt | 4 +- server/src/ConnectionStatistics.h | 32 +- server/src/InstanceHandler.cpp | 2 +- server/src/InstanceHandler.h | 6 +- server/src/ServerManagerSnapshot.cpp | 2 +- server/src/ServerManagerSnapshotDeploy.cpp | 10 +- server/src/SignalHandler.cpp | 2 +- server/src/VirtualServer.cpp | 11 - server/src/VirtualServer.h | 3 +- ...erManager.cpp => VirtualServerManager.cpp} | 46 +- ...ServerManager.h => VirtualServerManager.h} | 10 +- server/src/client/ConnectedClient.h | 2 +- .../ConnectedClientTextCommandHandler.cpp | 4 +- server/src/client/SpeakingClientHandshake.cpp | 2 +- .../src/client/query/QueryClientCommands.cpp | 10 +- server/src/client/query/QueryClientNotify.cpp | 2 +- server/src/client/voice/VoiceClient.cpp | 2 +- server/src/client/voice/VoiceClient.h | 14 +- .../client/voice/VoiceClientConnection.cpp | 479 ++++++++---------- .../src/client/voice/VoiceClientConnection.h | 49 +- .../client/voice/VoiceClientHandschake.cpp | 18 +- .../client/voice/VoiceClientPacketHandler.cpp | 32 +- server/src/client/web/WSWebClient.cpp | 2 +- server/src/client/web/WebClient.cpp | 2 +- server/src/server/POWHandler.cpp | 26 +- server/src/server/POWHandler.h | 6 +- server/src/server/QueryServer.h | 9 - server/src/server/VoiceServer.cpp | 28 +- server/src/server/VoiceServer.h | 2 +- server/src/terminal/CommandHandler.cpp | 2 +- server/src/weblist/WebListManager.cpp | 11 +- shared | 2 +- 33 files changed, 387 insertions(+), 447 deletions(-) rename server/src/{ServerManager.cpp => VirtualServerManager.cpp} (91%) rename server/src/{ServerManager.h => VirtualServerManager.h} (93%) diff --git a/music b/music index 6bdb628..7beec96 160000 --- a/music +++ b/music @@ -1 +1 @@ -Subproject commit 6bdb628586efd7f61c6746391c664c335b8b6d44 +Subproject commit 7beec96f4b9f00b3e63bc6d092ce6c671ea3c0d5 diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9955559..b589150 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -62,7 +62,7 @@ set(SERVER_SOURCE_FILES src/client/command_handler/misc.cpp src/client/ConnectedClientNotifyHandler.cpp - src/ServerManager.cpp + src/VirtualServerManager.cpp src/server/file/FileServer.cpp src/channel/ServerChannel.cpp src/channel/ClientChannelView.cpp @@ -235,7 +235,7 @@ target_link_libraries(PermMapHelper SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "4") -SET(CPACK_PACKAGE_VERSION_PATCH "6") +SET(CPACK_PACKAGE_VERSION_PATCH "7") if (BUILD_TYPE_NAME EQUAL OFF) SET(CPACK_PACKAGE_VERSION_DATA "beta") elseif (BUILD_TYPE_NAME STREQUAL "") diff --git a/server/src/ConnectionStatistics.h b/server/src/ConnectionStatistics.h index 78e6bfb..488b768 100644 --- a/server/src/ConnectionStatistics.h +++ b/server/src/ConnectionStatistics.h @@ -48,14 +48,32 @@ namespace ts { UNKNOWN }; + constexpr static std::array lookup_table{ + VOICE, /* Voice */ + VOICE, /* VoiceWhisper */ + COMMAND, /* Command */ + COMMAND, /* CommandLow */ + ACK, /* Ping */ + ACK, /* Pong */ + ACK, /* Ack */ + ACK, /* AckLow */ + COMMAND, /* */ + + UNKNOWN, + UNKNOWN, + UNKNOWN, + UNKNOWN, + UNKNOWN, + UNKNOWN + }; + + /* much faster than a switch */ + inline static category::value from_type(uint8_t type){ + return lookup_table[type & 0xFU]; + } + inline static category::value from_type(const protocol::PacketTypeInfo& type){ - if(type == protocol::PacketTypeInfo::Command || type == protocol::PacketTypeInfo::CommandLow) - return value::COMMAND; - else if(type == protocol::PacketTypeInfo::Ack || type == protocol::PacketTypeInfo::AckLow) - return value::ACK; - else if(type == protocol::PacketTypeInfo::Voice || type == protocol::PacketTypeInfo::VoiceWhisper) - return value::VOICE; - return value::UNKNOWN; + return from_type(type.type()); } }; explicit ConnectionStatistics(const std::shared_ptr& /* root */, bool /* spawn properties */); diff --git a/server/src/InstanceHandler.cpp b/server/src/InstanceHandler.cpp index 212ba73..d10a611 100644 --- a/server/src/InstanceHandler.cpp +++ b/server/src/InstanceHandler.cpp @@ -378,7 +378,7 @@ FwIDAQAB } } - this->voiceServerManager = new ServerManager(this); + this->voiceServerManager = new VirtualServerManager(this); if (!this->voiceServerManager->initialize(true)) { logCritical(LOG_INSTANCE, "Could not load servers!"); delete this->voiceServerManager; diff --git a/server/src/InstanceHandler.h b/server/src/InstanceHandler.h index d99799e..21a901d 100644 --- a/server/src/InstanceHandler.h +++ b/server/src/InstanceHandler.h @@ -2,7 +2,7 @@ #include #include -#include "ServerManager.h" +#include "VirtualServerManager.h" #include "../../license/shared/LicenseRequest.h" #include "lincense/LicenseHelper.h" #include @@ -38,7 +38,7 @@ namespace ts { std::shared_ptr getChannelTree() { return this->default_tree; } std::shared_mutex& getChannelTreeLock() { return this->default_tree_lock; } - ServerManager* getVoiceServerManager(){ return this->voiceServerManager; } + VirtualServerManager* getVoiceServerManager(){ return this->voiceServerManager; } FileServer* getFileServer(){ return fileServer; } QueryServer* getQueryServer(){ return queryServer; } DatabaseHelper* databaseHelper(){ return this->dbHelper; } @@ -107,7 +107,7 @@ namespace ts { FileServer* fileServer = nullptr; QueryServer* queryServer = nullptr; - ServerManager* voiceServerManager = nullptr; + VirtualServerManager* voiceServerManager = nullptr; DatabaseHelper* dbHelper = nullptr; BanManager* banMgr = nullptr; ssl::SSLManager* sslMgr = nullptr; diff --git a/server/src/ServerManagerSnapshot.cpp b/server/src/ServerManagerSnapshot.cpp index 66de0b7..b2786f7 100644 --- a/server/src/ServerManagerSnapshot.cpp +++ b/server/src/ServerManagerSnapshot.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "ServerManager.h" +#include "VirtualServerManager.h" #include "src/server/VoiceServer.h" #include "InstanceHandler.h" diff --git a/server/src/ServerManagerSnapshotDeploy.cpp b/server/src/ServerManagerSnapshotDeploy.cpp index 338c9e6..27d2009 100644 --- a/server/src/ServerManagerSnapshotDeploy.cpp +++ b/server/src/ServerManagerSnapshotDeploy.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "ServerManager.h" +#include "VirtualServerManager.h" #include "src/server/VoiceServer.h" #include "InstanceHandler.h" #include "InstanceHandler.h" @@ -163,9 +163,9 @@ struct SnapshotPermissionEntry { } }; -std::shared_ptr ServerManager::createServerFromSnapshot(shared_ptr old, std::string host, - uint16_t port, const ts::Command &arguments, - std::string &error) { +std::shared_ptr VirtualServerManager::createServerFromSnapshot(shared_ptr old, std::string host, + uint16_t port, const ts::Command &arguments, + std::string &error) { ServerId serverId = 0; map> channelGroupRelations; //cid is the new cgid map channelGroupMapping; @@ -767,7 +767,7 @@ struct DatabaseMusicbot { std::string bot_unique_id; }; -bool ServerManager::createServerSnapshot(Command &cmd, shared_ptr server, int version, std::string &error) { +bool VirtualServerManager::createServerSnapshot(Command &cmd, shared_ptr server, int version, std::string &error) { int index = 0; diff --git a/server/src/SignalHandler.cpp b/server/src/SignalHandler.cpp index 2b816ad..f1f48b0 100644 --- a/server/src/SignalHandler.cpp +++ b/server/src/SignalHandler.cpp @@ -2,7 +2,7 @@ #include #include "VirtualServer.h" #include "SignalHandler.h" -#include "ServerManager.h" +#include "VirtualServerManager.h" #include "InstanceHandler.h" #include "ShutdownHelper.h" #include diff --git a/server/src/VirtualServer.cpp b/server/src/VirtualServer.cpp index c434954..550e93e 100644 --- a/server/src/VirtualServer.cpp +++ b/server/src/VirtualServer.cpp @@ -575,17 +575,6 @@ OnlineClientReport VirtualServer::onlineStats() { return response; } -std::shared_ptr VirtualServer::findClient(sockaddr_in *addr) { - lock_guard lock(this->clients.lock); - for(const auto& elm : this->clients.clients) { - if(elm && elm->isAddressV4()) - if(elm->getAddressV4()->sin_addr.s_addr == addr->sin_addr.s_addr) - if(elm->getAddressV4()->sin_port == addr->sin_port) - return elm; - } - return nullptr; -} - std::shared_ptr VirtualServer::findClient(uint16_t client_id) { lock_guard lock(this->clients.lock); if(this->clients.clients.size() > client_id) diff --git a/server/src/VirtualServer.h b/server/src/VirtualServer.h index 2a66aa8..fb6caf1 100644 --- a/server/src/VirtualServer.h +++ b/server/src/VirtualServer.h @@ -134,7 +134,7 @@ namespace ts { friend class SpeakingClient; friend class music::MusicBotManager; friend class InstanceHandler; - friend class ServerManager; + friend class VirtualServerManager; public: VirtualServer(ServerId serverId, sql::SqlManager*); ~VirtualServer(); @@ -149,7 +149,6 @@ namespace ts { size_t onlineClients(); OnlineClientReport onlineStats(); size_t onlineChannels(){ return this->channelTree->channel_count(); } - std::shared_ptr findClient(sockaddr_in* addr); std::shared_ptr findClient(ClientId clientId); std::deque> findClientsByCldbId(ClientDbId cldbId); std::deque> findClientsByUid(ClientUid uid); diff --git a/server/src/ServerManager.cpp b/server/src/VirtualServerManager.cpp similarity index 91% rename from server/src/ServerManager.cpp rename to server/src/VirtualServerManager.cpp index 2fe1355..096bcab 100644 --- a/server/src/ServerManager.cpp +++ b/server/src/VirtualServerManager.cpp @@ -1,16 +1,17 @@ #include #include -#include "ServerManager.h" +#include "VirtualServerManager.h" #include "src/server/VoiceServer.h" #include "InstanceHandler.h" #include "src/server/file/FileServer.h" #include "src/client/ConnectedClient.h" +#include using namespace std; using namespace std::chrono; using namespace ts::server; -ServerManager::ServerManager(InstanceHandler* handle) : handle(handle) { +VirtualServerManager::VirtualServerManager(InstanceHandler* handle) : handle(handle) { this->puzzles = new protocol::PuzzleManager(); this->handshakeTickers = new threads::Scheduler(1, "handshake ticker"); this->execute_loop = new event::EventExecutor("executor #"); @@ -20,7 +21,7 @@ ServerManager::ServerManager(InstanceHandler* handle) : handle(handle) { this->handshakeTickers->schedule("ticker", [&](){ this->tickHandshakeClients(); }, seconds(1)); } -ServerManager::~ServerManager() { +VirtualServerManager::~VirtualServerManager() { this->state = State::STOPPED; { threads::MutexLock lock(this->instanceLock); @@ -29,9 +30,10 @@ ServerManager::~ServerManager() { { this->acknowledge.condition.notify_all(); - if(this->acknowledge.thread) - this->acknowledge.thread->join(); - delete this->acknowledge.thread; + if(!threads::timed_join(this->acknowledge.executor,std::chrono::seconds{2})) { + logCritical(LOG_GENERAL, "Failed to shutdown packet resend thread."); + this->acknowledge.executor.detach(); + } } delete this->puzzles; @@ -58,7 +60,7 @@ ServerManager::~ServerManager() { this->_ioManager = nullptr; } -bool ServerManager::initialize(bool autostart) { +bool VirtualServerManager::initialize(bool autostart) { this->execute_loop->initialize(1); this->state = State::STARTING; @@ -83,7 +85,7 @@ bool ServerManager::initialize(bool autostart) { auto beg = system_clock::now(); size_t server_count = 0; - sql::command(this->handle->getSql(), "SELECT `serverId`, `host`, `port` FROM `servers`").query([&](ServerManager* mgr, int length, std::string* values, std::string* columns){ + sql::command(this->handle->getSql(), "SELECT `serverId`, `host`, `port` FROM `servers`").query([&](VirtualServerManager* mgr, int length, std::string* values, std::string* columns){ ServerId id = 0; std::string host; uint16_t port = 0; @@ -158,7 +160,7 @@ bool ServerManager::initialize(bool autostart) { this->adjust_executor_threads(); { - this->acknowledge.thread = new threads::Thread(THREAD_SAVE_OPERATIONS, [&] { + this->acknowledge.executor = std::thread([&]{ system_clock::time_point next_execute = system_clock::now() + milliseconds(500); while(this->state == State::STARTED || this->state == State::STARTING) { unique_lock lock(this->acknowledge.lock); @@ -180,14 +182,14 @@ bool ServerManager::initialize(bool autostart) { return true; } -shared_ptr ServerManager::findServerById(ServerId sid) { +shared_ptr VirtualServerManager::findServerById(ServerId sid) { for(auto server : this->serverInstances()) if(server->getServerId() == sid) return server; return nullptr; } -shared_ptr ServerManager::findServerByPort(uint16_t port) { +shared_ptr VirtualServerManager::findServerByPort(uint16_t port) { for(const auto& server : this->serverInstances()){ if(server->properties()[property::VIRTUALSERVER_PORT] == port) return server; if(server->running() && server->getVoiceServer()) @@ -197,7 +199,7 @@ shared_ptr ServerManager::findServerByPort(uint16_t port) { return nullptr; } -uint16_t ServerManager::next_available_port() { +uint16_t VirtualServerManager::next_available_port() { auto instances = this->serverInstances(); deque unallowed_ports; for(const auto& instance : instances) { @@ -227,7 +229,7 @@ uint16_t ServerManager::next_available_port() { return port; } -ts::ServerId ServerManager::next_available_server_id(bool& success) { +ts::ServerId VirtualServerManager::next_available_server_id(bool& success) { auto server_id_base = this->handle->properties()[property::SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX].as(); if(server_id_base > 65530) { success = false; @@ -264,7 +266,7 @@ ts::ServerId ServerManager::next_available_server_id(bool& success) { return serverId; } -ServerReport ServerManager::report() { +ServerReport VirtualServerManager::report() { ServerReport result{}; for(const auto& sr : this->serverInstances()) { result.avariable++; @@ -279,7 +281,7 @@ ServerReport ServerManager::report() { return result; } -OnlineClientReport ServerManager::clientReport() { +OnlineClientReport VirtualServerManager::clientReport() { OnlineClientReport result{}; for(const auto& server : this->serverInstances()) { if(!server->running()) continue; @@ -292,21 +294,21 @@ OnlineClientReport ServerManager::clientReport() { return result; } -size_t ServerManager::runningServers() { +size_t VirtualServerManager::runningServers() { size_t res = 0; for(const auto& sr : this->serverInstances()) if(sr->running()) res++; return res; } -size_t ServerManager::usedSlots() { +size_t VirtualServerManager::usedSlots() { size_t res = 0; for(const auto& sr : this->serverInstances()) res += sr->properties()[property::VIRTUALSERVER_MAXCLIENTS].as(); return res; } -shared_ptr ServerManager::createServer(std::string hosts, uint16_t port) { +shared_ptr VirtualServerManager::createServer(std::string hosts, uint16_t port) { bool sid_success = false; ServerId serverId = this->next_available_server_id(sid_success); @@ -337,7 +339,7 @@ shared_ptr ServerManager::createServer(std::string hosts, uint16_ return server; } -bool ServerManager::deleteServer(shared_ptr server) { +bool VirtualServerManager::deleteServer(shared_ptr server) { { threads::MutexLock l(this->instanceLock); bool found = false; @@ -389,7 +391,7 @@ bool ServerManager::deleteServer(shared_ptr server) { return true; } -void ServerManager::executeAutostart() { +void VirtualServerManager::executeAutostart() { threads::MutexLock l(this->instanceLock); auto lastStart = system_clock::time_point(); for(const auto& server : this->instances){ @@ -408,7 +410,7 @@ void ServerManager::executeAutostart() { } } -void ServerManager::shutdownAll(const std::string& msg) { +void VirtualServerManager::shutdownAll(const std::string& msg) { for(const auto &server : this->serverInstances()) server->preStop(msg); for(const auto &server : this->serverInstances()){ @@ -418,7 +420,7 @@ void ServerManager::shutdownAll(const std::string& msg) { this->execute_loop->shutdown(); } -void ServerManager::tickHandshakeClients() { +void VirtualServerManager::tickHandshakeClients() { for(const auto& server : this->serverInstances()) { auto vserver = server->getVoiceServer(); if(vserver) diff --git a/server/src/ServerManager.h b/server/src/VirtualServerManager.h similarity index 93% rename from server/src/ServerManager.h rename to server/src/VirtualServerManager.h index 6ecde63..81b1ec1 100644 --- a/server/src/ServerManager.h +++ b/server/src/VirtualServerManager.h @@ -18,7 +18,7 @@ namespace ts { size_t onlineClients; size_t onlineChannels; }; - class ServerManager { + class VirtualServerManager { public: enum State { STOPPED, @@ -27,8 +27,8 @@ namespace ts { STOPPING }; - explicit ServerManager(InstanceHandler*); - ~ServerManager(); + explicit VirtualServerManager(InstanceHandler*); + ~VirtualServerManager(); bool initialize(bool execute_autostart = true); @@ -57,8 +57,6 @@ namespace ts { bool createServerSnapshot(Command &cmd, std::shared_ptr server, int version, std::string &error); std::shared_ptr createServerFromSnapshot(std::shared_ptr old, std::string, uint16_t, const ts::Command &, std::string &); - size_t maxSlotLimit(){ return 254; } - protocol::PuzzleManager* rsaPuzzles() { return this->puzzles; } event::EventExecutor* get_join_loop() { return this->join_loop; } @@ -90,7 +88,7 @@ namespace ts { io::VoiceIOManager* _ioManager = nullptr; struct { - threads::Thread* thread = nullptr; + std::thread executor{}; std::condition_variable condition; std::mutex lock; } acknowledge; diff --git a/server/src/client/ConnectedClient.h b/server/src/client/ConnectedClient.h index 1821c7d..6531d7b 100644 --- a/server/src/client/ConnectedClient.h +++ b/server/src/client/ConnectedClient.h @@ -68,7 +68,7 @@ namespace ts { friend class SpeakingClient; friend class connection::VoiceClientConnection; friend class ts::GroupManager; - friend class ServerManager; + friend class VirtualServerManager; public: explicit ConnectedClient(sql::SqlManager*, const std::shared_ptr& server); ~ConnectedClient() override; diff --git a/server/src/client/ConnectedClientTextCommandHandler.cpp b/server/src/client/ConnectedClientTextCommandHandler.cpp index f2e0f40..99636fd 100644 --- a/server/src/client/ConnectedClientTextCommandHandler.cpp +++ b/server/src/client/ConnectedClientTextCommandHandler.cpp @@ -642,8 +642,8 @@ bool ConnectedClient::handle_text_command( auto id = vc->getConnection()->getPacketIdManager().currentPacketId(type); auto gen = vc->getConnection()->getPacketIdManager().generationId(type); send_message(_this.lock(), " OUT " + type.name() + " => generation: " + to_string(gen) + " id: " + to_string(id)); - auto& buffer = vc->getConnection()->packet_buffers()[type.type()]; - send_message(_this.lock(), " IN " + type.name() + " => generation: " + to_string(buffer.generation(0)) + " id: " + to_string(buffer.current_index())); + //auto& buffer = vc->getConnection()->packet_buffers()[type.type()]; + //send_message(_this.lock(), " IN " + type.name() + " => generation: " + to_string(buffer.generation(0)) + " id: " + to_string(buffer.current_index())); } return true; } else if(TARG(0, "disconnect")) { diff --git a/server/src/client/SpeakingClientHandshake.cpp b/server/src/client/SpeakingClientHandshake.cpp index 2889c8c..3b4f43e 100644 --- a/server/src/client/SpeakingClientHandshake.cpp +++ b/server/src/client/SpeakingClientHandshake.cpp @@ -1,6 +1,6 @@ #include "SpeakingClient.h" #include -#include +#include #include #include #include diff --git a/server/src/client/query/QueryClientCommands.cpp b/server/src/client/query/QueryClientCommands.cpp index 0412861..0c6a510 100644 --- a/server/src/client/query/QueryClientCommands.cpp +++ b/server/src/client/query/QueryClientCommands.cpp @@ -2,7 +2,7 @@ #include "query/Command.h" #include #include -#include +#include #include #include #include @@ -576,7 +576,7 @@ command_result QueryClient::handleCommandServerCreate(Command& cmd) { CMD_RESET_IDLE; ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_create, 1); - if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) { + if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED) { return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"}; } @@ -653,7 +653,7 @@ command_result QueryClient::handleCommandServerDelete(Command& cmd) { CMD_RESET_IDLE; ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_delete, 1); - if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) + if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED) return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"}; auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]); @@ -665,7 +665,7 @@ command_result QueryClient::handleCommandServerDelete(Command& cmd) { command_result QueryClient::handleCommandServerStart(Command& cmd) { CMD_RESET_IDLE; - if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) + if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED) return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"}; auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]); @@ -683,7 +683,7 @@ command_result QueryClient::handleCommandServerStart(Command& cmd) { command_result QueryClient::handleCommandServerStop(Command& cmd) { CMD_RESET_IDLE; - if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) + if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED) return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"}; auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]); diff --git a/server/src/client/query/QueryClientNotify.cpp b/server/src/client/query/QueryClientNotify.cpp index f01fcdc..6f45233 100644 --- a/server/src/client/query/QueryClientNotify.cpp +++ b/server/src/client/query/QueryClientNotify.cpp @@ -2,7 +2,7 @@ #include "query/Command.h" #include #include -#include +#include #include #include "QueryClient.h" diff --git a/server/src/client/voice/VoiceClient.cpp b/server/src/client/voice/VoiceClient.cpp index f431ee5..21d30e4 100644 --- a/server/src/client/voice/VoiceClient.cpp +++ b/server/src/client/voice/VoiceClient.cpp @@ -264,7 +264,7 @@ void VoiceClient::finalDisconnect() { } void VoiceClient::execute_handle_packet(const std::chrono::system_clock::time_point &time) { - this->connection->execute_handle_packet(time); + this->connection->execute_handle_command_packets(time); } void VoiceClient::send_voice_packet(const pipes::buffer_view &voice_buffer, const SpeakingClient::VoicePacketFlags &flags) { diff --git a/server/src/client/voice/VoiceClient.h b/server/src/client/voice/VoiceClient.h index 6d75a28..60d2f79 100644 --- a/server/src/client/voice/VoiceClient.h +++ b/server/src/client/voice/VoiceClient.h @@ -11,7 +11,7 @@ #include #include "../SpeakingClient.h" #include "../ConnectedClient.h" -#include "protocol/CryptionHandler.h" +#include "protocol/CryptHandler.h" #include "VoiceClientConnection.h" #include "PrecomputedPuzzles.h" #include "../../lincense/TeamSpeakLicense.h" @@ -73,11 +73,11 @@ namespace ts { void initialize(); virtual void tick(const std::chrono::system_clock::time_point &time) override; - void handlePacketCommand(const std::unique_ptr&); - void handlePacketAck(const std::unique_ptr&); - void handlePacketVoice(const std::unique_ptr&); - void handlePacketPing(const std::unique_ptr&); - void handlePacketInit(const std::unique_ptr&); + void handlePacketCommand(const pipes::buffer_view&); + void handlePacketAck(const protocol::IncomingClientPacketParser&); + void handlePacketVoice(const protocol::IncomingClientPacketParser&); + void handlePacketPing(const protocol::IncomingClientPacketParser&); + void handlePacketInit(const protocol::IncomingClientPacketParser&); //Handshake helpers @@ -109,7 +109,7 @@ namespace ts { //General TS3 manager commands command_result handleCommandClientInitIv(Command&); - command_result handleCommandClientEk(const std::unique_ptr&, Command&); + command_result handleCommandClientEk(Command&); command_result handleCommandClientInit(Command&) override; command_result handleCommandClientDisconnect(Command&); diff --git a/server/src/client/voice/VoiceClientConnection.cpp b/server/src/client/voice/VoiceClientConnection.cpp index 1516b46..0552e64 100644 --- a/server/src/client/voice/VoiceClientConnection.cpp +++ b/server/src/client/voice/VoiceClientConnection.cpp @@ -13,8 +13,8 @@ //#define LOG_AUTO_ACK_AUTORESPONSE //#define FUZZING_TESTING_INCOMMING //#define FUZZING_TESTING_OUTGOING -#define FIZZING_TESTING_DISABLE_HANDSHAKE -#define FUZZING_TESTING_DROP 5 +//#define FIZZING_TESTING_DISABLE_HANDSHAKE +#define FUZZING_TESTING_DROP 8 #define FUZZING_TESTING_DROP_MAX 10 //#define CONNECTION_NO_STATISTICS @@ -65,7 +65,7 @@ void VoiceClientConnection::triggerWrite() { //Message handle methods -void VoiceClientConnection::handleDatagramReceived(const pipes::buffer_view& buffer) { +void VoiceClientConnection::handle_incoming_datagram(const pipes::buffer_view& buffer) { #ifdef FUZZING_TESTING_INCOMMING #ifdef FIZZING_TESTING_DISABLE_HANDSHAKE if (this->client->state == ConnectionState::CONNECTED) { @@ -79,226 +79,171 @@ void VoiceClientConnection::handleDatagramReceived(const pipes::buffer_view& buf #endif #endif - auto packet = ClientPacket::from_buffer(buffer); - - auto packet_type = packet->type(); - auto packet_id = packet->packetId(); - auto ordered = packet_type.type() == protocol::COMMAND || packet_type.type() == protocol::COMMAND_LOW; - - if(packet_type.type() < 0 || packet_type.type() >= this->_packet_buffers.size()) { - logError(this->client->getServerId(), "{} Received invalid packet. Invalid packet type {}. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), packet_type.type()); + IncomingClientPacketParser packet_parser{buffer}; + if(!packet_parser.valid()) { + logTrace(this->client->getServerId(), "{} Received invalid packet. Dropping.", CLIENT_STR_LOG_PREFIX_(this->client)); return; } + assert(packet_parser.type() >= 0 && packet_parser.type() < this->incoming_generation_estimators.size()); + packet_parser.set_estimated_generation(this->incoming_generation_estimators[packet_parser.type()].visit_packet(packet_parser.packet_id())); - auto& read_queue = this->_packet_buffers[packet_type.type()]; - packet->generationId(read_queue.generation(packet_id)); + auto is_command = packet_parser.type() == protocol::COMMAND || packet_parser.type() == protocol::COMMAND_LOW; + /* pretest if the packet is worth the effort of decoding it */ + if(is_command) { + /* handle the order stuff */ + auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(packet_parser.type())]; - if(ordered) { - unique_lock queue_lock(read_queue.buffer_lock); - auto result = read_queue.accept_index(packet_id); + unique_lock queue_lock(fragment_buffer.buffer_lock); + auto result = fragment_buffer.accept_index(packet_parser.packet_id()); if(result != 0) { /* packet index is ahead buffer index */ - debugMessage(this->client->getServerId(), "{} Got packet of type {} which is out of the buffer range of {} ({}). Packet ID: {}, Current index: {}. Dropping packet", - CLIENT_STR_LOG_PREFIX_(this->client), - packet_type.name(), - read_queue.capacity(), + debugMessage(this->client->getServerId(), "{} Dropping command packet because command assembly buffer has an {} ({}|{})", + CLIENT_STR_LOG_PREFIX_(this->client), result == -1 ? "underflow" : "overflow", - packet_id, - read_queue.current_index() + fragment_buffer.capacity(), + fragment_buffer.current_index() ); if(result == -1) { /* underflow */ - /* we've already got the packet, but the client dosnt know that so we've to send the acknowledge again */ - if(this->client->crypto.protocol_encrypted && (packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow)){ //needs an acknowledge - this->client->sendAcknowledge(packet->packetId(), packet->type() == PacketTypeInfo::CommandLow); - } + /* we've already got the packet, but the client dosn't know that so we've to send the acknowledge again */ + if(this->client->crypto.protocol_encrypted) + this->client->sendAcknowledge(packet_parser.packet_id(), packet_parser.type() == protocol::COMMAND_LOW); } return; } } - packet->setEncrypted(!packet->has_flag(PacketFlag::Unencrypted)); // && packet->type() != PacketType::Init1 - if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){ - packet->setCompressed(packet->has_flag(PacketFlag::Compressed)); - } //NOTICE I found out that the Compressed flag is set if the packet contains an audio header - string error = "success"; - if(this->client->state == ConnectionState::INIT_LOW && packet->type() != PacketTypeInfo::Init1){ - //Sends command packet as legacy support (skip step 1-3 | Direct clientinit with default key) + if(this->client->state == ConnectionState::INIT_LOW && packet_parser.type() != protocol::INIT1) return; - } - if(!this->crypt_handler.progressPacketIn(packet.get(), error, false)){ - //FIXME Only try to decrypt by default when its no flood attack! - if(!this->client->crypto.client_init && !this->crypt_handler.use_default()) { - if(!this->crypt_handler.progressPacketIn(packet.get(), error, true)){ - debugMessage( - this->client->getServerId(), - "{} Cant decrypt packet even with default key! Type: {}, Error: {}, Packet ID: {}, Generation: {}", - CLIENT_STR_LOG_PREFIX_(this->client), - packet->type().name(), - error, - packet_id, - packet->generationId() - ); - return; - } else { - debugMessage( - this->client->getServerId(), - "{} Cant decrypt packet with configured key {}. Error: {}. Succeeded with default key!", - CLIENT_STR_LOG_PREFIX_(this->client), - packet->type().name(), - error - ); - } + /* decrypt the packet if needed */ + if(packet_parser.is_encrypted()) { + std::string error; + + CryptHandler::key_t crypt_key{}; + CryptHandler::nonce_t crypt_nonce{}; + + auto data = (uint8_t*) packet_parser.mutable_data_ptr(); + bool use_default_key{!this->client->crypto.protocol_encrypted}, decrypt_result; + + decrypt_packet: + if(use_default_key) { + crypt_key = CryptHandler::default_key; + crypt_nonce = CryptHandler::default_nonce; } else { - bool succeeded = false; - if(packet_type == PacketTypeInfo::Voice) { - /* FIXME: This try and error should not happen! */ - packet->generationId(packet->generationId() + 1); - succeeded = this->crypt_handler.progressPacketIn(packet.get(), error, false); - } - if(succeeded) { - auto old_packet_id = read_queue.current_index(); - read_queue.set_generation_packet(packet->generationId(), packet->packetId()); - - logWarning(this->client->getServerId(), "{} Voice packet generation counter missed generation increasement. From {} to {} from packet id {} to {}", - CLIENT_STR_LOG_PREFIX_(this->client), - packet->generationId() - 1, - packet->generationId(), - old_packet_id, - packet->packetId() - ); - } else { - debugMessage( - this->client->getServerId(), - "{} Cant decrypt packet of type {}. Packet ID: {}, Estimated generation: {}, Full counter: {}. Dropping packet. Error: {}", - CLIENT_STR_LOG_PREFIX_(this->client), - packet->type().name(), - packet->packetId(), - packet->generationId(), - read_queue.full_index(), - error - ); + if(!this->crypt_handler.generate_key_nonce(true, packet_parser.type(), packet_parser.packet_id(), packet_parser.estimated_generation(), crypt_key, crypt_nonce)) { + logError(this->client->getServerId(), "{} Failed to generate crypt key/nonce. This should never happen! Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client)); return; } } - } - if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){ - if(packet->has_flag(PacketFlag::Unencrypted) && this->client->state != ConnectionState::INIT_HIGH){ - this->client->disconnect("Invalid packet. Command should not be unencrypted!"); - logger::logger(this->client->getServer()->getServerId())->error("{} Voice manager {}/{} tried to send a unencrypted command packet.", CLIENT_STR_LOG_PREFIX_(this->client), client->getDisplayName(), this->client->getLoggingPeerIp()); - return; + decrypt_result = this->crypt_handler.decrypt( + data + IncomingClientPacketParser::kHeaderOffset, IncomingClientPacketParser::kHeaderLength, + data + IncomingClientPacketParser::kPayloadOffset, packet_parser.payload_length(), + data, + crypt_key, crypt_nonce, + error + ); + + if(!decrypt_result) { + if(!this->client->crypto.client_init) { + if(use_default_key) { + logTrace(this->client->getServerId(), "{} Failed to decrypt packet with default key ({}). Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), error); + return; + } else { + logTrace(this->client->getServerId(), "{} Failed to decrypt packet ({}). Trying with default key.", CLIENT_STR_LOG_PREFIX_(this->client), error); + use_default_key = true; + goto decrypt_packet; + } + } else { + logTrace(this->client->getServerId(), "{} Failed to decrypt packet ({}). Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), error); + return; + } } + packet_parser.set_decrypted(); + } else if(is_command && this->client->state != ConnectionState::INIT_HIGH) { + logTrace(this->client->getServerId(), "{} Voice client {}/{} tried to send a unencrypted command packet. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), client->getDisplayName(), this->client->getLoggingPeerIp()); + return; } #ifndef CONNECTION_NO_STATISTICS if(this->client && this->client->getServer()) - this->client->connectionStatistics->logIncomingPacket(*packet); + this->client->connectionStatistics->logIncomingPacket(stats::ConnectionStatistics::category::from_type(packet_parser.type()), buffer.length()); #endif #ifdef LOG_INCOMPING_PACKET_FRAGMENTS debugMessage(lstream << CLIENT_LOG_PREFIX << "Recived packet. PacketId: " << packet->packetId() << " PacketType: " << packet->type().name() << " Flags: " << packet->flags() << " - " << packet->data() << endl); #endif - if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){ //needs an acknowledge - if(this->client->crypto.protocol_encrypted) { - #ifdef LOG_AUTO_ACK_AUTORESPONSE - logMessage(this->client->getServerId(), "{}[Ack] Sending ack for incoming command packet {}", CLIENT_STR_LOG_PREFIX_(this->client), packet->packetId()); - #endif - this->client->sendAcknowledge(packet->packetId(), packet->type() == PacketTypeInfo::CommandLow); - } else { - debugMessage(this->client->getServerId(), "{}[Ack] Ignoring ack for {}", CLIENT_STR_LOG_PREFIX_(this->client), packet->packetId()); - } - } + if(is_command) { + auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(packet_parser.type())]; + CommandFragment fragment_entry{ + packet_parser.packet_id(), + packet_parser.estimated_generation(), - { - unique_lock queue_lock(read_queue.buffer_lock); + packet_parser.flags(), + (uint32_t) packet_parser.payload_length(), + packet_parser.payload().own_buffer() + }; - if(ordered) { /* ordered */ - if(!read_queue.insert_index(packet_id, move(packet))) { - debugMessage(this->client->getServerId(), "{} Got ordered packet of type {} which is out of the buffer range of {}. Packet ID: {}, Full index: {}. Dropping packet", - CLIENT_STR_LOG_PREFIX_(this->client), - packet_type.name(), - read_queue.capacity(), - packet_id, - read_queue.full_index() - ); - /* return; dont stop here because we've to progress the packets */ - } - } else { - //TODO: Needs rethinking because read_queue.push_back increases the index, but this has not to be the packet id - if(!read_queue.push_back(move(packet))) { - debugMessage(this->client->getServerId(), "{} Got unordered packet of type {} which is out of the buffer capacity of {}. Packet ID: {}. Dropping packet.", - CLIENT_STR_LOG_PREFIX_(this->client), - packet_type.name(), - read_queue.capacity(), - packet_id, - read_queue.full_index() - ); - } - { - //A max entropy of 16 packets should not happen. This indicates more that 16 or more packets got lost - auto current_index = read_queue.current_index(); - if(current_index + 16 < packet_id) - read_queue.set_full_index_to(packet_id); + { + unique_lock queue_lock(fragment_buffer.buffer_lock); + + if(!fragment_buffer.insert_index(packet_parser.packet_id(), std::move(fragment_entry))) { + logTrace(this->client->getServerId(), "{} Failed to insert command packet into command packet buffer.", CLIENT_STR_LOG_PREFIX_(this->client)); + return; } } + this->client->sendAcknowledge(packet_parser.packet_id(), packet_parser.type() == protocol::COMMAND_LOW); + + auto voice_server = this->client->voice_server; + if(voice_server) + voice_server->schedule_command_handling(this->client); + } else { + if(packet_parser.type() == protocol::VOICE || packet_parser.type() == protocol::VOICE_WHISPER) + this->client->handlePacketVoice(packet_parser); + else if(packet_parser.type() == protocol::ACK || packet_parser.type() == protocol::ACK_LOW) + this->client->handlePacketAck(packet_parser); + else if(packet_parser.type() == protocol::PING || packet_parser.type() == protocol::PONG) + this->client->handlePacketPing(packet_parser); + else { + logError(this->client->getServerId(), "{} Received hand decoded packet, but we've no method to handle it. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client)); + } } - - auto voice_server = this->client->voice_server; - if(voice_server) - voice_server->schedule_execute(this->client); } -bool VoiceClientConnection::verify_encryption(const pipes::buffer_view &packet /* incl. mac etc */) { - if((packet[12] & 0x80) != 0) /* we want an encrypted packet to verify the encryption */ - return false; +bool VoiceClientConnection::verify_encryption(const pipes::buffer_view &buffer /* incl. mac etc */) { + IncomingClientPacketParser packet_parser{buffer}; + if(!packet_parser.valid() || !packet_parser.is_encrypted()) return false; - auto packet_type = (protocol::PacketType) (packet[12] & 0xF); - if(packet_type == protocol::PING || packet_type == protocol::PONG) return false; /* these packets could never be encrypted */ - - auto packet_id = (uint16_t) be2le16(&packet[8]); - auto generation = this->_packet_buffers[packet_type].generation(packet_id); - return this->crypt_handler.verify_encryption(packet, packet_id, generation); + assert(packet_parser.type() >= 0 && packet_parser.type() < this->incoming_generation_estimators.size()); + return this->crypt_handler.verify_encryption(buffer, packet_parser.packet_id(), this->incoming_generation_estimators[packet_parser.type()].generation()); } -void VoiceClientConnection::execute_handle_packet(const std::chrono::system_clock::time_point& /* scheduled */) { +void VoiceClientConnection::execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */) { if(this->client->state == ConnectionState::DISCONNECTED || !this->client->getServer()) return; - bool reexecute_handle = false; + //TODO: Remove the buffer_execute_lock and use the one within the this->client->handlePacketCommand method unique_lock buffer_execute_lock; - auto packet = this->next_reassembled_packet(buffer_execute_lock, reexecute_handle); + pipes::buffer payload{}; + auto reexecute_handle = this->next_reassembled_command(buffer_execute_lock, payload); - if(packet){ + if(!payload.empty()){ auto startTime = system_clock::now(); try { - const auto packet_type = packet->type(); - if(packet_type == PacketTypeInfo::Command || packet_type == PacketTypeInfo::CommandLow) - this->client->handlePacketCommand(packet); - else if(packet_type == PacketTypeInfo::Ack || packet_type == PacketTypeInfo::AckLow) - this->client->handlePacketAck(packet); - else if(packet_type == PacketTypeInfo::Voice || packet_type == PacketTypeInfo::VoiceWhisper) - this->client->handlePacketVoice(packet); - else if(packet_type == PacketTypeInfo::Ping || packet_type == PacketTypeInfo::Pong) - this->client->handlePacketPing(packet); - else if(packet_type == PacketTypeInfo::Init1) - this->client->handlePacketInit(packet); + this->client->handlePacketCommand(payload); } catch (std::exception& ex) { logCritical(this->client->getServerId(), "{} Exception reached root tree! {}", CLIENT_STR_LOG_PREFIX_(this->client), ex.what()); } auto end = system_clock::now(); if(end - startTime > milliseconds(10)) { - if(packet->type() != PacketTypeInfo::Command && packet->type() != PacketTypeInfo::CommandLow) { - logError(this->client->getServerId(), - "{} Handling of packet {} needs more than 10ms ({}ms)", - CLIENT_STR_LOG_PREFIX_(this->client), - packet->type().name(), - duration_cast(end - startTime).count() - ); - } + logError(this->client->getServerId(), + "{} Handling of command packet needs more than 10ms ({}ms)", + CLIENT_STR_LOG_PREFIX_(this->client), + duration_cast(end - startTime).count() + ); } } if(buffer_execute_lock.owns_lock()) @@ -306,24 +251,20 @@ void VoiceClientConnection::execute_handle_packet(const std::chrono::system_cloc auto voice_server = this->client->voice_server; if(voice_server && reexecute_handle) - this->client->voice_server->schedule_execute(this->client); + this->client->voice_server->schedule_command_handling(this->client); } /* buffer_execute_lock: lock for in order execution */ -unique_ptr VoiceClientConnection::next_reassembled_packet(unique_lock& buffer_execute_lock, bool& more) { - packet_buffer_t* buffer = nullptr; +bool VoiceClientConnection::next_reassembled_command(unique_lock& buffer_execute_lock, pipes::buffer& result) { + command_fragment_buffer_t* buffer{nullptr}; unique_lock buffer_lock; /* general buffer lock */ + bool have_more{false}; { - auto base_index = this->_packet_buffers_index; - auto select_index = base_index; - auto max_index = this->_packet_buffers.size(); + //FIXME: Currently command low packets cant be handeled if there is a command packet stuck in reassamble - for(uint8_t index = 0; index < max_index; index++) { - if(!buffer) - select_index++; - - auto& buf = this->_packet_buffers[base_index++ % max_index]; + /* handle commands before command low packets */ + for(auto& buf : this->_command_fragment_buffers) { unique_lock ring_lock(buf.buffer_lock, try_to_lock); if(!ring_lock.owns_lock()) continue; @@ -335,119 +276,94 @@ unique_ptr VoiceClientConnection::next_reassembled_packe buffer_lock = move(ring_lock); buffer = &buf; } else { - more = true; + have_more = true; break; } } } - this->_packet_buffers_index = static_cast(select_index % max_index); /* guarantee that we will not hangup with commands! */ } if(!buffer) - return nullptr; /* we've no packets */ + return false; /* we've no packets */ - auto current_packet = &*buffer->slot_value(0); - if(!current_packet) { - logCritical(this->client->getServer()->getServerId(), "buffer->slot_value(0) returned nullptr, but set flag has been set!"); - return buffer->pop_front(); /* should be null! */ - } + uint8_t packet_flags{0}; + pipes::buffer payload{}; - if(current_packet->type() != PacketTypeInfo::Command && current_packet->type() != PacketTypeInfo::CommandLow) { - auto tmp = buffer->pop_front(); /* we don't have to reassemble anything */ - more |= buffer->front_set(); /* set the more flag if we know that we have more of this packet */ - return tmp; - } - - unique_ptr final_packet; - uint16_t sequence_length = 1; - - if(current_packet->has_flag(PacketFlag::Fragmented)) { - size_t buffer_length = ClientPacket::META_SIZE; + /* lets find out if we've to reassemble the packet */ + if(buffer->slot_value(0).packet_flags & PacketFlag::Fragmented) { + uint16_t sequence_length = 1; + size_t total_payload_length{0}; do { if(sequence_length >= buffer->capacity()) { - logError(this->client->getServerId(), "{} Received fragmented packets which have a too long order. Dropping queue, which will cause a client drop.", CLIENT_STR_LOG_PREFIX_(this->client)); + logError(this->client->getServerId(), "{} Command fragment buffer is full, and there is not fragmented packet end. Dropping full buffer which will probably cause a connection loss.", CLIENT_STR_LOG_PREFIX_(this->client)); buffer->clear(); - return nullptr; /* we've nothing to handle */ + return false; /* we've nothing to handle */ } - buffer_length += current_packet->data_length(); - current_packet = &*buffer->slot_value(sequence_length++); - } while(current_packet && !current_packet->has_flag(PacketFlag::Fragmented)); - if(!current_packet) - return nullptr; /* we haven't found the end yet! */ - buffer_length += current_packet->data_length(); + if(!buffer->slot_set(sequence_length)) + return false; /* we need more packets */ - /* okey we have all fragments lets reassemble */ + auto& packet = buffer->slot_value(sequence_length++); + total_payload_length += packet.payload_length; + if(packet.packet_flags & PacketFlag::Fragmented) { + /* yep we find the end */ + break; + } + } while(true); + /* ok we have all fragments lets reassemble */ /* * Packet sequence could never be so long. If it is so then the data_length() returned an invalid value. * We're checking it here because we dont want to make a huge allocation */ - assert(buffer_length < 512 * 1024 * 1024); + assert(total_payload_length < 512 * 1024 * 1024); - pipes::buffer packet_buffer{buffer_length}; + pipes::buffer packet_buffer{total_payload_length}; char* packet_buffer_ptr = &packet_buffer[0]; size_t packet_count = 0; - unique_ptr packet; - - /* initialize packet flags etc */ - { - packet = buffer->pop_front(); - packet_count++; - - if(!packet) { - logCritical(this->client->getServer()->getServerId(), "buffer->pop_front() returned nullptr, but set flag has been set (0)!"); - return nullptr; - } - - const auto length = packet->buffer().length(); - memcpy(packet_buffer_ptr, &packet->buffer()[0], length); - packet_buffer_ptr += length; - } - + packet_flags = buffer->slot_value(0).packet_flags; while(packet_count < sequence_length) { - packet = buffer->pop_front(); + auto fragment = buffer->pop_front(); + memcpy(packet_buffer_ptr, fragment.payload.data_ptr(), fragment.payload_length); + + packet_buffer_ptr += fragment.payload_length; packet_count++; - - if(!packet) { - logCritical(this->client->getServer()->getServerId(), "buffer->pop_front() returned nullptr, but set flag has been set (1)!"); - return nullptr; - } - - const auto length = packet->data_length(); - memcpy(packet_buffer_ptr, &packet->data()[0], length); - packet_buffer_ptr += length; } +#ifndef _NDEBUG if((packet_buffer_ptr - 1) != &packet_buffer[packet_buffer.length() - 1]) { logCritical(this->client->getServer()->getServerId(), - "Buffer over/underflow: packet_buffer_ptr != &packet_buffer[packet_buffer.length() - 1]; packet_buffer_ptr := {}; packet_buffer.end() := {}", - (void*) packet_buffer_ptr, - (void*) &packet_buffer[packet_buffer.length() - 1] + "Buffer over/underflow: packet_buffer_ptr != &packet_buffer[packet_buffer.length() - 1]; packet_buffer_ptr := {}; packet_buffer.end() := {}", + (void*) packet_buffer_ptr, + (void*) &packet_buffer[packet_buffer.length() - 1] ); } - - final_packet = ClientPacket::from_buffer(packet_buffer); - final_packet->setCompressed(final_packet->has_flag(PacketFlag::Compressed)); +#endif } else { - final_packet = buffer->pop_front(); - if(!final_packet) { - logCritical(this->client->getServer()->getServerId(), "buffer->pop_front() returned nullptr, but set flag has been set (3)!"); - return nullptr; - } + auto packet = buffer->pop_front(); + packet_flags = packet.packet_flags; + payload = packet.payload; } - more |= buffer->front_set(); /* set the more flag if we have more to process */ + have_more |= buffer->front_set(); /* set the more flag if we have more to process */ buffer_lock.unlock(); - std::string error = "success"; - if(!this->compress_handler.progressPacketIn(&*final_packet, error)) { - logError(this->client->getServerId(), "{} Failed to decompress received packet. Error: {}", CLIENT_STR_LOG_PREFIX_(this->client), error); - final_packet = nullptr; + if(packet_flags & PacketFlag::Compressed) { + std::string error{}; + + auto decompressed_size = compression::qlz_decompressed_size(payload.data_ptr(), payload.length()); + auto buffer = buffer::allocate_buffer(decompressed_size); + if(!compression::qlz_decompress_payload(payload.data_ptr(), buffer.data_ptr(), &decompressed_size)) { + logTrace(this->client->getServerId(), "{} Failed to decompress received command. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client)); + return false; + } + + payload = buffer.range(0, decompressed_size); } - return final_packet; + result = std::move(payload); + return have_more; } @@ -499,7 +415,7 @@ bool VoiceClientConnection::prepare_packet_for_write(vector &resu string error = "success"; - if(packet->type().compressable() && !packet->memory_state.fragment_entry) { + if(packet->type().compressable() && !packet->memory_state.fragment_entry && false) { packet->enable_flag(PacketFlag::Compressed); if(!this->compress_handler.progressPacketOut(packet.get(), error)) { logError(this->getClient()->getServerId(), "{} Could not compress outgoing packet.\nThis could cause fatal failed for the client.\nError: {}", error); @@ -560,12 +476,33 @@ bool VoiceClientConnection::prepare_packet_for_write(vector &resu work_lock.unlock(); /* the rest could be unordered */ + CryptHandler::key_t crypt_key{}; + CryptHandler::nonce_t crypt_nonce{}; auto statistics = this->client ? this->client->connectionStatistics : nullptr; for(const auto& fragment : fragments) { - if(!this->crypt_handler.progressPacketOut(fragment.get(), error, false)){ - logError(this->client->getServerId(), "{} Failed to encrypt packet. Error: {}", CLIENT_STR_LOG_PREFIX_(this->client), error); - return false; + if(fragment->has_flag(PacketFlag::Unencrypted)) { + this->crypt_handler.write_default_mac(fragment->mac().data_ptr()); + } else { + if(!this->client->crypto.protocol_encrypted) { + crypt_key = CryptHandler::default_key; + crypt_nonce = CryptHandler::default_nonce; + } else { + if(!this->crypt_handler.generate_key_nonce(false, fragment->type().type(), fragment->packetId(), fragment->generationId(), crypt_key, crypt_nonce)) { + logError(this->client->getServerId(), "{} Failed to generate crypt key/nonce for sending a packet. This should never happen! Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client)); + return false; + } + } + + auto crypt_result = this->crypt_handler.encrypt(fragment->header().data_ptr(), fragment->header().length(), + fragment->data().data_ptr(), fragment->data().length(), + fragment->mac().data_ptr(), + crypt_key, crypt_nonce, error); + if(!crypt_result){ + logError(this->client->getServerId(), "{} Failed to encrypt packet. Error: {}", CLIENT_STR_LOG_PREFIX_(this->client), error); + return false; + } } + #ifndef CONNECTION_NO_STATISTICS if(statistics) statistics->logOutgoingPacket(*fragment); @@ -704,7 +641,35 @@ void VoiceClientConnection::reset() { { lock_guard buffer_lock(this->packet_buffer_lock); - for(auto& buffer : this->_packet_buffers) + for(auto& buffer : this->_command_fragment_buffers) buffer.reset(); } } + +void VoiceClientConnection::force_insert_command(const pipes::buffer_view &buffer) { + CommandFragment fragment_entry{ + 0, + 0, + + PacketFlag::Unencrypted, + (uint32_t) buffer.length(), + buffer.own_buffer() + }; + + + { + auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(protocol::COMMAND)]; + unique_lock queue_lock(fragment_buffer.buffer_lock); + fragment_buffer.push_front(std::move(fragment_entry)); + } + + auto voice_server = this->client->voice_server; + if(voice_server) + voice_server->schedule_command_handling(this->client); +} + +void VoiceClientConnection::register_initiv_packet() { + auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(protocol::COMMAND)]; + unique_lock buffer_lock(fragment_buffer.buffer_lock); + fragment_buffer.set_full_index_to(1); /* the first packet (0) is already the clientinitiv packet */ +} \ No newline at end of file diff --git a/server/src/client/voice/VoiceClientConnection.h b/server/src/client/voice/VoiceClientConnection.h index 3d4cf50..6761eef 100644 --- a/server/src/client/voice/VoiceClientConnection.h +++ b/server/src/client/voice/VoiceClientConnection.h @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include #include @@ -10,9 +10,11 @@ #include #include #include +#include #include #include "VoiceClient.h" #include "protocol/AcknowledgeManager.h" +#include //#define LOG_ACK_SYSTEM #ifdef LOG_ACK_SYSTEM @@ -36,15 +38,33 @@ namespace ts { friend class server::VoiceClient; friend class server::POWHandler; public: - typedef protocol::PacketRingBuffer> packet_buffer_t; - typedef std::array packet_buffers_t; + struct CommandFragment { + uint16_t packet_id{0}; + uint16_t packet_generation{0}; + + uint8_t packet_flags{0}; + uint32_t payload_length : 24; + pipes::buffer payload{}; + + CommandFragment() { this->payload_length = 0; } + CommandFragment(uint16_t packetId, uint16_t packetGeneration, uint8_t packetFlags, uint32_t payloadLength, pipes::buffer payload) : packet_id{packetId}, packet_generation{packetGeneration}, packet_flags{packetFlags}, + payload_length{payloadLength}, payload{std::move(payload)} {} + + CommandFragment& operator=(const CommandFragment&) = default; + CommandFragment(const CommandFragment& other) = default; + CommandFragment(CommandFragment&&) = default; + }; + static_assert(sizeof(CommandFragment) == 8 + sizeof(pipes::buffer)); + + typedef protocol::PacketRingBuffer command_fragment_buffer_t; + typedef std::array command_packet_reassembler; explicit VoiceClientConnection(server::VoiceClient*); virtual ~VoiceClientConnection(); void sendPacket(const std::shared_ptr& original_packet, bool copy = false, bool prepare_directly = false); - CryptionHandler* getCryptHandler(){ return &crypt_handler; } + CryptHandler* getCryptHandler(){ return &crypt_handler; } server::VoiceClient* getClient(){ return client; } @@ -62,12 +82,13 @@ namespace ts { bool wait_empty_write_and_prepare_queue(std::chrono::time_point until = std::chrono::time_point()); protocol::PacketIdManager& getPacketIdManager() { return this->packet_id_manager; } - packet_buffers_t& packet_buffers() { return this->_packet_buffers; } - void reset(); + + void force_insert_command(const pipes::buffer_view& /* payload */); + void register_initiv_packet(); //buffer::SortedBufferQueue** getReadQueue() { return this->readTypedQueue; } protected: - void handleDatagramReceived(const pipes::buffer_view&); + void handle_incoming_datagram(const pipes::buffer_view &buffer); bool verify_encryption(const pipes::buffer_view& /* full packet */); void triggerWrite(); @@ -75,13 +96,13 @@ namespace ts { server::VoiceClient* client = nullptr; //Decryption / encryption stuff - CryptionHandler crypt_handler; + CryptHandler crypt_handler; /* access to CryptHandler is thread save */ CompressionHandler compress_handler; AcknowledgeManager acknowledge_handler; //Handle stuff - void execute_handle_packet(const std::chrono::system_clock::time_point& /* scheduled */); - std::unique_ptr next_reassembled_packet(std::unique_lock& /* packet channel execute lock */, bool& /* have more */); + void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */); + bool next_reassembled_command(std::unique_lock &buffer_execute_lock /* packet channel execute lock */, pipes::buffer & /* buffer*/); /* ---------- Write declarations ---------- */ @@ -143,9 +164,13 @@ namespace ts { std::atomic prepare_process_count{0}; /* current thread count preparing a packet */ bool prepare_packet_for_write(std::vector &/* buffers which need to be transferred */, const std::shared_ptr &/* the packet */, std::unique_lock& /* work lock */); + std::array incoming_generation_estimators{}; /* implementation is thread save */ std::recursive_mutex packet_buffer_lock; - packet_buffers_t _packet_buffers; - uint8_t _packet_buffers_index = 0; + command_packet_reassembler _command_fragment_buffers; + + static inline uint8_t command_fragment_buffer_index(uint8_t packet_index) { + return packet_index & 0x1U; /* use 0 for command and 1 for command low */ + } }; } diff --git a/server/src/client/voice/VoiceClientHandschake.cpp b/server/src/client/voice/VoiceClientHandschake.cpp index 692f74e..3919002 100644 --- a/server/src/client/voice/VoiceClientHandschake.cpp +++ b/server/src/client/voice/VoiceClientHandschake.cpp @@ -55,12 +55,9 @@ ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) { this->closeConnection(); /* executing final disconnect right now! */ } this->connection->reset(); - { - auto& read_queue = this->connection->packet_buffers()[protocol::COMMAND]; - unique_lock buffer_lock(read_queue.buffer_lock); - read_queue.set_full_index_to(1); /* the first packet (0) is already the clientinitiv packet */ - } + this->connection->register_initiv_packet(); this->state = ConnectionState::INIT_HIGH; + this->crypto.protocol_encrypted = false; bool use_teaspeak = command.hasParm("teaspeak"); if(use_teaspeak) { @@ -157,30 +154,27 @@ ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) { } { - this->connection->getCryptHandler()->block(); //Block until the key is setuped string error; if(!this->connection->getCryptHandler()->setupSharedSecret(this->crypto.alpha, this->crypto.beta, this->crypto.remote_key.get(), this->server->serverKey(), error)){ - this->connection->getCryptHandler()->unblock(); logError(this->server->getServerId(), "Could not setup shared secret! (" + error + ")"); return ts::command_result{error::vs_critical}; } - this->connection->getCryptHandler()->unblock(); this->crypto.protocol_encrypted = true; } } return ts::command_result{error::ok}; } -ts::command_result VoiceClient::handleCommandClientEk(const std::unique_ptr& packet, Command& cmd) { +ts::command_result VoiceClient::handleCommandClientEk(Command& cmd) { this->last_packet_handshake = system_clock::now(); debugMessage(this->getServerId(), "{} Got client ek!", CLIENT_STR_LOG_PREFIX); auto client_key = base64::decode(cmd["ek"]); - auto x = this->crypto.chain_data->chain->generatePrivateKey(this->crypto.chain_data->root_key, this->crypto.chain_data->root_index); + auto private_key = this->crypto.chain_data->chain->generatePrivateKey(this->crypto.chain_data->root_key, this->crypto.chain_data->root_index); - this->connection->getCryptHandler()->setupSharedSecretNew(this->crypto.alpha, this->crypto.beta, (char*) x.data(), client_key.data()); + this->connection->getCryptHandler()->setupSharedSecretNew(this->crypto.alpha, this->crypto.beta, (char*) private_key.data(), client_key.data()); this->connection->acknowledge_handler.reset(); this->crypto.protocol_encrypted = true; - this->sendAcknowledge(packet->packetId()); //Send the encrypted acknowledge + this->sendAcknowledge(2); //Send the encrypted acknowledge (most the times the second packet; If not we're going into the resend loop) return ts::command_result{error::ok}; } \ No newline at end of file diff --git a/server/src/client/voice/VoiceClientPacketHandler.cpp b/server/src/client/voice/VoiceClientPacketHandler.cpp index c9e3470..fcf6f56 100644 --- a/server/src/client/voice/VoiceClientPacketHandler.cpp +++ b/server/src/client/voice/VoiceClientPacketHandler.cpp @@ -12,14 +12,14 @@ using namespace ts::protocol; //#define PKT_LOG_PING /* should never happen! */ -void VoiceClient::handlePacketInit(const unique_ptr &) {} +void VoiceClient::handlePacketInit(const ts::protocol::IncomingClientPacketParser &) {} -//TODO Packet handlers -> move back to voice manager? -void VoiceClient::handlePacketCommand(const std::unique_ptr& packet) { +//TODO Packet handlers -> move back to voice client? +void VoiceClient::handlePacketCommand(const pipes::buffer_view& command_string) { std::unique_ptr command; command_result result{}; try { - command = make_unique(Command::parse(packet->data(), true, !ts::config::server::strict_ut8_mode)); + command = make_unique(Command::parse(command_string, true, !ts::config::server::strict_ut8_mode)); } catch(std::invalid_argument& ex) { result = command_result{error::parameter_convert, std::string{ex.what()}}; goto handle_error; @@ -29,7 +29,7 @@ void VoiceClient::handlePacketCommand(const std::unique_ptrcommand() == "clientek") { - result = this->handleCommandClientEk(packet, *command); + result = this->handleCommandClientEk(*command); if(result.error_code()) goto handle_error; } else if(command->command() == "clientinitiv") { result = this->handleCommandClientInitIv(*command); @@ -42,9 +42,9 @@ void VoiceClient::handlePacketCommand(const std::unique_ptr& packet) { - if (packet->type() == PacketTypeInfo::Pong) { - uint16_t id = be2le16((char*) packet->data().data_ptr()); +void VoiceClient::handlePacketPing(const protocol::IncomingClientPacketParser& packet) { + if (packet.type() == protocol::PONG) { + uint16_t id = be2le16((char*) packet.payload().data_ptr()); if (this->lastPingId == id) { #ifdef PKT_LOG_PING logMessage(this->getServerId(), "{}[Ping] Got a valid pong for ping {}. Required time: {}", CLIENT_STR_LOG_PREFIX, id, duration_cast(system_clock::now() - this->lastPingRequest).count() / 1000.f); @@ -64,22 +64,22 @@ void VoiceClient::handlePacketPing(const std::unique_ptr logMessage(this->getServerId(), "{}[Ping] Sending pong for client requested ping {}", CLIENT_STR_LOG_PREFIX, packet->packetId()); #endif char buffer[2]; - le2be16(packet->packetId(), buffer); + le2be16(packet.packet_id(), buffer); auto pkt = make_shared(PacketTypeInfo::Pong, pipes::buffer_view{buffer, 2}); pkt->enable_flag(PacketFlag::Unencrypted); this->connection->sendPacket(pkt); } -void VoiceClient::handlePacketVoice(const std::unique_ptr& packet) { - if (packet->type() == PacketTypeInfo::Voice) { - SpeakingClient::handlePacketVoice(packet->data(), packet->has_flag(PacketFlag::Compressed), packet->has_flag(PacketFlag::Fragmented)); - } else if(packet->type() == PacketTypeInfo::VoiceWhisper) { - SpeakingClient::handlePacketVoiceWhisper(packet->data(), packet->has_flag(PacketFlag::NewProtocol)); +void VoiceClient::handlePacketVoice(const protocol::IncomingClientPacketParser& packet) { + if (packet.type() == protocol::VOICE) { + SpeakingClient::handlePacketVoice(packet.payload(), (packet.flags() & PacketFlag::Compressed) > 0, (packet.flags() & PacketFlag::Fragmented) > 0); + } else if(packet.type() == protocol::VOICE_WHISPER) { + SpeakingClient::handlePacketVoiceWhisper(packet.payload(), (packet.flags() & PacketFlag::NewProtocol) > 0); } } -void VoiceClient::handlePacketAck(const std::unique_ptr& packet) { +void VoiceClient::handlePacketAck(const protocol::IncomingClientPacketParser& packet) { string error; - if(!this->connection->acknowledge_handler.process_acknowledge(*packet, error)) + if(!this->connection->acknowledge_handler.process_acknowledge(packet.type(), packet.payload(), error)) debugMessage(this->getServerId(), "{} Failed to handle acknowledge: {}", CLIENT_STR_LOG_PREFIX, error); } \ No newline at end of file diff --git a/server/src/client/web/WSWebClient.cpp b/server/src/client/web/WSWebClient.cpp index 49ffb10..d7ba2c1 100644 --- a/server/src/client/web/WSWebClient.cpp +++ b/server/src/client/web/WSWebClient.cpp @@ -108,7 +108,7 @@ void WebClient::enqueue_raw_packet(const pipes::buffer_view &msg) { void WebClient::registerMessageProcess() { auto weakLock = this->_this; - if(serverInstance->getVoiceServerManager()->getState() == ServerManager::STARTED) + if(serverInstance->getVoiceServerManager()->getState() == VirtualServerManager::STARTED) serverInstance->getVoiceServerManager()->get_executor_loop()->schedule(this->event_handle_packet); } diff --git a/server/src/client/web/WebClient.cpp b/server/src/client/web/WebClient.cpp index 1ce7a61..4aac09a 100644 --- a/server/src/client/web/WebClient.cpp +++ b/server/src/client/web/WebClient.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/server/src/server/POWHandler.cpp b/server/src/server/POWHandler.cpp index 1a17ab1..1e645c0 100644 --- a/server/src/server/POWHandler.cpp +++ b/server/src/server/POWHandler.cpp @@ -1,6 +1,6 @@ #include "POWHandler.h" #include "src/InstanceHandler.h" -#include "src/ServerManager.h" +#include "src/VirtualServerManager.h" #include "src/client/voice/VoiceClient.h" #include #include @@ -138,7 +138,7 @@ void POWHandler::send_data(const std::shared_ptr le2be16(101, &datagram->data[8]); /* 1 byte flags and type */ - datagram->data[10] = (uint8_t) (0x08 | 0x80); + datagram->data[10] = (uint8_t) (0x08U | 0x80U); memcpy(&datagram->data[11], buffer.data_ptr(), buffer.length()); this->server->send_datagram(client->socket, datagram); @@ -275,27 +275,7 @@ void POWHandler::handle_puzzle_solve(const std::shared_ptrregister_verified_client(client); if(voice_client) { - auto& read_queue = voice_client->connection->packet_buffers()[protocol::COMMAND]; - - auto packet = make_unique(protocol::PacketTypeInfo::Command, command); - packet->memory_state.id_branded = false; - packet->applyPacketId(0, 0); /* first packet */ - - { - unique_lock buffer_lock(read_queue.buffer_lock); - if(read_queue.current_index() == 0) { - if(!read_queue.insert_index(0, move(packet))) { - #ifdef POW_ERROR - debugMessage(this->get_server_id(), "[POW][{}][Puzzle] Failed to insert command packet into buffer!", net::to_string(client->address)); - #endif - return; - } - } else { - read_queue.push_front(move(packet)); - } - } - - this->server->schedule_execute(&*voice_client); + voice_client->connection->force_insert_command(command); client->state = LowHandshakeState::COMPLETED; } else { #ifdef POW_ERROR diff --git a/server/src/server/POWHandler.h b/server/src/server/POWHandler.h index 8175b0c..ed53b01 100644 --- a/server/src/server/POWHandler.h +++ b/server/src/server/POWHandler.h @@ -8,8 +8,7 @@ #include "VoiceServer.h" #include "src/VirtualServer.h" -namespace ts { - namespace server { +namespace ts::server { class POWHandler { public: enum LowHandshakeState : uint8_t { @@ -65,5 +64,4 @@ namespace ts { void send_data(const std::shared_ptr &client /* client */, const pipes::buffer_view &buffer /* buffer */); void reset_client(const std::shared_ptr &client /* client */); }; - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/server/src/server/QueryServer.h b/server/src/server/QueryServer.h index c84f426..884df33 100644 --- a/server/src/server/QueryServer.h +++ b/server/src/server/QueryServer.h @@ -68,15 +68,6 @@ namespace ts { void unregisterConnection(const std::shared_ptr &); - /* - std::string createQueryLogin(const std::string &name, ClientUid uid, std::string = ""); - bool renameQueryLogin(ClientUid uid, const std::string &targetName); - std::string resetQueryPassword(const std::shared_ptr&, std::string = ""); - - std::shared_ptr findQueryLoginByName(const std::string &name); - std::shared_ptr findQueryLoginByUid(const std::string &uid); - */ - std::deque> list_query_accounts(OptionalServerId /* server */); std::shared_ptr create_query_account(const std::string& /* name */, ServerId /* server */, const std::string& /* owner unique id */, const std::string& /* password */); std::shared_ptr load_password(const std::shared_ptr& /* account */); diff --git a/server/src/server/VoiceServer.cpp b/server/src/server/VoiceServer.cpp index 83ba0ca..68a2aec 100644 --- a/server/src/server/VoiceServer.cpp +++ b/server/src/server/VoiceServer.cpp @@ -10,7 +10,7 @@ #include #include "src/VirtualServer.h" #include -#include "../ServerManager.h" +#include "src/VirtualServerManager.h" #include "../InstanceHandler.h" #include #include @@ -120,7 +120,7 @@ void VoiceServer::triggerWrite(const std::shared_ptr& client) { this->io->invoke_write(client); } -void VoiceServer::schedule_execute(const ts::server::VoiceClient *client) { +void VoiceServer::schedule_command_handling(const ts::server::VoiceClient *client) { auto vmanager = serverInstance->getVoiceServerManager(); if(!vmanager) return; @@ -161,8 +161,9 @@ void VoiceServer::execute_resend(const std::chrono::system_clock::time_point &no if(client->state == ConnectionState::CONNECTED) { client->disconnect(ViewReasonId::VREASON_TIMEOUT, config::messages::timeout::packet_resend_failed, nullptr, true); - } else + } else { client->closeConnection(system_clock::now() + seconds(1)); + } } else if(!buffers.empty()) { { lock_guard client_write_lock(connection->write_queue_lock); @@ -348,16 +349,7 @@ void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) { auto new_address = net::to_string(remote_address); auto command = "dummy_ipchange old_ip=" + old_address + " new_ip=" + new_address; - auto packet = make_unique(protocol::PacketTypeInfo::Command, pipes::buffer_view{command.data(), command.length()}); - packet->memory_state.id_branded = false; - packet->applyPacketId(0, 0); - - { - auto& buffer = client->connection->packet_buffers()[protocol::COMMAND]; - unique_lock buffer_lock(buffer.buffer_lock); - buffer.push_front(move(packet)); - } - + client->connection->force_insert_command(pipes::buffer_view{command.data(), command.length()}); memcpy(&client->remote_address, &remote_address, sizeof(remote_address)); io::DatagramPacket::extract_info(message, client->address_info); } @@ -367,15 +359,7 @@ void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) { } if(client->state != ConnectionState::DISCONNECTED){ -#ifdef VC_USE_READ_QUEUE - { - lock_guard lock(client->connection->queueLock); - client->connection->readQueue.push_back(read_buffer.view(0, readBytes).dup(buffer::allocate_buffer(readBytes))); - } - while(client->state != ConnectionState::DISCONNECTED && client->connection->handleNextDatagram()); -#else - client->connection->handleDatagramReceived(read_buffer.view(0, bytes_read)); -#endif + client->connection->handle_incoming_datagram(read_buffer.view(0, bytes_read)); client = nullptr; } } diff --git a/server/src/server/VoiceServer.h b/server/src/server/VoiceServer.h index 2ce418f..ee78955 100644 --- a/server/src/server/VoiceServer.h +++ b/server/src/server/VoiceServer.h @@ -72,7 +72,7 @@ namespace ts { std::deque> activeConnections; public: //lib event void triggerWrite(const std::shared_ptr &); - void schedule_execute(VoiceClient const *); + void schedule_command_handling(VoiceClient const *client); void tickHandshakingClients(); void execute_resend(const std::chrono::system_clock::time_point& /* now */, std::chrono::system_clock::time_point& /* next resend */); diff --git a/server/src/terminal/CommandHandler.cpp b/server/src/terminal/CommandHandler.cpp index c0fdf9b..6506a5c 100644 --- a/server/src/terminal/CommandHandler.cpp +++ b/server/src/terminal/CommandHandler.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/server/src/weblist/WebListManager.cpp b/server/src/weblist/WebListManager.cpp index b9c3477..6ba7ec7 100644 --- a/server/src/weblist/WebListManager.cpp +++ b/server/src/weblist/WebListManager.cpp @@ -112,15 +112,12 @@ void WebListManager::tick() { logError(_entry->server->getServerId(), "[WebList] Status update failed. Error: " + error); if(_entry->fail_count == 1 && retry) { - logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 5 seconds."); - _entry->scheduled_request = now + seconds(5); - } else if(_entry->fail_count == 2 && retry) { - logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 30 seconds."); - _entry->scheduled_request = now + seconds(30); - } else if(_entry->fail_count == 3 && retry) { logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 1 minute."); _entry->scheduled_request = now + seconds(60); - } else if(_entry->fail_count >= 4) { + } else if(_entry->fail_count == 2 && retry) { + logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 5 minutes."); + _entry->scheduled_request = now + seconds(5 * 60); + } else if(_entry->fail_count >= 3) { logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 10 minutes."); _entry->scheduled_request = now + minutes(10); } diff --git a/shared b/shared index c9bd905..d13c1e6 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c9bd9054f6ff4507cb3d919b544beb3a450e7f39 +Subproject commit d13c1e6d6812aa568b6cc7215100828016b92582