diff --git a/music b/music index ae7f8c7..ad24c38 160000 --- a/music +++ b/music @@ -1 +1 @@ -Subproject commit ae7f8c7f3d4121704d229cd8995ec33e4824841b +Subproject commit ad24c38923afe23d94452973337a416540e3c7aa diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 038dde8..17798b0 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -4,6 +4,7 @@ project(TeaSpeak-Server) set(CMAKE_VERBOSE_MAKEFILE ON) #--allow-multiple-definition set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -Wall -Wno-reorder -Wno-sign-compare -static-libgcc -static-libstdc++ -g -Wl,--no-whole-archive -pthread ${MEMORY_DEBUG_FLAGS} -Werror=return-type") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--unresolved-symbols=ignore-all") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") @@ -43,7 +44,7 @@ set(SERVER_SOURCE_FILES # MySQLLibSSLFix.c src/client/ConnectedClient.cpp - src/client/voice/PrecomputedPuzzles.cpp + src/server/udp-server/PrecomputedPuzzles.cpp src/client/voice/VoiceClient.cpp src/client/voice/VoiceClientHandschake.cpp src/client/voice/VoiceClientCommandHandler.cpp @@ -160,7 +161,7 @@ if (COMPILE_WEB_CLIENT) src/client/web/WSWebClient.cpp src/client/web/SampleHandler.cpp src/client/web/VoiceBridge.cpp - src/client/command_handler/helpers.h src/music/PlaylistPermissions.cpp src/music/PlaylistPermissions.h src/lincense/LicenseService.cpp src/lincense/LicenseService.h src/groups/GroupManager.cpp src/groups/GroupManager.h src/groups/GroupAssignmentManager.cpp src/groups/GroupAssignmentManager.h src/groups/Group.cpp src/groups/Group.h src/services/VirtualServerInformation.cpp src/services/VirtualServerInformation.h src/vserver/VirtualServerManager.cpp src/vserver/VirtualServerManager.h) + src/client/command_handler/helpers.h src/music/PlaylistPermissions.cpp src/music/PlaylistPermissions.h src/lincense/LicenseService.cpp src/lincense/LicenseService.h src/groups/GroupManager.cpp src/groups/GroupManager.h src/groups/GroupAssignmentManager.cpp src/groups/GroupAssignmentManager.h src/groups/Group.cpp src/groups/Group.h src/services/VirtualServerInformation.cpp src/services/VirtualServerInformation.h src/vserver/VirtualServerManager.cpp src/vserver/VirtualServerManager.h src/services/VirtualServerBroadcastService.cpp src/services/VirtualServerBroadcastService.h src/server/udp-server/UDPServer.cpp src/server/udp-server/UDPServer.h) endif () add_executable(PermHelper helpers/permgen.cpp) diff --git a/server/src/DatabaseHelper.cpp b/server/src/DatabaseHelper.cpp index 61b3e01..6bde76e 100644 --- a/server/src/DatabaseHelper.cpp +++ b/server/src/DatabaseHelper.cpp @@ -231,13 +231,12 @@ inline sql::result load_permissions_v2(VirtualServerId server_id, v2::Permission #define INSERT_COMMAND "INSERT INTO `permissions` (`serverId`, `type`, `id`, `channelId`, `permId`, `value`, `grant`, `flag_skip`, `flag_negate`) VALUES (:serverId, :type, :id, :chId, :permId, :value, :grant, :flag_skip, :flag_negate)" #define DELETE_COMMAND "DELETE FROM `permissions` WHERE `serverId` = :serverId AND `type` = :type AND `id` = :id AND `permId` = :permId AND `channelId` = :chId" -std::shared_ptr DatabaseHelper::loadClientPermissionManager(const std::shared_ptr& server, ClientDbId cldbid) { - auto server_id = server ? server->getServerId() : 0; +std::shared_ptr DatabaseHelper::loadClientPermissionManager(VirtualServerId server_id, ClientDbId cldbid) { #ifndef DISABLE_CACHING { lock_guard lock(permManagerLock); for(auto permMgr : this->cachedPermissionManagers) - if(permMgr->cldbid == cldbid && permMgr->sid == (server ? server->getServerId() : 0)) { + if(permMgr->cldbid == cldbid && permMgr->sid == server_id) { auto ptr = permMgr->manager.lock(); if(!ptr){ this->cachedPermissionManagers.erase(std::find(this->cachedPermissionManagers.begin(), this->cachedPermissionManagers.end(), permMgr)); @@ -253,12 +252,12 @@ std::shared_ptr DatabaseHelper::loadClientPermissionMana logTrace(server_id, "[Permission] Loading client permission manager for client {}", cldbid); auto permission_manager = std::make_shared(); bool loaded = false; - if(this->use_startup_cache && server) { + if(this->use_startup_cache) { shared_ptr entry; { threads::MutexLock lock(this->startup_lock); for(const auto& entries : this->startup_entries) { - if(entries->sid == server->getServerId()) { + if(entries->sid == server_id) { entry = entries; break; } @@ -267,10 +266,8 @@ std::shared_ptr DatabaseHelper::loadClientPermissionMana if(entry) { for(const auto& perm : entry->permissions) { if(perm->type == permission::SQL_PERM_USER && perm->id == cldbid) { - auto channel = perm->channelId > 0 ? server->getChannelTree()->findChannel(perm->channelId) : nullptr; - - if(channel) - permission_manager->load_permission(perm->permission->type, {perm->value, perm->grant}, channel->channelId(), perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted); + if(perm->channelId > 0) + permission_manager->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->channelId, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted); else permission_manager->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted); } @@ -281,10 +278,10 @@ std::shared_ptr DatabaseHelper::loadClientPermissionMana if(!loaded) { auto command = sql::command(this->sql, "SELECT `permId`, `value`, `channelId`, `grant`, `flag_skip`, `flag_negate` FROM `permissions` WHERE `serverId` = :serverId AND `type` = :type AND `id` = :id", - variable{":serverId", server ? server->getServerId() : 0}, + variable{":serverId", server_id}, variable{":type", permission::SQL_PERM_USER}, variable{":id", cldbid}); - LOG_SQL_CMD(load_permissions_v2(server ? server->getServerId() : 0, permission_manager.get(), command, true)); + LOG_SQL_CMD(load_permissions_v2(server_id, permission_manager.get(), command, true)); } @@ -303,12 +300,11 @@ std::shared_ptr DatabaseHelper::loadClientPermissionMana } -void DatabaseHelper::saveClientPermissions(const std::shared_ptr &server, ts::ClientDbId client_dbid, const std::shared_ptr &permissions) { +void DatabaseHelper::saveClientPermissions(VirtualServerId server_id, ts::ClientDbId client_dbid, const std::shared_ptr &permissions) { const auto updates = permissions->flush_db_updates(); if(updates.empty()) return; - auto server_id = server ? server->getServerId() : 0; for(auto& update : updates) { std::string query = update.flag_delete ? DELETE_COMMAND : (update.flag_db ? UPDATE_COMMAND : INSERT_COMMAND); @@ -323,7 +319,7 @@ void DatabaseHelper::saveClientPermissions(const std::shared_ptrsql, query, - variable{":serverId", server ? server->getServerId() : 0}, + variable{":serverId", server_id}, variable{":id", client_dbid}, variable{":chId", update.channel_id}, variable{":type", permission::SQL_PERM_USER}, diff --git a/server/src/DatabaseHelper.h b/server/src/DatabaseHelper.h index 4078086..0b7f15b 100644 --- a/server/src/DatabaseHelper.h +++ b/server/src/DatabaseHelper.h @@ -91,8 +91,8 @@ namespace ts { std::deque> queryDatabaseInfo(const std::shared_ptr&, const std::deque&); std::deque> queryDatabaseInfoByUid(const std::shared_ptr &, std::deque); - std::shared_ptr loadClientPermissionManager(const std::shared_ptr&, ClientDbId); - void saveClientPermissions(const std::shared_ptr&, ClientDbId , const std::shared_ptr& /* permission manager */); + std::shared_ptr loadClientPermissionManager(VirtualServerId, ClientDbId); + void saveClientPermissions(VirtualServerId, ClientDbId , const std::shared_ptr& /* permission manager */); std::shared_ptr loadChannelPermissions(const std::shared_ptr&, ChannelId); void saveChannelPermissions(const std::shared_ptr&, ChannelId, const std::shared_ptr& /* permission manager */); diff --git a/server/src/Group.cpp b/server/src/Group.cpp index 3ff0b45..0453f61 100644 --- a/server/src/Group.cpp +++ b/server/src/Group.cpp @@ -7,6 +7,7 @@ #include "src/client/ConnectedClient.h" #include "InstanceHandler.h" #include "src/server/file/FileServer.h" +#include "src/groups/Group.h" using namespace std; using namespace std::chrono; @@ -212,7 +213,7 @@ int GroupManager::insertGroupFromDb(int count, char **values, char **column) { group->properties()[property::GROUP_NAME] = targetName; - group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock(), group->groupId())); + group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock() ? this->server.lock()->getServerId() : 0, group->groupId(), (uint8_t) -1)); debugMessage(this->getServerId(), "Push back group -> " + to_string(group->groupId()) + " - " + group->name()); this->groups.push_back(group); @@ -304,7 +305,7 @@ std::shared_ptr GroupManager::createGroup(GroupTarget target, GroupType t std::shared_ptr group = std::make_shared(this, target, type, groupId); group->properties()[property::GROUP_NAME] = name; - group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock(), group->groupId())); + group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock() ? this->server.lock()->getServerId() : 0, group->groupId(), (uint8_t) -1)); this->groups.push_back(group); return group; } @@ -344,7 +345,7 @@ bool GroupManager::copyGroupPermissions(const shared_ptr &source, const s res = sql::command(this->sql, "INSERT INTO `permissions` (`serverId`, `type`, `id`, `channelId`, `permId`, `value`, `grant`) SELECT :tsid AS `serverId`, `type`, :target AS `id`, 0 AS `channelId`, `permId`, `value`,`grant` FROM `permissions` WHERE `serverId` = :ssid AND `type` = :type AND `id` = :source", variable{":ssid", sourceServer}, variable{":tsid", targetServer}, variable{":type", SQL_PERM_GROUP}, variable{":source", source->groupId()}, variable{":target", target->groupId()}).execute(); - target->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(target->handle->server.lock(), target->groupId())); + target->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(target->handle->server.lock() ? target->handle->server.lock()->getServerId() : 0, target->groupId(), (uint8_t) -1)); LOG_SQL_CMD(res); return true; } @@ -355,7 +356,7 @@ bool GroupManager::reloadGroupPermissions(std::shared_ptr group) { return false; } - group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock(), group->groupId())); + group->setPermissionManager(serverInstance->databaseHelper()->loadGroupPermissions(this->server.lock() ? this->server.lock()->getServerId() : 0, group->groupId(), (uint8_t) -1)); return true; } @@ -457,11 +458,6 @@ std::deque GroupManager::update_server_group_propert unique_lock chan_lock(client->channel_lock, defer_lock); if(channel_lock) chan_lock.lock(); - - client->cached_server_groups.clear(); - client->cached_server_groups.reserve(groups.size()); - for(const auto& group : groups) - client->cached_server_groups.push_back(group->group->groupId()); } } @@ -480,8 +476,6 @@ std::deque GroupManager::update_server_group_propert unique_lock chan_lock(client->channel_lock, defer_lock); if(channel_lock) chan_lock.lock(); - - client->cached_channel_group = group->group->groupId(); } } diff --git a/server/src/InstanceHandler.cpp b/server/src/InstanceHandler.cpp index a5e862d..a4f5928 100644 --- a/server/src/InstanceHandler.cpp +++ b/server/src/InstanceHandler.cpp @@ -188,7 +188,7 @@ InstanceHandler::InstanceHandler(SqlDataManager *sql) : sql(sql) { this->properties()[property::SERVERINSTANCE_MONTHLY_TIMESTAMP] = duration_cast(system_clock::now().time_since_epoch()).count(); } - this->banMgr = new BanManager(this->getSql()); + this->banMgr = new bans::BanManager(this->getSql()); this->banMgr->loadBans(); this->web_list = make_shared(); @@ -569,7 +569,7 @@ void InstanceHandler::save_group_permissions() { auto permissions = group->permissions(); if(permissions->require_db_updates()) { auto begin = system_clock::now(); - serverInstance->databaseHelper()->saveGroupPermissions(nullptr, group->groupId(), permissions); + serverInstance->databaseHelper()->saveGroupPermissions(0, group->groupId(), permissions); auto end = system_clock::now(); debugMessage(0, "Saved instance group permissions for group {} ({}) in {}ms", group->groupId(), group->name(), duration_cast(end - begin).count()); } diff --git a/server/src/InstanceHandler.h b/server/src/InstanceHandler.h index 8f3569d..823cbd9 100644 --- a/server/src/InstanceHandler.h +++ b/server/src/InstanceHandler.h @@ -45,7 +45,7 @@ namespace ts { FileServer* getFileServer(){ return fileServer; } QueryServer* getQueryServer(){ return queryServer; } DatabaseHelper* databaseHelper(){ return this->dbHelper; } - BanManager* banManager(){ return this->banMgr; } + bans::BanManager* banManager(){ return this->banMgr; } ssl::SSLManager* sslManager(){ return this->sslMgr; } sql::SqlManager* getSql(){ return sql->sql(); } @@ -114,7 +114,7 @@ namespace ts { QueryServer* queryServer = nullptr; VirtualServerManager* voiceServerManager = nullptr; DatabaseHelper* dbHelper = nullptr; - BanManager* banMgr = nullptr; + bans::BanManager* banMgr = nullptr; ssl::SSLManager* sslMgr = nullptr; ts::Properties* _properties = nullptr; diff --git a/server/src/TS3ServerClientManager.cpp b/server/src/TS3ServerClientManager.cpp index 732f173..b1a90bb 100644 --- a/server/src/TS3ServerClientManager.cpp +++ b/server/src/TS3ServerClientManager.cpp @@ -122,7 +122,7 @@ bool VirtualServer::unregisterClient(shared_ptr cl, std::string this->client_move(cl, nullptr, nullptr, reason, ViewReasonId::VREASON_SERVER_LEFT, false, chan_tree_lock); } - serverInstance->databaseHelper()->saveClientPermissions(this->ref(), cl->getClientDatabaseId(), cl->clientPermissions); + serverInstance->databaseHelper()->saveClientPermissions(this->serverId, cl->getClientDatabaseId(), cl->clientPermissions); cl->setClientId(0); return true; } diff --git a/server/src/TS3ServerHeartbeat.cpp b/server/src/TS3ServerHeartbeat.cpp index a27c801..89d302f 100644 --- a/server/src/TS3ServerHeartbeat.cpp +++ b/server/src/TS3ServerHeartbeat.cpp @@ -152,7 +152,7 @@ void VirtualServer::executeServerTick() { if(cl->clientPermissions->require_db_updates()) { auto begin = system_clock::now(); - serverInstance->databaseHelper()->saveClientPermissions(this->ref(), cl->getClientDatabaseId(), cl->clientPermissions); + serverInstance->databaseHelper()->saveClientPermissions(this->serverId, cl->getClientDatabaseId(), cl->clientPermissions); auto end = system_clock::now(); debugMessage(this->serverId, "Saved client permissions for client {} ({}) in {}ms", cl->getClientDatabaseId(), cl->getDisplayName(), duration_cast(end - begin).count()); } @@ -250,7 +250,7 @@ void VirtualServer::executeServerTick() { auto permissions = group->permissions(); if(permissions->require_db_updates()) { auto begin = system_clock::now(); - serverInstance->databaseHelper()->saveGroupPermissions(this->ref(), group->groupId(), permissions); + serverInstance->databaseHelper()->saveGroupPermissions(this->serverId, group->groupId(), permissions); auto end = system_clock::now(); debugMessage(this->serverId, "Saved group permissions for group {} ({}) in {}ms", group->groupId(), group->name(), duration_cast(end - begin).count()); } diff --git a/server/src/VirtualServer.cpp b/server/src/VirtualServer.cpp index 4687ff0..6867a08 100644 --- a/server/src/VirtualServer.cpp +++ b/server/src/VirtualServer.cpp @@ -792,7 +792,7 @@ vectorclient_permissions) { - cache->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(self.lock(), client_dbid); + cache->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(this->serverId, client_dbid); } bool have_skip_permission = false; diff --git a/server/src/VirtualServerManager.cpp b/server/src/VirtualServerManager.cpp index 11bed8a..1a6fc4d 100644 --- a/server/src/VirtualServerManager.cpp +++ b/server/src/VirtualServerManager.cpp @@ -13,7 +13,7 @@ using namespace std::chrono; using namespace ts::server; VirtualServerManager::VirtualServerManager(InstanceHandler* handle) : handle(handle) { - this->puzzles = new protocol::PuzzleManager(); + this->puzzles = new server::udp::PuzzleManager(); this->handshakeTickers = new threads::Scheduler(1, "handshake ticker"); this->execute_loop = new event::EventExecutor("executor #"); //this->join_loop = new event::EventExecutor("joiner #"); diff --git a/server/src/VirtualServerManager.h b/server/src/VirtualServerManager.h index 887d533..049da6b 100644 --- a/server/src/VirtualServerManager.h +++ b/server/src/VirtualServerManager.h @@ -2,7 +2,7 @@ #include #include -#include "client/voice/PrecomputedPuzzles.h" +#include "src/server/udp-server/PrecomputedPuzzles.h" #include "server/VoiceIOManager.h" #include "VirtualServer.h" @@ -57,7 +57,7 @@ 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 &); - protocol::PuzzleManager* rsaPuzzles() { return this->puzzles; } + server::udp::PuzzleManager* rsaPuzzles() { return this->puzzles; } event::EventExecutor* get_join_loop() { return this->join_loop; } event::EventExecutor* get_executor_loop() { return this->execute_loop; } @@ -80,7 +80,7 @@ namespace ts { InstanceHandler* handle; threads::Mutex instanceLock; std::deque> instances; - protocol::PuzzleManager* puzzles = nullptr; + server::udp::PuzzleManager* puzzles = nullptr; event::EventExecutor* execute_loop = nullptr; event::EventExecutor* join_loop = nullptr; diff --git a/server/src/client/ConnectedClient.cpp b/server/src/client/ConnectedClient.cpp index a2dc31f..4d5ef7a 100644 --- a/server/src/client/ConnectedClient.cpp +++ b/server/src/client/ConnectedClient.cpp @@ -846,13 +846,13 @@ bool ConnectedClient::handleCommandFull(Command& cmd, bool disconnectOnFail) { return true; } -std::shared_ptr ConnectedClient::resolveActiveBan(const std::string& ip_address) { +std::shared_ptr ConnectedClient::resolveActiveBan(const std::string& ip_address) { if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_ignore_bans, 0))) return nullptr; //Check if manager banned auto banManager = serverInstance->banManager(); - shared_ptr banEntry = nullptr; - deque> entries; + shared_ptr banEntry = nullptr; + deque> entries; if (!banEntry) { banEntry = banManager->findBanByName(this->server->getServerId(), this->getDisplayName()); diff --git a/server/src/client/ConnectedClient.h b/server/src/client/ConnectedClient.h index fdcfbf7..561eb31 100644 --- a/server/src/client/ConnectedClient.h +++ b/server/src/client/ConnectedClient.h @@ -8,6 +8,7 @@ #include "../channel/ClientChannelView.h" #include "DataClient.h" #include "query/command3.h" +#include "src/manager/BanManager.h" #define CLIENT_STR_LOG_PREFIX_(this) (std::string("[") + this->getLoggingPeerIp() + ":" + std::to_string(this->getPeerPort()) + "/" + this->getDisplayName() + " | " + std::to_string(this->getClientId()) + "]") #define CLIENT_STR_LOG_PREFIX CLIENT_STR_LOG_PREFIX_(this) @@ -244,7 +245,7 @@ namespace ts { virtual void updateChannelClientProperties(bool /* lock channel tree */, bool /* notify our self */); void updateTalkRights(permission::PermissionValue talk_power); - virtual std::shared_ptr resolveActiveBan(const std::string& ip_address); + virtual std::shared_ptr resolveActiveBan(const std::string& ip_address); inline std::shared_ptr getConnectionStatistics() { return this->connectionStatistics; @@ -295,7 +296,8 @@ namespace ts { return this->_subscribed_playlist.lock() == playlist; } - [[nodiscard]] inline auto lock_command_handling() { return std::lock_guard{this->command_lock}; } + template > + [[nodiscard]] inline auto lock_command_handling() { return T{this->command_lock}; } void increase_join_state() { this->join_state_id++; } protected: std::weak_ptr _this; diff --git a/server/src/client/DataClient.cpp b/server/src/client/DataClient.cpp index ee92d42..478e134 100644 --- a/server/src/client/DataClient.cpp +++ b/server/src/client/DataClient.cpp @@ -112,7 +112,7 @@ bool DataClient::loadDataForCurrentServer() { //TODO for query } this->_properties->toggleSave(true); - this->clientPermissions = serverInstance->databaseHelper()->loadClientPermissionManager(ref_server, this->getClientDatabaseId()); + this->clientPermissions = serverInstance->databaseHelper()->loadClientPermissionManager(ref_server ? ref_server->serverId : 0, this->getClientDatabaseId()); //Setup / fix stuff if(!this->properties()[property::CLIENT_FLAG_AVATAR].as().empty()){ diff --git a/server/src/client/DataClient.h b/server/src/client/DataClient.h index 1761a7c..9b9e848 100644 --- a/server/src/client/DataClient.h +++ b/server/src/client/DataClient.h @@ -98,6 +98,8 @@ namespace ts { virtual bool loadDataForCurrentServer(); + + [[nodiscard]] inline std::shared_ptr permissions() { return this->clientPermissions; } protected: sql::SqlManager* sql; std::shared_ptr server; diff --git a/server/src/client/SpeakingClient.cpp b/server/src/client/SpeakingClient.cpp index 9949045..bf16381 100644 --- a/server/src/client/SpeakingClient.cpp +++ b/server/src/client/SpeakingClient.cpp @@ -174,6 +174,7 @@ void SpeakingClient::handlePacketVoiceWhisper(const pipes::buffer_view& data, bo #endif deque> available_clients; + auto type_id_string = std::to_string(type_id); for(const auto& client : this->server->getClients()) { auto speakingClient = dynamic_pointer_cast(client); if(!speakingClient || client == this) continue; @@ -185,16 +186,15 @@ void SpeakingClient::handlePacketVoiceWhisper(const pipes::buffer_view& data, bo if(type_id == 0) available_clients.push_back(speakingClient); else { - shared_lock client_lock(this->channel_lock); - for(const auto& id : client->cached_server_groups) { - if(id == type_id) { - available_clients.push_back(speakingClient); - break; - } - } + auto client_groups = client->properties()[property::CLIENT_SERVERGROUPS].as(); + auto index = client_groups.find(client_groups); + if(index == std::string::npos) continue; + if(index != client_groups.length() && client_groups[index] != ',') continue; + + available_clients.push_back(speakingClient); } } else if(type == WhisperType::CHANNEL_GROUP) { - if(client->cached_channel_group == type_id) + if(client->properties()[property::CLIENT_CHANNEL_GROUP_ID].as_save() == type_id) available_clients.push_back(speakingClient); } else if(type == WhisperType::CHANNEL_COMMANDER) { if(client->properties()[property::CLIENT_IS_CHANNEL_COMMANDER].as()) diff --git a/server/src/client/command_handler/channel.cpp b/server/src/client/command_handler/channel.cpp index 0842fa7..81a41ad 100644 --- a/server/src/client/command_handler/channel.cpp +++ b/server/src/client/command_handler/channel.cpp @@ -1654,7 +1654,7 @@ command_result ConnectedClient::handleCommandChannelClientPermList(Command &cmd) ACTION_REQUIRES_PERMISSION(permission::b_virtualserver_channelclient_permission_list, 1, channel_id); if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return command_result{error::client_invalid_id}; - auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"].as()); + auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server ? this->server->serverId : 0, cmd["cldbid"].as()); Command res(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifychannelclientpermlist" : ""); @@ -1714,7 +1714,7 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd) auto channel = dynamic_pointer_cast(l_channel->entry); if(!channel) return command_result{error::vs_critical}; - auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid); + auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server ? this->server->serverId : 0, cldbid); { auto required_permissions = this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cmd["cldbid"], ClientType::CLIENT_TEAMSPEAK, channel_id); ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id); @@ -1740,7 +1740,7 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd) } } - serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr); + serverInstance->databaseHelper()->saveClientPermissions(this->server ? this->server->serverId : 0, cldbid, mgr); if (!cll.empty()) { for (const auto &elm : cll) { if(elm->update_cached_permissions()) /* update cached calculated permissions */ @@ -1784,7 +1784,7 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) auto channel = dynamic_pointer_cast(l_channel->entry); if(!channel) return command_result{error::vs_critical}; - auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid); + auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server ? this->server->serverId : 0, cldbid); { auto required_permissions = this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cmd["cldbid"], ClientType::CLIENT_TEAMSPEAK, channel_id); ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id); @@ -1821,7 +1821,7 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) } } - serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr); + serverInstance->databaseHelper()->saveClientPermissions(this->server ? this->server->serverId : 0, cldbid, mgr); if (!onlineClientInstances.empty()) for (const auto &elm : onlineClientInstances) { if (elm->update_cached_permissions()) /* update cached calculated permissions */ diff --git a/server/src/client/command_handler/client.cpp b/server/src/client/command_handler/client.cpp index 3800eda..e020de6 100644 --- a/server/src/client/command_handler/client.cpp +++ b/server/src/client/command_handler/client.cpp @@ -867,7 +867,7 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) { auto cldbid = cmd["cldbid"].as(); if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cldbid)) return command_result{error::client_invalid_id}; - auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid); + auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server ? this->server->getServerId() : 0, cldbid); ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_permission_modify_power, this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cldbid, ClientType::CLIENT_TEAMSPEAK, 0)); auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, true); @@ -897,7 +897,7 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) { update_channels |= permission_is_client_property(permType); } } - serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr); + serverInstance->databaseHelper()->saveClientPermissions(this->server ? this->server->getServerId() : 0, cldbid, mgr); auto onlineClients = this->server->findClientsByCldbId(cldbid); if (!onlineClients.empty()) for (const auto &elm : onlineClients) { @@ -919,7 +919,7 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) { auto cldbid = cmd["cldbid"].as(); if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cldbid)) return command_result{error::client_invalid_id}; - auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid); + auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server ? this->server->serverId : 0, cldbid); ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_permission_modify_power, this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cldbid, ClientType::CLIENT_TEAMSPEAK, 0)); auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0)); @@ -943,7 +943,7 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) { } } - serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr); + serverInstance->databaseHelper()->saveClientPermissions(this->server ? this->server->serverId : 0, cldbid, mgr); if (!onlineClients.empty()) for (const auto &elm : onlineClients) { if(elm->update_cached_permissions()) /* update cached calculated permissions */ @@ -962,7 +962,7 @@ command_result ConnectedClient::handleCommandClientPermList(Command &cmd) { ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_client_permission_list, 1); if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return command_result{error::client_invalid_id}; - auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"]); + auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server ? this->server->getServerId() : 0, cmd["cldbid"]); if (!this->notifyClientPermList(cmd["cldbid"], mgr, cmd.hasParm("permsid"))) return command_result{error::database_empty_result}; return command_result{error::ok}; } diff --git a/server/src/client/command_handler/misc.cpp b/server/src/client/command_handler/misc.cpp index c424398..24932bf 100644 --- a/server/src/client/command_handler/misc.cpp +++ b/server/src/client/command_handler/misc.cpp @@ -1561,7 +1561,7 @@ command_result ConnectedClient::handleCommandPermOverview(Command &cmd) { auto server_groups = this->server->getGroupManager()->getServerGroups(client_dbid, ClientType::CLIENT_TEAMSPEAK); auto channel_group = this->server->getGroupManager()->getChannelGroup(client_dbid, channel, true); - auto permission_manager = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServer(), client_dbid); + auto permission_manager = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), client_dbid); Command result(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifypermoverview" : ""); size_t index = 0; diff --git a/server/src/client/voice/PrecomputedPuzzles.h b/server/src/client/voice/PrecomputedPuzzles.h deleted file mode 100644 index ef4a642..0000000 --- a/server/src/client/voice/PrecomputedPuzzles.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace ts { - namespace server { - class ConnectedClient; - } - - namespace protocol { - struct Puzzle { - mp_int x; - mp_int n; - int level; - - mp_int result; - - uint8_t data_x[64]; - uint8_t data_n[64]; - uint8_t data_result[64]; - }; - class PuzzleManager { - public: - PuzzleManager(); - ~PuzzleManager(); - - bool precomputePuzzles(size_t limit); - - size_t precomputedPuzzleCount(); - - std::shared_ptr nextPuzzle(); - private: - void generatePuzzle(); - - threads::Mutex indexLock; - size_t cacheIndex = 0; - - std::deque> cached; - }; - } -} \ No newline at end of file diff --git a/server/src/client/voice/VoiceClient.h b/server/src/client/voice/VoiceClient.h index f3d9989..ec84452 100644 --- a/server/src/client/voice/VoiceClient.h +++ b/server/src/client/voice/VoiceClient.h @@ -13,7 +13,7 @@ #include "../ConnectedClient.h" #include "protocol/CryptHandler.h" #include "VoiceClientConnection.h" -#include "PrecomputedPuzzles.h" +#include "src/server/udp-server/PrecomputedPuzzles.h" #include "../../lincense/TeamSpeakLicense.h" //#define LOG_INCOMPING_PACKET_FRAGMENTS @@ -42,7 +42,7 @@ namespace ts { class VoiceClient : public SpeakingClient { friend class VirtualServer; friend class VoiceServer; - friend class POWHandler; + friend class ts::server::server::udp::POWHandler; friend class ts::connection::VoiceClientConnection; friend class ConnectedClient; friend class io::IOServerHandler; diff --git a/server/src/groups/Group.h b/server/src/groups/Group.h index 1239360..cb58165 100644 --- a/server/src/groups/Group.h +++ b/server/src/groups/Group.h @@ -80,4 +80,6 @@ namespace ts::server::groups { public: ChannelGroup(VirtualServerId /* server id */, GroupId /* id */, GroupType /* type */, std::string /* name */, std::shared_ptr /* permissions */); }; -} \ No newline at end of file +} +DEFINE_TRANSFORMS(ts::server::groups::GroupType, uint8_t); +DEFINE_TRANSFORMS(ts::server::groups::GroupNameMode, uint8_t); \ No newline at end of file diff --git a/server/src/groups/GroupAssignmentManager.cpp b/server/src/groups/GroupAssignmentManager.cpp index 6bfea0e..1729c3e 100644 --- a/server/src/groups/GroupAssignmentManager.cpp +++ b/server/src/groups/GroupAssignmentManager.cpp @@ -332,7 +332,7 @@ GroupAssignmentResult GroupAssignmentManager::add_server_group(ClientDbId client auto cache = std::make_unique(); cache->client_database_id = client; cache->server_group_assignments.emplace_back(group); - this->client_cache.push_back(cache); + this->client_cache.push_back(std::move(cache)); } } @@ -424,7 +424,7 @@ GroupAssignmentResult GroupAssignmentManager::set_channel_group(ClientDbId clien auto cache = std::make_unique(); cache->client_database_id = client; cache->channel_group_assignments.emplace_back(channel_id, group, temporary); - this->client_cache.push_back(cache); + this->client_cache.push_back(std::move(cache)); } else { return GroupAssignmentResult::SUCCESS; } diff --git a/server/src/groups/GroupAssignmentManager.h b/server/src/groups/GroupAssignmentManager.h index 5517262..e7d6e63 100644 --- a/server/src/groups/GroupAssignmentManager.h +++ b/server/src/groups/GroupAssignmentManager.h @@ -32,6 +32,7 @@ namespace ts::server { ChannelGroupAssignment(ChannelId channel_id, GroupId group_id, bool t) : channel_id{channel_id}, group_id{group_id}, temporary_assignment{t} { } ChannelGroupAssignment(const ChannelGroupAssignment& other) = default; ChannelGroupAssignment(ChannelGroupAssignment&&) = default; + ChannelGroupAssignment&operator=(const ChannelGroupAssignment&) = default; ChannelId channel_id; GroupId group_id; @@ -42,6 +43,7 @@ namespace ts::server { explicit ServerGroupAssignment(GroupId group_id) : group_id{group_id} { } ServerGroupAssignment(const ServerGroupAssignment& other) = default; ServerGroupAssignment(ServerGroupAssignment&&) = default; + ServerGroupAssignment&operator=(const ServerGroupAssignment&) = default; GroupId group_id; }; diff --git a/server/src/manager/BanManager.cpp b/server/src/manager/BanManager.cpp index 16129f1..cd52d55 100644 --- a/server/src/manager/BanManager.cpp +++ b/server/src/manager/BanManager.cpp @@ -275,7 +275,7 @@ void BanManager::trigger_ban(const std::shared_ptr& record, ).executeLater().waitAndGetLater(LOG_SQL_CMD, {1, "future failed"}); } -std::deque> BanManager::trigger_list(const std::shared_ptr &record, ServerId server_id, ssize_t offset, ssize_t length) { +std::deque> BanManager::trigger_list(const std::shared_ptr &record, ServerId server_id, ssize_t offset, ssize_t length) { std::deque> result; if(offset < 0) offset = 0; diff --git a/server/src/server/POWHandler.cpp b/server/src/server/POWHandler.cpp index d1063eb..eee59a4 100644 --- a/server/src/server/POWHandler.cpp +++ b/server/src/server/POWHandler.cpp @@ -9,7 +9,7 @@ using namespace std; using namespace std::chrono; using namespace ts; -using namespace ts::server; +using namespace ts::server::server::udp; //#define POW_DEBUG //#define POW_ERROR @@ -33,7 +33,7 @@ void POWHandler::execute_tick() { }), this->pending_clients.end()); } -void POWHandler::delete_client(const std::shared_ptr &client) { +void POWHandler::delete_client(const std::shared_ptr &client) { lock_guard lock(this->pending_clients_lock); auto it = find(this->pending_clients.begin(), this->pending_clients.end(), client); if(it != this->pending_clients.end()) @@ -127,7 +127,7 @@ void POWHandler::handle_datagram(int socket, const sockaddr_storage &address,msg } } -void POWHandler::send_data(const std::shared_ptr &client, const pipes::buffer_view &buffer) { +void POWHandler::send_data(const std::shared_ptr &client, const pipes::buffer_view &buffer) { auto datagram = io::DatagramPacket::create(client->address, client->address_info, buffer.length() + MAC_SIZE + SERVER_HEADER_SIZE, nullptr); if(!datagram) return; //Should never happen @@ -144,7 +144,7 @@ void POWHandler::send_data(const std::shared_ptr this->server->send_datagram(client->socket, datagram); } -void POWHandler::reset_client(const std::shared_ptr &client) { +void POWHandler::reset_client(const std::shared_ptr &client) { uint8_t buffer[2] = {COMMAND_RESET, 0}; this->send_data(client, pipes::buffer_view{buffer, 2}); client->state = LowHandshakeState::COOKIE_GET; @@ -161,7 +161,7 @@ inline void write_reversed(uint8_t* destination, uint8_t* source, size_t length) *(--destination) = *(source++); } -void POWHandler::handle_cookie_get(const std::shared_ptr &client, const pipes::buffer_view &buffer) { +void POWHandler::handle_cookie_get(const std::shared_ptr &client, const pipes::buffer_view &buffer) { if(buffer.length() != 21) { #ifdef POW_ERROR debugMessage(this->get_server_id(), "[POW][{}][Cookie] Received an invalid packet with an invalid length. Expected {} bytes, but got {} bytes", net::to_string(client->address), 21, buffer.length()); @@ -191,7 +191,7 @@ void POWHandler::handle_cookie_get(const std::shared_ptrstate = LowHandshakeState::PUZZLE_GET; } -void POWHandler::handle_puzzle_get(const std::shared_ptr &client, const pipes::buffer_view &buffer) { +void POWHandler::handle_puzzle_get(const std::shared_ptr &client, const pipes::buffer_view &buffer) { if(buffer.length() != 25) { #ifdef POW_ERROR debugMessage(this->get_server_id(), "[POW][{}][Puzzle] Received an invalid puzzle request with an invalid length. Expected {} bytes, but got {} bytes", net::to_string(client->address), 25, buffer.length()); @@ -211,7 +211,7 @@ void POWHandler::handle_puzzle_get(const std::shared_ptrrsa_challenge) - client->rsa_challenge = serverInstance->getVoiceServerManager()->rsaPuzzles()->nextPuzzle(); + client->rsa_challenge = serverInstance->getVoiceServerManager()->rsaPuzzles()->next_puzzle(); /* send response */ { @@ -239,7 +239,7 @@ void POWHandler::handle_puzzle_get(const std::shared_ptrstate = LowHandshakeState::PUZZLE_SOLVE; } -void POWHandler::handle_puzzle_solve(const std::shared_ptr &client, const pipes::buffer_view &buffer) { +void POWHandler::handle_puzzle_solve(const std::shared_ptr &client, const pipes::buffer_view &buffer) { if(buffer.length() < 301) { #ifdef POW_ERROR debugMessage(this->get_server_id(), "[POW][{}][Puzzle] Received an invalid puzzle solution with an invalid length. Expected at least {} bytes, but got {} bytes", net::to_string(client->address), 301, buffer.length()); @@ -283,7 +283,7 @@ void POWHandler::handle_puzzle_solve(const std::shared_ptr POWHandler::register_verified_client(const std::shared_ptr &client) { +shared_ptr POWHandler::register_verified_client(const std::shared_ptr &client) { shared_ptr voice_client; { lock_guard lock(this->server->connectionLock); diff --git a/server/src/server/POWHandler.h b/server/src/server/POWHandler.h index ed53b01..585ea7b 100644 --- a/server/src/server/POWHandler.h +++ b/server/src/server/POWHandler.h @@ -3,12 +3,12 @@ #include #include #include -#include #include #include "VoiceServer.h" #include "src/VirtualServer.h" +#include "./udp-server/PrecomputedPuzzles.h" -namespace ts::server { +namespace ts::server::server::udp { class POWHandler { public: enum LowHandshakeState : uint8_t { @@ -38,7 +38,7 @@ namespace ts::server { uint32_t client_version; - std::shared_ptr rsa_challenge; + std::shared_ptr rsa_challenge; }; explicit POWHandler(VoiceServer* /* server */); diff --git a/server/src/server/VoiceServer.h b/server/src/server/VoiceServer.h index ee78955..f512ec1 100644 --- a/server/src/server/VoiceServer.h +++ b/server/src/server/VoiceServer.h @@ -11,11 +11,11 @@ #include "VoiceIOManager.h" namespace ts { - namespace protocol { - class PuzzleManager; - } - namespace server { + namespace server::udp { + class POWHandler; + } + class VirtualServer; class ConnectedClient; class VoiceClient; @@ -33,7 +33,7 @@ namespace ts { friend class VoiceClient; friend class io::VoiceIOManager; friend struct io::IOEventLoopEvents; - friend class POWHandler; + friend class server::udp::POWHandler; public: explicit VoiceServer(const std::shared_ptr& server); ~VoiceServer(); diff --git a/server/src/client/voice/PrecomputedPuzzles.cpp b/server/src/server/udp-server/PrecomputedPuzzles.cpp similarity index 50% rename from server/src/client/voice/PrecomputedPuzzles.cpp rename to server/src/server/udp-server/PrecomputedPuzzles.cpp index 02ba330..dc0ad39 100644 --- a/server/src/client/voice/PrecomputedPuzzles.cpp +++ b/server/src/server/udp-server/PrecomputedPuzzles.cpp @@ -1,50 +1,50 @@ -#include "PrecomputedPuzzles.h" -#include "../../Configuration.h" -#include "../ConnectedClient.h" +#include "./PrecomputedPuzzles.h" +#include "src/Configuration.h" #include using namespace std; -using namespace ts; -using namespace ts::protocol; +using namespace ts::server::server::udp; -PuzzleManager::PuzzleManager() {} -PuzzleManager::~PuzzleManager() {} +PuzzleManager::PuzzleManager() = default; +PuzzleManager::~PuzzleManager() = default; -size_t PuzzleManager::precomputedPuzzleCount() { return this->cached.size(); } - -bool PuzzleManager::precomputePuzzles(size_t limit) { - while(precomputedPuzzleCount() < limit) generatePuzzle(); - return true; +size_t PuzzleManager::precomputed_puzzle_count() { + std::lock_guard lock{this->cache_lock}; + return this->cached_puzzles.size(); } -std::shared_ptr PuzzleManager::nextPuzzle() { - this->indexLock.lock(); - size_t index = this->cacheIndex++ % this->cached.size(); - this->indexLock.unlock(); - return this->cached[index]; +bool PuzzleManager::precompute_puzzles(size_t amount) { + std::random_device rd{}; + std::mt19937 mt{rd()}; + + while(this->precomputed_puzzle_count() < amount) + this->generate_puzzle(); + return this->precomputed_puzzle_count() > 0; } -inline void rndNum(mp_int *result, int byteLength){ - uint8_t buffer[byteLength]; +std::shared_ptr PuzzleManager::next_puzzle() { + std::lock_guard lock{this->cache_lock}; + return this->cached_puzzles[this->cache_index++ % this->cached_puzzles.size()]; +} - for(int index = 0; index < byteLength; index++) { - int rnd = rand(); - uint8_t urnd = static_cast(rnd & 0xFF); - buffer[index] = urnd; //TODO more secure! +inline void random_number(std::mt19937& generator, mp_int *result, int length){ + std::uniform_int_distribution dist{}; - } + uint8_t buffer[length]; + for(auto& byte : buffer) + byte = dist(generator); mp_zero(result); - mp_read_unsigned_bin(result, buffer, byteLength); + mp_read_unsigned_bin(result, buffer, length); } -inline bool solvePuzzle(Puzzle *puzzle){ +inline bool solve_puzzle(Puzzle *puzzle) { mp_int exp{}; mp_init(&exp); mp_2expt(&exp, puzzle->level); - if (mp_exptmod(&puzzle->x, &exp, &puzzle->n, &puzzle->result) != CRYPT_OK) { //Sometimes it fails (unknow why :D) + if (mp_exptmod(&puzzle->x, &exp, &puzzle->n, &puzzle->result) != CRYPT_OK) { //Sometimes it fails (unknown why :D) mp_clear(&exp); return false; } @@ -66,17 +66,17 @@ inline bool write_bin_data(mp_int& data, uint8_t* result, size_t length) { return true; } -void PuzzleManager::generatePuzzle() { +void PuzzleManager::generate_puzzle(std::mt19937& random_generator) { auto puzzle = new Puzzle{}; + puzzle->level = ts::config::voice::RsaPuzzleLevel; mp_init_multi(&puzzle->x, &puzzle->n, &puzzle->result, nullptr); generate_new: - rndNum(&puzzle->x, 64); - rndNum(&puzzle->n, 64); - puzzle->level = ts::config::voice::RsaPuzzleLevel; + random_number(random_generator, &puzzle->x, 64); + random_number(random_generator, &puzzle->n, 64); - if(!solvePuzzle(puzzle)) + if(!solve_puzzle(puzzle)) goto generate_new; auto valid_x = mp_unsigned_bin_size(&puzzle->x) <= 64; @@ -94,7 +94,7 @@ void PuzzleManager::generatePuzzle() { if(!write_bin_data(puzzle->result, puzzle->data_result, 64)) goto generate_new; - this->cached.push_back(shared_ptr(puzzle, [](Puzzle* elm){ + this->cached_puzzles.push_back(shared_ptr(puzzle, [](Puzzle* elm){ mp_clear_multi(&elm->n, &elm->x, &elm->result, nullptr); delete elm; })); diff --git a/server/src/server/udp-server/PrecomputedPuzzles.h b/server/src/server/udp-server/PrecomputedPuzzles.h new file mode 100644 index 0000000..2e34529 --- /dev/null +++ b/server/src/server/udp-server/PrecomputedPuzzles.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace ts::server::server::udp { + struct Puzzle { + mp_int x; + mp_int n; + int level; + + mp_int result; + + uint8_t data_x[64]; + uint8_t data_n[64]; + uint8_t data_result[64]; + }; + + class PuzzleManager { + public: + PuzzleManager(); + ~PuzzleManager(); + + [[nodiscard]] bool precompute_puzzles(size_t amount); + + [[nodiscard]] size_t precomputed_puzzle_count(); + + [[nodiscard]] std::shared_ptr next_puzzle(); + private: + void generate_puzzle(std::mt19937&); + + size_t cache_index{0}; + spin_lock cache_lock{}; + std::vector> cached_puzzles{}; + }; +} \ No newline at end of file diff --git a/server/src/server/udp-server/UDPServer.cpp b/server/src/server/udp-server/UDPServer.cpp new file mode 100644 index 0000000..079c3d8 --- /dev/null +++ b/server/src/server/udp-server/UDPServer.cpp @@ -0,0 +1,5 @@ +// +// Created by WolverinDEV on 07/03/2020. +// + +#include "UDPServer.h" diff --git a/server/src/server/udp-server/UDPServer.h b/server/src/server/udp-server/UDPServer.h new file mode 100644 index 0000000..d89632c --- /dev/null +++ b/server/src/server/udp-server/UDPServer.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ts::server { + class VoiceClient; +} + +namespace ts::server::server::udp { + struct datagram_packet { + union pktinfo_storage { + in_pktinfo v4; + in6_pktinfo v6; + }; + + datagram_packet* next_packet; + + sockaddr_storage address; + pktinfo_storage address_info; + + size_t data_length; + uint8_t data[0]; + }; + static_assert(std::is_trivially_destructible::value); + static_assert(std::is_trivially_constructible::value); + + template + struct write_ring_queue { + std::array memory{}; + size_t current_index{0}; + size_t filled_index{0}; + + [[nodiscard]] constexpr inline auto max_size() const { return N; } + [[nodiscard]] inline size_t current_size() const { return this->filled_index - this->current_index; } + + [[nodiscard]] inline bool pop_entry(T& result) { + if(this->current_index >= this->filled_index) return false; + return this->memory[this->current_index++ % N]; + } + + [[nodiscard]] inline bool push_entry(T&& entry) { + if(this->filled_index - this->current_index >= N) return false; + this->memory[this->filled_index++ % N] = std::forward(entry); + return true; + } + }; + + struct io_loop; + struct io_loop_entry { + io_loop* io_loop{nullptr}; + + int file_descriptor{0}; + + event* event_read{}; + event* event_write{}; + + spin_lock write_queue_lock{}; + datagram_packet* dg_write_queue_head{nullptr}; + datagram_packet* dg_write_queue_tail{nullptr}; + + write_ring_queue, 1024 * 8> voice_write_queue{}; + }; + + struct io_loop { + std::thread base_dispatcher{}; + struct event_base* event_base{nullptr}; + + std::mutex entries_mutex{}; + std::vector registered_entries{}; + }; + + struct io_binding { + VirtualServerId server_id{0}; + sockaddr_storage address{}; + + size_t loop_entry_index{0}; + std::vector loop_entries{}; + + struct server_client { + std::shared_ptr client{}; + ClientId client_id{0}; + }; + + std::mutex client_lock{}; + std::deque known_clients{}; + }; + + class Server { + public: + + + void schedule_client_write(const std::shared_ptr& /* client */); + + void unregister_client(const std::shared_ptr& /* client */); + private: + std::mutex io_lock{}; + std::vector io_loops{}; + + std::mutex bindings_lock{}; + std::vector io_bindings{}; + }; +} \ No newline at end of file diff --git a/server/src/services/ClientChannelService.cpp b/server/src/services/ClientChannelService.cpp index aff84ae..e4d63ef 100644 --- a/server/src/services/ClientChannelService.cpp +++ b/server/src/services/ClientChannelService.cpp @@ -317,13 +317,14 @@ ClientMoveResult ClientChannelService::client_move(const std::shared_ptrnotifyClientPropertyUpdates(target, client_updates, s_source_channel ? true : false); + this->virtual_server_->broadcast_service().client_updated(target, client_updates, s_source_channel ? true : false); TIMING_STEP(timings, "notify cpro"); if(s_target_channel) { target->updateChannelClientProperties(false, s_source_channel ? true : false); TIMING_STEP(timings, "notify_t_pr"); } debugMessage(this->get_server_id(), "{} Client move timings: {}", CLIENT_STR_LOG_PREFIX_(target), TIMING_FINISH(timings)); + return ClientMoveResult ::SUCCESS; } /* @@ -361,7 +362,7 @@ ChannelDeleteResult ClientChannelService::delete_channel(std::shared_ptr> command_locks; for(const auto& client : clients) - command_locks.push_back(std::move(std::unique_lock(client->get_channel_lock()))); + command_locks.push_back(std::move(client->lock_command_handling>())); for(const auto& client : clients) { auto result = this->client_move(client, default_channel, invoker, kick_message, ViewReasonId::VREASON_CHANNEL_KICK, true, tree_lock); diff --git a/server/src/services/PermissionsService.cpp b/server/src/services/PermissionsService.cpp index 575e232..2ad549b 100644 --- a/server/src/services/PermissionsService.cpp +++ b/server/src/services/PermissionsService.cpp @@ -62,7 +62,7 @@ std::vectorclient_database_id = client_dbid; if(!cache->client_permissions) - cache->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(this->virtual_server_->server_ref(), client_dbid); + cache->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(this->get_server_id(), client_dbid); bool have_skip_permission = false; int skip_permission_type = -1; /* -1 := unset | 0 := skip, not explicit | 1 := skip, explicit */ @@ -361,7 +361,7 @@ PermissionResetResult PermissionService::reset_server_permissions() { client->notifyChannelGroupList(); } - if(this->notifyClientPropertyUpdates(client, group_manager->assignments().update_client_group_properties(client, client->getChannelId()))) { + if(this->virtual_server_->broadcast_service().client_updated(client, group_manager->assignments().update_client_group_properties(client, client->getChannelId()))) { if(client->update_cached_permissions()) /* update cached calculated permissions */ client->sendNeededPermissions(false); /* cached permissions had changed, notify the client */ } diff --git a/server/src/services/PermissionsService.h b/server/src/services/PermissionsService.h index 0b17b5a..4149cf4 100644 --- a/server/src/services/PermissionsService.h +++ b/server/src/services/PermissionsService.h @@ -51,7 +51,7 @@ namespace ts::server::permissions { ClientType type, ChannelId channel, bool granted, - std::shared_ptr cache{nullptr} + std::shared_ptr cache = nullptr ); std::vector> calculate_client_permissions( @@ -60,7 +60,7 @@ namespace ts::server::permissions { ClientType type, ChannelId channel, bool granted, - std::shared_ptr cache{nullptr} + std::shared_ptr cache = nullptr ); private: vserver::VirtualServerBase* virtual_server_{nullptr}; diff --git a/server/src/services/VirtualServerBroadcastService.cpp b/server/src/services/VirtualServerBroadcastService.cpp new file mode 100644 index 0000000..2cc9d4c --- /dev/null +++ b/server/src/services/VirtualServerBroadcastService.cpp @@ -0,0 +1,5 @@ +// +// Created by WolverinDEV on 07/03/2020. +// + +#include "VirtualServerBroadcastService.h" diff --git a/server/src/services/VirtualServerBroadcastService.h b/server/src/services/VirtualServerBroadcastService.h new file mode 100644 index 0000000..7742b10 --- /dev/null +++ b/server/src/services/VirtualServerBroadcastService.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include + +namespace ts::server { + class ConnectedClient; +} + +namespace ts::server::vserver { + class VirtualServerBase; + + class BroadcastService { + public: + explicit BroadcastService(VirtualServerBase*); + + bool client_updated(const std::shared_ptr& /* client */, + const std::deque>& /* keys */, bool /* notify_client */ = true); + + inline bool client_updated(const std::shared_ptr& client, const std::deque& keys, bool notify_client = true) { + if(keys.empty()) return false; + + std::deque> _keys{}; + for(const auto& key : keys) _keys.push_back(property::impl::info(key)); + return this->client_updated(client, _keys, notify_client); + }; + private: + VirtualServerBase* virtual_server_; + }; +} \ No newline at end of file diff --git a/server/src/services/VirtualServerInformation.cpp b/server/src/services/VirtualServerInformation.cpp index 77ebf67..ed80192 100644 --- a/server/src/services/VirtualServerInformation.cpp +++ b/server/src/services/VirtualServerInformation.cpp @@ -11,5 +11,5 @@ InformationService::InformationService(ts::server::vserver::VirtualServerBase *h InformationService::~InformationService() {} float InformationService::averagePing() { - + return -2; } \ No newline at end of file diff --git a/server/src/vserver/VirtualServerBase.cpp b/server/src/vserver/VirtualServerBase.cpp index 53bdd89..a945cd5 100644 --- a/server/src/vserver/VirtualServerBase.cpp +++ b/server/src/vserver/VirtualServerBase.cpp @@ -7,6 +7,7 @@ #include "../client/ConnectedClient.h" #include "VirtualServerBase.h" #include +#include using namespace ts::server::vserver; @@ -78,6 +79,9 @@ VirtualServerStopResult VirtualServerBase::stop_server() { VirtualServerStartResult VirtualServerBase::start_server_(ts::rwshared_lock &slock, std::string &error) { //TODO: Load server permissions, etc + + error = "Not implemented"; + return VirtualServerStartResult::CUSTOM; } VirtualServerClientRegisterResult VirtualServerBase::register_client(const std::shared_ptr &client) { @@ -201,14 +205,14 @@ void VirtualServerBase::unregister_client(const std::shared_ptr } { - if(!chan_tree_lock.owns_lock()) - chan_tree_lock.lock(); - - if(cl->currentChannel) //We dont have to make him invisible if he hasnt even a channel - this->client_move(cl, nullptr, nullptr, reason, ViewReasonId::VREASON_SERVER_LEFT, false, chan_tree_lock); + auto channel_clients_lock = this->lock_channel_clients(); + if(client->getChannel()) {//We dont have to make him invisible if he hasn't even a channel + auto result = this->channel_service().client_move(client, nullptr, nullptr, "", ViewReasonId::VREASON_SERVER_LEFT, false, channel_clients_lock);; + if(result != channels::ClientMoveResult::SUCCESS) + logCritical(this->server_id(), "Failed to unregister client {} from the server channel tree ({}).", client->getDisplayName(), (int) result); + } } - serverInstance->databaseHelper()->saveClientPermissions(this->ref(), cl->getClientDatabaseId(), cl->clientPermissions); - cl->setClientId(0); - return true; + serverInstance->databaseHelper()->saveClientPermissions(this->server_id(), client->getClientDatabaseId(), client->permissions()); + client->setClientId(0); } \ No newline at end of file diff --git a/server/src/vserver/VirtualServerBase.h b/server/src/vserver/VirtualServerBase.h index 19b3847..71097b9 100644 --- a/server/src/vserver/VirtualServerBase.h +++ b/server/src/vserver/VirtualServerBase.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "../services/PermissionsService.h" #include "../services/ClientChannelService.h" @@ -93,7 +94,8 @@ do { \ [[nodiscard]] inline const std::shared_ptr& server_connection_statistics() { return this->server_connection_statistics_; } [[nodiscard]] inline permissions::PermissionService& permission_service() { return this->permission_service_; } - + [[nodiscard]] inline BroadcastService& broadcast_service() { return this->broadcast_service_; } + [[nodiscard]] inline channels::ClientChannelService& channel_service() { return this->channel_service_; } [[nodiscard]] inline ts::rwshared_lock lock_channel_clients() { return ts::rwshared_lock{this->channel_clients_lock_, ts::rw_lock_shared}; } [[nodiscard]] inline std::mutex& client_nickname_lock() { return this->client_nickname_lock_; } @@ -135,6 +137,7 @@ do { \ /* some services */ permissions::PermissionService permission_service_; channels::ClientChannelService channel_service_; + BroadcastService broadcast_service_; struct { size_t count{0}; diff --git a/shared b/shared index 0d0d7dd..9533fe8 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 0d0d7dd1924ee93bcbe4875c3cf007117d05e4d7 +Subproject commit 9533fe8920ea82313dcd49a4e003f39e50c7d81e