1818#include " host.h"
1919#include " eiface.h"
2020#include " server.h"
21+ #include " utlmap.h"
2122
2223extern ConVar sv_tags;
2324extern ConVar sv_lan;
2425
2526#define S2A_EXTRA_DATA_HAS_GAMETAG_DATA 0x01 // Next bytes are the game tag string
27+ #define RETRY_INFO_REQUEST_TIME 0.4 // seconds
28+ #define INFO_REQUEST_TIMEOUT 5.0 // seconds
2629
2730// -----------------------------------------------------------------------------
2831// Purpose: List of master servers and some state info about them
@@ -62,6 +65,7 @@ class CMaster : public IMaster, public IServersInfo
6265 void UseDefault ( void );
6366 void CheckHeartbeat (void );
6467 void RespondToHeartbeatChallenge ( netadr_t &from, bf_read &msg );
68+ void PingServer ( netadr_t &svadr );
6569
6670 void ProcessConnectionlessPacket ( netpacket_t *packet );
6771
@@ -70,23 +74,35 @@ class CMaster : public IMaster, public IServersInfo
7074
7175 void RunFrame ();
7276 void RequestServersInfo ();
73- void ReplyInfo ( const netadr_t &adr );
77+
78+ void ReplyInfo ( const netadr_t &adr, uint sequence );
7479 newgameserver_t &ProcessInfo ( bf_read &buf );
7580
7681 // SeversInfo
7782 void RequestInternetServerList ( const char *gamedir, IServerListResponse *response );
7883 void RequestLANServerList ( const char *gamedir, IServerListResponse *response );
7984 void AddServerAddresses ( netadr_t **adr, int count );
85+ void StopRefresh ();
86+
8087private:
8188 // List of known master servers
8289 adrlist_t *m_pMasterAddresses;
8390
8491 bool m_bInitialized;
92+ bool m_bWaitingForReplys;
93+
94+ int m_iServersResponded;
95+
96+ double m_flStartRequestTime;
97+ double m_flRetryRequestTime;
98+
99+ uint m_iInfoSequence;
85100
86101 // If nomaster is true, the server will not send heartbeats to the master server
87102 bool m_bNoMasters;
88103
89- CUtlLinkedList<netadr_t > m_serverAddresses;
104+ CUtlMap<netadr_t , bool > m_serverAddresses;
105+ CUtlMap<uint, double > m_serversRequestTime;
90106
91107 IServerListResponse *m_serverListResponse;
92108};
@@ -108,8 +124,13 @@ CMaster::CMaster( void )
108124 m_pMasterAddresses = NULL ;
109125 m_bNoMasters = false ;
110126 m_bInitialized = false ;
127+ m_iServersResponded = 0 ;
111128
112129 m_serverListResponse = NULL ;
130+ SetDefLessFunc ( m_serverAddresses );
131+ SetDefLessFunc ( m_serversRequestTime );
132+ m_bWaitingForReplys = false ;
133+ m_iInfoSequence = 0 ;
113134
114135 Init ();
115136}
@@ -121,9 +142,34 @@ CMaster::~CMaster( void )
121142void CMaster::RunFrame ()
122143{
123144 CheckHeartbeat ();
145+
146+ if ( !m_bWaitingForReplys )
147+ return ;
148+
149+ if ( m_serverListResponse &&
150+ m_flStartRequestTime < Plat_FloatTime ()-INFO_REQUEST_TIMEOUT )
151+ {
152+ m_serverListResponse->RefreshComplete ( NServerResponse::nServerFailedToRespond );
153+ m_bWaitingForReplys = false ;
154+ }
155+
156+ if ( m_flRetryRequestTime < Plat_FloatTime () - RETRY_INFO_REQUEST_TIME )
157+ {
158+ m_flRetryRequestTime = Plat_FloatTime ();
159+
160+ if ( m_iServersResponded < m_serverAddresses.Count () )
161+ RequestServersInfo ();
162+ }
124163}
125164
126- void CMaster::ReplyInfo ( const netadr_t &adr )
165+ void CMaster::StopRefresh ()
166+ {
167+ m_bWaitingForReplys = false ;
168+ m_serverAddresses.RemoveAll ();
169+ m_serversRequestTime.RemoveAll ();
170+ }
171+
172+ void CMaster::ReplyInfo ( const netadr_t &adr, uint sequence )
127173{
128174 static char gamedir[MAX_OSPATH];
129175 Q_FileBase ( com_gamedir, gamedir, sizeof ( gamedir ) );
@@ -134,6 +180,7 @@ void CMaster::ReplyInfo( const netadr_t &adr )
134180 buf.PutUnsignedInt ( LittleDWord ( CONNECTIONLESS_HEADER ) );
135181 buf.PutUnsignedChar ( S2C_INFOREPLY );
136182
183+ buf.PutUnsignedInt (sequence);
137184 buf.PutUnsignedChar ( PROTOCOL_VERSION ); // Hardcoded protocol version number
138185 buf.PutString ( sv.GetName () );
139186 buf.PutString ( sv.GetMapName () );
@@ -217,8 +264,7 @@ void CMaster::ProcessConnectionlessPacket( netpacket_t *packet )
217264 }
218265 case M2C_QUERY:
219266 {
220- if ( m_serverAddresses.Count () > 0 )
221- m_serverAddresses.RemoveAll ();
267+ m_serverAddresses.RemoveAll ();
222268
223269 ip = msg.ReadLong ();
224270 port = msg.ReadShort ();
@@ -227,33 +273,48 @@ void CMaster::ProcessConnectionlessPacket( netpacket_t *packet )
227273 {
228274 netadr_t adr (ip, port);
229275
230- m_serverAddresses.AddToHead (adr);
276+ m_serverAddresses.Insert (adr, false );
231277
232278 ip = msg.ReadLong ();
233279 port = msg.ReadShort ();
234280 }
235281
282+ m_iServersResponded = 0 ;
236283 RequestServersInfo ();
284+ m_flRetryRequestTime = m_flStartRequestTime = Plat_FloatTime ();
237285 break ;
238286 }
239287 case C2S_INFOREQUEST:
240288 {
241- ReplyInfo (packet->from );
289+ ReplyInfo (packet->from , msg. ReadLong () );
242290 break ;
243291 }
244292 case S2C_INFOREPLY:
245293 {
294+ uint sequence = msg.ReadLong ();
246295 newgameserver_t &s = ProcessInfo ( msg );
247- Msg (" hostname = %s\n players: %d/%d\n bots: %d\n " , s.m_szServerName , s.m_nPlayers , s.m_nMaxPlayers , s.m_nBotPlayers );
248296
297+ unsigned short index = m_serverAddresses.Find (packet->from );
298+ unsigned short rindex = m_serversRequestTime.Find (sequence);
299+
300+ if ( index == m_serverAddresses.InvalidIndex () ||
301+ rindex == m_serversRequestTime.InvalidIndex () )
302+ break ;
303+
304+ double requestTime = m_serversRequestTime[rindex];
305+
306+ m_serverAddresses[index] = true ;
307+ s.m_nPing = (packet->received -requestTime)*1000.0 ;
249308 s.m_NetAdr = packet->from ;
250309 m_serverListResponse->ServerResponded ( s );
251- break ;
252- }
253- case A2A_PING:
254- {
255- const char p = A2A_ACK;
256- NET_SendPacket ( NULL , NS_SERVER, packet->from , (unsigned char *)&p, 1 );
310+
311+ m_iServersResponded++;
312+
313+ if ( m_iServersResponded >= m_serverAddresses.Count () )
314+ {
315+ StopRefresh ();
316+ m_serverListResponse->RefreshComplete ( NServerResponse::nServerResponded );
317+ }
257318 break ;
258319 }
259320 }
@@ -265,17 +326,24 @@ void CMaster::RequestServersInfo()
265326
266327 bf_write msg ( string, sizeof (string) );
267328
268- FOR_EACH_LL ( m_serverAddresses, i )
329+ FOR_EACH_MAP_FAST ( m_serverAddresses, i )
269330 {
270- const netadr_t adr = m_serverAddresses[i];
331+ bool bResponded = m_serverAddresses.Element (i);
332+ if ( bResponded )
333+ continue ;
271334
272- Msg ( " Request server info %s \n " , adr. ToString () );
335+ const netadr_t adr = m_serverAddresses. Key (i );
273336
274337 msg.WriteLong ( CONNECTIONLESS_HEADER );
275338 msg.WriteByte ( C2S_INFOREQUEST );
339+ msg.WriteLong ( m_iInfoSequence );
340+ m_serversRequestTime.Insert (m_iInfoSequence, net_time);
276341
342+ m_iInfoSequence++;
277343 NET_SendPacket ( NULL , NS_CLIENT, adr, msg.GetData (), msg.GetNumBytesWritten () );
278344 }
345+
346+ m_bWaitingForReplys = true ;
279347}
280348
281349// -----------------------------------------------------------------------------
@@ -410,7 +478,7 @@ void CMaster::AddServer( netadr_t *adr )
410478
411479 n = ( adrlist_t * ) malloc ( sizeof ( adrlist_t ) );
412480 if ( !n )
413- Sys_Error ( " Error allocating %i bytes for master address." , sizeof ( adrlist_t ) );
481+ Sys_Error ( " Error allocating %zd bytes for master address." , sizeof ( adrlist_t ) );
414482
415483 memset ( n, 0 , sizeof ( adrlist_t ) );
416484
0 commit comments