Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/source/network/NetClient.cpp b/source/network/NetClient.cpp
- index c99a626b5c..662e537086 100644
- --- a/source/network/NetClient.cpp
- +++ b/source/network/NetClient.cpp
- @@ -36,6 +36,8 @@
- #include "scriptinterface/ScriptInterface.h"
- #include "simulation2/Simulation2.h"
- +#include <map>
- +
- CNetClient *g_NetClient = NULL;
- /**
- @@ -201,36 +203,25 @@ void CNetClient::Poll()
- void CNetClient::CheckServerConnection()
- {
- - // Trigger local warnings if the connection to the server is bad.
- - // At most once per second.
- std::time_t now = std::time(nullptr);
- if (now <= m_LastConnectionCheck)
- return;
- m_LastConnectionCheck = now;
- - JSContext* cx = GetScriptInterface().GetContext();
- - JSAutoRequest rq(cx);
- + m_ClientPerformance[m_GUID] = std::make_tuple(
- + std::make_pair(m_Session->GetMeanRTT(), now),
- + std::make_pair(m_Session->GetLastReceivedTime(), now),
- + m_Session->GetPacketLossRatio());
- - // Report if we are losing the connection to the server
- - u32 lastReceived = m_Session->GetLastReceivedTime();
- - if (lastReceived > NETWORK_WARNING_TIMEOUT)
- + // Remove old timeouts and pings, a23 fallback code
- + for (std::map<std::string, std::tuple<std::pair<u32, u32>, std::pair<u32, u32>, double>>::iterator iter = m_ClientPerformance.begin(); iter != m_ClientPerformance.end(); ++iter)
- {
- - JS::RootedValue msg(cx);
- - GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'server-timeout' })", &msg);
- - GetScriptInterface().SetProperty(msg, "lastReceivedTime", lastReceived);
- - PushGuiMessage(msg);
- - return;
- - }
- + if (now - std::get<0>(iter->second).second >= 3)
- + std::get<0>(iter->second) = std::make_pair(0, now);
- - // Report if we have a bad ping to the server
- - u32 meanRTT = m_Session->GetMeanRTT();
- - if (meanRTT > DEFAULT_TURN_LENGTH_MP)
- - {
- - JS::RootedValue msg(cx);
- - GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'server-latency' })", &msg);
- - GetScriptInterface().SetProperty(msg, "meanRTT", meanRTT);
- - PushGuiMessage(msg);
- + if (now - std::get<1>(iter->second).second >= 3)
- + std::get<1>(iter->second) = std::make_pair(0, now);
- }
- }
- @@ -663,10 +654,20 @@ bool CNetClient::OnPlayerAssignment(void* context, CFsmEvent* event)
- assignment.m_PlayerID = message->m_Hosts[i].m_PlayerID;
- assignment.m_Status = message->m_Hosts[i].m_Status;
- newPlayerAssignments[message->m_Hosts[i].m_GUID] = assignment;
- +
- + if (!client->m_ClientPerformance.count(message->m_Hosts[i].m_GUID))
- + client->m_ClientPerformance[message->m_Hosts[i].m_GUID] = std::make_tuple(std::make_pair(0, 0), std::make_pair(0, 0), 0.d);
- }
- client->m_PlayerAssignments.swap(newPlayerAssignments);
- + for (std::map<std::string, std::tuple<std::pair<u32, u32>, std::pair<u32, u32>, double>>::iterator iter = client->m_ClientPerformance.begin(); iter != client->m_ClientPerformance.end(); ++iter)
- + if (!client->m_PlayerAssignments.count(iter->first))
- + {
- + client->m_ClientPerformance.erase(iter);
- + break;
- + }
- +
- client->PostPlayerAssignmentsToScript();
- return true;
- @@ -780,14 +781,9 @@ bool CNetClient::OnClientTimeout(void *context, CFsmEvent* event)
- JSAutoRequest rq(cx);
- CClientTimeoutMessage* message = (CClientTimeoutMessage*)event->GetParamRef();
- - JS::RootedValue msg(cx);
- + std::get<1>(client->m_ClientPerformance[message->m_GUID]) = std::make_pair(message->m_LastReceivedTime, std::time(nullptr));
- - client->GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'client-timeout' })", &msg);
- - client->GetScriptInterface().SetProperty(msg, "guid", std::string(message->m_GUID));
- - client->GetScriptInterface().SetProperty(msg, "lastReceivedTime", message->m_LastReceivedTime);
- - client->PushGuiMessage(msg);
- -
- - return true;
- + return true;
- }
- bool CNetClient::OnClientPerformance(void *context, CFsmEvent* event)
- @@ -802,17 +798,10 @@ bool CNetClient::OnClientPerformance(void *context, CFsmEvent* event)
- CClientPerformanceMessage* message = (CClientPerformanceMessage*)event->GetParamRef();
- - // Display warnings for other clients with bad ping
- - for (size_t i = 0; i < message->m_Clients.size(); ++i)
- + for (const CClientPerformanceMessage::S_m_Clients& mClient : message->m_Clients)
- {
- - if (message->m_Clients[i].m_MeanRTT < DEFAULT_TURN_LENGTH_MP || message->m_Clients[i].m_GUID == client->m_GUID)
- - continue;
- -
- - JS::RootedValue msg(cx);
- - client->GetScriptInterface().Eval("({ 'type':'netwarn', 'warntype': 'client-latency' })", &msg);
- - client->GetScriptInterface().SetProperty(msg, "guid", message->m_Clients[i].m_GUID);
- - client->GetScriptInterface().SetProperty(msg, "meanRTT", message->m_Clients[i].m_MeanRTT);
- - client->PushGuiMessage(msg);
- + std::get<0>(client->m_ClientPerformance[mClient.m_GUID]) = std::make_pair(mClient.m_MeanRTT, std::time(nullptr));
- + std::get<2>(client->m_ClientPerformance[mClient.m_GUID]) = (double) mClient.m_PacketLoss / (double) ENET_PEER_PACKET_LOSS_SCALE;
- }
- return true;
- @@ -924,3 +913,22 @@ bool CNetClient::OnInGame(void *context, CFsmEvent* event)
- return true;
- }
- +
- +JS::Value CNetClient::GetClientPerformance()
- +{
- + JSContext* cx = GetScriptInterface().GetContext();
- + JSAutoRequest rq(cx);
- +
- + JS::RootedValue performanceVals(cx, JS::ObjectValue(*JS_NewPlainObject(cx)));
- +
- + for (const std::pair<std::string, std::tuple<std::pair<u32, u32>, std::pair<u32, u32>, double>>& clientPerf : m_ClientPerformance)
- + {
- + JS::RootedValue performanceVal(cx, JS::ObjectValue(*JS_NewPlainObject(cx)));
- + GetScriptInterface().SetProperty(performanceVal, "meanRTT", std::get<0>(clientPerf.second).first);
- + GetScriptInterface().SetProperty(performanceVal, "lastReceivedTime", std::get<1>(clientPerf.second).first);
- + GetScriptInterface().SetProperty(performanceVal, "packetLoss", std::get<2>(clientPerf.second));
- + GetScriptInterface().SetProperty(performanceVals, clientPerf.first.c_str(), performanceVal);
- + }
- +
- + return performanceVals;
- +}
- diff --git a/source/network/NetClient.h b/source/network/NetClient.h
- index 9f0772f6e5..db28f2e170 100644
- --- a/source/network/NetClient.h
- +++ b/source/network/NetClient.h
- @@ -149,6 +149,8 @@ public:
- */
- void GuiPoll(JS::MutableHandleValue);
- + JS::Value GetClientPerformance();
- +
- /**
- * Add a message to the queue, to be read by GuiPoll.
- * The script value must be in the GetScriptInterface() JS context.
- @@ -284,6 +286,9 @@ private:
- /// Latest copy of player assignments heard from the server
- PlayerAssignmentMap m_PlayerAssignments;
- + // Latest copy of roundtrip time and lost packets
- + std::map<std::string, std::tuple<std::pair<u32, u32>, std::pair<u32, u32>, double>> m_ClientPerformance;
- +
- /// Globally unique identifier to distinguish users beyond the lifetime of a single network session
- CStr m_GUID;
- diff --git a/source/network/NetClientTurnManager.cpp b/source/network/NetClientTurnManager.cpp
- index d94c75fc4f..0363aba9b5 100644
- --- a/source/network/NetClientTurnManager.cpp
- +++ b/source/network/NetClientTurnManager.cpp
- @@ -27,6 +27,8 @@
- #include "ps/Util.h"
- #include "simulation2/Simulation2.h"
- +#include <chrono>
- +
- #if 0
- #define NETCLIENTTURN_LOG(...) debug_printf(__VA_ARGS__)
- #else
- @@ -78,6 +80,8 @@ void CNetClientTurnManager::NotifyFinishedUpdate(u32 turn)
- ENSURE(m_Simulation2.ComputeStateHash(hash, quick));
- }
- + //debug_printf("%lu NotifyFinishedUpdate turn %d\n", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), turn);
- +
- NETCLIENTTURN_LOG("NotifyFinishedUpdate(%d, %hs)\n", turn, Hexify(hash).c_str());
- m_Replay.Hash(hash, quick);
- diff --git a/source/network/NetMessages.h b/source/network/NetMessages.h
- index 902058935d..99be37ffae 100644
- --- a/source/network/NetMessages.h
- +++ b/source/network/NetMessages.h
- @@ -194,6 +194,7 @@ START_NMT_CLASS_(ClientPerformance, NMT_CLIENT_PERFORMANCE)
- NMT_START_ARRAY(m_Clients)
- NMT_FIELD(CStr, m_GUID)
- NMT_FIELD_INT(m_MeanRTT, u32, 4)
- + NMT_FIELD_INT(m_PacketLoss, u32, 4)
- NMT_END_ARRAY()
- END_NMT_CLASS()
- diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp
- index 7f884fc455..7988404adb 100644
- --- a/source/network/NetServer.cpp
- +++ b/source/network/NetServer.cpp
- @@ -45,6 +45,7 @@
- #include <miniupnpc/upnperrors.h>
- #endif
- +#include <chrono>
- #include <string>
- /**
- @@ -137,7 +138,7 @@ CNetServerWorker::CNetServerWorker(bool useLobbyAuth, int autostartPlayers) :
- m_Shutdown(false),
- m_ScriptInterface(NULL),
- m_NextHostID(1), m_Host(NULL), m_HostGUID(), m_Stats(NULL),
- - m_LastConnectionCheck(0)
- + m_LastConnectionCheck(std::chrono::high_resolution_clock::now())
- {
- m_State = SERVER_STATE_UNCONNECTED;
- @@ -361,6 +362,24 @@ bool CNetServerWorker::Broadcast(const CNetMessage* message, const std::vector<N
- return ok;
- }
- +std::string CNetServerWorker::GetClientIPAddress(const std::string& guid)
- +{
- + for (CNetServerSession* session : m_Sessions)
- + if (session->GetGUID() == guid)
- + return session->GetIPAddressString();
- +
- + return "";
- +}
- +
- +std::string CNetServerWorker::GetHostname(const std::string& guid)
- +{
- + for (CNetServerSession* session : m_Sessions)
- + if (session->GetGUID() == guid)
- + return session->GetHostname();
- +
- + return "";
- +}
- +
- void* CNetServerWorker::RunThread(void* data)
- {
- debug_SetThreadName("NetServer");
- @@ -452,7 +471,7 @@ bool CNetServerWorker::RunStep()
- for (CNetServerSession* session : m_Sessions)
- session->GetFileTransferer().Poll();
- - CheckClientConnections();
- + BroadcastClientPerformance();
- // Process network events:
- @@ -555,57 +574,54 @@ bool CNetServerWorker::RunStep()
- return true;
- }
- -void CNetServerWorker::CheckClientConnections()
- +void CNetServerWorker::BroadcastClientPerformance()
- {
- // Send messages at most once per second
- - std::time_t now = std::time(nullptr);
- - if (now <= m_LastConnectionCheck)
- + std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
- + if (std::chrono::duration_cast<std::chrono::milliseconds>(now - m_LastConnectionCheck).count() < DEFAULT_TURN_LENGTH_MP * 2)
- return;
- m_LastConnectionCheck = now;
- - for (size_t i = 0; i < m_Sessions.size(); ++i)
- + for (CNetServerSession* addresseeSession : m_Sessions)
- {
- - u32 lastReceived = m_Sessions[i]->GetLastReceivedTime();
- - u32 meanRTT = m_Sessions[i]->GetMeanRTT();
- + // Skip disconnecting clients and clients in the loading screen
- + if (addresseeSession->GetLastReceivedTime() >= 2000 ||
- + addresseeSession->GetCurrState() == FSM_INVALID_STATE ||
- + addresseeSession->GetCurrState() < NSS_PREGAME ||
- + (addresseeSession->GetCurrState() == NSS_PREGAME && m_State == SERVER_STATE_LOADING))
- + continue;
- +
- + CClientPerformanceMessage performanceMsg;
- + for (CNetServerSession* measuredSession : m_Sessions)
- + {
- + // Inform clients about every connection except their own (since they measure that themself)
- + if (measuredSession == addresseeSession)
- + continue;
- - CNetMessage* message = nullptr;
- + // Step 1: Remember meanRTT
- + u32 simDelay = m_ServerTurnManager ? m_ServerTurnManager->GetClientSimulationDelay(*measuredSession) : 0;
- + if (simDelay < DEFAULT_TURN_LENGTH_MP * 1.1 ||
- + std::find(m_PausingPlayers.begin(), m_PausingPlayers.end(), measuredSession->GetGUID()) != m_PausingPlayers.end())
- + simDelay = 0;
- - // Report if we didn't hear from the client since few seconds
- - if (lastReceived > NETWORK_WARNING_TIMEOUT)
- - {
- - CClientTimeoutMessage* msg = new CClientTimeoutMessage();
- - msg->m_GUID = m_Sessions[i]->GetGUID();
- - msg->m_LastReceivedTime = lastReceived;
- - message = msg;
- - }
- - // Report if the client has bad ping
- - else if (meanRTT > DEFAULT_TURN_LENGTH_MP)
- - {
- - CClientPerformanceMessage* msg = new CClientPerformanceMessage();
- - CClientPerformanceMessage::S_m_Clients client;
- - client.m_GUID = m_Sessions[i]->GetGUID();
- - client.m_MeanRTT = meanRTT;
- - msg->m_Clients.push_back(client);
- - message = msg;
- - }
- + CClientPerformanceMessage::S_m_Clients msgPerformanceClient;
- + msgPerformanceClient.m_GUID = measuredSession->GetGUID();
- + msgPerformanceClient.m_MeanRTT = std::max(measuredSession->GetMeanRTT(), simDelay);
- + msgPerformanceClient.m_PacketLoss = measuredSession->GetPacketLoss();
- +
- + performanceMsg.m_Clients.push_back(msgPerformanceClient);
- - // Send to all clients except the affected one
- - // (since that will show the locally triggered warning instead).
- - // Also send it to clients that finished the loading screen while
- - // the game is still waiting for other clients to finish the loading screen.
- - if (message)
- - for (size_t j = 0; j < m_Sessions.size(); ++j)
- + // Step 2: Send timeout message per client
- + if (measuredSession->GetLastReceivedTime() >= 2000)
- {
- - if (i != j && (
- - (m_Sessions[j]->GetCurrState() == NSS_PREGAME && m_State == SERVER_STATE_PREGAME) ||
- - m_Sessions[j]->GetCurrState() == NSS_INGAME))
- - {
- - m_Sessions[j]->SendMessage(message);
- - }
- + CClientTimeoutMessage timeoutMsg;
- + timeoutMsg.m_GUID = measuredSession->GetGUID();
- + timeoutMsg.m_LastReceivedTime = measuredSession->GetLastReceivedTime();
- + addresseeSession->SendMessage(&timeoutMsg);
- }
- -
- - SAFE_DELETE(message);
- + }
- + addresseeSession->SendMessage(&performanceMsg);
- }
- }
- @@ -686,6 +702,8 @@ bool CNetServerWorker::HandleConnect(CNetServerSession* session)
- return false;
- }
- + // TODO: check for banned hostnames
- +
- CSrvHandshakeMessage handshake;
- handshake.m_Magic = PS_PROTOCOL_MAGIC;
- handshake.m_ProtocolVersion = PS_PROTOCOL_VERSION;
- @@ -1580,6 +1598,19 @@ bool CNetServer::SetupConnection(const u16 port)
- return m_Worker->SetupConnection(port);
- }
- +std::string CNetServer::GetClientIPAddress(const std::string& guid)
- +{
- + // The server should broadcast the countries, IPs and hostnames in an admin packet each time a player joins/disconnects
- + CScopeLock lock(m_Worker->m_WorkerMutex);
- + return m_Worker->GetClientIPAddress(guid);
- +}
- +
- +std::string CNetServer::GetHostname(const std::string& guid)
- +{
- + CScopeLock lock(m_Worker->m_WorkerMutex);
- + return m_Worker->GetHostname(guid);
- +}
- +
- void CNetServer::StartGame()
- {
- CScopeLock lock(m_Worker->m_WorkerMutex);
- diff --git a/source/network/NetServer.h b/source/network/NetServer.h
- index f17aebecc7..1b228cc6e7 100644
- --- a/source/network/NetServer.h
- +++ b/source/network/NetServer.h
- @@ -25,6 +25,7 @@
- #include "ps/ThreadUtil.h"
- #include "scriptinterface/ScriptTypes.h"
- +#include <chrono>
- #include <string>
- #include <utility>
- #include <vector>
- @@ -141,6 +142,9 @@ public:
- bool UseLobbyAuth() const;
- + std::string GetClientIPAddress(const std::string& guid);
- + std::string GetHostname(const std::string& guid);
- +
- void OnLobbyAuth(const CStr& name, const CStr& token);
- void SendHolePunchingMessage(const CStr& ip, u16 port);
- @@ -184,6 +188,9 @@ public:
- */
- bool Broadcast(const CNetMessage* message, const std::vector<NetServerSessionState>& targetStates);
- + std::string GetClientIPAddress(const std::string& guid);
- + std::string GetHostname(const std::string& guid);
- +
- private:
- friend class CNetServer;
- friend class CNetFileReceiveTask_ServerRejoin;
- @@ -281,9 +288,9 @@ private:
- void HandleMessageReceive(const CNetMessage* message, CNetServerSession* session);
- /**
- - * Send a network warning if the connection to a client is being lost or has bad latency.
- + * Inform clients if the connection to a client is being lost or has bad latency.
- */
- - void CheckClientConnections();
- + void BroadcastClientPerformance();
- void SendHolePunchingMessage(const CStr& ip, u16 port);
- @@ -321,6 +328,11 @@ private:
- std::vector<u32> m_BannedIPs;
- std::vector<CStrW> m_BannedPlayers;
- + /**
- + * Caches hostname per GUID of connected players.
- + */
- + //std::vector<std::string, std::string> g_HostNames;
- +
- /**
- * Holds the GUIDs of all currently paused players.
- */
- @@ -348,7 +360,7 @@ private:
- /**
- * Time when the clients connections were last checked for timeouts and latency.
- */
- - std::time_t m_LastConnectionCheck;
- + std::chrono::high_resolution_clock::time_point m_LastConnectionCheck;
- private:
- // Thread-related stuff:
- diff --git a/source/network/NetServerTurnManager.cpp b/source/network/NetServerTurnManager.cpp
- index 11130b29a3..53f7b30032 100644
- --- a/source/network/NetServerTurnManager.cpp
- +++ b/source/network/NetServerTurnManager.cpp
- @@ -32,7 +32,8 @@
- #endif
- CNetServerTurnManager::CNetServerTurnManager(CNetServerWorker& server)
- - : m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP), m_HasSyncError(false)
- + : m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP), m_HasSyncError(false),
- + m_ReadyTurnStartTime(std::chrono::high_resolution_clock::now())
- {
- // The first turn we will actually execute is number 2,
- // so store dummy values into the saved lengths list
- @@ -62,6 +63,7 @@ void CNetServerTurnManager::NotifyFinishedClientCommands(CNetServerSession& sess
- }
- m_ClientsReady[client] = turn;
- + //debug_printf("%lu Client %d ready for turn %d\n", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), m_ReadyTurn);
- // Check whether this was the final client to become ready
- CheckClientsReady();
- @@ -78,6 +80,8 @@ void CNetServerTurnManager::CheckClientsReady()
- }
- ++m_ReadyTurn;
- + m_ReadyTurnStartTime = std::chrono::high_resolution_clock::now();
- + //debug_printf("%lu Next turn %d %d\n", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), m_ReadyTurn);
- NETSERVERTURN_LOG("CheckClientsReady: ready for turn %d\n", m_ReadyTurn);
- @@ -199,3 +203,11 @@ u32 CNetServerTurnManager::GetSavedTurnLength(u32 turn)
- ENSURE(turn <= m_ReadyTurn);
- return m_SavedTurnLengths.at(turn);
- }
- +
- +u32 CNetServerTurnManager::GetClientSimulationDelay(CNetServerSession& session)
- +{
- + if (m_ClientsReady.find(session.GetHostID()) == m_ClientsReady.end() || m_ClientsReady[session.GetHostID()] > m_ReadyTurn)
- + return 0;
- +
- + return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_ReadyTurnStartTime).count();
- +}
- diff --git a/source/network/NetServerTurnManager.h b/source/network/NetServerTurnManager.h
- index 2eb3b81b50..10bb473280 100644
- --- a/source/network/NetServerTurnManager.h
- +++ b/source/network/NetServerTurnManager.h
- @@ -18,9 +18,11 @@
- #ifndef INCLUDED_NETSERVERTURNMANAGER
- #define INCLUDED_NETSERVERTURNMANAGER
- -#include <map>
- #include "ps/CStr.h"
- +#include <chrono>
- +#include <map>
- +
- class CNetServerWorker;
- class CNetServerSession;
- @@ -67,6 +69,11 @@ public:
- */
- u32 GetSavedTurnLength(u32 turn);
- + /**
- + * Returns the number of milliseconds everyone is waiting for the client to progress.
- + */
- + u32 GetClientSimulationDelay(CNetServerSession& session);
- +
- private:
- void CheckClientsReady();
- @@ -86,6 +93,9 @@ private:
- // Map of client ID -> playername
- std::map<u32, CStrW> m_ClientPlayernames;
- + // Time since when the server is waiting for clients
- + std::chrono::high_resolution_clock::time_point m_ReadyTurnStartTime;
- +
- // Current turn length
- u32 m_TurnLength;
- diff --git a/source/network/NetSession.cpp b/source/network/NetSession.cpp
- index f0a5bbf2af..a318e5ff4f 100644
- --- a/source/network/NetSession.cpp
- +++ b/source/network/NetSession.cpp
- @@ -27,10 +27,11 @@
- #include "ps/Profile.h"
- #include "scriptinterface/ScriptInterface.h"
- -const u32 NETWORK_WARNING_TIMEOUT = 2000;
- -
- const u32 MAXIMUM_HOST_TIMEOUT = std::numeric_limits<u32>::max();
- +const double PACKET_LOSS_SCALE = (1 << 16);
- +const double PACKET_LOSS_SCALE_FACTOR = PACKET_LOSS_SCALE / ENET_PEER_PACKET_LOSS_SCALE;
- +
- static const int CHANNEL_COUNT = 1;
- // Only disable long timeouts after a packet from the remote enet peer has been processed.
- @@ -149,6 +150,7 @@ void CNetClientSession::Poll()
- // Report the server address
- char hostname[256] = "(error)";
- enet_address_get_host_ip(&event.peer->address, hostname, ARRAY_SIZE(hostname));
- +
- LOGMESSAGE("Net client: Connected to %s:%u", hostname, (unsigned int)event.peer->address.port);
- m_Client.HandleConnect();
- @@ -221,6 +223,14 @@ u32 CNetClientSession::GetMeanRTT() const
- return m_Server->roundTripTime;
- }
- +double CNetClientSession::GetPacketLossRatio() const
- +{
- + if (!m_Server)
- + return 0;
- +
- + return (double) m_Server->packetLoss / (double) ENET_PEER_PACKET_LOSS_SCALE;
- +}
- +
- void CNetClientSession::SetLongTimeout(bool enabled)
- {
- SetEnetLongTimeout(m_Server, m_IsLocalClient, enabled);
- @@ -229,6 +239,9 @@ void CNetClientSession::SetLongTimeout(bool enabled)
- CNetServerSession::CNetServerSession(CNetServerWorker& server, ENetPeer* peer) :
- m_Server(server), m_FileTransferer(this), m_Peer(peer), m_IsLocalClient(false), m_HostID(0), m_GUID(), m_UserName()
- {
- + char hostname[256] = "(error)";
- + if (enet_address_get_host(&peer->address, hostname, ARRAY_SIZE(hostname)) == 0)
- + m_Hostname = hostname;
- }
- u32 CNetServerSession::GetIPAddress() const
- @@ -236,6 +249,22 @@ u32 CNetServerSession::GetIPAddress() const
- return m_Peer->address.host;
- }
- +std::string CNetServerSession::GetIPAddressString() const
- +{
- + char ipAddress[256];
- + ipAddress[255] = '\0';
- +
- + if (enet_address_get_host_ip(&m_Peer->address, ipAddress, sizeof ipAddress) != 0)
- + return std::string();
- +
- + return ipAddress;
- +}
- +
- +std::string CNetServerSession::GetHostname() const
- +{
- + return m_Hostname;
- +}
- +
- u32 CNetServerSession::GetLastReceivedTime() const
- {
- if (!m_Peer)
- @@ -252,6 +281,14 @@ u32 CNetServerSession::GetMeanRTT() const
- return m_Peer->roundTripTime;
- }
- +u32 CNetServerSession::GetPacketLoss() const
- +{
- + if (!m_Peer)
- + return 0;
- +
- + return (double) m_Peer->packetLoss * PACKET_LOSS_SCALE_FACTOR;
- +}
- +
- void CNetServerSession::Disconnect(u32 reason)
- {
- Update((uint)NMT_CONNECTION_LOST, NULL);
- diff --git a/source/network/NetSession.h b/source/network/NetSession.h
- index 298d99c75f..5fba4f7ac9 100644
- --- a/source/network/NetSession.h
- +++ b/source/network/NetSession.h
- @@ -25,14 +25,14 @@
- #include "scriptinterface/ScriptVal.h"
- /**
- - * Report the peer if we didn't receive a packet after this time (milliseconds).
- + * Maximum timeout of the local client of the host (milliseconds).
- */
- -extern const u32 NETWORK_WARNING_TIMEOUT;
- +extern const u32 MAXIMUM_HOST_TIMEOUT;
- /**
- - * Maximum timeout of the local client of the host (milliseconds).
- + * Denominator of the packet loss ratio, whereas the numerator is sent as u32.
- */
- -extern const u32 MAXIMUM_HOST_TIMEOUT;
- +extern const double PACKET_LOSS_SCALE;
- class CNetClient;
- class CNetServerWorker;
- @@ -105,6 +105,11 @@ public:
- */
- u32 GetMeanRTT() const;
- + /**
- + * Average ratio of packets lost.
- + */
- + double GetPacketLossRatio() const;
- +
- /**
- * Allows increasing the timeout to prevent drops during an expensive operation,
- * and decreasing it back to normal afterwards.
- @@ -153,6 +158,8 @@ public:
- void SetHostID(u32 id) { m_HostID = id; }
- u32 GetIPAddress() const;
- + std::string GetIPAddressString() const;
- + std::string GetHostname() const;
- /**
- * Whether this client is running in the same process as the server.
- @@ -169,6 +176,11 @@ public:
- */
- u32 GetMeanRTT() const;
- + /**
- + * Average ratio of packets lost with regards to ENET_PEER_PACKET_LOSS_SCALE. Indicates connection quality.
- + */
- + u32 GetPacketLoss() const;
- +
- /**
- * Sends a disconnection notification to the client,
- * and sends a NMT_CONNECTION_LOST message to the session FSM.
- @@ -213,6 +225,9 @@ private:
- CStrW m_UserName;
- u32 m_HostID;
- + // Cache
- + CStr m_Hostname;
- +
- bool m_IsLocalClient;
- };
- diff --git a/source/network/scripting/JSInterface_Network.cpp b/source/network/scripting/JSInterface_Network.cpp
- index 9b7fd7136a..b21b71e023 100644
- --- a/source/network/scripting/JSInterface_Network.cpp
- +++ b/source/network/scripting/JSInterface_Network.cpp
- @@ -23,12 +23,14 @@
- #include "lib/external_libraries/libsdl.h"
- #include "lib/types.h"
- #include "lobby/IXmppClient.h"
- +#include "network/IPTools.h"
- #include "network/NetClient.h"
- #include "network/NetMessage.h"
- #include "network/NetServer.h"
- #include "network/StunClient.h"
- #include "ps/CLogger.h"
- #include "ps/Game.h"
- +#include "simulation2/system/TurnManager.h"
- #include "scriptinterface/ScriptInterface.h"
- u16 JSI_Network::GetDefaultPort(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
- @@ -163,6 +165,18 @@ JS::Value JSI_Network::PollNetworkClient(ScriptInterface::CxPrivate* pCxPrivate)
- return pCxPrivate->pScriptInterface->CloneValueFromOtherContext(g_NetClient->GetScriptInterface(), pollNet);
- }
- +JS::Value JSI_Network::GetNetworkClientPerformance(ScriptInterface::CxPrivate* pCxPrivate)
- +{
- + if (!g_NetClient)
- + return JS::UndefinedValue();
- +// TODO: Too many questionmarks in the dialog
- + // Convert from net client context to GUI script context
- + JSContext* cxNet = g_NetClient->GetScriptInterface().GetContext();
- + JSAutoRequest rqNet(cxNet);
- + JS::RootedValue pollNet(cxNet, g_NetClient->GetClientPerformance());
- + return pCxPrivate->pScriptInterface->CloneValueFromOtherContext(g_NetClient->GetScriptInterface(), pollNet);
- +}
- +
- void JSI_Network::SetNetworkGameAttributes(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue attribs1)
- {
- ENSURE(g_NetClient);
- @@ -216,6 +230,11 @@ void JSI_Network::StartNetworkGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate
- g_NetClient->SendStartGameMessage();
- }
- +u32 JSI_Network::GetTurnLength(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
- +{
- + return DEFAULT_TURN_LENGTH_MP;
- +}
- +
- void JSI_Network::SetTurnLength(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), int length)
- {
- if (g_NetServer)
- @@ -224,6 +243,32 @@ void JSI_Network::SetTurnLength(ScriptInterface::CxPrivate* UNUSED(pCxPrivate),
- LOGERROR("Only network host can change turn length");
- }
- +std::string JSI_Network::GetClientIPAddress(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& guid)
- +{
- + if (!g_NetServer)
- + return std::string();
- +
- + return g_NetServer->GetClientIPAddress(guid);
- +}
- +
- +std::string JSI_Network::LookupClientHostname(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& guid)
- +{
- + if (!g_NetServer)
- + return std::string();
- +
- + return g_NetServer->GetHostname(guid);
- +}
- +
- +u32 JSI_Network::IPv4ToNumber(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& ipAddress)
- +{
- + u32 ipAddressNum = 0;
- +
- + if (!IPTools::ParseIPv4Address(ipAddress, ipAddressNum))
- + return 0;
- +
- + return ipAddressNum;
- +}
- +
- void JSI_Network::RegisterScriptFunctions(const ScriptInterface& scriptInterface)
- {
- scriptInterface.RegisterFunction<u16, &GetDefaultPort>("GetDefaultPort");
- @@ -235,6 +280,7 @@ void JSI_Network::RegisterScriptFunctions(const ScriptInterface& scriptInterface
- scriptInterface.RegisterFunction<void, &DisconnectNetworkGame>("DisconnectNetworkGame");
- scriptInterface.RegisterFunction<CStr, &GetPlayerGUID>("GetPlayerGUID");
- scriptInterface.RegisterFunction<JS::Value, &PollNetworkClient>("PollNetworkClient");
- + scriptInterface.RegisterFunction<JS::Value, &GetNetworkClientPerformance>("GetNetworkClientPerformance");
- scriptInterface.RegisterFunction<void, JS::HandleValue, &SetNetworkGameAttributes>("SetNetworkGameAttributes");
- scriptInterface.RegisterFunction<void, int, CStr, &AssignNetworkPlayer>("AssignNetworkPlayer");
- scriptInterface.RegisterFunction<void, CStrW, bool, &KickPlayer>("KickPlayer");
- @@ -242,5 +288,9 @@ void JSI_Network::RegisterScriptFunctions(const ScriptInterface& scriptInterface
- scriptInterface.RegisterFunction<void, int, &SendNetworkReady>("SendNetworkReady");
- scriptInterface.RegisterFunction<void, &ClearAllPlayerReady>("ClearAllPlayerReady");
- scriptInterface.RegisterFunction<void, &StartNetworkGame>("StartNetworkGame");
- + scriptInterface.RegisterFunction<u32, &GetTurnLength>("GetTurnLength");
- scriptInterface.RegisterFunction<void, int, &SetTurnLength>("SetTurnLength");
- + scriptInterface.RegisterFunction<std::string, std::string, &GetClientIPAddress>("GetClientIPAddress");
- + scriptInterface.RegisterFunction<u32, std::string, &IPv4ToNumber>("IPv4ToNumber");
- + scriptInterface.RegisterFunction<std::string, std::string, &LookupClientHostname>("LookupClientHostname");
- }
- diff --git a/source/network/scripting/JSInterface_Network.h b/source/network/scripting/JSInterface_Network.h
- index 852bc47ace..7ccdbb2d28 100644
- --- a/source/network/scripting/JSInterface_Network.h
- +++ b/source/network/scripting/JSInterface_Network.h
- @@ -34,13 +34,18 @@ namespace JSI_Network
- JS::Value FindStunEndpoint(ScriptInterface::CxPrivate* pCxPrivate, int port);
- void DisconnectNetworkGame(ScriptInterface::CxPrivate* pCxPrivate);
- JS::Value PollNetworkClient(ScriptInterface::CxPrivate* pCxPrivate);
- + JS::Value GetNetworkClientPerformance(ScriptInterface::CxPrivate* pCxPrivate);
- CStr GetPlayerGUID(ScriptInterface::CxPrivate* pCxPrivate);
- void KickPlayer(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& playerName, bool ban);
- void AssignNetworkPlayer(ScriptInterface::CxPrivate* pCxPrivate, int playerID, const CStr& guid);
- void ClearAllPlayerReady (ScriptInterface::CxPrivate* pCxPrivate);
- void SendNetworkChat(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& message);
- void SendNetworkReady(ScriptInterface::CxPrivate* pCxPrivate, int message);
- + u32 GetTurnLength(ScriptInterface::CxPrivate* pCxPrivate);
- void SetTurnLength(ScriptInterface::CxPrivate* pCxPrivate, int length);
- + std::string GetClientIPAddress(ScriptInterface::CxPrivate* pCxPrivate, const std::string& guid);
- + std::string LookupClientHostname(ScriptInterface::CxPrivate* pCxPrivate, const std::string& guid);
- + u32 IPv4ToNumber(ScriptInterface::CxPrivate* pCxPrivate, const std::string& ipAddress);
- void RegisterScriptFunctions(const ScriptInterface& scriptInterface);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement