From 1a3fb29ff3849e70f30a4f6601ae8df6a7eae04a Mon Sep 17 00:00:00 2001 From: elexis Date: Sun, 8 May 2016 11:46:19 +0000 Subject: [PATCH] Network cleanup, fixes #3953. Don't compare for "127.0.0.1" to identify the host, but check for a new boolean flag that is set by the client, refs #2854. Remove an unneeded IP address conversion from u32 to string, refs #3241. This was SVN commit r18140. --- source/gui/scripting/ScriptFunctions.cpp | 4 +-- source/network/NetClient.cpp | 6 ++-- source/network/NetClient.h | 5 ++- source/network/NetMessages.h | 3 +- source/network/NetServer.cpp | 14 +++------ source/network/NetServer.h | 3 +- source/network/NetSession.cpp | 40 +++++++++++++----------- source/network/NetSession.h | 19 ++++++++--- source/network/tests/test_Net.h | 14 ++++----- source/ps/GameSetup/GameSetup.cpp | 4 +-- 10 files changed, 64 insertions(+), 48 deletions(-) diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index dea9301f9e..41520edc6b 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -359,7 +359,7 @@ void StartNetworkHost(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring } g_Game = new CGame(); - g_NetClient = new CNetClient(g_Game); + g_NetClient = new CNetClient(g_Game, true); g_NetClient->SetUserName(playerName); if (!g_NetClient->SetupConnection("127.0.0.1")) @@ -377,7 +377,7 @@ void StartNetworkJoin(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring ENSURE(!g_Game); g_Game = new CGame(); - g_NetClient = new CNetClient(g_Game); + g_NetClient = new CNetClient(g_Game, false); g_NetClient->SetUserName(playerName); if (!g_NetClient->SetupConnection(serverAddress)) { diff --git a/source/network/NetClient.cpp b/source/network/NetClient.cpp index a6050ce6f5..2a59c50b07 100644 --- a/source/network/NetClient.cpp +++ b/source/network/NetClient.cpp @@ -66,11 +66,12 @@ private: CNetClient& m_Client; }; -CNetClient::CNetClient(CGame* game) : +CNetClient::CNetClient(CGame* game, bool isLocalClient) : m_Session(NULL), m_UserName(L"anonymous"), m_GUID(ps_generate_guid()), m_HostID((u32)-1), m_ClientTurnManager(NULL), m_Game(game), m_GameAttributes(game->GetSimulation2()->GetScriptInterface().GetContext()), + m_IsLocalClient(isLocalClient), m_LastConnectionCheck(0) { m_Game->SetTurnManager(NULL); // delete the old local turn manager so we don't accidentally use it @@ -154,7 +155,7 @@ void CNetClient::SetUserName(const CStrW& username) bool CNetClient::SetupConnection(const CStr& server) { CNetClientSession* session = new CNetClientSession(*this); - bool ok = session->Connect(PS_DEFAULT_PORT, server); + bool ok = session->Connect(PS_DEFAULT_PORT, server, m_IsLocalClient); SetAndOwnSession(session); return ok; } @@ -467,6 +468,7 @@ bool CNetClient::OnHandshakeResponse(void* context, CFsmEvent* event) authenticate.m_GUID = client->m_GUID; authenticate.m_Name = client->m_UserName; authenticate.m_Password = L""; // TODO + authenticate.m_IsLocalClient = client->m_IsLocalClient; client->SendMessage(&authenticate); return true; diff --git a/source/network/NetClient.h b/source/network/NetClient.h index 5ac7f7e7d6..e65b4aa320 100644 --- a/source/network/NetClient.h +++ b/source/network/NetClient.h @@ -65,7 +65,7 @@ public: * Construct a client associated with the given game object. * The game must exist for the lifetime of this object. */ - CNetClient(CGame* game); + CNetClient(CGame* game, bool isLocalClient); virtual ~CNetClient(); @@ -239,6 +239,9 @@ private: /// Unique-per-game identifier of this client, used to identify the sender of simulation commands u32 m_HostID; + /// Whether to prevent the client of the host from timing out + bool m_IsLocalClient; + /// Latest copy of game setup attributes heard from the server JS::PersistentRootedValue m_GameAttributes; diff --git a/source/network/NetMessages.h b/source/network/NetMessages.h index 7dc678c75f..f6e52e3ead 100644 --- a/source/network/NetMessages.h +++ b/source/network/NetMessages.h @@ -28,7 +28,7 @@ #define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?' #define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!' -#define PS_PROTOCOL_VERSION 0x01010011 // Arbitrary protocol +#define PS_PROTOCOL_VERSION 0x01010012 // Arbitrary protocol #define PS_DEFAULT_PORT 0x5073 // 'P', 's' // Defines the list of message types. The order of the list must not change. @@ -112,6 +112,7 @@ START_NMT_CLASS_(Authenticate, NMT_AUTHENTICATE) NMT_FIELD(CStr8, m_GUID) NMT_FIELD(CStrW, m_Name) NMT_FIELD(CStrW, m_Password) + NMT_FIELD_INT(m_IsLocalClient, u8, 1) END_NMT_CLASS() START_NMT_CLASS_(AuthenticateResult, NMT_AUTHENTICATE_RESULT) diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp index a1d19b6789..f529ec23f5 100644 --- a/source/network/NetServer.cpp +++ b/source/network/NetServer.cpp @@ -25,7 +25,6 @@ #include "NetStats.h" #include "NetTurnManager.h" -#include "lib/external_libraries/enet.h" #include "ps/CLogger.h" #include "ps/ConfigDB.h" #include "scriptinterface/ScriptInterface.h" @@ -486,12 +485,6 @@ bool CNetServerWorker::RunStep() CNetServerSession* session = new CNetServerSession(*this, event.peer); - // Prevent the local client of the host from timing out too quickly -#if (ENET_VERSION >= ENET_VERSION_CREATE(1, 3, 4)) - if (session->GetIPAddress() == "127.0.0.1") - enet_peer_timeout(event.peer, 0, MAXIMUM_HOST_TIMEOUT, MAXIMUM_HOST_TIMEOUT); -#endif - m_Sessions.push_back(session); SetupSession(session); @@ -690,7 +683,7 @@ void CNetServerWorker::OnUserJoin(CNetServerSession* session) { AddPlayer(session->GetGUID(), session->GetUserName()); - if (m_HostGUID.empty() && session->GetIPAddress() == "127.0.0.1") + if (m_HostGUID.empty() && session->IsLocalClient()) m_HostGUID = session->GetGUID(); CGameSetupMessage gameSetupMessage(GetScriptInterface()); @@ -802,8 +795,8 @@ bool CNetServerWorker::KickPlayer(const CStrW& playerName, const bool ban) m_BannedPlayers.push_back(playerName); // Remember IP address - CStr ipAddress = (*it)->GetIPAddress(); - if (!ipAddress.empty() && std::find(m_BannedIPs.begin(), m_BannedIPs.end(), ipAddress) == m_BannedIPs.end()) + enet_uint32 ipAddress = (*it)->GetIPAddress(); + if (std::find(m_BannedIPs.begin(), m_BannedIPs.end(), ipAddress) == m_BannedIPs.end()) m_BannedIPs.push_back(ipAddress); } @@ -999,6 +992,7 @@ bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event) session->SetUserName(username); session->SetGUID(message->m_GUID); session->SetHostID(newHostID); + session->SetLocalClient(message->m_IsLocalClient); CAuthenticateResultMessage authenticateResult; authenticateResult.m_Code = isRejoining ? ARC_OK_REJOINING : ARC_OK; diff --git a/source/network/NetServer.h b/source/network/NetServer.h index 7e5afb9b8b..9dc096474c 100644 --- a/source/network/NetServer.h +++ b/source/network/NetServer.h @@ -22,6 +22,7 @@ #include "NetHost.h" #include "lib/config2.h" +#include "lib/external_libraries/enet.h" #include "ps/ThreadUtil.h" #include "scriptinterface/ScriptVal.h" @@ -313,7 +314,7 @@ private: CStrW m_ServerName; CStrW m_WelcomeMessage; - std::vector m_BannedIPs; + std::vector m_BannedIPs; std::vector m_BannedPlayers; u32 m_NextHostID; diff --git a/source/network/NetSession.cpp b/source/network/NetSession.cpp index a321e05d73..fbee01c133 100644 --- a/source/network/NetSession.cpp +++ b/source/network/NetSession.cpp @@ -21,7 +21,6 @@ #include "NetServer.h" #include "NetMessage.h" #include "NetStats.h" -#include "lib/external_libraries/enet.h" #include "ps/CLogger.h" #include "scriptinterface/ScriptInterface.h" @@ -51,7 +50,7 @@ CNetClientSession::~CNetClientSession() } } -bool CNetClientSession::Connect(u16 port, const CStr& server) +bool CNetClientSession::Connect(u16 port, const CStr& server, bool isLocalClient) { ENSURE(!m_Host); ENSURE(!m_Server); @@ -77,7 +76,7 @@ bool CNetClientSession::Connect(u16 port, const CStr& server) // Prevent the local client of the host from timing out too quickly. #if (ENET_VERSION >= ENET_VERSION_CREATE(1, 3, 4)) - if (GetIPAddress() == "127.0.0.1") + if (isLocalClient) enet_peer_timeout(peer, 1, MAXIMUM_HOST_TIMEOUT, MAXIMUM_HOST_TIMEOUT); #endif @@ -178,15 +177,6 @@ bool CNetClientSession::SendMessage(const CNetMessage* message) return CNetHost::SendMessage(message, m_Server, "server"); } -CStr CNetClientSession::GetIPAddress() const -{ - char ipAddress[256] = ""; - if (enet_address_get_host_ip(&m_Server->address, ipAddress, ARRAY_SIZE(ipAddress)) < 0) - LOGMESSAGE("Could not get IP address of the server!"); - - return ipAddress; -} - u32 CNetClientSession::GetLastReceivedTime() const { if (!m_Server) @@ -210,13 +200,9 @@ CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) : { } -CStr CNetServerSession::GetIPAddress() const +enet_uint32 CNetServerSession::GetIPAddress() const { - char ipAddress[256] = ""; - if (enet_address_get_host_ip(&m_Peer->address, ipAddress, ARRAY_SIZE(ipAddress)) < 0) - LOGMESSAGE("Could not get IP address of a client!"); - - return ipAddress; + return m_Peer->address.host; } u32 CNetServerSession::GetLastReceivedTime() const @@ -251,3 +237,21 @@ bool CNetServerSession::SendMessage(const CNetMessage* message) { return m_Server.SendMessage(m_Peer, message); } + +bool CNetServerSession::IsLocalClient() const +{ + return m_IsLocalClient; +} + +void CNetServerSession::SetLocalClient(bool isLocalClient) +{ + m_IsLocalClient = isLocalClient; + + if (!isLocalClient) + return; + + // Prevent the local client of the host from timing out too quickly +#if (ENET_VERSION >= ENET_VERSION_CREATE(1, 3, 4)) + enet_peer_timeout(m_Peer, 0, MAXIMUM_HOST_TIMEOUT, MAXIMUM_HOST_TIMEOUT); +#endif +} diff --git a/source/network/NetSession.h b/source/network/NetSession.h index e74b90c189..9942536de9 100644 --- a/source/network/NetSession.h +++ b/source/network/NetSession.h @@ -21,6 +21,7 @@ #include "network/fsm.h" #include "network/NetFileTransfer.h" #include "network/NetHost.h" +#include "lib/external_libraries/enet.h" #include "ps/CStr.h" #include "scriptinterface/ScriptVal.h" @@ -70,7 +71,7 @@ public: CNetClientSession(CNetClient& client); ~CNetClientSession(); - bool Connect(u16 port, const CStr& server); + bool Connect(u16 port, const CStr& server, bool isLocalClient); /** * Process queued incoming messages. @@ -93,8 +94,6 @@ public: */ virtual bool SendMessage(const CNetMessage* message); - CStr GetIPAddress() const; - /** * Number of milliseconds since the most recent packet of the server was received. */ @@ -144,7 +143,12 @@ public: u32 GetHostID() const { return m_HostID; } void SetHostID(u32 id) { m_HostID = id; } - CStr GetIPAddress() const; + enet_uint32 GetIPAddress() const; + + /** + * Whether this client is running in the same process as the server. + */ + bool IsLocalClient() const; /** * Number of milliseconds since the latest packet of that client was received. @@ -171,6 +175,11 @@ public: */ void DisconnectNow(u32 reason); + /** + * Prevent timeouts for the client running in the same process as the server. + */ + void SetLocalClient(bool isLocalClient); + /** * Send a message to the client. */ @@ -188,6 +197,8 @@ private: CStr m_GUID; CStrW m_UserName; u32 m_HostID; + + bool m_IsLocalClient; }; #endif // NETSESSION_H diff --git a/source/network/tests/test_Net.h b/source/network/tests/test_Net.h index 9ef752ca95..20378df4d2 100644 --- a/source/network/tests/test_Net.h +++ b/source/network/tests/test_Net.h @@ -152,9 +152,9 @@ public: scriptInterface.Eval("({mapType:'scenario',map:'maps/scenarios/Saharan Oases',mapPath:'maps/scenarios/',thing:'example'})", &attrs); server.UpdateGameAttributes(&attrs, scriptInterface); - CNetClient client1(&client1Game); - CNetClient client2(&client2Game); - CNetClient client3(&client3Game); + CNetClient client1(&client1Game, false); + CNetClient client2(&client2Game, false); + CNetClient client3(&client3Game, false); clients.push_back(&client1); clients.push_back(&client2); @@ -217,9 +217,9 @@ public: scriptInterface.Eval("({mapType:'scenario',map:'maps/scenarios/Saharan Oases',mapPath:'maps/scenarios/',thing:'example'})", &attrs); server.UpdateGameAttributes(&attrs, scriptInterface); - CNetClient client1(&client1Game); - CNetClient client2(&client2Game); - CNetClient client3(&client3Game); + CNetClient client1(&client1Game, false); + CNetClient client2(&client2Game, false); + CNetClient client3(&client3Game, false); client1.SetUserName(L"alice"); client2.SetUserName(L"bob"); @@ -269,7 +269,7 @@ public: debug_printf("==== Connecting client 2B\n"); CGame client2BGame(true); - CNetClient client2B(&client2BGame); + CNetClient client2B(&client2BGame, false); client2B.SetUserName(L"bob"); clients.push_back(&client2B); diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index c64caddfee..f39bc03004 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -1486,7 +1486,7 @@ bool Autostart(const CmdLineArgs& args) bool ok = g_NetServer->SetupConnection(); ENSURE(ok); - g_NetClient = new CNetClient(g_Game); + g_NetClient = new CNetClient(g_Game, true); g_NetClient->SetUserName(userName); g_NetClient->SetupConnection("127.0.0.1"); } @@ -1494,7 +1494,7 @@ bool Autostart(const CmdLineArgs& args) { InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); - g_NetClient = new CNetClient(g_Game); + g_NetClient = new CNetClient(g_Game, false); g_NetClient->SetUserName(userName); CStr ip = args.Get("autostart-client");