1
0
forked from mirrors/0ad

Store the server-worker inside the server

This becomes possible by reordering the class definition.
This commit is contained in:
phosit
2026-04-16 18:16:41 +02:00
parent 0171a58f26
commit 2b1b1dc1e3
2 changed files with 86 additions and 93 deletions
+15 -20
View File
@@ -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<std::mutex> lock(m_Worker->m_WorkerMutex);
if (!m_Worker->m_Host || !StunClient::FindPublicIP(*m_Worker->m_Host, m_PublicIp, m_PublicPort))
std::lock_guard<std::mutex> 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<std::mutex> lock(m_Worker->m_WorkerMutex);
if (!m_Worker->m_Host)
std::lock_guard<std::mutex> 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<std::string, int>::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<std::mutex> lock(m_Worker->m_WorkerMutex);
m_Worker->m_StartGameQueue.push_back(true);
std::lock_guard<std::mutex> lock(m_Worker.m_WorkerMutex);
m_Worker.m_StartGameQueue.push_back(true);
}
void CNetServer::OnLobbyAuth(const CStr& name, const CStr& token)
{
std::lock_guard<std::mutex> lock(m_Worker->m_WorkerMutex);
m_Worker->m_LobbyAuthQueue.push_back(std::make_pair(name, token));
std::lock_guard<std::mutex> lock(m_Worker.m_WorkerMutex);
m_Worker.m_LobbyAuthQueue.push_back(std::make_pair(name, token));
}
void CNetServer::SetTurnLength(u32 msecs)
{
std::lock_guard<std::mutex> lock(m_Worker->m_WorkerMutex);
m_Worker->m_TurnLengthQueue.push_back(msecs);
std::lock_guard<std::mutex> 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);
}
+71 -73
View File
@@ -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<std::string, int> 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<u32> 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<std::string, int> m_FailedAttempts;
};
/// Global network server for the standard game
extern CNetServer *g_NetServer;