1955: Cache serverinfo responses r=def- a=Learath2

I'm not sure I like it but it works

Co-authored-by: Learath2 <learath2@gmail.com>
This commit is contained in:
bors[bot] 2019-11-03 20:09:21 +00:00 committed by GitHub
commit 0de012572b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 158 additions and 42 deletions

View file

@ -188,6 +188,7 @@ public:
virtual void SetTimeoutProtected(int ClientID) = 0;
virtual void SetErrorShutdown(const char *pReason) = 0;
virtual void ExpireServerInfo() = 0;
virtual char *GetMapName() = 0;
};

View file

@ -285,6 +285,7 @@ CServer::CServer()
m_ServerInfoFirstRequest = 0;
m_ServerInfoNumRequests = 0;
m_ServerInfoNeedsUpdate = false;
#ifdef CONF_FAMILY_UNIX
m_ConnLoggingSocketCreated = false;
@ -1266,6 +1267,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
m_aClients[ClientID].m_State = CClient::STATE_INGAME;
GameServer()->OnClientEnter(ClientID);
ExpireServerInfo();
}
}
else if(Msg == NETMSG_INPUT)
@ -1503,8 +1505,36 @@ void CServer::SendServerInfoConnless(const NETADDR *pAddr, int Token, int Type)
SendServerInfo(pAddr, Token, Type, SendClients);
}
void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool SendClients)
CServer::CCache::CCache()
{
m_lCache.clear();
}
CServer::CCache::~CCache()
{
Clear();
}
CServer::CCache::CCacheChunk::CCacheChunk(const void *pData, int Size)
{
mem_copy(m_aData, pData, Size);
m_DataSize = Size;
}
void CServer::CCache::AddChunk(const void *pData, int Size)
{
m_lCache.emplace_back(pData, Size);
}
void CServer::CCache::Clear()
{
m_lCache.clear();
}
void CServer::CacheServerInfo(CCache *pCache, int Type, bool SendClients)
{
pCache->Clear();
// One chance to improve the protocol!
CPacker p;
char aBuf[128];
@ -1527,17 +1557,6 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool Sen
#define ADD_RAW(p, x) (p).AddRaw(x, sizeof(x))
#define ADD_INT(p, x) do { str_format(aBuf, sizeof(aBuf), "%d", x); (p).AddString(aBuf, 0); } while(0)
switch(Type)
{
case SERVERINFO_EXTENDED: ADD_RAW(p, SERVERBROWSE_INFO_EXTENDED); break;
case SERVERINFO_64_LEGACY: ADD_RAW(p, SERVERBROWSE_INFO_64_LEGACY); break;
case SERVERINFO_VANILLA: ADD_RAW(p, SERVERBROWSE_INFO); break;
case SERVERINFO_INGAME: ADD_RAW(p, SERVERBROWSE_INFO); break;
default: dbg_assert(false, "unknown serverinfo type");
}
ADD_INT(p, Token);
p.AddString(GameServer()->Version(), 32);
if(Type != SERVERINFO_VANILLA)
{
@ -1597,20 +1616,14 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool Sen
int PrefixSize = p.Size();
CPacker pp;
CNetChunk Packet;
int PacketsSent = 0;
int PlayersSent = 0;
Packet.m_ClientID = -1;
Packet.m_Address = *pAddr;
Packet.m_Flags = NETSENDFLAG_CONNLESS;
int ChunksStored = 0;
int PlayersStored = 0;
#define SEND(size) \
#define SAVE(size) \
do \
{ \
Packet.m_pData = pp.Data(); \
Packet.m_DataSize = size; \
m_NetServer.Send(&Packet); \
PacketsSent++; \
pCache->AddChunk(pp.Data(), size); \
ChunksStored++; \
} while(0)
#define RESET() \
@ -1623,18 +1636,18 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool Sen
RESET();
if(Type == SERVERINFO_64_LEGACY)
pp.AddInt(PlayersSent); // offset
pp.AddInt(PlayersStored); // offset
if(!SendClients)
{
SEND(pp.Size());
SAVE(pp.Size());
return;
}
if(Type == SERVERINFO_EXTENDED)
{
pPrefix = SERVERBROWSE_INFO_EXTENDED_MORE;
PrefixSize = sizeof(SERVERBROWSE_INFO_EXTENDED_MORE);
pPrefix = "";
PrefixSize = 0;
}
int Remaining;
@ -1662,9 +1675,9 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool Sen
break;
// Otherwise we're SERVERINFO_64_LEGACY.
SEND(pp.Size());
SAVE(pp.Size());
RESET();
pp.AddInt(PlayersSent); // offset
pp.AddInt(PlayersStored); // offset
Remaining = 24;
}
if(Remaining > 0)
@ -1689,36 +1702,104 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool Sen
{
// Retry current player.
i--;
SEND(PreviousSize);
SAVE(PreviousSize);
RESET();
ADD_INT(pp, Token);
ADD_INT(pp, PacketsSent);
ADD_INT(pp, ChunksStored);
pp.AddString("", 0); // extra info, reserved
continue;
}
}
PlayersSent++;
PlayersStored++;
}
}
SEND(pp.Size());
#undef SEND
SAVE(pp.Size());
#undef SAVE
#undef RESET
#undef ADD_RAW
#undef ADD_INT
}
void CServer::UpdateServerInfo()
void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool SendClients)
{
for(int i = 0; i < MAX_CLIENTS; ++i)
CPacker p;
char aBuf[128];
p.Reset();
CCache *pCache = &m_ServerInfoCache[Type * 2 + SendClients];
CCache::CCacheChunk &FirstChunk = pCache->m_lCache.front();
#define ADD_RAW(p, x) (p).AddRaw(x, sizeof(x))
#define ADD_INT(p, x) do { str_format(aBuf, sizeof(aBuf), "%d", x); (p).AddString(aBuf, 0); } while(0)
switch(Type)
{
if(m_aClients[i].m_State != CClient::STATE_EMPTY)
case SERVERINFO_EXTENDED: ADD_RAW(p, SERVERBROWSE_INFO_EXTENDED); break;
case SERVERINFO_64_LEGACY: ADD_RAW(p, SERVERBROWSE_INFO_64_LEGACY); break;
case SERVERINFO_VANILLA:
case SERVERINFO_INGAME: ADD_RAW(p, SERVERBROWSE_INFO); break;
default: dbg_assert(false, "unknown serverinfo type");
}
ADD_INT(p, Token);
p.AddRaw(FirstChunk.m_aData, FirstChunk.m_DataSize);
CNetChunk Packet;
Packet.m_ClientID = -1;
Packet.m_Address = *pAddr;
Packet.m_Flags = NETSENDFLAG_CONNLESS;
Packet.m_pData = p.Data();
Packet.m_DataSize = p.Size();
m_NetServer.Send(&Packet);
if(Type == SERVERINFO_INGAME || Type == SERVERINFO_VANILLA)
return;
for(const auto &Chunk : pCache->m_lCache)
{
p.Reset();
if(Type == SERVERINFO_EXTENDED)
{
SendServerInfo(m_NetServer.ClientAddr(i), -1, SERVERINFO_INGAME, false);
p.AddRaw(SERVERBROWSE_INFO_EXTENDED_MORE, sizeof(SERVERBROWSE_INFO_EXTENDED_MORE));
ADD_INT(p, Token);
}
else if(Type == SERVERINFO_64_LEGACY)
{
p.AddRaw(FirstChunk.m_aData, FirstChunk.m_DataSize);
}
p.AddRaw(Chunk.m_aData, Chunk.m_DataSize);
Packet.m_pData = p.Data();
Packet.m_DataSize = p.Size();
m_NetServer.Send(&Packet);
}
}
void CServer::ExpireServerInfo()
{
m_ServerInfoNeedsUpdate = true;
}
void CServer::UpdateServerInfo(bool Resend)
{
for(int i = 0; i < 3; i++)
for(int j = 0; j < 2; j++)
CacheServerInfo(&m_ServerInfoCache[i * 2 + j], i, j);
if(Resend)
{
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(m_aClients[i].m_State != CClient::STATE_EMPTY)
{
SendServerInfo(m_NetServer.ClientAddr(i), -1, SERVERINFO_INGAME, false);
}
}
}
m_ServerInfoNeedsUpdate = false;
}
void CServer::PumpNetwork()
{
@ -1923,6 +2004,7 @@ int CServer::Run()
m_Lastheartbeat = 0;
m_GameStartTime = time_get();
UpdateServerInfo();
while(m_RunServer)
{
if(NonActive)
@ -1963,7 +2045,7 @@ int CServer::Run()
{
break;
}
UpdateServerInfo();
UpdateServerInfo(true);
}
else
{
@ -2067,6 +2149,9 @@ int CServer::Run()
// master server stuff
m_Register.RegisterUpdate(m_NetServer.NetType());
if(m_ServerInfoNeedsUpdate)
UpdateServerInfo();
if(!NonActive)
PumpNetwork();
@ -2701,7 +2786,7 @@ void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserD
{
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments())
((CServer *)pUserData)->UpdateServerInfo();
((CServer *)pUserData)->UpdateServerInfo(true);
}
void CServer::ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)

