Measure the ping to the current server occasionally

This is done using the serverbrowser extended GETINFO packet. It's done
when the client enters the game and every ten minutes afterwards.
This commit is contained in:
heinrich5991 2021-04-23 23:12:16 +02:00
parent ed561c3602
commit a0df2bdf9c
4 changed files with 99 additions and 19 deletions

View file

@ -335,6 +335,11 @@ CClient::CClient() :
m_Points = -1;
m_CurrentServerInfoRequestTime = -1;
m_CurrentServerPingInfoType = -1;
m_CurrentServerPingBasicToken = -1;
m_CurrentServerPingToken = -1;
m_CurrentServerCurrentPingTime = -1;
m_CurrentServerNextPingTime = -1;
m_CurrentInput[0] = 0;
m_CurrentInput[1] = 0;
@ -655,6 +660,7 @@ void CClient::EnterGame()
OnEnterGame();
ServerInfoRequest(); // fresh one for timeout protection
m_CurrentServerNextPingTime = time_get() + time_freq() / 2;
m_aTimeoutCodeSent[0] = false;
m_aTimeoutCodeSent[1] = false;
}
@ -782,6 +788,11 @@ void CClient::DisconnectWithReason(const char *pReason)
m_NetClient[CLIENT_MAIN].Disconnect(pReason);
SetState(IClient::STATE_OFFLINE);
m_pMap->Unload();
m_CurrentServerPingInfoType = -1;
m_CurrentServerPingBasicToken = -1;
m_CurrentServerPingToken = -1;
m_CurrentServerCurrentPingTime = -1;
m_CurrentServerNextPingTime = -1;
// disable all downloads
m_MapdownloadChunk = 0;
@ -1458,14 +1469,6 @@ void CClient::ProcessServerInfo(int RawType, NETADDR *pFrom, const void *pData,
if(!DuplicatedPacket && (!pEntry || !pEntry->m_GotInfo || SavedType >= pEntry->m_Info.m_Type))
{
m_ServerBrowser.Set(*pFrom, IServerBrowser::SET_TOKEN, Token, &Info);
pEntry = m_ServerBrowser.Find(*pFrom);
if(SavedType == SERVERINFO_VANILLA && Is64Player(&Info) && pEntry)
{
pEntry->m_Request64Legacy = true;
// Force a quick update.
m_ServerBrowser.RequestImpl64(pEntry->m_Addr, pEntry);
}
}
// Player info is irrelevant for the client (while connected),
@ -1484,6 +1487,30 @@ void CClient::ProcessServerInfo(int RawType, NETADDR *pFrom, const void *pData,
m_CurrentServerInfo.m_NetAddr = m_ServerAddress;
m_CurrentServerInfoRequestTime = -1;
}
bool ValidPong = false;
if(m_CurrentServerCurrentPingTime >= 0 && SavedType >= m_CurrentServerPingInfoType)
{
if(RawType == SERVERINFO_VANILLA)
{
ValidPong = Token == m_CurrentServerPingBasicToken;
}
else if(RawType == SERVERINFO_EXTENDED)
{
ValidPong = Token == m_CurrentServerPingToken;
}
}
if(ValidPong)
{
int LatencyMs = (time_get() - m_CurrentServerCurrentPingTime) * 1000 / time_freq();
m_ServerBrowser.SetCurrentServerPing(m_ServerAddress, LatencyMs);
m_CurrentServerPingInfoType = SavedType;
m_CurrentServerCurrentPingTime = -1;
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "got pong from current server, latency=%dms", LatencyMs);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
}
}
}
@ -2765,9 +2792,23 @@ void CClient::Update()
m_CurrentServerInfoRequestTime >= 0 &&
time_get() > m_CurrentServerInfoRequestTime)
{
m_ServerBrowser.RequestCurrentServer(m_ServerAddress);
m_ServerBrowser.RequestCurrentServer(m_ServerAddress, nullptr, nullptr);
m_CurrentServerInfoRequestTime = time_get() + time_freq() * 2;
}
// periodically ping server
if(State() == IClient::STATE_ONLINE &&
m_CurrentServerNextPingTime >= 0 &&
time_get() > m_CurrentServerNextPingTime)
{
int64 Now = time_get();
int64 Freq = time_freq();
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", "pinging current server");
m_ServerBrowser.RequestCurrentServer(m_ServerAddress, &m_CurrentServerPingBasicToken, &m_CurrentServerPingToken);
m_CurrentServerCurrentPingTime = Now;
m_CurrentServerNextPingTime = Now + 600 * Freq; // ping every 10 minutes
}
}
m_LastDummy = (bool)g_Config.m_ClDummy;

