mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
engine: implement new static master server protocol
This commit is contained in:
@@ -1864,19 +1864,6 @@ static void CL_InternetServers_f( void )
|
||||
cls.internetservers_wait = NET_MasterQuery( 1, 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_CURRENT:
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CL_QueryServer_f( void )
|
||||
{
|
||||
netadr_t adr;
|
||||
@@ -1902,7 +1889,7 @@ static void CL_QueryServer_f( void )
|
||||
if( !CL_StringToProtocol( Cmd_Argv( 2 ), &proto ))
|
||||
return;
|
||||
|
||||
CL_QueryServer( adr, proto );
|
||||
NET_QueryServerByAddress( adr, proto );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2652,7 +2639,7 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||
break;
|
||||
|
||||
NET_Config( true, false ); // allow remote
|
||||
CL_QueryServer( servadr, proto );
|
||||
NET_QueryServerByAddress( servadr, proto );
|
||||
}
|
||||
|
||||
if( cls.internetservers_pending )
|
||||
|
||||
@@ -901,6 +901,7 @@ 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 );
|
||||
void NET_QueryServerByAddress( netadr_t adr, connprotocol_t proto );
|
||||
|
||||
//
|
||||
// munge.c
|
||||
|
||||
@@ -14,6 +14,7 @@ GNU General Public License for more details.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "netchan.h"
|
||||
#include "net_ws.h"
|
||||
#include "server.h"
|
||||
|
||||
typedef struct master_s
|
||||
@@ -32,9 +33,18 @@ typedef struct master_s
|
||||
double resolve_time;
|
||||
} master_t;
|
||||
|
||||
typedef struct masterstatic_s
|
||||
{
|
||||
struct masterstatic_s *next;
|
||||
qboolean save;
|
||||
qboolean in_flight;
|
||||
char base[];
|
||||
} masterstatic_t;
|
||||
|
||||
static struct masterlist_s
|
||||
{
|
||||
master_t *head, *tail;
|
||||
masterstatic_t *static_head, *static_tail;
|
||||
qboolean modified;
|
||||
} ml;
|
||||
|
||||
@@ -199,9 +209,119 @@ void NET_MasterClear( void )
|
||||
m->last_heartbeat = MAX_HEARTBEAT;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
NET_QueryServerByAddress
|
||||
|
||||
========================
|
||||
*/
|
||||
void NET_QueryServerByAddress( netadr_t adr, connprotocol_t proto )
|
||||
{
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
Netchan_OutOfBand( NS_CLIENT, adr, sizeof( A2S_GOLDSRC_INFO ), (const byte *)A2S_GOLDSRC_INFO ); // includes null terminator
|
||||
else
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO " %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
static int NET_ParseMasterStaticBody( char *body )
|
||||
{
|
||||
char token[MAX_TOKEN];
|
||||
char *pfile = body;
|
||||
int count = 0;
|
||||
|
||||
while(( pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL )))
|
||||
{
|
||||
qboolean gs;
|
||||
|
||||
if( !Q_strcmp( token, "ip" ))
|
||||
gs = false;
|
||||
else if( !Q_strcmp( token, "gs" ))
|
||||
gs = true;
|
||||
else
|
||||
{
|
||||
pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL );
|
||||
if( !pfile )
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
pfile = COM_ParseFileSafe( pfile, token, sizeof( token ), PFILE_HASH_AS_COMMENT, NULL, NULL );
|
||||
if( !pfile )
|
||||
break;
|
||||
|
||||
netadr_t adr = { 0 };
|
||||
|
||||
if( !NET_StringToAdr( token, &adr ))
|
||||
{
|
||||
Con_Reportf( S_WARN "masterstatic: can't parse address \"%s\"\n", token );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( adr.port == 0 )
|
||||
adr.port = MSG_BigShort( PORT_SERVER );
|
||||
|
||||
NET_QueryServerByAddress( adr, gs );
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
NET_MasterStaticResponse
|
||||
|
||||
========================
|
||||
*/
|
||||
static void NET_MasterStaticResponse( const char *url, qboolean success, const byte *data, size_t size, void *userdata )
|
||||
{
|
||||
masterstatic_t *ms = (masterstatic_t *)userdata;
|
||||
|
||||
if( ms )
|
||||
ms->in_flight = false;
|
||||
|
||||
if( !success || !data || size == 0 )
|
||||
{
|
||||
Con_Reportf( "masterstatic: %s returned no data\n", url );
|
||||
return;
|
||||
}
|
||||
|
||||
// HTTP buffer isn't NUL-terminated; COM_ParseFileSafe needs one.
|
||||
char *body = Mem_Malloc( host.mempool, size + 1 );
|
||||
memcpy( body, data, size );
|
||||
body[size] = 0;
|
||||
|
||||
NET_Config( true, false ); // allow remote sends
|
||||
|
||||
int count = NET_ParseMasterStaticBody( body );
|
||||
|
||||
Mem_Free( body );
|
||||
|
||||
Con_Reportf( "masterstatic: %s yielded %d server(s)\n", url, count );
|
||||
}
|
||||
|
||||
static void NET_MasterStaticQuery( void )
|
||||
{
|
||||
const char *gamedir = GI ? GI->gamefolder : "valve";
|
||||
|
||||
for( masterstatic_t *ms = ml.static_head; ms; ms = ms->next )
|
||||
{
|
||||
char url[1024];
|
||||
|
||||
if( ms->in_flight )
|
||||
continue;
|
||||
|
||||
Q_snprintf( url, sizeof( url ), "%s/v1/servers/%s", ms->base, gamedir );
|
||||
|
||||
if( HTTP_GetToMemory( url, NET_MasterStaticResponse, ms ))
|
||||
ms->in_flight = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
NET_MasterQuery
|
||||
|
||||
=================
|
||||
*/
|
||||
qboolean NET_MasterQuery( uint32_t key, qboolean nat, const char *filter )
|
||||
@@ -217,6 +337,8 @@ qboolean NET_MasterQuery( uint32_t key, qboolean nat, const char *filter )
|
||||
wait |= NET_SendToMasters( NS_CLIENT, len, buf, PROTO_GOLDSRC );
|
||||
}
|
||||
|
||||
NET_MasterStaticQuery();
|
||||
|
||||
if( !wait )
|
||||
NET_ClearSendState();
|
||||
|
||||
@@ -298,6 +420,7 @@ static master_t *NET_GetMasterFromAdr( netadr_t adr )
|
||||
/*
|
||||
========================
|
||||
NET_GetMaster
|
||||
|
||||
========================
|
||||
*/
|
||||
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat )
|
||||
@@ -380,6 +503,54 @@ static void NET_AddMaster_f( void )
|
||||
ml.modified = true; // save config
|
||||
}
|
||||
|
||||
static masterstatic_t *NET_AddMasterStatic( const char *base )
|
||||
{
|
||||
size_t base_len = Q_strlen( base );
|
||||
|
||||
while( base_len > 0 && base[base_len - 1] == '/' )
|
||||
base_len--;
|
||||
|
||||
if( base_len == 0 )
|
||||
return NULL;
|
||||
|
||||
for( masterstatic_t *ms = ml.static_head; ms; ms = ms->next )
|
||||
{
|
||||
if( Q_strlen( ms->base ) == base_len && !Q_strnicmp( ms->base, base, base_len ))
|
||||
return ms;
|
||||
}
|
||||
|
||||
masterstatic_t *ms = Mem_Calloc( host.mempool, sizeof( *ms ) + base_len + 1 );
|
||||
memcpy( ms->base, base, base_len );
|
||||
|
||||
if( ml.static_tail )
|
||||
{
|
||||
ml.static_tail->next = ms;
|
||||
ml.static_tail = ms;
|
||||
}
|
||||
else
|
||||
{
|
||||
ml.static_head = ml.static_tail = ms;
|
||||
}
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
static void NET_AddMasterStatic_f( void )
|
||||
{
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Msg( S_USAGE "addmasterstatic <base-url>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
masterstatic_t *ms = NET_AddMasterStatic( Cmd_Argv( 1 ));
|
||||
if( !ms )
|
||||
return;
|
||||
|
||||
ms->save = true;
|
||||
ml.modified = true;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
NET_ClearMasters
|
||||
@@ -397,6 +568,15 @@ static void NET_ClearMasters_f( void )
|
||||
}
|
||||
|
||||
ml.tail = NULL;
|
||||
|
||||
while( ml.static_head )
|
||||
{
|
||||
masterstatic_t *head = ml.static_head;
|
||||
ml.static_head = ml.static_head->next;
|
||||
Mem_Free( head );
|
||||
}
|
||||
|
||||
ml.static_tail = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -425,6 +605,13 @@ static void NET_ListMasters_f( void )
|
||||
|
||||
Con_Printf( "\n" );
|
||||
}
|
||||
|
||||
if( ml.static_head )
|
||||
Con_Printf( "Static master base URLs:\n" );
|
||||
|
||||
i = 1;
|
||||
for( masterstatic_t *ms = ml.static_head; ms; i++, ms = ms->next )
|
||||
Con_Printf( "%d\t%s%s\n", i, ms->base, ms->in_flight ? " (in flight)" : "" );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -472,6 +659,16 @@ static void NET_LoadMasters( void )
|
||||
master = NET_AddMaster( token );
|
||||
master->gs = true;
|
||||
}
|
||||
else if( !Q_strcmp( token, "masterstatic" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
if( pfile )
|
||||
{
|
||||
masterstatic_t *ms = NET_AddMasterStatic( token );
|
||||
if( ms )
|
||||
ms->save = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( master )
|
||||
master->save = true;
|
||||
@@ -519,6 +716,14 @@ void NET_SaveMasters( void )
|
||||
FS_Printf( f, "%s %s\n", key, m->address );
|
||||
}
|
||||
|
||||
for( masterstatic_t *ms = ml.static_head; ms; ms = ms->next )
|
||||
{
|
||||
if( !ms->save )
|
||||
continue;
|
||||
|
||||
FS_Printf( f, "masterstatic \"%s\"\n", ms->base );
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
}
|
||||
|
||||
@@ -532,6 +737,7 @@ Initialize master server list
|
||||
void NET_InitMasters( void )
|
||||
{
|
||||
Cmd_AddRestrictedCommand( "addmaster", NET_AddMaster_f, "add address to masterserver list" );
|
||||
Cmd_AddRestrictedCommand( "addmasterstatic", NET_AddMasterStatic_f, "add static HTTP masterserver base URL" );
|
||||
Cmd_AddRestrictedCommand( "clearmasters", NET_ClearMasters_f, "clear masterserver list" );
|
||||
Cmd_AddCommand( "listmasters", NET_ListMasters_f, "list masterservers" );
|
||||
|
||||
@@ -548,10 +754,13 @@ void NET_InitMasters( void )
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010" )->v6only = true;
|
||||
}
|
||||
|
||||
{ // testing servers, might be offline
|
||||
NET_AddMaster( "mentality.rip:27011" );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011" )->v6only = true;
|
||||
}
|
||||
#if 0
|
||||
NET_AddMasterStatic( "http://meltdown.lan/test" );
|
||||
#endif
|
||||
NET_AddMasterStatic( "http://fwgs.github.io/server-list" );
|
||||
// FIXME: https raw.githubcontent source
|
||||
// FIXME: cloudflare'd sources both HTTP and HTTPS
|
||||
|
||||
|
||||
NET_LoadMasters();
|
||||
}
|
||||
|
||||
@@ -99,4 +99,7 @@ void HTTP_ResetProcessState( void );
|
||||
void HTTP_Init( void );
|
||||
void HTTP_Run( void );
|
||||
|
||||
typedef void ( *http_memory_cb_t )( const char *url, qboolean success, const byte *data, size_t size, void *userdata );
|
||||
qboolean HTTP_GetToMemory( const char *url, http_memory_cb_t cb, void *userdata );
|
||||
|
||||
#endif//NET_WS_H
|
||||
|
||||
Reference in New Issue
Block a user