View file

@ -23,6 +23,8 @@
#include <base/tl/array.h>
#include <list>
#include "authmanager.h"
#include "name_ban.h"
@ -291,9 +293,33 @@ public:
void ProcessClientPacket(CNetChunk *pPacket);
class CCache {
public:
class CCacheChunk {
public:
CCacheChunk(const void *pData, int Size);
CCacheChunk(const CCacheChunk &) = delete;
int m_DataSize;
unsigned char m_aData[NET_MAX_PAYLOAD];
};
std::list<CCacheChunk> m_lCache;
CCache();
~CCache();
void AddChunk(const void *pData, int Size);
void Clear();
};
CCache m_ServerInfoCache[3 * 2];
bool m_ServerInfoNeedsUpdate;
void ExpireServerInfo();
void CacheServerInfo(CCache *pCache, int Type, bool SendClients);
void SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool SendClients);
void SendServerInfoConnless(const NETADDR *pAddr, int Token, int Type);
void UpdateServerInfo();
void UpdateServerInfo(bool Resend = false);
void PumpNetwork();

View file

@ -1837,6 +1837,8 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
pPlayer->m_TeeInfos.m_UseCustomColor = pMsg->m_UseCustomColor;
pPlayer->m_TeeInfos.m_ColorBody = pMsg->m_ColorBody;
pPlayer->m_TeeInfos.m_ColorFeet = pMsg->m_ColorFeet;
Server()->ExpireServerInfo();
}
else if (MsgID == NETMSGTYPE_CL_EMOTICON && !m_World.m_Paused)
{
@ -1955,6 +1957,8 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
CNetMsg_Sv_ReadyToEnter m;
Server()->SendPackMsg(&m, MSGFLAG_VITAL|MSGFLAG_FLUSH, ClientID);
}
Server()->ExpireServerInfo();
}
}