mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
engine: implement GoldSrc A2S query for NetAPI
As Xash also supports GoldSrc like queries, it's netinfo is dropped.
This commit is contained in:
committed by
Alibek Omarov
parent
e0ab44213a
commit
2127735456
@@ -2073,12 +2073,47 @@ static void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
|
|||||||
UI_AddServerToList( from, infostring );
|
UI_AddServerToList( from, infostring );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static net_request_t *CL_NetRequestFind( netadr_t from, int type )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
|
{
|
||||||
|
net_request_t *nr = &clgame.net_requests[i];
|
||||||
|
|
||||||
|
if( !nr->pfnFunc || nr->resp.type != type )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( NET_CompareAdr( nr->resp.remote_address, from ))
|
||||||
|
return nr;
|
||||||
|
|
||||||
|
// broadcast requests accept a response from anyone
|
||||||
|
if( NET_NetadrType( &nr->resp.remote_address ) == NA_BROADCAST )
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_NetRequestComplete( net_request_t *nr, netadr_t from, const char *response )
|
||||||
|
{
|
||||||
|
netadr_t request_adr = nr->resp.remote_address;
|
||||||
|
|
||||||
|
nr->resp.response = (void *)response;
|
||||||
|
nr->resp.remote_address = from;
|
||||||
|
nr->resp.error = NET_SUCCESS;
|
||||||
|
nr->resp.ping = host.realtime - nr->timesend;
|
||||||
|
|
||||||
|
nr->pfnFunc( &nr->resp );
|
||||||
|
|
||||||
|
if( FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
|
||||||
|
nr->resp.remote_address = request_adr;
|
||||||
|
else memset( nr, 0, sizeof( *nr )); // done
|
||||||
|
}
|
||||||
|
|
||||||
static void CL_ParseGoldSrcStatusMessage( netadr_t from, sizebuf_t *msg, qboolean legacy_format )
|
static void CL_ParseGoldSrcStatusMessage( netadr_t from, sizebuf_t *msg, qboolean legacy_format )
|
||||||
{
|
{
|
||||||
static char s[512+8];
|
static char s[512+8];
|
||||||
int p, numcl, maxcl, password, remaining, bots;
|
int p, numcl, maxcl, password, bots;
|
||||||
string host, map, gamedir, version;
|
string host, map, gamedir, version;
|
||||||
char *replace;
|
|
||||||
|
|
||||||
// set to beginning but skip header
|
// set to beginning but skip header
|
||||||
MSG_SeekToBit( msg, (sizeof( uint32_t ) + sizeof( uint8_t )) << 3, SEEK_SET );
|
MSG_SeekToBit( msg, (sizeof( uint32_t ) + sizeof( uint8_t )) << 3, SEEK_SET );
|
||||||
@@ -2163,7 +2198,7 @@ static void CL_ParseGoldSrcStatusMessage( netadr_t from, sizebuf_t *msg, qboolea
|
|||||||
|
|
||||||
// write host last so we can try to cut off too long hostnames
|
// write host last so we can try to cut off too long hostnames
|
||||||
// TODO: value size limit for infostrings
|
// TODO: value size limit for infostrings
|
||||||
remaining = sizeof( s ) - Q_strlen( s ) - sizeof( "\\host\\" ) - 1;
|
int remaining = sizeof( s ) - Q_strlen( s ) - sizeof( "\\host\\" ) - 1;
|
||||||
if( remaining < 0 )
|
if( remaining < 0 )
|
||||||
{
|
{
|
||||||
// should never happen?
|
// should never happen?
|
||||||
@@ -2171,103 +2206,205 @@ static void CL_ParseGoldSrcStatusMessage( netadr_t from, sizebuf_t *msg, qboolea
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *replace;
|
||||||
while(( replace = Q_strpbrk( host, "\\\"" )))
|
while(( replace = Q_strpbrk( host, "\\\"" )))
|
||||||
{
|
|
||||||
*replace = ' '; // find a better replacement?
|
*replace = ' '; // find a better replacement?
|
||||||
}
|
|
||||||
|
|
||||||
Info_SetValueForKey( s, "host", host, sizeof( s ));
|
Info_SetValueForKey( s, "host", host, sizeof( s ));
|
||||||
|
|
||||||
|
// tell mainui about server
|
||||||
UI_AddServerToList( from, s );
|
UI_AddServerToList( from, s );
|
||||||
|
|
||||||
|
// now process NetAPI requst
|
||||||
|
net_request_t *nr = CL_NetRequestFind( from, NETAPI_REQUEST_DETAILS );
|
||||||
|
|
||||||
|
if( !nr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
s[0] = 0;
|
||||||
|
Info_SetValueForKey( s, "gamedir", gamedir, sizeof( s ));
|
||||||
|
Info_SetValueForKeyf( s, "current", sizeof( s ), "%i", numcl );
|
||||||
|
Info_SetValueForKeyf( s, "max", sizeof( s ), "%i", maxcl );
|
||||||
|
Info_SetValueForKey( s, "map", map, sizeof( s ));
|
||||||
|
Info_SetValueForKey( s, "hostname", host, sizeof( s ));
|
||||||
|
|
||||||
|
CL_NetRequestComplete( nr, from, s );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CL_ParseNETInfoMessage
|
CL_NetRequestSend
|
||||||
|
|
||||||
Handle a reply from a netinfo
|
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static void CL_ParseNETInfoMessage( netadr_t from, const char *s )
|
qboolean CL_NetRequestSend( net_request_t *nr )
|
||||||
{
|
{
|
||||||
net_request_t *nr = NULL;
|
byte buf[64];
|
||||||
static char infostring[MAX_PRINT_MSG];
|
sizebuf_t msg;
|
||||||
int i, context, type;
|
|
||||||
int errorBits = 0;
|
|
||||||
const char *val;
|
|
||||||
|
|
||||||
context = Q_atoi( Cmd_Argv( 1 ));
|
if( nr->resp.type == NETAPI_REQUEST_PING )
|
||||||
type = Q_atoi( Cmd_Argv( 2 ));
|
|
||||||
|
|
||||||
// find request with specified context and type
|
|
||||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
|
||||||
{
|
{
|
||||||
if( clgame.net_requests[i].resp.context == context && clgame.net_requests[i].resp.type == type )
|
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, A2A_GOLDSRC_PING );
|
||||||
{
|
return true;
|
||||||
nr = &clgame.net_requests[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// not found, ignore
|
MSG_Init( &msg, "NetRequest", buf, sizeof( buf ));
|
||||||
if( nr == NULL )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// find the payload
|
switch( nr->resp.type )
|
||||||
s = Q_strchr( s, ' ' ); // skip netinfo
|
|
||||||
if( !s )
|
|
||||||
return;
|
|
||||||
|
|
||||||
s = Q_strchr( s + 1, ' ' ); // skip challenge
|
|
||||||
if( !s )
|
|
||||||
return;
|
|
||||||
|
|
||||||
s = Q_strchr( s + 1, ' ' ); // skip type
|
|
||||||
if( s )
|
|
||||||
s++; // skip final whitespace
|
|
||||||
else if( type != NETAPI_REQUEST_PING ) // ping have no payload, and that's ok
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( s )
|
|
||||||
{
|
{
|
||||||
if( s[0] == '\\' )
|
case NETAPI_REQUEST_DETAILS:
|
||||||
{
|
MSG_WriteString( &msg, A2S_GOLDSRC_INFO );
|
||||||
// check for errors
|
break;
|
||||||
val = Info_ValueForKey( s, "neterror" );
|
case NETAPI_REQUEST_PLAYERS:
|
||||||
|
MSG_WriteByte( &msg, A2S_GOLDSRC_PLAYERS );
|
||||||
if( !Q_stricmp( val, "protocol" ))
|
break;
|
||||||
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
|
case NETAPI_REQUEST_RULES:
|
||||||
else if( !Q_stricmp( val, "undefined" ))
|
MSG_WriteByte( &msg, A2S_GOLDSRC_RULES );
|
||||||
SetBits( errorBits, NET_ERROR_UNDEFINED );
|
break;
|
||||||
else if( !Q_stricmp( val, "forbidden" ))
|
default:
|
||||||
SetBits( errorBits, NET_ERROR_FORBIDDEN );
|
return false;
|
||||||
|
|
||||||
CL_FixupColorStringsForInfoString( s, infostring, sizeof( infostring ));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Q_strncpy( infostring, s, sizeof( infostring ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
infostring[0] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the answer
|
MSG_WriteLong( &msg, nr->challenge );
|
||||||
nr->resp.response = infostring;
|
|
||||||
nr->resp.remote_address = from;
|
|
||||||
nr->resp.error = NET_SUCCESS;
|
|
||||||
nr->resp.ping = host.realtime - nr->timesend;
|
|
||||||
|
|
||||||
if( nr->timeout <= host.realtime )
|
Netchan_OutOfBand( NS_CLIENT, nr->resp.remote_address, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg ));
|
||||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
|
||||||
SetBits( nr->resp.error, errorBits ); // misc error bits
|
|
||||||
|
|
||||||
nr->pfnFunc( &nr->resp );
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
|
/*
|
||||||
memset( nr, 0, sizeof( *nr )); // done
|
=================
|
||||||
|
CL_HasActiveNetRequest
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean CL_HasActiveNetRequest( netadr_t from )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
|
{
|
||||||
|
const net_request_t *nr = &clgame.net_requests[i];
|
||||||
|
|
||||||
|
if( !nr->pfnFunc )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( nr->resp.type != NETAPI_REQUEST_RULES && nr->resp.type != NETAPI_REQUEST_PLAYERS )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( NET_CompareAdr( nr->resp.remote_address, from ))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_NetRequestChallenge
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void CL_NetRequestChallenge( netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
MSG_SeekToBit( msg, ( sizeof( uint32_t ) + sizeof( uint8_t )) << 3, SEEK_SET );
|
||||||
|
int challenge = MSG_ReadLong( msg );
|
||||||
|
|
||||||
|
// give the challenge to the first request without one,
|
||||||
|
// the server sends a challenge per received query
|
||||||
|
for( int i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
|
{
|
||||||
|
net_request_t *nr = &clgame.net_requests[i];
|
||||||
|
|
||||||
|
if( !nr->pfnFunc || nr->resp.type == NETAPI_REQUEST_PING )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( nr->challenge != -1 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !NET_CompareAdr( nr->resp.remote_address, from ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nr->challenge = challenge;
|
||||||
|
CL_NetRequestSend( nr );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_NetRequestPing
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void CL_NetRequestPing( netadr_t from )
|
||||||
|
{
|
||||||
|
net_request_t *nr = CL_NetRequestFind( from, NETAPI_REQUEST_PING );
|
||||||
|
|
||||||
|
if( !nr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
CL_NetRequestComplete( nr, from, "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_NetRequestPlayers
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void CL_NetRequestPlayers( netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
static char s[MAX_PRINT_MSG];
|
||||||
|
net_request_t *nr = CL_NetRequestFind( from, NETAPI_REQUEST_PLAYERS );
|
||||||
|
|
||||||
|
if( !nr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
MSG_SeekToBit( msg, ( sizeof( uint32_t ) + sizeof( uint8_t )) << 3, SEEK_SET );
|
||||||
|
|
||||||
|
int count = MSG_ReadByte( msg );
|
||||||
|
|
||||||
|
s[0] = 0;
|
||||||
|
for( int i = 0; i < count && !MSG_CheckOverflow( msg ); i++ )
|
||||||
|
{
|
||||||
|
MSG_ReadByte( msg ); // index, GoldSrc servers always send 0 here
|
||||||
|
Info_SetValueForKey( s, va( "p%iname", i ), MSG_ReadString( msg ), sizeof( s ));
|
||||||
|
Info_SetValueForKeyf( s, va( "p%ifrags", i ), sizeof( s ), "%i", MSG_ReadLong( msg ));
|
||||||
|
Info_SetValueForKeyf( s, va( "p%itime", i ), sizeof( s ), "%f", MSG_ReadFloat( msg ));
|
||||||
|
}
|
||||||
|
Info_SetValueForKeyf( s, "players", sizeof( s ), "%i", count );
|
||||||
|
|
||||||
|
if( MSG_CheckOverflow( msg ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CL_NetRequestComplete( nr, from, s );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_NetRequestRules
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void CL_NetRequestRules( netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
static char s[MAX_PRINT_MSG];
|
||||||
|
net_request_t *nr = CL_NetRequestFind( from, NETAPI_REQUEST_RULES );
|
||||||
|
|
||||||
|
if( !nr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
MSG_SeekToBit( msg, ( sizeof( uint32_t ) + sizeof( uint8_t )) << 3, SEEK_SET );
|
||||||
|
|
||||||
|
int count = MSG_ReadShort( msg );
|
||||||
|
|
||||||
|
s[0] = 0;
|
||||||
|
for( int i = 0; i < count && !MSG_CheckOverflow( msg ); i++ )
|
||||||
|
{
|
||||||
|
string key;
|
||||||
|
|
||||||
|
Q_strncpy( key, MSG_ReadString( msg ), sizeof( key ));
|
||||||
|
Info_SetValueForKey( s, key, MSG_ReadString( msg ), sizeof( s ));
|
||||||
|
}
|
||||||
|
Info_SetValueForKeyf( s, "rules", sizeof( s ), "%i", count );
|
||||||
|
|
||||||
|
if( MSG_CheckOverflow( msg ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CL_NetRequestComplete( nr, from, s );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2279,14 +2416,13 @@ check for timeouts
|
|||||||
*/
|
*/
|
||||||
static void CL_ProcessNetRequests( void )
|
static void CL_ProcessNetRequests( void )
|
||||||
{
|
{
|
||||||
net_request_t *nr;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// find a request with specified context
|
// find a request with specified context
|
||||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
for( int i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
{
|
{
|
||||||
nr = &clgame.net_requests[i];
|
net_request_t *nr = &clgame.net_requests[i];
|
||||||
if( !nr->pfnFunc ) continue; // not used
|
|
||||||
|
if( !nr->pfnFunc )
|
||||||
|
continue; // not used
|
||||||
|
|
||||||
if( nr->timeout <= host.realtime )
|
if( nr->timeout <= host.realtime )
|
||||||
{
|
{
|
||||||
@@ -2524,8 +2660,16 @@ static void CL_Print( const char *c, const char *args, netadr_t from, sizebuf_t
|
|||||||
Con_Printf( "%s%c", s, s[Q_strlen( s ) - 1] != '\n' ? '\n' : '\0' );
|
Con_Printf( "%s%c", s, s[Q_strlen( s ) - 1] != '\n' ? '\n' : '\0' );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CL_Challenge( const char *c, netadr_t from )
|
static void CL_Challenge( const char *c, netadr_t from, sizebuf_t *msg )
|
||||||
{
|
{
|
||||||
|
// connection challenge is text and always comes as literal A00000000,
|
||||||
|
// query challenge is binary: challenge type byte and the challenge value
|
||||||
|
if( c[0] == S2C_GOLDSRC_CHALLENGE[0] && Q_strcmp( c, S2C_GOLDSRC_CHALLENGE ))
|
||||||
|
{
|
||||||
|
CL_NetRequestChallenge( from, msg );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( cls.state != ca_connecting )
|
if( cls.state != ca_connecting )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2727,9 +2871,13 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||||||
{
|
{
|
||||||
CL_ParseGoldSrcStatusMessage( from, msg, true );
|
CL_ParseGoldSrcStatusMessage( from, msg, true );
|
||||||
}
|
}
|
||||||
else if( !Q_strcmp( c, A2A_NETINFO ))
|
else if( c[0] == S2A_GOLDSRC_PLAYERS )
|
||||||
{
|
{
|
||||||
CL_ParseNETInfoMessage( from, args ); // server responding to a status broadcast
|
CL_NetRequestPlayers( from, msg );
|
||||||
|
}
|
||||||
|
else if( c[0] == S2A_GOLDSRC_RULES )
|
||||||
|
{
|
||||||
|
CL_NetRequestRules( from, msg );
|
||||||
}
|
}
|
||||||
else if( c[0] == A2C_GOLDSRC_PRINT || !Q_strcmp( c, A2C_PRINT ))
|
else if( c[0] == A2C_GOLDSRC_PRINT || !Q_strcmp( c, A2C_PRINT ))
|
||||||
{
|
{
|
||||||
@@ -2749,11 +2897,11 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||||||
}
|
}
|
||||||
else if( !Q_strcmp( c, A2A_ACK ) || !Q_strcmp( c, A2A_GOLDSRC_ACK ))
|
else if( !Q_strcmp( c, A2A_ACK ) || !Q_strcmp( c, A2A_GOLDSRC_ACK ))
|
||||||
{
|
{
|
||||||
// no-op
|
CL_NetRequestPing( from ); // server responding to a NetAPI ping
|
||||||
}
|
}
|
||||||
else if( !Q_strcmp( c, S2C_CHALLENGE ) || !Q_strcmp( c, S2C_GOLDSRC_CHALLENGE ))
|
else if( !Q_strcmp( c, S2C_CHALLENGE ) || c[0] == S2C_GOLDSRC_CHALLENGE[0] )
|
||||||
{
|
{
|
||||||
CL_Challenge( c, from );
|
CL_Challenge( c, from, msg );
|
||||||
}
|
}
|
||||||
else if( !Q_strcmp( c, S2C_REJECT ) || c[0] == S2C_GOLDSRC_REJECT || c[0] == S2C_GOLDSRC_REJECT_BADPASSWORD )
|
else if( !Q_strcmp( c, S2C_REJECT ) || c[0] == S2C_GOLDSRC_REJECT || c[0] == S2C_GOLDSRC_REJECT_BADPASSWORD )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -445,6 +445,7 @@ typedef struct
|
|||||||
double timeout;
|
double timeout;
|
||||||
double timesend; // time when request was sended
|
double timesend; // time when request was sended
|
||||||
int flags; // FNETAPI_MULTIPLE_RESPONSE etc
|
int flags; // FNETAPI_MULTIPLE_RESPONSE etc
|
||||||
|
int challenge; // GoldSrc query challenge, -1 until received
|
||||||
} net_request_t;
|
} net_request_t;
|
||||||
|
|
||||||
// new versions of client dlls have a single export with all callbacks
|
// new versions of client dlls have a single export with all callbacks
|
||||||
@@ -793,6 +794,7 @@ void CL_ClearState( void );
|
|||||||
void CL_SetCheatState( qboolean multiplayer, qboolean allow_cheats );
|
void CL_SetCheatState( qboolean multiplayer, qboolean allow_cheats );
|
||||||
void CL_SendGoldSrcConnectPacket( netadr_t adr, int challenge, const void *ticket, size_t ticketlen );
|
void CL_SendGoldSrcConnectPacket( netadr_t adr, int challenge, const void *ticket, size_t ticketlen );
|
||||||
void CL_NotifyServerListResponse( void );
|
void CL_NotifyServerListResponse( void );
|
||||||
|
qboolean CL_NetRequestSend( net_request_t *nr );
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_demo.c
|
// cl_demo.c
|
||||||
|
|||||||
@@ -3364,44 +3364,60 @@ NetAPI_SendRequest
|
|||||||
*/
|
*/
|
||||||
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
|
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
|
||||||
{
|
{
|
||||||
net_request_t *nr = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !response )
|
if( !response )
|
||||||
{
|
{
|
||||||
Con_DPrintf( S_ERROR "%s: no callbcak specified for request with context %i!\n", __func__, context );
|
Con_DPrintf( S_ERROR "%s: no callback specified for request with context %i!\n", __func__, context );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: call pfnFunc and tell client.dll about errors?
|
||||||
|
|
||||||
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
||||||
return; // IPX no longer support
|
return; // IPX no longer support
|
||||||
|
|
||||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
switch( request )
|
||||||
|
{
|
||||||
|
case NETAPI_REQUEST_SERVERLIST:
|
||||||
return; // no support for server list requests
|
return; // no support for server list requests
|
||||||
|
case NETAPI_REQUEST_PING:
|
||||||
|
case NETAPI_REQUEST_RULES:
|
||||||
|
case NETAPI_REQUEST_PLAYERS:
|
||||||
|
case NETAPI_REQUEST_DETAILS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Con_Printf( S_ERROR "%s: unknown request type %d, context %i\n", __func__, request, context );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// find a free request
|
// find a free request
|
||||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
net_request_t *nr = NULL, *oldest_nr = NULL;
|
||||||
|
int i;
|
||||||
|
double max_timeout = 0;
|
||||||
|
for( i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
{
|
{
|
||||||
nr = &clgame.net_requests[i];
|
nr = &clgame.net_requests[i];
|
||||||
if( !nr->pfnFunc ) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( i == MAX_REQUESTS )
|
if(( host.realtime - nr->timesend ) > max_timeout )
|
||||||
{
|
|
||||||
double max_timeout = 0;
|
|
||||||
|
|
||||||
// no free requests? use oldest
|
|
||||||
for( i = 0, nr = NULL; i < MAX_REQUESTS; i++ )
|
|
||||||
{
|
{
|
||||||
if(( host.realtime - clgame.net_requests[i].timesend ) > max_timeout )
|
max_timeout = host.realtime - nr->timesend;
|
||||||
{
|
oldest_nr = nr;
|
||||||
max_timeout = host.realtime - clgame.net_requests[i].timesend;
|
|
||||||
nr = &clgame.net_requests[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !nr->pfnFunc )
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert( nr != NULL );
|
if( i == ARRAYSIZE( clgame.net_requests ))
|
||||||
|
{
|
||||||
|
// no free requests? use oldest
|
||||||
|
nr = oldest_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !nr )
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "%s: no free requests\n", __func__ );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// clear slot
|
// clear slot
|
||||||
memset( nr, 0, sizeof( *nr ));
|
memset( nr, 0, sizeof( *nr ));
|
||||||
@@ -3414,9 +3430,10 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
|||||||
nr->resp.type = request;
|
nr->resp.type = request;
|
||||||
nr->resp.remote_address = *remote_address;
|
nr->resp.remote_address = *remote_address;
|
||||||
nr->flags = flags;
|
nr->flags = flags;
|
||||||
|
nr->challenge = -1;
|
||||||
|
|
||||||
// local servers request
|
if( !CL_NetRequestSend( nr ))
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, A2A_NETINFO" %i %i %i", PROTOCOL_VERSION, context, request );
|
Con_Printf( S_ERROR "%s: failed to send net request for type %d with context %i\n", __func__, request, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3428,7 +3445,7 @@ NetAPI_CancelRequest
|
|||||||
static void GAME_EXPORT NetAPI_CancelRequest( int context )
|
static void GAME_EXPORT NetAPI_CancelRequest( int context )
|
||||||
{
|
{
|
||||||
// find a specified request
|
// find a specified request
|
||||||
for( int i = 0; i < MAX_REQUESTS; i++ )
|
for( int i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
{
|
{
|
||||||
net_request_t *nr = &clgame.net_requests[i];
|
net_request_t *nr = &clgame.net_requests[i];
|
||||||
|
|
||||||
@@ -3456,7 +3473,7 @@ NetAPI_CancelAllRequests
|
|||||||
void GAME_EXPORT NetAPI_CancelAllRequests( void )
|
void GAME_EXPORT NetAPI_CancelAllRequests( void )
|
||||||
{
|
{
|
||||||
// tell the user about cancel
|
// tell the user about cancel
|
||||||
for( int i = 0; i < MAX_REQUESTS; i++ )
|
for( int i = 0; i < ARRAYSIZE( clgame.net_requests ); i++ )
|
||||||
{
|
{
|
||||||
net_request_t *nr = &clgame.net_requests[i];
|
net_request_t *nr = &clgame.net_requests[i];
|
||||||
if( !nr->pfnFunc ) continue; // not used
|
if( !nr->pfnFunc ) continue; // not used
|
||||||
|
|||||||
@@ -1364,9 +1364,14 @@ static qboolean NET_QueuePacket( int net_socket, netsrc_t sock, netadr_t *from,
|
|||||||
// check for split message
|
// check for split message
|
||||||
if( sock == NS_CLIENT && *(int *)data == NET_HEADER_SPLITPACKET )
|
if( sock == NS_CLIENT && *(int *)data == NET_HEADER_SPLITPACKET )
|
||||||
{
|
{
|
||||||
if( !CL_IsFromConnectingServer( *from ))
|
if( CL_IsFromConnectingServer( *from ))
|
||||||
return false;
|
return NET_GetLong( data, ret, length, CL_GetSplitSize( ), CL_Protocol( ));
|
||||||
return NET_GetLong( data, ret, length, CL_GetSplitSize( ), CL_Protocol( ));
|
|
||||||
|
// GoldSrc servers (e.g. ReUnion) can split large query responses
|
||||||
|
if( CL_HasActiveNetRequest( *from ))
|
||||||
|
return NET_GetLong( data, ret, length, 1400, PROTO_GOLDSRC );
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ void NET_GetLocalAddress( netadr_t *ip4, netadr_t *ip6 );
|
|||||||
#if !XASH_DEDICATED
|
#if !XASH_DEDICATED
|
||||||
size_t CL_GetSplitSize( void );
|
size_t CL_GetSplitSize( void );
|
||||||
qboolean CL_IsFromConnectingServer( netadr_t from );
|
qboolean CL_IsFromConnectingServer( netadr_t from );
|
||||||
|
qboolean CL_HasActiveNetRequest( netadr_t from );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void HTTP_AddCustomServer( const char *url );
|
void HTTP_AddCustomServer( const char *url );
|
||||||
|
|||||||
Reference in New Issue
Block a user