diff --git a/server/src/VirtualServer.cpp b/server/src/VirtualServer.cpp index 41d8175..5b4c832 100644 --- a/server/src/VirtualServer.cpp +++ b/server/src/VirtualServer.cpp @@ -15,6 +15,7 @@ #include "./client/voice/VoiceClient.h" #include "./client/InternalClient.h" #include "./client/music/MusicClient.h" +#include "./client/query/QueryClient.h" #include "music/MusicBotManager.h" #include "server/VoiceServer.h" #include "server/file/FileServer.h" @@ -318,12 +319,12 @@ bool VirtualServer::start(std::string& error) { if(host.empty()){ error = "invalid host (\"" + host + "\")"; - this->stop("failed to start"); + this->stop("failed to start", true); return false; } if(this->properties()[property::VIRTUALSERVER_PORT].as() <= 0){ error = "invalid port"; - this->stop("failed to start"); + this->stop("failed to start", true); return false; } @@ -360,7 +361,7 @@ bool VirtualServer::start(std::string& error) { } if(bindings.empty()) { error = "failed to resole any host!"; - this->stop("failed to start"); + this->stop("failed to start", false); return false; } @@ -368,7 +369,7 @@ bool VirtualServer::start(std::string& error) { udpVoiceServer = make_shared(self.lock()); if(!udpVoiceServer->start(bindings, error)) { error = "could not start voice server. Message: " + error; - this->stop("failed to start"); + this->stop("failed to start", false); return false; } @@ -405,7 +406,7 @@ bool VirtualServer::start(std::string& error) { logMessage(this->serverId, "[Web] Starting server on {}:{}", web_host_string, web_port); if(!webControlServer->start(bindings, error)) { error = "could not start web server. Message: " + error; - this->stop("failed to start"); + this->stop("failed to start", false); return false; } #endif @@ -466,7 +467,7 @@ void VirtualServer::preStop(const std::string& reason) { } } -void VirtualServer::stop(const std::string& reason) { +void VirtualServer::stop(const std::string& reason, bool disconnect_query) { auto self_lock = this->self.lock(); assert(self_lock); { @@ -475,7 +476,7 @@ void VirtualServer::stop(const std::string& reason) { this->state = ServerState::SUSPENDING; } - this->preStop(reason); + this->preStop(reason); for(const auto& cl : this->getClients()) { //start disconnecting if(cl->getType() == CLIENT_TEAMSPEAK || cl->getType() == CLIENT_TEASPEAK || cl->getType() == CLIENT_WEB) { @@ -484,9 +485,10 @@ void VirtualServer::stop(const std::string& reason) { threads::MutexLock lock(cl->command_lock); cl->currentChannel = nullptr; - continue; //We dont need to disconnect the query - cl->server = nullptr; - cl->loadDataForCurrentServer(); + if(disconnect_query) { + auto qc = dynamic_pointer_cast(cl); + qc->disconnect_from_virtual_server(); + } } else if(cl->getType() == CLIENT_MUSIC) { cl->disconnect(""); cl->currentChannel = nullptr; diff --git a/server/src/VirtualServer.h b/server/src/VirtualServer.h index 17dc13c..6ff1131 100644 --- a/server/src/VirtualServer.h +++ b/server/src/VirtualServer.h @@ -144,7 +144,7 @@ namespace ts { bool start(std::string& error); bool running(); void preStop(const std::string&); - void stop(const std::string& reason = ts::config::messages::serverStopped); + void stop(const std::string& reason, bool /* disconnect query */); size_t onlineClients(); OnlineClientReport onlineStats(); diff --git a/server/src/VirtualServerManager.cpp b/server/src/VirtualServerManager.cpp index 955be71..11bed8a 100644 --- a/server/src/VirtualServerManager.cpp +++ b/server/src/VirtualServerManager.cpp @@ -2,6 +2,7 @@ #include #include "VirtualServerManager.h" #include "src/server/VoiceServer.h" +#include "src/client/query/QueryClient.h" #include "InstanceHandler.h" #include "src/server/file/FileServer.h" #include "src/client/ConnectedClient.h" @@ -361,7 +362,21 @@ bool VirtualServerManager::deleteServer(shared_ptr server) { this->adjust_executor_threads(); if(server->getState() != ServerState::OFFLINE) - server->stop("server deleted"); + server->stop("server deleted", true); + for(const auto& cl : server->getClients()) { //start disconnecting + if(cl->getType() == CLIENT_TEAMSPEAK || cl->getType() == CLIENT_TEASPEAK || cl->getType() == CLIENT_WEB) { + cl->close_connection(chrono::system_clock::now()); + } else if(cl->getType() == CLIENT_QUERY){ + auto qc = dynamic_pointer_cast(cl); + qc->disconnect_from_virtual_server(); + } else if(cl->getType() == CLIENT_MUSIC) { + cl->disconnect(""); + cl->currentChannel = nullptr; + } else if(cl->getType() == CLIENT_INTERNAL) { + + } else { + } + } { for(const shared_ptr& client : server->getClients()) { if(client && client->getType() == ClientType::CLIENT_QUERY) { @@ -419,7 +434,7 @@ void VirtualServerManager::shutdownAll(const std::string& msg) { for(const auto &server : this->serverInstances()) server->preStop(msg); for(const auto &server : this->serverInstances()){ - if(server->running()) server->stop(msg); + if(server->running()) server->stop(msg, true); } this->execute_loop->shutdown(); diff --git a/server/src/client/command_handler/music.cpp b/server/src/client/command_handler/music.cpp index 7742b58..b7739a7 100644 --- a/server/src/client/command_handler/music.cpp +++ b/server/src/client/command_handler/music.cpp @@ -956,8 +956,29 @@ command_result ConnectedClient::handleCommandMusicBotQueueList(Command& cmd) { if(!bulked) notify = Command(this->notify_response_command("notifymusicqueueentry")); - //TODO! - //apply_song(notify, *it, command_index); + auto song = *it; + notify[command_index]["song_id"] = song->id; + notify[command_index]["song_url"] = song->url; + notify[command_index]["song_invoker"] = song->invoker; + notify[command_index]["song_loaded"] = song->loaded; + + auto entry = song->load_future ? song->load_future->getValue({}) : nullptr; + if(entry) { + notify[command_index]["song_loaded"] = true; + if(entry->type != ::music::TYPE_STREAM && entry->type != ::music::TYPE_VIDEO) + continue; + + auto info = reinterpret_pointer_cast<::music::UrlSongInfo>(entry); + if(info) { + notify[command_index]["song_title"] = info->title; + notify[command_index]["song_description"] = info->description; + if(auto thumbnail = reinterpret_pointer_cast<::music::ThumbnailUrl>(info->thumbnail); thumbnail && thumbnail->type() == ::music::THUMBNAIL_URL) + notify[command_index]["song_thumbnail"] = thumbnail->url(); + else + notify[command_index]["song_thumbnail"] = ""; + notify[command_index]["song_length"] = info->length.count(); + } + } notify[command_index]["queue_index"] = begin_index++; if(!bulked) @@ -966,7 +987,6 @@ command_result ConnectedClient::handleCommandMusicBotQueueList(Command& cmd) { command_index++; } - debugMessage(this->getServerId(),"Send: {}",notify.build()); if(bulked) { if(command_index > 0) { this->sendCommand(notify); diff --git a/server/src/client/query/QueryClient.cpp b/server/src/client/query/QueryClient.cpp index c5a7808..e794abe 100644 --- a/server/src/client/query/QueryClient.cpp +++ b/server/src/client/query/QueryClient.cpp @@ -562,3 +562,24 @@ bool QueryClient::notifyChannelUnsubscribed(const deque bool QueryClient::ignoresFlood() { return this->whitelisted || ConnectedClient::ignoresFlood(); } + +void QueryClient::disconnect_from_virtual_server() { + threads::MutexLock lock(this->command_lock); + + auto server_locked = this->server; + if(server_locked) { + //unregister manager from old server + { + unique_lock tree_lock(this->server->channel_tree_lock); + if(this->currentChannel) + this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); + this->server->unregisterClient(_this.lock(), "server switch", tree_lock); + } + server_locked->groups->disableCache(this->getClientDatabaseId()); + this->channels->reset(); + this->currentChannel = nullptr; + this->server = nullptr; + this->loadDataForCurrentServer(); + } + serverInstance->getGroupManager()->enableCache(this->getClientDatabaseId()); +} \ No newline at end of file diff --git a/server/src/client/query/QueryClient.h b/server/src/client/query/QueryClient.h index 68c4195..6d84a55 100644 --- a/server/src/client/query/QueryClient.h +++ b/server/src/client/query/QueryClient.h @@ -6,178 +6,178 @@ #include #include "misc/queue.h" -namespace ts { - namespace server { - class QueryServer; +namespace ts::server { + class QueryServer; + class QueryAccount; - class QueryClient : public ConnectedClient { - friend class QueryServer; + class QueryClient : public ConnectedClient { + friend class QueryServer; - enum ConnectionType { - PLAIN, - SSL_ENCRIPTED, - UNKNOWN - }; - public: - QueryClient(QueryServer*, int sockfd); - ~QueryClient() override; + enum ConnectionType { + PLAIN, + SSL_ENCRIPTED, + UNKNOWN + }; + public: + QueryClient(QueryServer*, int sockfd); + ~QueryClient() override; - void writeMessage(const std::string&); + void writeMessage(const std::string&); - void sendCommand(const ts::Command &command, bool low = false) override; - void sendCommand(const ts::command_builder &command, bool low) override; + void sendCommand(const ts::Command &command, bool low = false) override; + void sendCommand(const ts::command_builder &command, bool low) override; - bool disconnect(const std::string &reason) override; - bool close_connection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override; - void disconnectFinal(); + bool disconnect(const std::string &reason) override; + bool close_connection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override; + void disconnectFinal(); - bool eventActive(QueryEventGroup, QueryEventSpecifier); - void toggleEvent(QueryEventGroup, QueryEventSpecifier, bool); - void resetEventMask(); + bool eventActive(QueryEventGroup, QueryEventSpecifier); + void toggleEvent(QueryEventGroup, QueryEventSpecifier, bool); + void resetEventMask(); - bool ignoresFlood() override; + bool ignoresFlood() override; + void disconnect_from_virtual_server(); - inline std::shared_ptr getQueryAccount() { return this->query_account; } - protected: - void preInitialize(); - void postInitialize(); - void tick(const std::chrono::system_clock::time_point &time) override; - void queryTick(); + inline std::shared_ptr getQueryAccount() { return this->query_account; } + protected: + void preInitialize(); + void postInitialize(); + void tick(const std::chrono::system_clock::time_point &time) override; + void queryTick(); - protected: - void initializeSSL(); + protected: + void initializeSSL(); - bool handleMessage(const pipes::buffer_view&); - bool tickIOMessageProgress(); + bool handleMessage(const pipes::buffer_view&); + bool tickIOMessageProgress(); - void handleMessageRead(int, short, void*); - void handleMessageWrite(int, short, void*); - void writeRawMessage(const std::string&); + void handleMessageRead(int, short, void*); + void handleMessageWrite(int, short, void*); + void writeRawMessage(const std::string&); - void applySelfLock(const std::shared_ptr &cl); - private: - QueryServer* handle; + void applySelfLock(const std::shared_ptr &cl); + private: + QueryServer* handle; - ConnectionType connectionType = ConnectionType::UNKNOWN; + ConnectionType connectionType = ConnectionType::UNKNOWN; - bool whitelisted = false; - int clientFd = -1; + bool whitelisted = false; + int clientFd = -1; - ::event* readEvent = nullptr; - ::event* writeEvent = nullptr; - threads::Mutex closeLock; + ::event* readEvent = nullptr; + ::event* writeEvent = nullptr; + threads::Mutex closeLock; - pipes::SSL ssl_handler; + pipes::SSL ssl_handler; - std::mutex buffer_lock; - std::deque writeQueue; - std::deque readQueue; + std::mutex buffer_lock; + std::deque writeQueue; + std::deque readQueue; - threads::Mutex flushThreadLock; - threads::Thread* flushThread = nullptr; - bool final_disconnected = false; + threads::Mutex flushThreadLock; + threads::Thread* flushThread = nullptr; + bool final_disconnected = false; - std::string lineBuffer; - std::chrono::time_point connectedTimestamp; - uint16_t eventMask[QueryEventGroup::QEVENTGROUP_MAX]; + std::string lineBuffer; + std::chrono::time_point connectedTimestamp; + uint16_t eventMask[QueryEventGroup::QEVENTGROUP_MAX]; - std::recursive_mutex lock_packet_handle; - std::recursive_mutex lock_query_tick; + std::recursive_mutex lock_packet_handle; + std::recursive_mutex lock_query_tick; - std::shared_ptr query_account; - protected: - command_result handleCommand(Command &command) override; + std::shared_ptr query_account; + protected: + command_result handleCommand(Command &command) override; - public: - //Silent events - bool notifyClientNeededPermissions() override; - bool notifyChannelSubscribed(const std::deque> &deque) override; - bool notifyChannelUnsubscribed(const std::deque> &deque) override; + public: + //Silent events + bool notifyClientNeededPermissions() override; + bool notifyChannelSubscribed(const std::deque> &deque) override; + bool notifyChannelUnsubscribed(const std::deque> &deque) override; - bool notifyServerUpdated(std::shared_ptr ptr) override; - bool notifyClientPoke(std::shared_ptr invoker, std::string msg) override; + bool notifyServerUpdated(std::shared_ptr ptr) override; + bool notifyClientPoke(std::shared_ptr invoker, std::string msg) override; - bool notifyClientUpdated(const std::shared_ptr &ptr, const std::deque> &deque, bool lock_channel_tree) override; + bool notifyClientUpdated(const std::shared_ptr &ptr, const std::deque> &deque, bool lock_channel_tree) override; - bool notifyPluginCmd(std::string name, std::string msg,std::shared_ptr) override; - bool notifyClientChatComposing(const std::shared_ptr &ptr) override; - bool notifyClientChatClosed(const std::shared_ptr &ptr) override; - bool notifyTextMessage(ChatMessageMode mode, const std::shared_ptr &sender, uint64_t targetId, ChannelId channel_id, const std::chrono::system_clock::time_point&, const std::string &textMessage) override; - bool notifyServerGroupClientAdd(const std::shared_ptr &invoker, const std::shared_ptr &client, const std::shared_ptr &group) override; - bool notifyServerGroupClientRemove(std::shared_ptr invoker, std::shared_ptr client, std::shared_ptr group) override; + bool notifyPluginCmd(std::string name, std::string msg,std::shared_ptr) override; + bool notifyClientChatComposing(const std::shared_ptr &ptr) override; + bool notifyClientChatClosed(const std::shared_ptr &ptr) override; + bool notifyTextMessage(ChatMessageMode mode, const std::shared_ptr &sender, uint64_t targetId, ChannelId channel_id, const std::chrono::system_clock::time_point&, const std::string &textMessage) override; + bool notifyServerGroupClientAdd(const std::shared_ptr &invoker, const std::shared_ptr &client, const std::shared_ptr &group) override; + bool notifyServerGroupClientRemove(std::shared_ptr invoker, std::shared_ptr client, std::shared_ptr group) override; - bool notifyClientChannelGroupChanged(const std::shared_ptr &invoker, const std::shared_ptr &client, const std::shared_ptr &ptr, const std::shared_ptr &shared_ptr, - const std::shared_ptr &group, bool lock_channel_tree) override; + bool notifyClientChannelGroupChanged(const std::shared_ptr &invoker, const std::shared_ptr &client, const std::shared_ptr &ptr, const std::shared_ptr &shared_ptr, + const std::shared_ptr &group, bool lock_channel_tree) override; - bool notifyChannelMoved(const std::shared_ptr &channel, ChannelId order, const std::shared_ptr &invoker) override; - bool notifyChannelCreate(const std::shared_ptr &channel, ChannelId orderId, - const std::shared_ptr &invoker) override; - bool notifyChannelDescriptionChanged(std::shared_ptr channel) override; - bool notifyChannelPasswordChanged(std::shared_ptr ) override; + bool notifyChannelMoved(const std::shared_ptr &channel, ChannelId order, const std::shared_ptr &invoker) override; + bool notifyChannelCreate(const std::shared_ptr &channel, ChannelId orderId, + const std::shared_ptr &invoker) override; + bool notifyChannelDescriptionChanged(std::shared_ptr channel) override; + bool notifyChannelPasswordChanged(std::shared_ptr ) override; - bool notifyChannelEdited(const std::shared_ptr &ptr, const std::vector &vector, const std::shared_ptr &sharedPtr, bool b) override; + bool notifyChannelEdited(const std::shared_ptr &ptr, const std::vector &vector, const std::shared_ptr &sharedPtr, bool b) override; - bool notifyChannelDeleted(const std::deque &deque, const std::shared_ptr &ptr) override; + bool notifyChannelDeleted(const std::deque &deque, const std::shared_ptr &ptr) override; - bool notifyMusicQueueAdd(const std::shared_ptr &bot, const std::shared_ptr &entry, int index, const std::shared_ptr &invoker) override; - bool notifyMusicQueueRemove(const std::shared_ptr &bot, const std::deque> &entry, const std::shared_ptr &invoker) override; - bool notifyMusicQueueOrderChange(const std::shared_ptr &bot, const std::shared_ptr &entry, int order, const std::shared_ptr &invoker) override; + bool notifyMusicQueueAdd(const std::shared_ptr &bot, const std::shared_ptr &entry, int index, const std::shared_ptr &invoker) override; + bool notifyMusicQueueRemove(const std::shared_ptr &bot, const std::deque> &entry, const std::shared_ptr &invoker) override; + bool notifyMusicQueueOrderChange(const std::shared_ptr &bot, const std::shared_ptr &entry, int order, const std::shared_ptr &invoker) override; - bool notifyMusicPlayerSongChange(const std::shared_ptr &bot, const std::shared_ptr &newEntry) override; + bool notifyMusicPlayerSongChange(const std::shared_ptr &bot, const std::shared_ptr &newEntry) override; - bool notifyClientEnterView(const std::shared_ptr &client, const std::shared_ptr &invoker, const std::string &string, const std::shared_ptr &to, ViewReasonId reasonId, - const std::shared_ptr &from, bool) override; + bool notifyClientEnterView(const std::shared_ptr &client, const std::shared_ptr &invoker, const std::string &string, const std::shared_ptr &to, ViewReasonId reasonId, + const std::shared_ptr &from, bool) override; - bool notifyClientEnterView(const std::deque> &deque, const ViewReasonSystemT &t) override; + bool notifyClientEnterView(const std::deque> &deque, const ViewReasonSystemT &t) override; - bool notifyClientMoved(const std::shared_ptr &client, const std::shared_ptr &target_channel, ViewReasonId reason, std::string msg, std::shared_ptr invoker, bool lock_channel_tree) override; + bool notifyClientMoved(const std::shared_ptr &client, const std::shared_ptr &target_channel, ViewReasonId reason, std::string msg, std::shared_ptr invoker, bool lock_channel_tree) override; - bool notifyClientLeftView(const std::shared_ptr &client, const std::shared_ptr &target_channel, ViewReasonId reasonId, const std::string &reasonMessage, std::shared_ptr invoker, - bool lock_channel_tree) override; + bool notifyClientLeftView(const std::shared_ptr &client, const std::shared_ptr &target_channel, ViewReasonId reasonId, const std::string &reasonMessage, std::shared_ptr invoker, + bool lock_channel_tree) override; - bool notifyClientLeftView(const std::deque> &deque, const std::string &string, bool b, const ViewReasonServerLeftT &t) override; + bool notifyClientLeftView(const std::deque> &deque, const std::string &string, bool b, const ViewReasonServerLeftT &t) override; - bool notifyClientLeftViewKicked(const std::shared_ptr &client, const std::shared_ptr &target_channel, const std::string &message, std::shared_ptr invoker, bool lock_channel_tree) override; + bool notifyClientLeftViewKicked(const std::shared_ptr &client, const std::shared_ptr &target_channel, const std::string &message, std::shared_ptr invoker, bool lock_channel_tree) override; - bool notifyClientLeftViewBanned(const std::shared_ptr &client, const std::string &message, std::shared_ptr invoker, size_t length, bool lock_channel_tree) override; + bool notifyClientLeftViewBanned(const std::shared_ptr &client, const std::string &message, std::shared_ptr invoker, size_t length, bool lock_channel_tree) override; - private: - command_result handleCommandExit(Command&); - command_result handleCommandLogin(Command&); - command_result handleCommandLogout(Command&); - command_result handleCommandServerSelect(Command &); - command_result handleCommandServerInfo(Command&); - command_result handleCommandChannelList(Command&); - command_result handleCommandJoin(Command&); - command_result handleCommandLeft(Command&); + private: + command_result handleCommandExit(Command&); + command_result handleCommandLogin(Command&); + command_result handleCommandLogout(Command&); + command_result handleCommandServerSelect(Command &); + command_result handleCommandServerInfo(Command&); + command_result handleCommandChannelList(Command&); + command_result handleCommandJoin(Command&); + command_result handleCommandLeft(Command&); - command_result handleCommandServerList(Command&); - command_result handleCommandServerCreate(Command&); - command_result handleCommandServerDelete(Command&); - command_result handleCommandServerStart(Command&); - command_result handleCommandServerStop(Command&); + command_result handleCommandServerList(Command&); + command_result handleCommandServerCreate(Command&); + command_result handleCommandServerDelete(Command&); + command_result handleCommandServerStart(Command&); + command_result handleCommandServerStop(Command&); - command_result handleCommandInstanceInfo(Command&); - command_result handleCommandInstanceEdit(Command&); + command_result handleCommandInstanceInfo(Command&); + command_result handleCommandInstanceEdit(Command&); - command_result handleCommandBindingList(Command&); + command_result handleCommandBindingList(Command&); - command_result handleCommandHostInfo(Command&); + command_result handleCommandHostInfo(Command&); - command_result handleCommandGlobalMessage(Command&); + command_result handleCommandGlobalMessage(Command&); - command_result handleCommandServerIdGetByPort(Command&); + command_result handleCommandServerIdGetByPort(Command&); - command_result handleCommandServerSnapshotDeploy(Command&); - command_result handleCommandServerSnapshotCreate(Command&); - command_result handleCommandServerProcessStop(Command&); + command_result handleCommandServerSnapshotDeploy(Command&); + command_result handleCommandServerSnapshotCreate(Command&); + command_result handleCommandServerProcessStop(Command&); - command_result handleCommandServerNotifyRegister(Command&); - command_result handleCommandServerNotifyList(Command&); - command_result handleCommandServerNotifyUnregister(Command&); + command_result handleCommandServerNotifyRegister(Command&); + command_result handleCommandServerNotifyList(Command&); + command_result handleCommandServerNotifyUnregister(Command&); - command_result handleCommandSetCompressionMode(Command&); - }; - } + command_result handleCommandSetCompressionMode(Command&); + }; } \ No newline at end of file diff --git a/server/src/client/query/QueryClientCommands.cpp b/server/src/client/query/QueryClientCommands.cpp index f184190..b83899c 100644 --- a/server/src/client/query/QueryClientCommands.cpp +++ b/server/src/client/query/QueryClientCommands.cpp @@ -316,21 +316,7 @@ command_result QueryClient::handleCommandServerSelect(Command &cmd) { } } - { - auto server_locked = this->server; - if(server_locked) { - //unregister manager from old server - { - unique_lock tree_lock(this->server->channel_tree_lock); - if(this->currentChannel) - this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); - this->server->unregisterClient(_this.lock(), "server switch", tree_lock); - } - server_locked->groups->disableCache(this->getClientDatabaseId()); - this->channels->reset(); - } else - serverInstance->getGroupManager()->disableCache(this->getClientDatabaseId()); - } + this->disconnect_from_virtual_server(); this->resetEventMask(); //register at current server @@ -713,7 +699,7 @@ command_result QueryClient::handleCommandServerStop(Command& cmd) { if(!permission::v2::permission_granted(1, server->calculate_permission(permission::b_virtualserver_stop, this->getClientDatabaseId(), ClientType::CLIENT_QUERY, 0))) ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_stop_any, 1); - server->stop("server stopped"); + server->stop("server stopped", false); return command_result{error::ok}; }