From 2b1b1dc1e3ce2dedabb8d2ea4f67024c1c9b3b11 Mon Sep 17 00:00:00 2001 From: phosit Date: Thu, 16 Apr 2026 18:16:41 +0200 Subject: [PATCH] Store the server-worker inside the server This becomes possible by reordering the class definition. --- source/network/NetServer.cpp | 35 ++++----- source/network/NetServer.h | 144 +++++++++++++++++------------------ 2 files changed, 86 insertions(+), 93 deletions(-) diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp index 58773d0621..7f88cc7bce 100644 --- a/source/network/NetServer.cpp +++ b/source/network/NetServer.cpp @@ -1670,8 +1670,8 @@ void CNetServerWorker::SendHolePunchingMessage(const CStr& ipStr, u16 port) CNetServer::CNetServer(const bool continueSavedGame, std::uint16_t port, const bool useLobbyAuth, std::string password, std::string controllerSecret, std::string initAttributes) : - m_Worker{new CNetServerWorker{continueSavedGame, port, useLobbyAuth, password, - std::move(controllerSecret), std::move(initAttributes)}}, + m_Worker{continueSavedGame, port, useLobbyAuth, password, std::move(controllerSecret), + std::move(initAttributes)}, m_LobbyAuth{useLobbyAuth}, m_Password{std::move(password)} { @@ -1680,16 +1680,11 @@ CNetServer::CNetServer(const bool continueSavedGame, std::uint16_t port, const b // In lobby, we send our public ip and port on request to the players who want to connect. // Thus we need to know our public IP and use STUN to get it. - std::lock_guard lock(m_Worker->m_WorkerMutex); - if (!m_Worker->m_Host || !StunClient::FindPublicIP(*m_Worker->m_Host, m_PublicIp, m_PublicPort)) + std::lock_guard lock(m_Worker.m_WorkerMutex); + if (!m_Worker.m_Host || !StunClient::FindPublicIP(*m_Worker.m_Host, m_PublicIp, m_PublicPort)) throw std::runtime_error{"Failed to resolve public IP-address."}; } -CNetServer::~CNetServer() -{ - delete m_Worker; -} - bool CNetServer::UseLobbyAuth() const { return m_LobbyAuth; @@ -1707,16 +1702,16 @@ u16 CNetServer::GetPublicPort() const u16 CNetServer::GetLocalPort() const { - std::lock_guard lock(m_Worker->m_WorkerMutex); - if (!m_Worker->m_Host) + std::lock_guard lock(m_Worker.m_WorkerMutex); + if (!m_Worker.m_Host) return 0; - return m_Worker->m_Host->address.port; + return m_Worker.m_Host->address.port; } bool CNetServer::CheckPasswordAndIncrement(const std::string& username, const std::string& password, const std::string& salt) { std::unordered_map::iterator it = m_FailedAttempts.find(username); - if (m_Worker->CheckPassword(password, salt)) + if (m_Worker.CheckPassword(password, salt)) { if (it != m_FailedAttempts.end()) it->second = 0; @@ -1737,23 +1732,23 @@ bool CNetServer::IsBanned(const std::string& username) const void CNetServer::StartGame() { - std::lock_guard lock(m_Worker->m_WorkerMutex); - m_Worker->m_StartGameQueue.push_back(true); + std::lock_guard lock(m_Worker.m_WorkerMutex); + m_Worker.m_StartGameQueue.push_back(true); } void CNetServer::OnLobbyAuth(const CStr& name, const CStr& token) { - std::lock_guard lock(m_Worker->m_WorkerMutex); - m_Worker->m_LobbyAuthQueue.push_back(std::make_pair(name, token)); + std::lock_guard lock(m_Worker.m_WorkerMutex); + m_Worker.m_LobbyAuthQueue.push_back(std::make_pair(name, token)); } void CNetServer::SetTurnLength(u32 msecs) { - std::lock_guard lock(m_Worker->m_WorkerMutex); - m_Worker->m_TurnLengthQueue.push_back(msecs); + std::lock_guard lock(m_Worker.m_WorkerMutex); + m_Worker.m_TurnLengthQueue.push_back(msecs); } void CNetServer::SendHolePunchingMessage(const CStr& ip, u16 port) { - m_Worker->SendHolePunchingMessage(ip, port); + m_Worker.SendHolePunchingMessage(ip, port); } diff --git a/source/network/NetServer.h b/source/network/NetServer.h index 117e7bd7c1..e08c2faf16 100644 --- a/source/network/NetServer.h +++ b/source/network/NetServer.h @@ -39,7 +39,6 @@ class CNetMessage; class CNetServerSession; class CNetServerTurnManager; -class CNetServerWorker; class CNetStatsTable; class CPlayerAssignmentMessage; class CSimulationMessage; @@ -98,77 +97,6 @@ enum NetServerSessionState NSS_INGAME }; -/** - * Network server interface. Handles all the coordination between players. - * One person runs this object, and every player (including the host) connects their CNetClient to it. - * - * The actual work is performed by CNetServerWorker in a separate thread. - */ -class CNetServer -{ - NONCOPYABLE(CNetServer); -public: - CNetServer(const bool isSavedGame, std::uint16_t port, const bool useLobbyAuth = false, - std::string password = {}, std::string controllerSecret = {}, std::string initAttributes = {}); - ~CNetServer(); - - /** - * Call from the GUI to asynchronously notify all clients that they should start loading the game. - * SetupConnection must be called at least once. - */ - void StartGame(); - - /** - * Set the turn length to a fixed value. - * TODO: we should replace this with some adapative lag-dependent computation. - */ - void SetTurnLength(u32 msecs); - - bool UseLobbyAuth() const; - - void OnLobbyAuth(const CStr& name, const CStr& token); - - void SendHolePunchingMessage(const CStr& ip, u16 port); - - /** - * Return the externally accessible IP. - */ - CStr GetPublicIp() const; - - /** - * Return the externally accessible port. - */ - u16 GetPublicPort() const; - - /** - * Return the serving port on the local machine. - */ - u16 GetLocalPort() const; - - /** - * Check if password is valid. If is not, increase number of failed attempts of the lobby user. - * This is used without established direct session with the client, to prevent brute force attacks - * when guessing password trying to get connection data from the host. - * @return true iff password is valid - */ - bool CheckPasswordAndIncrement(const std::string& username, const std::string& password, const std::string& salt); - - /** - * Check if user reached certain number of failed attempts. - * @see m_BanAfterNumberOfTries - * @see CheckPasswordAndBan - */ - bool IsBanned(const std::string& username) const; - -private: - CNetServerWorker* m_Worker; - const bool m_LobbyAuth; - u16 m_PublicPort{20595}; - CStr m_PublicIp; - CStr m_Password; - std::unordered_map m_FailedAttempts; -}; - /** * Network server worker thread. * (This is run in a thread so that client/server communication is not delayed @@ -407,7 +335,7 @@ private: bool RunStep(); std::thread m_WorkerThread; - std::mutex m_WorkerMutex; + mutable std::mutex m_WorkerMutex; // protected by m_WorkerMutex bool m_Shutdown{false}; @@ -418,6 +346,76 @@ private: std::vector m_TurnLengthQueue; }; +/** + * Network server interface. Handles all the coordination between players. + * One person runs this object, and every player (including the host) connects their CNetClient to it. + * + * The actual work is performed by CNetServerWorker in a separate thread. + */ +class CNetServer +{ + NONCOPYABLE(CNetServer); +public: + CNetServer(const bool isSavedGame, std::uint16_t port, const bool useLobbyAuth = false, + std::string password = {}, std::string controllerSecret = {}, std::string initAttributes = {}); + + /** + * Call from the GUI to asynchronously notify all clients that they should start loading the game. + * SetupConnection must be called at least once. + */ + void StartGame(); + + /** + * Set the turn length to a fixed value. + * TODO: we should replace this with some adapative lag-dependent computation. + */ + void SetTurnLength(u32 msecs); + + bool UseLobbyAuth() const; + + void OnLobbyAuth(const CStr& name, const CStr& token); + + void SendHolePunchingMessage(const CStr& ip, u16 port); + + /** + * Return the externally accessible IP. + */ + CStr GetPublicIp() const; + + /** + * Return the externally accessible port. + */ + u16 GetPublicPort() const; + + /** + * Return the serving port on the local machine. + */ + u16 GetLocalPort() const; + + /** + * Check if password is valid. If is not, increase number of failed attempts of the lobby user. + * This is used without established direct session with the client, to prevent brute force attacks + * when guessing password trying to get connection data from the host. + * @return true iff password is valid + */ + bool CheckPasswordAndIncrement(const std::string& username, const std::string& password, const std::string& salt); + + /** + * Check if user reached certain number of failed attempts. + * @see m_BanAfterNumberOfTries + * @see CheckPasswordAndBan + */ + bool IsBanned(const std::string& username) const; + +private: + CNetServerWorker m_Worker; + const bool m_LobbyAuth; + u16 m_PublicPort{20595}; + CStr m_PublicIp; + CStr m_Password; + std::unordered_map m_FailedAttempts; +}; + /// Global network server for the standard game extern CNetServer *g_NetServer;