View file

@ -242,6 +242,12 @@ class CClient : public IClient, public CDemoPlayer::IListener
class CServerInfo m_CurrentServerInfo;
int64 m_CurrentServerInfoRequestTime; // >= 0 should request, == -1 got info
int m_CurrentServerPingInfoType;
int m_CurrentServerPingBasicToken;
int m_CurrentServerPingToken;
int64 m_CurrentServerCurrentPingTime; // >= 0 request running
int64 m_CurrentServerNextPingTime; // >= 0 should request
// version info
struct CVersionInfo
{

View file

@ -706,15 +706,24 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer
}
}
if(!pEntry->m_RequestIgnoreInfo)
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
{
SetInfo(pEntry, *pInfo);
}
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
pEntry->m_Info.m_Latency = minimum(static_cast<int>((time_get() - m_BroadcastTime) * 1000 / time_freq()), 999);
if(pInfo->m_Type == SERVERINFO_VANILLA && Is64Player(pInfo))
{
pEntry->m_Request64Legacy = true;
// Force a quick update.
RequestImpl64(pEntry->m_Addr, pEntry);
}
}
else if(pEntry->m_RequestTime > 0)
{
if(!pEntry->m_RequestIgnoreInfo)
{
SetInfo(pEntry, *pInfo);
}
int Latency = minimum(static_cast<int>((time_get() - pEntry->m_RequestTime) * 1000 / time_freq()), 999);
if(!pEntry->m_RequestIgnoreInfo)
{
@ -728,6 +737,16 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer
SetLatency(Addr, Latency);
}
pEntry->m_RequestTime = -1; // Request has been answered
if(!pEntry->m_RequestIgnoreInfo)
{
if(pInfo->m_Type == SERVERINFO_VANILLA && Is64Player(pInfo))
{
pEntry->m_Request64Legacy = true;
// Force a quick update.
RequestImpl64(pEntry->m_Addr, pEntry);
}
}
}
RemoveRequest(pEntry);
}
@ -792,7 +811,7 @@ void CServerBrowser::Refresh(int Type)
}
}
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken) const
{
unsigned char Buffer[sizeof(SERVERBROWSE_GETINFO) + 1];
CNetChunk Packet;
@ -807,6 +826,14 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons
}
int Token = GenerateToken(Addr);
if(pToken)
{
*pToken = Token;
}
if(pBasicToken)
{
*pBasicToken = GetBasicToken(Token);
}
mem_copy(Buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
Buffer[sizeof(SERVERBROWSE_GETINFO)] = GetBasicToken(Token);
@ -855,9 +882,14 @@ void CServerBrowser::RequestImpl64(const NETADDR &Addr, CServerEntry *pEntry) co
pEntry->m_RequestTime = time_get();
}
void CServerBrowser::RequestCurrentServer(const NETADDR &Addr) const
void CServerBrowser::RequestCurrentServer(const NETADDR &Addr, int *pBasicToken, int *pToken) const
{
RequestImpl(Addr, 0);
RequestImpl(Addr, nullptr, pBasicToken, pToken);
}
void CServerBrowser::SetCurrentServerPing(const NETADDR &Addr, int Ping)
{
SetLatency(Addr, std::min(Ping, 999));
}
void ServerBrowserFillEstimatedLatency(int OwnLocation, const IServerBrowserPingCache::CEntry *pEntries, int NumEntries, int *pIndex, NETADDR Addr, CServerInfo *pInfo)
@ -1097,7 +1129,7 @@ void CServerBrowser::Update(bool ForceResort)
if(pEntry->m_Request64Legacy)
RequestImpl64(pEntry->m_Addr, pEntry);
else
RequestImpl(pEntry->m_Addr, pEntry);
RequestImpl(pEntry->m_Addr, pEntry, nullptr, nullptr);
}
Count++;

View file

@ -129,7 +129,8 @@ public:
//
void Update(bool ForceResort);
void Set(const NETADDR &Addr, int Type, int Token, const CServerInfo *pInfo);
void RequestCurrentServer(const NETADDR &Addr) const;
void RequestCurrentServer(const NETADDR &Addr, int *pBasicToken, int *pToken) const;
void SetCurrentServerPing(const NETADDR &Addr, int Ping);
void SetBaseInfo(class CNetClient *pClient, const char *pNetVersion);
@ -211,7 +212,7 @@ private:
void RemoveRequest(CServerEntry *pEntry);
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const;
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry, int *pBasicToken, int *pToken) const;
void RegisterCommands();
static void Con_LeakIpAddress(IConsole::IResult *pResult, void *pUserData);