mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-08 13:21:51 +08:00
engine: support querying legacy goldsrc master servers
* General refactoring, hide out of band messages under cl_log_outofband cvar, similar to sv_log_outofband.
This commit is contained in:
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <address>\n");
|
||||
Msg( S_USAGE "addmaster <address> [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 <addr>\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();
|
||||
}
|
||||
|
||||
@@ -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 ))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user