From cc5f95d1caebc3feb9e9c9216339215365b0f973 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Fri, 3 Oct 2025 21:54:54 +0500 Subject: [PATCH] engine: support querying legacy goldsrc master servers * General refactoring, hide out of band messages under cl_log_outofband cvar, similar to sv_log_outofband. --- engine/client/cl_main.c | 154 +++++++++-------------- engine/client/client.h | 8 +- engine/common/common.h | 4 +- engine/common/masterlist.c | 249 ++++++++++++++++++++++++++++--------- engine/server/sv_client.c | 4 +- 5 files changed, 257 insertions(+), 162 deletions(-) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 004d77dc..fc87d357 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -98,13 +98,12 @@ CVAR_DEFINE_AUTO( rate, "25000", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" ); static CVAR_DEFINE_AUTO( cl_advertise_engine_in_name, "1", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "add [Xash3D] to the nickname when connecting to GoldSrc servers" ); +static CVAR_DEFINE_AUTO( cl_log_outofband, "0", FCVAR_ARCHIVE, "log out of band messages, can be useful for server admins and for engine debugging" ); client_t cl; client_static_t cls; clgame_static_t clgame; -static void CL_SendMasterServerScanRequest( void ); - //====================================================================== int GAME_EXPORT CL_Active( void ) { @@ -1232,7 +1231,13 @@ static void CL_CheckForResend( void ) qboolean bandwidthTest; if( cls.internetservers_wait ) - CL_SendMasterServerScanRequest(); + { + cls.internetservers_wait = NET_MasterQuery( + cls.internetservers_key, + cls.internetservers_nat, + cls.internetservers_customfilter + ); + } // if the local server is running and we aren't then connect if( cls.state == ca_disconnected && SV_Active( )) @@ -1755,60 +1760,6 @@ static void CL_LocalServers_f( void ) Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION ); } -/* -================= -CL_BuildMasterServerScanRequest -================= -*/ -static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, uint32_t *key, qboolean nat, const char *filter ) -{ - size_t remaining; - char *info, temp[32]; - - if( unlikely( size < sizeof( MS_SCAN_REQUEST ))) - return 0; - - Q_strncpy( buf, MS_SCAN_REQUEST, size ); - - info = buf + sizeof( MS_SCAN_REQUEST ) - 1; - remaining = size - sizeof( MS_SCAN_REQUEST ); - - Q_strncpy( info, filter, remaining ); - - *key = COM_RandomLong( 0, 0x7FFFFFFF ); - -#ifndef XASH_ALL_SERVERS - Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); -#endif - // let master know about client version - Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); - Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining ); - Info_SetValueForKey( info, "commit", g_buildcommit, remaining ); - Info_SetValueForKey( info, "branch", g_buildbranch, remaining ); - Info_SetValueForKey( info, "os", Q_buildos(), remaining ); - Info_SetValueForKey( info, "arch", Q_buildarch(), remaining ); - - Q_snprintf( temp, sizeof( temp ), "%d", Q_buildnum() ); - Info_SetValueForKey( info, "buildnum", temp, remaining ); - - Q_snprintf( temp, sizeof( temp ), "%x", *key ); - Info_SetValueForKey( info, "key", temp, remaining ); - - return sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ); -} - -/* -================= -CL_SendMasterServerScanRequest -================= -*/ -static void CL_SendMasterServerScanRequest( void ) -{ - cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, - cls.internetservers_query_len, cls.internetservers_query ); - cls.internetservers_pending = true; -} - /* ================= CL_InternetServers_f @@ -1816,24 +1767,42 @@ CL_InternetServers_f */ static void CL_InternetServers_f( void ) { - qboolean nat = cl_nat.value != 0.0f; - uint32_t key; - if( Cmd_Argc( ) > 2 || ( Cmd_Argc( ) == 2 && !Info_IsValid( Cmd_Argv( 1 )))) { Con_Printf( S_USAGE "internetservers [filter]\n" ); return; } - cls.internetservers_query_len = CL_BuildMasterServerScanRequest( - cls.internetservers_query, sizeof( cls.internetservers_query ), - &cls.internetservers_key, nat, Cmd_Argv( 1 )); - Con_Printf( "Scanning for servers on the internet area...\n" ); NET_Config( true, true ); // allow remote - CL_SendMasterServerScanRequest(); + cls.internetservers_nat = cl_nat.value != 0.0f; + cls.internetservers_pending = true; + cls.internetservers_key = COM_RandomLong( 0, 0xFFFFFFFF ); + Q_strncpy( cls.internetservers_customfilter, Cmd_Argv( 1 ), sizeof( cls.internetservers_customfilter )); + + cls.internetservers_wait = NET_MasterQuery( + cls.internetservers_key, + cls.internetservers_nat, + cls.internetservers_customfilter + ); +} + +static void CL_QueryServer( netadr_t adr, connprotocol_t proto ) +{ + switch( proto ) + { + case PROTO_GOLDSRC: + Netchan_OutOfBand( NS_CLIENT, adr, sizeof( A2S_GOLDSRC_INFO ), A2S_GOLDSRC_INFO ); // includes null terminator! + break; + case PROTO_LEGACY: + Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_LEGACY_VERSION ); + break; + case PROTO_CURRENT: + Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION ); + break; + } } static void CL_QueryServer_f( void ) @@ -1861,18 +1830,7 @@ static void CL_QueryServer_f( void ) if( !CL_StringToProtocol( Cmd_Argv( 2 ), &proto )) return; - switch( proto ) - { - case PROTO_GOLDSRC: - Netchan_OutOfBand( NS_CLIENT, adr, sizeof( A2S_GOLDSRC_INFO ), A2S_GOLDSRC_INFO ); // includes null terminator! - break; - case PROTO_LEGACY: - Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_LEGACY_VERSION ); - break; - case PROTO_CURRENT: - Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION ); - break; - } + CL_QueryServer( adr, proto ); } /* @@ -2059,6 +2017,9 @@ static void CL_ParseGoldSrcStatusMessage( netadr_t from, sizebuf_t *msg ) password = MSG_ReadByte( msg ); Q_strncpy( version, MSG_ReadString( msg ), sizeof( version )); + if( maxcl > MAX_CLIENTS || numcl > MAX_CLIENTS ) + return; + if( MSG_CheckOverflow( msg )) { Con_Printf( "%s: malfored info packet from %s\n", __func__, NET_AdrToString( from )); @@ -2466,29 +2427,34 @@ static void CL_Reject( const char *c, const char *args, netadr_t from ) static void CL_ServerList( netadr_t from, sizebuf_t *msg ) { - if( !NET_IsMasterAdr( from )) + connprotocol_t proto; + + if( !NET_IsMasterAdr( from, &proto )) { Con_Printf( S_WARN "unexpected server list packet from %s\n", NET_AdrToString( from )); return; } // check the extra header - if( MSG_ReadByte( msg ) == 0x7f ) + if( proto == PROTO_CURRENT ) { - uint32_t key = MSG_ReadDword( msg ); - - if( cls.internetservers_key != key ) + if( MSG_ReadByte( msg ) == 0x7f ) { - Con_Printf( S_WARN "unexpected server list packet from %s (invalid key)\n", NET_AdrToString( from )); + uint32_t key = MSG_ReadDword( msg ); + + if( cls.internetservers_key != key ) + { + Con_Printf( S_WARN "unexpected server list packet from %s (invalid key)\n", NET_AdrToString( from )); + return; + } + + MSG_ReadByte( msg ); // reserved byte + } + else + { + Con_Printf( S_WARN "invalid server list packet from %s (missing extra header)\n", NET_AdrToString( from )); return; } - - MSG_ReadByte( msg ); // reserved byte - } - else - { - Con_Printf( S_WARN "invalid server list packet from %s (missing extra header)\n", NET_AdrToString( from )); - return; } // serverlist got from masterserver @@ -2515,7 +2481,7 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg ) break; NET_Config( true, false ); // allow remote - Netchan_OutOfBandPrint( NS_CLIENT, servadr, A2A_INFO" %i", PROTOCOL_VERSION ); + CL_QueryServer( servadr, proto ); } if( cls.internetservers_pending ) @@ -2545,7 +2511,8 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) Cmd_TokenizeString( args ); c = Cmd_Argv( 0 ); - Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c ); + if( cl_log_outofband.value ) + Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c ); // server connection if( !Q_strcmp( c, S2C_GOLDSRC_CONNECTION ) || !Q_strcmp( c, S2C_CONNECTION )) @@ -2611,7 +2578,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, (byte *)buf ); } - else + else if( cl_log_outofband.value ) { Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); } @@ -3376,6 +3343,7 @@ static void CL_InitLocal( void ) Cvar_RegisterVariable( &cl_ticket_generator ); Cvar_RegisterVariable( &cl_advertise_engine_in_name ); + Cvar_RegisterVariable( &cl_log_outofband ); Cvar_RegisterVariable( &showpause ); Cvar_RegisterVariable( &mp_decals ); diff --git a/engine/client/client.h b/engine/client/client.h index 5750aea4..96d98a90 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -622,11 +622,11 @@ typedef struct file_t *demofile; file_t *demoheader; // contain demo startup info in case we record a demo on this level - qboolean internetservers_wait; // internetservers is waiting for dns request + qboolean internetservers_wait; // internetservers is waiting for dns request qboolean internetservers_pending; // if true, clean master server pings - uint32_t internetservers_key; // compare key to validate master server reply - char internetservers_query[512]; // cached query - uint32_t internetservers_query_len; + qboolean internetservers_nat; + string internetservers_customfilter; + uint32_t internetservers_key; // compare key to validate master server reply // multiprotocol support connprotocol_t legacymode; diff --git a/engine/common/common.h b/engine/common/common.h index 7d7450c6..0c8f1ddb 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -892,12 +892,12 @@ intptr_t V_GetGammaPtr( int parm ); // void NET_InitMasters( void ); void NET_SaveMasters( void ); -qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data ); -qboolean NET_IsMasterAdr( netadr_t adr ); +qboolean NET_IsMasterAdr( netadr_t adr, connprotocol_t *proto ); void NET_MasterHeartbeat( void ); void NET_MasterClear( void ); void NET_MasterShutdown( void ); qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat ); +qboolean NET_MasterQuery( uint32_t key, qboolean net, const char *filter ); // // munge.c diff --git a/engine/common/masterlist.c b/engine/common/masterlist.c index 905bf60d..0fb9d89a 100644 --- a/engine/common/masterlist.c +++ b/engine/common/masterlist.c @@ -22,6 +22,7 @@ typedef struct master_s qboolean sent; // TODO: get rid of this internal state qboolean save; qboolean v6only; + qboolean gs; string address; netadr_t adr; // temporary, rewritten after each send @@ -31,7 +32,7 @@ typedef struct master_s static struct masterlist_s { - master_t *list; + master_t *head, *tail; qboolean modified; } ml; @@ -39,6 +40,43 @@ static CVAR_DEFINE_AUTO( sv_verbose_heartbeats, "0", 0, "print every heartbeat t #define HEARTBEAT_SECONDS ((sv_nat.value > 0.0f) ? 60.0f : 300.0f) // 1 or 5 minutes +static size_t NET_BuildMasterServerScanRequest( char *buf, size_t size, uint32_t key, qboolean nat, const char *filter, connprotocol_t proto ) +{ + size_t remaining; + char *info, temp[32]; + + // TODO: pagination and region + Q_strncpy( buf, MS_SCAN_REQUEST, size ); + + info = buf + sizeof( MS_SCAN_REQUEST ) - 1; + remaining = size - sizeof( MS_SCAN_REQUEST ); + + Q_strncpy( info, filter, remaining ); + +#ifndef XASH_ALL_SERVERS + Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); +#endif // XASH_ALL_SERVERS + + if( proto != PROTO_GOLDSRC ) + { + // let master know about client version + Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); + Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining ); + Info_SetValueForKey( info, "commit", g_buildcommit, remaining ); + Info_SetValueForKey( info, "branch", g_buildbranch, remaining ); + Info_SetValueForKey( info, "os", Q_buildos(), remaining ); + Info_SetValueForKey( info, "arch", Q_buildarch(), remaining ); + + Q_snprintf( temp, sizeof( temp ), "%d", Q_buildnum() ); + Info_SetValueForKey( info, "buildnum", temp, remaining ); + + Q_snprintf( temp, sizeof( temp ), "%x", key ); + Info_SetValueForKey( info, "key", temp, remaining ); + } + + return sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ); +} + /* ======================== NET_GetMasterHostByName @@ -66,28 +104,39 @@ Send request to all masterservers list return true if would block ======================== */ -qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data ) +static qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data, connprotocol_t proto ) { - master_t *list; + master_t *master; qboolean wait = false; - for( list = ml.list; list; list = list->next ) + for( master = ml.head; master; master = master->next ) { - if( list->sent ) + if( master->sent ) continue; - switch( NET_GetMasterHostByName( list )) + if( master->gs ) + { + if( proto != PROTO_GOLDSRC ) + continue; + } + else + { + if( proto != PROTO_CURRENT ) + continue; + } + + switch( NET_GetMasterHostByName( master )) { case NET_EAI_AGAIN: - list->sent = false; + master->sent = false; wait = true; break; case NET_EAI_NONAME: - list->sent = true; + master->sent = true; break; case NET_EAI_OK: - list->sent = true; - NET_SendPacket( sock, len, data, list->adr ); + master->sent = true; + NET_SendPacket( sock, len, data, master->adr ); break; } } @@ -95,8 +144,8 @@ qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data ) if( !wait ) { // reset sent state - for( list = ml.list; list; list = list->next ) - list->sent = false; + for( master = ml.head; master; master = master->next ) + master->sent = false; } return wait; @@ -138,10 +187,34 @@ void NET_MasterClear( void ) { master_t *m; - for( m = ml.list; m; m = m->next ) + for( m = ml.head; m; m = m->next ) m->last_heartbeat = MAX_HEARTBEAT; } +/* +================= +NET_MasterQuery +================= +*/ +qboolean NET_MasterQuery( uint32_t key, qboolean nat, const char *filter ) +{ + char buf[512]; + size_t len; + qboolean wait = false; + + len = NET_BuildMasterServerScanRequest( buf, sizeof( buf ), key, nat, filter, PROTO_CURRENT ); + wait = NET_SendToMasters( NS_CLIENT, len, buf, PROTO_CURRENT ); + + // goldsrc don't have nat traversal extensions + if( !nat ) + { + len = NET_BuildMasterServerScanRequest( buf, sizeof( buf ), 0, false, filter, PROTO_GOLDSRC ); + wait = NET_SendToMasters( NS_CLIENT, len, buf, PROTO_GOLDSRC ); + } + + return wait; +} + /* ======================== NET_MasterHeartbeat @@ -155,11 +228,14 @@ void NET_MasterHeartbeat( void ) if(( !public_server.value && !sv_nat.value ) || svs.maxclients == 1 ) return; // only public servers send heartbeats - for( m = ml.list; m; m = m->next ) + for( m = ml.head; m; m = m->next ) { if( host.realtime - m->last_heartbeat < HEARTBEAT_SECONDS ) continue; + if( m->gs ) + continue; + switch( NET_GetMasterHostByName( m )) { case NET_EAI_AGAIN: @@ -190,7 +266,7 @@ Informs all masters that this server is going down void NET_MasterShutdown( void ) { NET_Config( true, false ); // allow remote - while( NET_SendToMasters( NS_SERVER, 2, "\x62\x0A" )); + while( NET_SendToMasters( NS_SERVER, 2, "\x62\x0A", PROTO_CURRENT )); } @@ -204,7 +280,7 @@ static master_t *NET_GetMasterFromAdr( netadr_t adr ) { master_t *master; - for( master = ml.list; master; master = master->next ) + for( master = ml.head; master; master = master->next ) { if( NET_CompareAdr( adr, master->adr )) return master; @@ -240,9 +316,17 @@ NET_IsMasterAdr ======================== */ -qboolean NET_IsMasterAdr( netadr_t adr ) +qboolean NET_IsMasterAdr( netadr_t adr, connprotocol_t *proto ) { - return NET_GetMasterFromAdr( adr ) != NULL; + master_t *master = NET_GetMasterFromAdr( adr ); + + if( !master ) + return false; + + if( proto ) + *proto = master->gs ? PROTO_GOLDSRC : PROTO_CURRENT; + + return true; } /* @@ -252,40 +336,48 @@ NET_AddMaster Add master to the list ======================== */ -static void NET_AddMaster( const char *addr, qboolean save, qboolean v6only ) +static master_t *NET_AddMaster( const char *addr ) { - master_t *master, *last; + master_t *master; - for( last = ml.list; last && last->next; last = last->next ) + for( master = ml.head; master; master = master->next ) { - if( !Q_strcmp( last->address, addr ) ) // already exists - return; + if( !Q_stricmp( master->address, addr )) // already exists + return master; } - master = Mem_Malloc( host.mempool, sizeof( *master ) ); + master = Mem_Calloc( host.mempool, sizeof( *master )); Q_strncpy( master->address, addr, sizeof( master->address )); - master->sent = false; - master->save = save; - master->v6only = v6only; - master->next = NULL; - master->adr.type = 0; - // link in - if( last ) - last->next = master; + if( ml.tail ) + { + ml.tail->next = master; + ml.tail = master; + } else - ml.list = master; + { + ml.head = ml.tail = master; + } + + return master; } static void NET_AddMaster_f( void ) { + master_t *master; + if( Cmd_Argc() != 2 ) { - Msg( S_USAGE "addmaster
\n"); + Msg( S_USAGE "addmaster
[gs]\n"); return; } - NET_AddMaster( Cmd_Argv( 1 ), true, false ); // save them into config + master = NET_AddMaster( Cmd_Argv( 1 )); + master->save = true; + + if( Q_stricmp( Cmd_Argv( 2 ), "gs" )) + master->gs = true; + ml.modified = true; // save config } @@ -298,12 +390,14 @@ Clear master list */ static void NET_ClearMasters_f( void ) { - while( ml.list ) + while( ml.head ) { - master_t *prev = ml.list; - ml.list = ml.list->next; - Mem_Free( prev ); + master_t *head = ml.head; + ml.head = ml.head->next; + Mem_Free( head ); } + + ml.tail = NULL; } /* @@ -315,17 +409,24 @@ Display current master linked list */ static void NET_ListMasters_f( void ) { - master_t *list; + master_t *master; int i; Con_Printf( "Master servers:\n" ); - for( i = 1, list = ml.list; list; i++, list = list->next ) + for( i = 1, master = ml.head; master; i++, master = master->next ) { - Con_Printf( "%d\t%s", i, list->address ); - if( list->adr.type != 0 ) - Con_Printf( "\t%s\n", NET_AdrToString( list->adr )); - else Con_Printf( "\n" ); + Con_Printf( "%d\t%s", i, master->address ); + if( master->adr.type != 0 ) + Con_Printf( "\t%s", NET_AdrToString( master->adr )); + + if( master->gs ) + Con_Printf( " GoldSrc" ); + + if( master->v6only ) + Con_Printf( " IPv6-only"); + + Con_Printf( "\n" ); } } @@ -353,18 +454,33 @@ static void NET_LoadMasters( void ) pfile = (char*)afile; // format: master \n - while( ( pfile = COM_ParseFile( pfile, token, sizeof( token ) ) ) ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token )))) { + master_t *master = NULL; + + //if( !Q_strcmp( token, "clear" )) + // NET_ClearMasters_f(); + if( !Q_strcmp( token, "master" )) // load addr { - pfile = COM_ParseFile( pfile, token, sizeof( token ) ); - NET_AddMaster( token, true, false ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); + master = NET_AddMaster( token ); } else if( !Q_strcmp( token, "master6" )) { - pfile = COM_ParseFile( pfile, token, sizeof( token ) ); - NET_AddMaster( token, true, true ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); + master = NET_AddMaster( token ); + master->v6only = true; } + else if( !Q_strcmp( token, "mastergs" )) + { + pfile = COM_ParseFile( pfile, token, sizeof( token )); + master = NET_AddMaster( token ); + master->gs = true; + } + + if( master ) + master->save = true; } Mem_Free( afile ); @@ -395,10 +511,21 @@ void NET_SaveMasters( void ) return; } - for( m = ml.list; m; m = m->next ) + for( m = ml.head; m; m = m->next ) { - if( m->save ) - FS_Printf( f, "%s %s\n", m->v6only ? "master6" : "master", m->address ); + const char *key; + + if( !m->save ) + continue; + + if( m->v6only ) + key = "master6"; + else if( m->gs ) + key = "mastergs"; + else + key = "master"; + + FS_Printf( f, "%s %s\n", key, m->address ); } FS_Close( f ); @@ -420,20 +547,20 @@ void NET_InitMasters( void ) Cvar_RegisterVariable( &sv_verbose_heartbeats ); { // IPv4-only - NET_AddMaster( "mentality.rip:27010", false, false ); - NET_AddMaster( "ms2.mentality.rip:27010", false, false ); - NET_AddMaster( "ms3.mentality.rip:27010", false, false ); + NET_AddMaster( "mentality.rip:27010" ); + NET_AddMaster( "ms2.mentality.rip:27010" ); + NET_AddMaster( "ms3.mentality.rip:27010" ); } { // IPv6-only - NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); - NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, true ); + NET_AddMaster( "aaaa.mentality.rip:27010" )->v6only = true; + NET_AddMaster( "aaaa.ms2.mentality.rip:27010" )->v6only = true; } { // testing servers, might be offline - NET_AddMaster( "mentality.rip:27011", false, false ); - NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); + NET_AddMaster( "mentality.rip:27011" ); + NET_AddMaster( "aaaa.mentality.rip:27011" )->v6only = true; } - NET_LoadMasters( ); + NET_LoadMasters(); } diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index 3869d1d9..64be897c 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -902,7 +902,7 @@ static void SV_ConnectNatClient( netadr_t from ) { netadr_t to; - if( !sv_nat.value || !NET_IsMasterAdr( from )) + if( !sv_nat.value || !NET_IsMasterAdr( from, NULL )) return; if( !NET_StringToAdr( Cmd_Argv( 1 ), &to )) @@ -3175,7 +3175,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) return; } - if( NET_IsMasterAdr( from )) + if( NET_IsMasterAdr( from, NULL )) { if( !Q_strcmp( pcmd, M2S_CHALLENGE )) {