diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9043bff..ce31097 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -82,6 +82,7 @@ set(SERVER_SOURCE_FILES src/client/query/QueryClientCommands.cpp src/client/query/QueryClientNotify.cpp + src/file/FileServer.cpp src/manager/IpListManager.cpp diff --git a/server/src/client/ConnectedClient.cpp b/server/src/client/ConnectedClient.cpp index 94062d6..9f3413b 100644 --- a/server/src/client/ConnectedClient.cpp +++ b/server/src/client/ConnectedClient.cpp @@ -182,14 +182,17 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool client_channel_lock.lock(); } - deque deleted; - for(const auto& update_entry : this->channels->update_channel_path(server_ref->channelTree->tree_head(), server_ref->channelTree->find_linked_entry(this->currentChannel->channelId()))) { - if(update_entry.first) - this->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel); - else deleted.push_back(update_entry.second->channelId()); + /* might have been changed since we locked the tree */ + if(this->currentChannel) { + deque deleted; + for(const auto& update_entry : this->channels->update_channel_path(server_ref->channelTree->tree_head(), server_ref->channelTree->find_linked_entry(this->currentChannel->channelId()))) { + if(update_entry.first) + this->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel); + else deleted.push_back(update_entry.second->channelId()); + } + if(!deleted.empty()) + this->notifyChannelHide(deleted, false); /* we've locked the tree before */ } - if(!deleted.empty()) - this->notifyChannelHide(deleted, false); /* we've locked the tree before */ } } diff --git a/server/src/client/command_handler/client.cpp b/server/src/client/command_handler/client.cpp index 38d688e..091f4cb 100644 --- a/server/src/client/command_handler/client.cpp +++ b/server/src/client/command_handler/client.cpp @@ -203,14 +203,14 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) { } } clients.emplace_back(std::move(target_client)); - result.emplace_result(permission::ok); + result.emplace_result(error::ok); } if (!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as() || !channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as()) { if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_ignore_maxclients, channel->channelId()))) { if(!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as()) { auto maxClients = channel->properties()[property::CHANNEL_MAXCLIENTS].as(); - if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size() + clients.size()) + if (maxClients >= 0 && maxClients < this->server->getClientsByChannel(channel).size() + clients.size()) return command_result{error::channel_maxclients_reached}; } if(!channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as()) { @@ -227,7 +227,7 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) { for(const auto& entry : this->server->getClientsByChannelRoot(channel, false)) if(entry.get() != this) client_count++; //Dont count the client itself - if (maxClients >= 0 && maxClients <= client_count + clients.size()) + if (maxClients >= 0 && maxClients < client_count + clients.size()) return command_result{error::channel_maxfamily_reached}; } } diff --git a/server/src/client/command_handler/server.cpp b/server/src/client/command_handler/server.cpp index 5860b8b..f673e83 100644 --- a/server/src/client/command_handler/server.cpp +++ b/server/src/client/command_handler/server.cpp @@ -754,6 +754,9 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd) for(const auto& _server : target_server ? std::deque>{target_server} : serverInstance->getVoiceServerManager()->serverInstances()) { for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) { + ConnectedLockedClient clock{targetClient}; + if(!clock) continue; + if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true, targetClient->getChannel()))) { for (const auto &client : _server->getClients()) { if(client->isClientVisible(targetClient, true) || client == targetClient) diff --git a/server/src/file/FileServer.cpp b/server/src/file/FileServer.cpp new file mode 100644 index 0000000..446f074 --- /dev/null +++ b/server/src/file/FileServer.cpp @@ -0,0 +1,5 @@ +// +// Created by WolverinDEV on 28/04/2020. +// + +#include "FileServer.h" diff --git a/server/src/file/FileServer.h b/server/src/file/FileServer.h new file mode 100644 index 0000000..cfc9f03 --- /dev/null +++ b/server/src/file/FileServer.h @@ -0,0 +1,124 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ts::server::file { + enum struct ExecuteStatus { + UNKNOWN, + WAITING, + SUCCESS, + ERROR + }; + + template + class ExecuteResponse { + public: + ExecuteStatus status{ExecuteStatus::UNKNOWN}; + + [[nodiscard]] inline const response_t& response() const { return std::get(this->response_); } + [[nodiscard]] inline const response_t& error() const { return std::get(this->response_); } + + inline void wait() const { + std::unique_lock nlock{this->notify_mutex}; + this->notify_cv.wait(nlock, [&]{ return this->status != ExecuteStatus::WAITING; }); + } + + template + [[nodiscard]] inline bool wait_for(const std::chrono::duration<_Rep, _Period>& time) const { + std::unique_lock nlock{this->notify_mutex}; + return this->notify_cv.wait_for(nlock, time, [&]{ return this->status != ExecuteStatus::WAITING; }); + } + private: + std::variant response_{}; + + std::mutex& notify_mutex; + std::condition_variable& notify_cv; + }; + + namespace filesystem { + struct DirectoryQueryError { + enum Type { + UNKNOWN, + }; + Type type{}; + std::string extra_message{}; + }; + + struct DirectoryEntry { + enum Type { + UNKNOWN, + DIRECTORY, + FILE + }; + + Type type{Type::UNKNOWN}; + std::string name{}; + std::chrono::system_clock::time_point created_at{}; + std::chrono::system_clock::time_point modified_at{}; + + size_t size{0}; + }; + + struct DirectoryModifyError { + enum Type { + UNKNOWN, + }; + Type type{}; + std::string extra_message{}; + }; + + struct FileModifyError { + enum Type { + UNKNOWN, + }; + Type type{}; + std::string extra_message{}; + }; + + class AbstractProvider { + public: + typedef ExecuteResponse> directory_query_response_t; + + /* channels */ + [[nodiscard]] virtual std::shared_ptr query_channel_directory(ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + [[nodiscard]] virtual std::shared_ptr> create_channel_directory(ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + [[nodiscard]] virtual std::shared_ptr> delete_channel_directory(ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + + [[nodiscard]] virtual std::shared_ptr> delete_channel_file(ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + [[nodiscard]] virtual std::shared_ptr> rename_channel_file(ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + + /* icons */ + [[nodiscard]] virtual std::shared_ptr query_icon_directory(ServerId /* server */); + [[nodiscard]] virtual std::shared_ptr> delete_icon(ServerId /* server */, const std::string& /* name */); + + /* avatars */ + [[nodiscard]] virtual std::shared_ptr query_avatar_directory(ServerId /* server */); + [[nodiscard]] virtual std::shared_ptr> delete_avatar(ServerId /* server */, const std::string& /* name */); + private: + }; + } + + namespace transfer { + class AbstractProvider { + public: + enum TransferDirection { + UPLOAD, + DOWNLOAD + }; + void initialize_channel_transfer(TransferDirection /* direction */, ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + void initialize_icon_transfer(TransferDirection /* direction */, ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + void initialize_avatar_transfer(TransferDirection /* direction */, ServerId /* server */, ChannelId /* channel */, const std::string& /* path */); + private: + }; + } + + class AbstractFileServer { + public: + private: + }; +} \ No newline at end of file