#pragma once #include #include #include "client/voice/PrecomputedPuzzles.h" #include "server/VoiceIOManager.h" #include "VirtualServer.h" #include #include "snapshots/snapshot.h" namespace ts::server { class InstanceHandler; struct ServerReport { size_t avariable; size_t online; size_t slots; size_t onlineClients; size_t onlineChannels; }; class VirtualServerManager { public: enum State { STOPPED, STARTING, STARTED, STOPPING }; explicit VirtualServerManager(InstanceHandler*); ~VirtualServerManager(); bool initialize(bool execute_autostart = true); std::shared_ptr create_server(std::string hosts, uint16_t port); bool deleteServer(std::shared_ptr); std::shared_ptr findServerById(ServerId); std::shared_ptr findServerByPort(uint16_t); uint16_t next_available_port(const std::string& /* host string */); ServerId next_available_server_id(bool& /* success */); std::deque> serverInstances(){ threads::MutexLock l(this->instanceLock); return instances; } ServerReport report(); OnlineClientReport clientReport(); size_t runningServers(); size_t usedSlots(); void executeAutostart(); void shutdownAll(const std::string&); //Dotn use shared_ptr references to keep sure that they be hold in memory 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 &); bool deploy_snapshot(std::string& /* error */, ServerId /* target server id */, const command_parser& /* source */); udp::PuzzleManager* rsaPuzzles() { return this->puzzles; } event::EventExecutor* get_join_loop() { return this->join_loop; } event::EventExecutor* get_executor_loop() { return this->execute_loop; } inline void adjust_executor_threads() { std::unique_lock instance_lock(this->instanceLock); auto instance_count = this->instances.size(); instance_lock.unlock(); auto threads = std::min(config::threads::voice::execute_per_server * instance_count, config::threads::voice::execute_limit); this->execute_loop->threads(threads); } io::VoiceIOManager* ioManager(){ return this->_ioManager; } threads::Mutex server_create_lock; State getState() { return this->state; } private: State state = State::STOPPED; InstanceHandler* handle; threads::Mutex instanceLock; std::deque> instances; udp::PuzzleManager* puzzles{nullptr}; event::EventExecutor* execute_loop = nullptr; event::EventExecutor* join_loop = nullptr; threads::Scheduler* handshakeTickers = nullptr; io::VoiceIOManager* _ioManager = nullptr; struct { std::thread executor{}; std::condition_variable condition; std::mutex lock; } acknowledge; void tickHandshakeClients(); void delete_server_in_db(ServerId /* server id */); /* methods used to preprocess a snapshot */ bool deploy_ts3_snapshot(std::string& /* error */, ServerId /* target server id */, const command_parser& /* source */); bool deploy_teaspeak_snapshot(std::string& /* error */, ServerId /* target server id */, const command_parser& /* source */); /* actual deploy method */ bool deploy_raw_snapshot(std::string& /* error */, ServerId /* target server id */, const command_parser& /* source */, const std::string& /* hash */, size_t /* offset */, snapshots::type /* type */, snapshots::version_t /* version */); }; }