mirror of
https://github.com/FWGS/xash3d-fwgs
synced 2024-11-22 09:56:22 +01:00
engine: global refactoring of connectionless packets, now they can be customized from single protocol.h header
This commit is contained in:
parent
2d546ccbf7
commit
e3e4bcc015
@ -3485,7 +3485,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
|||||||
nr->flags = flags;
|
nr->flags = flags;
|
||||||
|
|
||||||
// local servers request
|
// local servers request
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
|
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, A2A_NETINFO" %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1144,7 +1144,7 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
|||||||
|
|
||||||
MSG_Init( &send, "GoldSrcConnect", send_buf, sizeof( send_buf ));
|
MSG_Init( &send, "GoldSrcConnect", send_buf, sizeof( send_buf ));
|
||||||
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET );
|
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET );
|
||||||
MSG_WriteStringf( &send, "connect %i %i \"%s\" \"%s\"\n",
|
MSG_WriteStringf( &send, C2S_CONNECT" %i %i \"%s\" \"%s\"\n",
|
||||||
PROTOCOL_GOLDSRC_VERSION, challenge, protinfo, cls.userinfo );
|
PROTOCOL_GOLDSRC_VERSION, challenge, protinfo, cls.userinfo );
|
||||||
MSG_SeekToBit( &send, -8, SEEK_CUR ); // rewrite null terminator
|
MSG_SeekToBit( &send, -8, SEEK_CUR ); // rewrite null terminator
|
||||||
CL_WriteSteamTicket( &send );
|
CL_WriteSteamTicket( &send );
|
||||||
@ -1172,7 +1172,7 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
|||||||
|
|
||||||
Info_SetValueForKey( protinfo, "i", key, sizeof( protinfo ));
|
Info_SetValueForKey( protinfo, "i", key, sizeof( protinfo ));
|
||||||
|
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i %i \"%s\" %d \"%s\"\n",
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, C2S_CONNECT" %i %i %i \"%s\" %d \"%s\"\n",
|
||||||
PROTOCOL_LEGACY_VERSION, qport, challenge, cls.userinfo, NET_LEGACY_EXT_SPLIT, protinfo );
|
PROTOCOL_LEGACY_VERSION, qport, challenge, cls.userinfo, NET_LEGACY_EXT_SPLIT, protinfo );
|
||||||
Con_Printf( "Trying to connect with legacy protocol\n" );
|
Con_Printf( "Trying to connect with legacy protocol\n" );
|
||||||
}
|
}
|
||||||
@ -1195,7 +1195,7 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
|||||||
Info_SetValueForKey( protinfo, "qport", qport, sizeof( protinfo ));
|
Info_SetValueForKey( protinfo, "qport", qport, sizeof( protinfo ));
|
||||||
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", extensions);
|
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", extensions);
|
||||||
|
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, challenge, protinfo, cls.userinfo );
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, C2S_CONNECT" %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, challenge, protinfo, cls.userinfo );
|
||||||
Con_Printf( "Trying to connect with modern protocol\n" );
|
Con_Printf( "Trying to connect with modern protocol\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1223,7 +1223,7 @@ static void CL_SendGetChallenge( netadr_t to )
|
|||||||
// always send GoldSrc-styled getchallenge message
|
// always send GoldSrc-styled getchallenge message
|
||||||
// Xash servers will ignore it but for GoldSrc it will help
|
// Xash servers will ignore it but for GoldSrc it will help
|
||||||
// in auto-detection
|
// in auto-detection
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, to, "getchallenge steam\n" );
|
Netchan_OutOfBandPrint( NS_CLIENT, to, C2S_GETCHALLENGE" steam\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1314,14 +1314,15 @@ static void CL_CheckForResend( void )
|
|||||||
cls.connect_retry++;
|
cls.connect_retry++;
|
||||||
|
|
||||||
if( bandwidthTest )
|
if( bandwidthTest )
|
||||||
|
{
|
||||||
Con_Printf( "Connecting to %s... (retry #%i, fragment size %i)\n", cls.servername, cls.connect_retry, cls.max_fragment_size );
|
Con_Printf( "Connecting to %s... (retry #%i, fragment size %i)\n", cls.servername, cls.connect_retry, cls.max_fragment_size );
|
||||||
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, C2S_BANDWIDTHTEST" %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Con_Printf( "Connecting to %s... (retry #%i)\n", cls.servername, cls.connect_retry );
|
Con_Printf( "Connecting to %s... (retry #%i)\n", cls.servername, cls.connect_retry );
|
||||||
|
|
||||||
if( bandwidthTest )
|
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
|
|
||||||
else
|
|
||||||
CL_SendGetChallenge( adr );
|
CL_SendGetChallenge( adr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static resource_t *CL_AddResource( resourcetype_t type, const char *name, int size, qboolean bFatalIfMissing, int index )
|
static resource_t *CL_AddResource( resourcetype_t type, const char *name, int size, qboolean bFatalIfMissing, int index )
|
||||||
@ -1470,7 +1471,7 @@ static void CL_Rcon_f( void )
|
|||||||
|
|
||||||
NET_Config( true, false ); // allow remote
|
NET_Config( true, false ); // allow remote
|
||||||
|
|
||||||
Q_strncat( message, "rcon ", sizeof( message ));
|
Q_strncat( message, C2S_RCON" ", sizeof( message ));
|
||||||
Q_strncat( message, rcon_password.string, sizeof( message ));
|
Q_strncat( message, rcon_password.string, sizeof( message ));
|
||||||
Q_strncat( message, " ", sizeof( message ) );
|
Q_strncat( message, " ", sizeof( message ) );
|
||||||
|
|
||||||
@ -1746,10 +1747,10 @@ static void CL_LocalServers_f( void )
|
|||||||
// send a broadcast packet
|
// send a broadcast packet
|
||||||
adr.type = NA_BROADCAST;
|
adr.type = NA_BROADCAST;
|
||||||
adr.port = MSG_BigShort( PORT_SERVER );
|
adr.port = MSG_BigShort( PORT_SERVER );
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "info %i", PROTOCOL_VERSION );
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||||
|
|
||||||
adr.type = NA_MULTICAST_IP6;
|
adr.type = NA_MULTICAST_IP6;
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "info %i", PROTOCOL_VERSION );
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1951,7 +1952,7 @@ static void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
|
|||||||
|
|
||||||
if( len >= magiclen && !Q_strcmp( s + len - magiclen, magic ))
|
if( len >= magiclen && !Q_strcmp( s + len - magiclen, magic ))
|
||||||
{
|
{
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, from, "info %i", PROTOCOL_LEGACY_VERSION );
|
Netchan_OutOfBandPrint( NS_CLIENT, from, A2A_INFO" %i", PROTOCOL_LEGACY_VERSION );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2155,6 +2156,235 @@ static qboolean CL_IsFromConnectingServer( netadr_t from )
|
|||||||
NET_CompareAdr( cls.serveradr, from );
|
NET_CompareAdr( cls.serveradr, from );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CL_HandleTestPacket( netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
byte recv_buf[NET_MAX_FRAGMENT];
|
||||||
|
dword crcValue;
|
||||||
|
int realsize;
|
||||||
|
dword crcValue2 = 0;
|
||||||
|
|
||||||
|
// this message only used during connection
|
||||||
|
// it doesn't make sense after client_connect
|
||||||
|
if( cls.state != ca_connecting )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !CL_IsFromConnectingServer( from ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
crcValue = MSG_ReadLong( msg );
|
||||||
|
realsize = MSG_GetMaxBytes( msg ) - MSG_GetNumBytesRead( msg );
|
||||||
|
|
||||||
|
if( cls.max_fragment_size != MSG_GetMaxBytes( msg ))
|
||||||
|
{
|
||||||
|
if( cls.connect_retry >= CL_TEST_RETRIES )
|
||||||
|
{
|
||||||
|
// too many fails use default connection method
|
||||||
|
Con_Printf( "hi-speed connection is failed, use default method\n" );
|
||||||
|
CL_SendGetChallenge( from );
|
||||||
|
Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE );
|
||||||
|
cls.connect_time = host.realtime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we waiting more than cl_timeout or packet was trashed
|
||||||
|
cls.connect_time = MAX_HEARTBEAT;
|
||||||
|
return; // just wait for a next responce
|
||||||
|
}
|
||||||
|
|
||||||
|
// reading test buffer
|
||||||
|
MSG_ReadBytes( msg, recv_buf, realsize );
|
||||||
|
|
||||||
|
// procssing the CRC
|
||||||
|
CRC32_ProcessBuffer( &crcValue2, recv_buf, realsize );
|
||||||
|
|
||||||
|
if( crcValue == crcValue2 )
|
||||||
|
{
|
||||||
|
// packet was sucessfully delivered, adjust the fragment size and get challenge
|
||||||
|
|
||||||
|
Con_DPrintf( "CRC %x is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size );
|
||||||
|
CL_SendGetChallenge( from );
|
||||||
|
Cvar_SetValue( "cl_dlmax", cls.max_fragment_size );
|
||||||
|
cls.connect_time = host.realtime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( cls.connect_retry >= CL_TEST_RETRIES )
|
||||||
|
{
|
||||||
|
// too many fails use default connection method
|
||||||
|
Con_Printf( "hi-speed connection is failed, use default method\n" );
|
||||||
|
CL_SendGetChallenge( from );
|
||||||
|
Cvar_SetValue( "cl_dlmax", FRAGMENT_MIN_SIZE );
|
||||||
|
cls.connect_time = host.realtime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Msg( "got testpacket, CRC mismatched 0x%08x should be 0x%08x, trying next fragment size %d\n", crcValue2, crcValue, cls.max_fragment_size >> 1 );
|
||||||
|
|
||||||
|
// trying the next size of packet
|
||||||
|
cls.connect_time = MAX_HEARTBEAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_ClientConnect( const char *c, netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
if( !CL_IsFromConnectingServer( from ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( cls.state == ca_connected )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "dup connect received. ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cls.legacymode != PROTO_GOLDSRC && !Q_strcmp( c, S2C_GOLDSRC_CONNECTION ))
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "GoldSrc client connect received but wasn't expected, ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CL_Reconnect( true );
|
||||||
|
UI_SetActiveMenu( cl.background );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_Print( const char *c, const char *args, netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
s = c[0] == A2C_GOLDSRC_PRINT ? args + 1 : MSG_ReadString( msg );
|
||||||
|
|
||||||
|
if( !COM_CheckStringEmpty( s ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Con_Printf( "Remote message from %s:\n", NET_AdrToString( from ));
|
||||||
|
Con_Printf( "%s%c", s, s[Q_strlen( s ) - 1] != '\n' ? '\n' : '\0' );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_Challenge( const char *c, netadr_t from )
|
||||||
|
{
|
||||||
|
if( cls.state != ca_connecting )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !CL_IsFromConnectingServer( from ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// try to autodetect protocol by challenge response
|
||||||
|
if( !Q_strcmp( c, S2C_GOLDSRC_CHALLENGE ))
|
||||||
|
cls.legacymode = PROTO_GOLDSRC;
|
||||||
|
|
||||||
|
// challenge from the server we are connecting to
|
||||||
|
CL_SendConnectPacket( cls.legacymode, Q_atoi( Cmd_Argv( 1 )));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_ErrorMsg( const char *c, const char *args, netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
char formatted_msg[MAX_VA_STRING];
|
||||||
|
|
||||||
|
if( !CL_IsFromConnectingServer( from ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( msg != NULL && !Q_strcmp( c, S2C_ERRORMSG ))
|
||||||
|
{
|
||||||
|
const char *s = MSG_ReadString( msg );
|
||||||
|
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", s );
|
||||||
|
}
|
||||||
|
else if( c[0] == S2C_GOLDSRC_REJECT )
|
||||||
|
{
|
||||||
|
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args + 1 );
|
||||||
|
}
|
||||||
|
else if( c[0] == S2C_GOLDSRC_REJECT_BADPASSWORD )
|
||||||
|
{
|
||||||
|
if( !Q_strnicmp( &c[1], "BADPASSWORD", 11 ))
|
||||||
|
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args + 12 );
|
||||||
|
else
|
||||||
|
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case we're in console or it's classic mainui which doesn't support messageboxes
|
||||||
|
if( !UI_IsVisible() || !UI_ShowMessageBox( formatted_msg ))
|
||||||
|
Msg( "%s\n", formatted_msg );
|
||||||
|
|
||||||
|
// don't disconnect, errormsg is a FWGS extension and
|
||||||
|
// always followed by disconnect message
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_Reject( const char *c, const char *args, netadr_t from )
|
||||||
|
{
|
||||||
|
// this message only used during connection
|
||||||
|
// it doesn't make sense after client_connect
|
||||||
|
if( cls.state != ca_connecting )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !CL_IsFromConnectingServer( from ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CL_ErrorMsg( c, args, from, NULL );
|
||||||
|
|
||||||
|
// a disconnect message from the server, which will happen if the server
|
||||||
|
// dropped the connection but it is still getting packets from us
|
||||||
|
CL_Disconnect_f();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
if( !NET_IsMasterAdr( from ))
|
||||||
|
{
|
||||||
|
Con_Printf( S_WARN "unexpected server list packet from %s\n", NET_AdrToString( from ));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the extra header
|
||||||
|
if( MSG_ReadByte( msg ) == 0x7f )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// serverlist got from masterserver
|
||||||
|
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||||
|
{
|
||||||
|
uint8_t addr[16];
|
||||||
|
netadr_t servadr;
|
||||||
|
|
||||||
|
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||||
|
{
|
||||||
|
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
||||||
|
NET_IP6BytesToNetadr( &servadr, addr );
|
||||||
|
servadr.type6 = NA_IP6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||||
|
servadr.type = NA_IP;
|
||||||
|
}
|
||||||
|
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||||
|
|
||||||
|
// list is ends here
|
||||||
|
if( !servadr.port )
|
||||||
|
break;
|
||||||
|
|
||||||
|
NET_Config( true, false ); // allow remote
|
||||||
|
Netchan_OutOfBandPrint( NS_CLIENT, servadr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cls.internetservers_pending )
|
||||||
|
{
|
||||||
|
UI_ResetPing();
|
||||||
|
cls.internetservers_pending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CL_ConnectionlessPacket
|
CL_ConnectionlessPacket
|
||||||
@ -2166,9 +2396,6 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||||||
{
|
{
|
||||||
char *args;
|
char *args;
|
||||||
const char *c;
|
const char *c;
|
||||||
char buf[MAX_SYSPATH];
|
|
||||||
int len = sizeof( buf );
|
|
||||||
netadr_t servadr;
|
|
||||||
|
|
||||||
MSG_Clear( msg );
|
MSG_Clear( msg );
|
||||||
MSG_ReadLong( msg ); // skip the -1
|
MSG_ReadLong( msg ); // skip the -1
|
||||||
@ -2181,290 +2408,70 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||||||
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
|
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
|
||||||
|
|
||||||
// server connection
|
// server connection
|
||||||
if( !Q_strcmp( c, "client_connect" ) || !Q_strcmp( c, S2C_CONNECTION ))
|
if( !Q_strcmp( c, S2C_GOLDSRC_CONNECTION ) || !Q_strcmp( c, S2C_CONNECTION ))
|
||||||
{
|
{
|
||||||
if( !CL_IsFromConnectingServer( from ))
|
CL_ClientConnect( c, from, msg );
|
||||||
return;
|
}
|
||||||
|
else if( !Q_strcmp( c, A2A_INFO ))
|
||||||
|
{
|
||||||
|
CL_ParseStatusMessage( from, msg ); // server responding to a status broadcast
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, A2A_NETINFO ))
|
||||||
|
{
|
||||||
|
CL_ParseNETInfoMessage( from, args ); // server responding to a status broadcast
|
||||||
|
}
|
||||||
|
else if( c[0] == A2C_GOLDSRC_PRINT || !Q_strcmp( c, A2C_PRINT ))
|
||||||
|
{
|
||||||
|
CL_Print( c, args, from, msg );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, S2C_BANDWIDTHTEST ))
|
||||||
|
{
|
||||||
|
CL_HandleTestPacket( from, msg );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, A2A_PING ))
|
||||||
|
{
|
||||||
|
Netchan_OutOfBandPrint( NS_CLIENT, from, A2A_ACK );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, A2A_GOLDSRC_PING ))
|
||||||
|
{
|
||||||
|
Netchan_OutOfBandPrint( NS_CLIENT, from, A2A_GOLDSRC_ACK );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, A2A_ACK ) || !Q_strcmp( c, A2A_GOLDSRC_ACK ))
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, S2C_CHALLENGE ) || !Q_strcmp( c, S2C_GOLDSRC_CHALLENGE ))
|
||||||
|
{
|
||||||
|
CL_Challenge( c, from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, S2C_REJECT ) || c[0] == S2C_GOLDSRC_REJECT || c[0] == S2C_GOLDSRC_REJECT_BADPASSWORD )
|
||||||
|
{
|
||||||
|
CL_Reject( c, args, from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, S2C_ERRORMSG ))
|
||||||
|
{
|
||||||
|
CL_ErrorMsg( c, args, from, msg );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( c, M2A_SERVERSLIST ))
|
||||||
|
{
|
||||||
|
CL_ServerList( from, msg );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[MAX_SYSPATH];
|
||||||
|
int len = sizeof( buf );
|
||||||
|
|
||||||
if( cls.state == ca_connected )
|
if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
||||||
{
|
{
|
||||||
Con_DPrintf( S_ERROR "dup connect received. ignored\n");
|
// user out of band message (must be handled in SV_ConnectionlessPacket)
|
||||||
return;
|
if( len > 0 )
|
||||||
}
|
Netchan_OutOfBand( NS_SERVER, from, len, (byte *)buf );
|
||||||
|
|
||||||
if( cls.legacymode != PROTO_GOLDSRC && !Q_strcmp( c, S2C_CONNECTION ))
|
|
||||||
{
|
|
||||||
Con_DPrintf( S_ERROR "GoldSrc client connect received but wasn't expected, ignored\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CL_Reconnect( true );
|
|
||||||
UI_SetActiveMenu( cl.background );
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "info" ))
|
|
||||||
{
|
|
||||||
// server responding to a status broadcast
|
|
||||||
CL_ParseStatusMessage( from, msg );
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "netinfo" ))
|
|
||||||
{
|
|
||||||
// server responding to a status broadcast
|
|
||||||
CL_ParseNETInfoMessage( from, args );
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "cmd" ))
|
|
||||||
{
|
|
||||||
// remote command from gui front end
|
|
||||||
if( !NET_IsLocalAddress( from ))
|
|
||||||
{
|
|
||||||
Con_Printf( "Command packet from remote host. Ignored.\n" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if XASH_SDL == 2
|
|
||||||
SDL_ShowWindow( host.hWnd );
|
|
||||||
#endif
|
|
||||||
args = MSG_ReadString( msg );
|
|
||||||
Cbuf_AddText( args );
|
|
||||||
Cbuf_AddText( "\n" );
|
|
||||||
}
|
|
||||||
else if( c[0] == 'l' )
|
|
||||||
{
|
|
||||||
char *s = args + 1;
|
|
||||||
|
|
||||||
Con_Printf( S_CYAN "r:" S_DEFAULT " %s", s );
|
|
||||||
if( !COM_CheckStringEmpty( s ) || s[Q_strlen( s ) - 1] != '\n' )
|
|
||||||
Con_Printf( "\n" );
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "print" ))
|
|
||||||
{
|
|
||||||
// print command from somewhere
|
|
||||||
char *s = MSG_ReadString( msg );
|
|
||||||
|
|
||||||
Con_Printf( S_CYAN "r:" S_DEFAULT " %s", s );
|
|
||||||
if( !COM_CheckStringEmpty( s ) || s[Q_strlen( s ) - 1] != '\n' )
|
|
||||||
Con_Printf( "\n" );
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "testpacket" ))
|
|
||||||
{
|
|
||||||
byte recv_buf[NET_MAX_FRAGMENT];
|
|
||||||
dword crcValue;
|
|
||||||
int realsize;
|
|
||||||
dword crcValue2 = 0;
|
|
||||||
|
|
||||||
// this message only used during connection
|
|
||||||
// it doesn't make sense after client_connect
|
|
||||||
if( cls.state != ca_connecting )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !CL_IsFromConnectingServer( from ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
crcValue = MSG_ReadLong( msg );
|
|
||||||
realsize = MSG_GetMaxBytes( msg ) - MSG_GetNumBytesRead( msg );
|
|
||||||
|
|
||||||
if( cls.max_fragment_size != MSG_GetMaxBytes( msg ))
|
|
||||||
{
|
|
||||||
if( cls.connect_retry >= CL_TEST_RETRIES )
|
|
||||||
{
|
|
||||||
// too many fails use default connection method
|
|
||||||
Con_Printf( "hi-speed connection is failed, use default method\n" );
|
|
||||||
CL_SendGetChallenge( from );
|
|
||||||
Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE );
|
|
||||||
cls.connect_time = host.realtime;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we waiting more than cl_timeout or packet was trashed
|
|
||||||
cls.connect_time = MAX_HEARTBEAT;
|
|
||||||
return; // just wait for a next responce
|
|
||||||
}
|
|
||||||
|
|
||||||
// reading test buffer
|
|
||||||
MSG_ReadBytes( msg, recv_buf, realsize );
|
|
||||||
|
|
||||||
// procssing the CRC
|
|
||||||
CRC32_ProcessBuffer( &crcValue2, recv_buf, realsize );
|
|
||||||
|
|
||||||
if( crcValue == crcValue2 )
|
|
||||||
{
|
|
||||||
// packet was sucessfully delivered, adjust the fragment size and get challenge
|
|
||||||
|
|
||||||
Con_DPrintf( "CRC %x is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size );
|
|
||||||
CL_SendGetChallenge( from );
|
|
||||||
Cvar_SetValue( "cl_dlmax", cls.max_fragment_size );
|
|
||||||
cls.connect_time = host.realtime;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( cls.connect_retry >= CL_TEST_RETRIES )
|
Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
|
||||||
{
|
|
||||||
// too many fails use default connection method
|
|
||||||
Con_Printf( "hi-speed connection is failed, use default method\n" );
|
|
||||||
CL_SendGetChallenge( from );
|
|
||||||
Cvar_SetValue( "cl_dlmax", FRAGMENT_MIN_SIZE );
|
|
||||||
cls.connect_time = host.realtime;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Msg( "got testpacket, CRC mismatched 0x%08x should be 0x%08x, trying next fragment size %d\n", crcValue2, crcValue, cls.max_fragment_size >> 1 );
|
|
||||||
|
|
||||||
// trying the next size of packet
|
|
||||||
cls.connect_time = MAX_HEARTBEAT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( !Q_strcmp( c, "ping" ))
|
|
||||||
{
|
|
||||||
// ping from somewhere
|
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, from, "ack" );
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "challenge" ) || !Q_strcmp( c, S2C_CHALLENGE ))
|
|
||||||
{
|
|
||||||
// this message only used during connection
|
|
||||||
// it doesn't make sense after client_connect
|
|
||||||
if( cls.state != ca_connecting )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !CL_IsFromConnectingServer( from ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// try to autodetect protocol by challenge response
|
|
||||||
if( !Q_strcmp( c, S2C_CHALLENGE ))
|
|
||||||
cls.legacymode = PROTO_GOLDSRC;
|
|
||||||
|
|
||||||
// challenge from the server we are connecting to
|
|
||||||
CL_SendConnectPacket( cls.legacymode, Q_atoi( Cmd_Argv( 1 )));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "echo" ))
|
|
||||||
{
|
|
||||||
if( !CL_IsFromConnectingServer( from ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// echo request from server
|
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv( 1 ));
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "disconnect" ))
|
|
||||||
{
|
|
||||||
// this message only used during connection
|
|
||||||
// it doesn't make sense after client_connect
|
|
||||||
if( cls.state != ca_connecting )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !CL_IsFromConnectingServer( from ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// a disconnect message from the server, which will happen if the server
|
|
||||||
// dropped the connection but it is still getting packets from us
|
|
||||||
CL_Disconnect_f();
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "errormsg" ) || c[0] == S2C_REJECT || c[0] == S2C_REJECT_BADPASSWORD )
|
|
||||||
{
|
|
||||||
char formatted_msg[MAX_VA_STRING];
|
|
||||||
|
|
||||||
if( !CL_IsFromConnectingServer( from ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
args = MSG_ReadString( msg );
|
|
||||||
if( c[0] == S2C_REJECT || c[0] == S2C_REJECT_BADPASSWORD )
|
|
||||||
args++; // skip one byte
|
|
||||||
|
|
||||||
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args );
|
|
||||||
|
|
||||||
// in case we're in console or it's classic mainui which doesn't support messageboxes
|
|
||||||
if( !UI_IsVisible() || !UI_ShowMessageBox( formatted_msg ))
|
|
||||||
Msg( "%s\n", formatted_msg );
|
|
||||||
|
|
||||||
CL_Disconnect_f();
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "updatemsg" ))
|
|
||||||
{
|
|
||||||
// got an update message from master server
|
|
||||||
// show update dialog from menu
|
|
||||||
netadr_t adr;
|
|
||||||
qboolean preferStore = true;
|
|
||||||
|
|
||||||
if( !Q_strcmp( Cmd_Argv( 1 ), "nostore" ) )
|
|
||||||
preferStore = false;
|
|
||||||
|
|
||||||
// trust only hardcoded master server
|
|
||||||
if( NET_StringToAdr( MASTERSERVER_ADR, &adr ) )
|
|
||||||
{
|
|
||||||
if( NET_CompareAdr( from, adr ))
|
|
||||||
{
|
|
||||||
UI_ShowUpdateDialog( preferStore );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// in case we don't have master anymore
|
|
||||||
UI_ShowUpdateDialog( preferStore );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( !Q_strcmp( c, "f" ))
|
|
||||||
{
|
|
||||||
if( !NET_IsMasterAdr( from ))
|
|
||||||
{
|
|
||||||
Con_Printf( S_WARN "unexpected server list packet from %s\n", NET_AdrToString( from ));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the extra header
|
|
||||||
if( MSG_ReadByte( msg ) == 0x7f )
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverlist got from masterserver
|
|
||||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
|
||||||
{
|
|
||||||
uint8_t addr[16];
|
|
||||||
|
|
||||||
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
|
||||||
{
|
|
||||||
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
|
||||||
NET_IP6BytesToNetadr( &servadr, addr );
|
|
||||||
servadr.type6 = NA_IP6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
|
||||||
servadr.type = NA_IP;
|
|
||||||
}
|
|
||||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
|
||||||
|
|
||||||
// list is ends here
|
|
||||||
if( !servadr.port )
|
|
||||||
break;
|
|
||||||
|
|
||||||
NET_Config( true, false ); // allow remote
|
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( cls.internetservers_pending )
|
|
||||||
{
|
|
||||||
UI_ResetPing();
|
|
||||||
cls.internetservers_pending = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
|
||||||
{
|
|
||||||
// user out of band message (must be handled in CL_ConnectionlessPacket)
|
|
||||||
if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, (byte *)buf );
|
|
||||||
}
|
|
||||||
else Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -343,12 +343,6 @@ extern const char *const clc_strings[clc_lastmsg+1];
|
|||||||
#define clc_goldsrc_requestcvarvalue2 11
|
#define clc_goldsrc_requestcvarvalue2 11
|
||||||
#define clc_goldsrc_lastmsg 11
|
#define clc_goldsrc_lastmsg 11
|
||||||
|
|
||||||
#define S2C_REJECT_BADPASSWORD '8'
|
|
||||||
#define S2C_REJECT '9'
|
|
||||||
#define S2C_CHALLENGE "A00000000"
|
|
||||||
#define S2C_CONNECTION "B"
|
|
||||||
#define A2C_PRINT 'l'
|
|
||||||
|
|
||||||
#define MAX_GOLDSRC_BACKUP_CMDS 8
|
#define MAX_GOLDSRC_BACKUP_CMDS 8
|
||||||
#define MAX_GOLDSRC_TOTAL_CMDS 16
|
#define MAX_GOLDSRC_TOTAL_CMDS 16
|
||||||
#define MAX_GOLDSRC_MODEL_BITS 10
|
#define MAX_GOLDSRC_MODEL_BITS 10
|
||||||
@ -358,4 +352,55 @@ extern const char *const clc_strings[clc_lastmsg+1];
|
|||||||
#define MAX_GOLDSRC_EDICTS ( BIT( MAX_ENTITY_BITS ) + ( MAX_CLIENTS * 15 ))
|
#define MAX_GOLDSRC_EDICTS ( BIT( MAX_ENTITY_BITS ) + ( MAX_CLIENTS * 15 ))
|
||||||
#define LAST_GOLDSRC_EDICT ( BIT( MAX_ENTITY_BITS ) - 1 )
|
#define LAST_GOLDSRC_EDICT ( BIT( MAX_ENTITY_BITS ) - 1 )
|
||||||
|
|
||||||
|
|
||||||
|
// from any to any (must be handled on both server and client)
|
||||||
|
|
||||||
|
#define A2A_PING "ping" // reply with A2A_ACK
|
||||||
|
#define A2A_ACK "ack" // no-op
|
||||||
|
#define A2A_INFO "info" // different format for client and server, see code
|
||||||
|
#define A2A_NETINFO "netinfo" // different format for client and server, see code
|
||||||
|
#define A2A_GOLDSRC_PING "i" // reply with A2A_GOLDSRC_ACK
|
||||||
|
#define A2A_GOLDSRC_ACK "j" // no-op
|
||||||
|
|
||||||
|
// from any to server
|
||||||
|
#define A2S_GOLDSRC_INFO 'T'
|
||||||
|
#define A2S_GOLDSRC_RULES 'V'
|
||||||
|
#define A2S_GOLDSRC_PLAYERS 'U'
|
||||||
|
|
||||||
|
// from server to any
|
||||||
|
#define S2A_GOLDSRC_INFO 'I'
|
||||||
|
#define S2A_GOLDSRC_RULES 'E'
|
||||||
|
#define S2A_GOLDSRC_PLAYERS 'D'
|
||||||
|
|
||||||
|
// from master to server
|
||||||
|
#define M2S_CHALLENGE "s"
|
||||||
|
#define M2S_NAT_CONNECT "c"
|
||||||
|
|
||||||
|
// from server to master
|
||||||
|
#define S2M_INFO "0\n"
|
||||||
|
|
||||||
|
// from client to server
|
||||||
|
#define C2S_BANDWIDTHTEST "bandwidth"
|
||||||
|
#define C2S_GETCHALLENGE "getchallenge"
|
||||||
|
#define C2S_CONNECT "connect"
|
||||||
|
#define C2S_RCON "rcon"
|
||||||
|
|
||||||
|
// from server to client
|
||||||
|
#define S2C_BANDWIDTHTEST "testpacket"
|
||||||
|
#define S2C_CHALLENGE "challenge"
|
||||||
|
#define S2C_CONNECTION "client_connect"
|
||||||
|
#define S2C_ERRORMSG "errormsg"
|
||||||
|
#define S2C_REJECT "disconnect"
|
||||||
|
#define S2C_GOLDSRC_REJECT_BADPASSWORD '8'
|
||||||
|
#define S2C_GOLDSRC_REJECT '9'
|
||||||
|
#define S2C_GOLDSRC_CHALLENGE "A00000000"
|
||||||
|
#define S2C_GOLDSRC_CONNECTION "B"
|
||||||
|
|
||||||
|
// from any to client
|
||||||
|
#define A2C_PRINT "print"
|
||||||
|
#define A2C_GOLDSRC_PRINT 'l'
|
||||||
|
|
||||||
|
// from master to client
|
||||||
|
#define M2A_SERVERSLIST "f"
|
||||||
|
|
||||||
#endif//NET_PROTOCOL_H
|
#endif//NET_PROTOCOL_H
|
||||||
|
@ -683,6 +683,6 @@ int SV_LightForEntity( edict_t *pEdict );
|
|||||||
//
|
//
|
||||||
// sv_query.c
|
// sv_query.c
|
||||||
//
|
//
|
||||||
qboolean SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from );
|
void SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from );
|
||||||
|
|
||||||
#endif//SERVER_H
|
#endif//SERVER_H
|
||||||
|
@ -131,7 +131,7 @@ static void SV_GetChallenge( netadr_t from )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send it back
|
// send it back
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "challenge %i", svs.challenges[i].challenge );
|
Netchan_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, S2C_CHALLENGE" %i", svs.challenges[i].challenge );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SV_GetFragmentSize( void *pcl, fragsize_t mode )
|
static int SV_GetFragmentSize( void *pcl, fragsize_t mode )
|
||||||
@ -194,9 +194,9 @@ void SV_RejectConnection( netadr_t from, const char *fmt, ... )
|
|||||||
va_end( argptr );
|
va_end( argptr );
|
||||||
|
|
||||||
Con_Reportf( "%s connection refused. Reason: %s\n", NET_AdrToString( from ), text );
|
Con_Reportf( "%s connection refused. Reason: %s\n", NET_AdrToString( from ), text );
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\n^1Server was reject the connection:^7 %s", text );
|
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_ERRORMSG"\n^1Server was reject the connection:^7 %s", text );
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "print\n^1Server was reject the connection:^7 %s", text );
|
Netchan_OutOfBandPrint( NS_SERVER, from, A2C_PRINT"\n^1Server was reject the connection:^7 %s", text );
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
|
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_REJECT"\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -456,7 +456,7 @@ static void SV_ConnectClient( netadr_t from )
|
|||||||
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", newcl->extensions );
|
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", newcl->extensions );
|
||||||
|
|
||||||
// send the connect packet to the client
|
// send the connect packet to the client
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect %s", protinfo );
|
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_CONNECTION" %s", protinfo );
|
||||||
|
|
||||||
newcl->upstate = us_inactive;
|
newcl->upstate = us_inactive;
|
||||||
newcl->connection_started = host.realtime;
|
newcl->connection_started = host.realtime;
|
||||||
@ -604,7 +604,7 @@ void SV_KickPlayer( sv_client_t *cl, const char *fmt, ... )
|
|||||||
SV_BroadcastPrintf( cl, "%s was kicked with message: \"%s\"\n", cl->name, buf );
|
SV_BroadcastPrintf( cl, "%s was kicked with message: \"%s\"\n", cl->name, buf );
|
||||||
SV_ClientPrintf( cl, "You were kicked from the game with message: \"%s\"\n", buf );
|
SV_ClientPrintf( cl, "You were kicked from the game with message: \"%s\"\n", buf );
|
||||||
if( cl->useragent[0] )
|
if( cl->useragent[0] )
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, "errormsg\nKicked with message:\n%s\n", buf );
|
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, S2C_ERRORMSG"\nKicked with message:\n%s\n", buf );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -612,7 +612,7 @@ void SV_KickPlayer( sv_client_t *cl, const char *fmt, ... )
|
|||||||
SV_BroadcastPrintf( cl, "%s was kicked\n", cl->name );
|
SV_BroadcastPrintf( cl, "%s was kicked\n", cl->name );
|
||||||
SV_ClientPrintf( cl, "You were kicked from the game\n" );
|
SV_ClientPrintf( cl, "You were kicked from the game\n" );
|
||||||
if( cl->useragent[0] )
|
if( cl->useragent[0] )
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, "errormsg\nYou were kicked from the game\n" );
|
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, S2C_ERRORMSG"\nYou were kicked from the game\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_DropClient( cl, false );
|
SV_DropClient( cl, false );
|
||||||
@ -720,7 +720,7 @@ static void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
|
|||||||
switch( dest )
|
switch( dest )
|
||||||
{
|
{
|
||||||
case RD_PACKET:
|
case RD_PACKET:
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, adr, "print\n%s", buf );
|
Netchan_OutOfBandPrint( NS_SERVER, adr, A2C_PRINT"\n%s", buf );
|
||||||
break;
|
break;
|
||||||
case RD_CLIENT:
|
case RD_CLIENT:
|
||||||
if( !sv.current_client ) return; // client not set
|
if( !sv.current_client ) return; // client not set
|
||||||
@ -960,7 +960,23 @@ static void SV_Info( netadr_t from, int protocolVersion )
|
|||||||
Info_SetValueForKey( s, "host", temp, sizeof( s ));
|
Info_SetValueForKey( s, "host", temp, sizeof( s ));
|
||||||
}
|
}
|
||||||
|
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "info\n%s", s );
|
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_INFO"\n%s", s );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SV_ConnectNatClient( netadr_t from )
|
||||||
|
{
|
||||||
|
netadr_t to;
|
||||||
|
|
||||||
|
if( !sv_nat.value || !NET_IsMasterAdr( from ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !NET_StringToAdr( Cmd_Argv( 1 ), &to ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( NET_IsReservedAdr( to ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SV_Info( to, PROTOCOL_VERSION );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -994,7 +1010,7 @@ static void SV_BuildNetAnswer( netadr_t from )
|
|||||||
{
|
{
|
||||||
// send error unsupported protocol
|
// send error unsupported protocol
|
||||||
Info_SetValueForKey( string, "neterror", "protocol", sizeof( string ));
|
Info_SetValueForKey( string, "neterror", "protocol", sizeof( string ));
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "netinfo %i %i %s\n", context, type, string );
|
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_NETINFO" %i %i %s\n", context, type, string );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1065,19 +1081,7 @@ static void SV_BuildNetAnswer( netadr_t from )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "netinfo %i %i %s\n", context, type, string );
|
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_NETINFO" %i %i %s\n", context, type, string );
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
SV_Ping
|
|
||||||
|
|
||||||
Just responds with an acknowledgement
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
static void SV_Ping( netadr_t from )
|
|
||||||
{
|
|
||||||
Netchan_OutOfBandPrint( NS_SERVER, from, "ack" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3148,17 +3152,14 @@ connectionless packets.
|
|||||||
*/
|
*/
|
||||||
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||||
{
|
{
|
||||||
char *args;
|
const char *pcmd, *args;
|
||||||
const char *pcmd;
|
|
||||||
char buf[MAX_SYSPATH];
|
|
||||||
int len = sizeof( buf );
|
|
||||||
|
|
||||||
// prevent flooding from banned address
|
// prevent flooding from banned address
|
||||||
if( SV_CheckIP( &from ) )
|
if( SV_CheckIP( &from ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MSG_Clear( msg );
|
MSG_Clear( msg );
|
||||||
MSG_ReadLong( msg );// skip the -1 marker
|
MSG_SeekToBit( msg, sizeof( uint32_t ) << 3, SEEK_CUR ); // skip the -1 marker
|
||||||
|
|
||||||
args = MSG_ReadStringLine( msg );
|
args = MSG_ReadStringLine( msg );
|
||||||
Cmd_TokenizeString( args );
|
Cmd_TokenizeString( args );
|
||||||
@ -3168,29 +3169,79 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||||||
if( sv_log_outofband.value )
|
if( sv_log_outofband.value )
|
||||||
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), pcmd );
|
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), pcmd );
|
||||||
|
|
||||||
if( !Q_strcmp( pcmd, "ping" )) SV_Ping( from );
|
if( !svs.initialized )
|
||||||
else if( !Q_strcmp( pcmd, "ack" )) SV_Ack( from );
|
|
||||||
else if( !Q_strcmp( pcmd, "info" )) SV_Info( from, Q_atoi( Cmd_Argv( 1 )));
|
|
||||||
else if( !Q_strcmp( pcmd, "bandwidth" )) SV_TestBandWidth( from );
|
|
||||||
else if( !Q_strcmp( pcmd, "getchallenge" )) SV_GetChallenge( from );
|
|
||||||
else if( !Q_strcmp( pcmd, "connect" )) SV_ConnectClient( from );
|
|
||||||
else if( !Q_strcmp( pcmd, "rcon" )) SV_RemoteCommand( from, msg );
|
|
||||||
else if( !Q_strcmp( pcmd, "netinfo" )) SV_BuildNetAnswer( from );
|
|
||||||
else if( !Q_strcmp( pcmd, "s" )) SV_AddToMaster( from, msg );
|
|
||||||
else if( !Q_strcmp( pcmd, "i" )) NET_SendPacket( NS_SERVER, 5, "\xFF\xFF\xFF\xFFj", from ); // A2A_PING
|
|
||||||
else if( SV_SourceQuery_HandleConnnectionlessPacket( pcmd, from )) { } // function handles replies
|
|
||||||
else if( !Q_strcmp( pcmd, "c" ) && sv_nat.value && NET_IsMasterAdr( from ))
|
|
||||||
{
|
{
|
||||||
netadr_t to;
|
// only process rcon if server not initialized
|
||||||
if( NET_StringToAdr( Cmd_Argv( 1 ), &to ) && !NET_IsReservedAdr( to ))
|
if( !Q_strcmp( pcmd, C2S_RCON ))
|
||||||
SV_Info( to, PROTOCOL_VERSION );
|
SV_RemoteCommand( net_from, &net_message );
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if( svgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
|
||||||
|
if( pcmd[0] == A2S_GOLDSRC_INFO || pcmd[0] == A2S_GOLDSRC_PLAYERS || pcmd[0] == A2S_GOLDSRC_RULES )
|
||||||
{
|
{
|
||||||
// user out of band message (must be handled in CL_ConnectionlessPacket)
|
SV_SourceQuery_HandleConnnectionlessPacket( pcmd, from );
|
||||||
if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, (byte*)buf );
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, A2A_NETINFO ))
|
||||||
|
{
|
||||||
|
SV_BuildNetAnswer( from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, A2A_INFO ))
|
||||||
|
{
|
||||||
|
SV_Info( from, Q_atoi( Cmd_Argv( 1 )));
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, M2S_CHALLENGE ))
|
||||||
|
{
|
||||||
|
SV_AddToMaster( from, msg );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, M2S_NAT_CONNECT ))
|
||||||
|
{
|
||||||
|
SV_ConnectNatClient( from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, C2S_BANDWIDTHTEST ))
|
||||||
|
{
|
||||||
|
SV_TestBandWidth( from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, C2S_GETCHALLENGE ))
|
||||||
|
{
|
||||||
|
SV_GetChallenge( from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, C2S_CONNECT ))
|
||||||
|
{
|
||||||
|
SV_ConnectClient( from );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, A2A_PING ))
|
||||||
|
{
|
||||||
|
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_ACK );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, A2A_GOLDSRC_PING ))
|
||||||
|
{
|
||||||
|
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_GOLDSRC_ACK );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, C2S_RCON ))
|
||||||
|
{
|
||||||
|
SV_RemoteCommand( from, msg );
|
||||||
|
}
|
||||||
|
else if( !Q_strcmp( pcmd, A2A_ACK ) || !Q_strcmp( pcmd, A2A_GOLDSRC_ACK ))
|
||||||
|
{
|
||||||
|
SV_Ack( from );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[MAX_SYSPATH];
|
||||||
|
int len = sizeof( buf );
|
||||||
|
|
||||||
|
if( svgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
|
||||||
|
{
|
||||||
|
// user out of band message (must be handled in CL_ConnectionlessPacket)
|
||||||
|
if( len > 0 )
|
||||||
|
Netchan_OutOfBand( NS_SERVER, from, len, (byte*)buf );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -973,7 +973,7 @@ static void SV_GenerateTestPacket( void )
|
|||||||
// write packet base data
|
// write packet base data
|
||||||
MSG_Init( &svs.testpacket, "BandWidthTest", svs.testpacket_buf, maxsize );
|
MSG_Init( &svs.testpacket, "BandWidthTest", svs.testpacket_buf, maxsize );
|
||||||
MSG_WriteLong( &svs.testpacket, -1 );
|
MSG_WriteLong( &svs.testpacket, -1 );
|
||||||
MSG_WriteString( &svs.testpacket, "testpacket" );
|
MSG_WriteString( &svs.testpacket, S2C_BANDWIDTHTEST );
|
||||||
svs.testpacket_crcpos = svs.testpacket.pData + MSG_GetNumBytesWritten( &svs.testpacket );
|
svs.testpacket_crcpos = svs.testpacket.pData + MSG_GetNumBytesWritten( &svs.testpacket );
|
||||||
MSG_WriteDword( &svs.testpacket, 0 ); // to be changed by crc
|
MSG_WriteDword( &svs.testpacket, 0 ); // to be changed by crc
|
||||||
|
|
||||||
|
@ -389,23 +389,7 @@ static void SV_ReadPackets( void )
|
|||||||
// check for connectionless packet (0xffffffff) first
|
// check for connectionless packet (0xffffffff) first
|
||||||
if( MSG_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 )
|
if( MSG_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 )
|
||||||
{
|
{
|
||||||
if( !svs.initialized )
|
SV_ConnectionlessPacket( net_from, &net_message );
|
||||||
{
|
|
||||||
char *args;
|
|
||||||
const char *c;
|
|
||||||
|
|
||||||
MSG_Clear( &net_message );
|
|
||||||
MSG_ReadLong( &net_message );// skip the -1 marker
|
|
||||||
|
|
||||||
args = MSG_ReadStringLine( &net_message );
|
|
||||||
Cmd_TokenizeString( args );
|
|
||||||
c = Cmd_Argv( 0 );
|
|
||||||
|
|
||||||
if( !Q_strcmp( c, "rcon" ))
|
|
||||||
SV_RemoteCommand( net_from, &net_message );
|
|
||||||
}
|
|
||||||
else SV_ConnectionlessPacket( net_from, &net_message );
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +714,7 @@ Master will validate challenge and this server to public list
|
|||||||
void SV_AddToMaster( netadr_t from, sizebuf_t *msg )
|
void SV_AddToMaster( netadr_t from, sizebuf_t *msg )
|
||||||
{
|
{
|
||||||
uint challenge, challenge2, heartbeat_challenge;
|
uint challenge, challenge2, heartbeat_challenge;
|
||||||
char s[MAX_INFO_STRING] = "0\n"; // skip 2 bytes of header
|
char s[MAX_INFO_STRING] = S2M_INFO; // skip 2 bytes of header
|
||||||
int clients, bots;
|
int clients, bots;
|
||||||
double last_heartbeat;
|
double last_heartbeat;
|
||||||
const int len = sizeof( s );
|
const int len = sizeof( s );
|
||||||
|
@ -16,15 +16,6 @@ GNU General Public License for more details.
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
#define SOURCE_QUERY_DETAILS 'T'
|
|
||||||
#define SOURCE_QUERY_DETAILS_RESPONSE 'I'
|
|
||||||
|
|
||||||
#define SOURCE_QUERY_RULES 'V'
|
|
||||||
#define SOURCE_QUERY_RULES_RESPONSE 'E'
|
|
||||||
|
|
||||||
#define SOURCE_QUERY_PLAYERS 'U'
|
|
||||||
#define SOURCE_QUERY_PLAYERS_RESPONSE 'D'
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
SV_SourceQuery_Details
|
SV_SourceQuery_Details
|
||||||
@ -41,7 +32,8 @@ static void SV_SourceQuery_Details( netadr_t from )
|
|||||||
|
|
||||||
MSG_Init( &buf, "TSourceEngineQuery", answer, sizeof( answer ));
|
MSG_Init( &buf, "TSourceEngineQuery", answer, sizeof( answer ));
|
||||||
|
|
||||||
MSG_WriteByte( &buf, SOURCE_QUERY_DETAILS_RESPONSE );
|
MSG_WriteDword( &buf, 0xFFFFFFFFU );
|
||||||
|
MSG_WriteByte( &buf, S2A_GOLDSRC_INFO );
|
||||||
MSG_WriteByte( &buf, PROTOCOL_VERSION );
|
MSG_WriteByte( &buf, PROTOCOL_VERSION );
|
||||||
|
|
||||||
MSG_WriteString( &buf, hostname.string );
|
MSG_WriteString( &buf, hostname.string );
|
||||||
@ -69,7 +61,7 @@ static void SV_SourceQuery_Details( netadr_t from )
|
|||||||
MSG_WriteByte( &buf, GI->secure );
|
MSG_WriteByte( &buf, GI->secure );
|
||||||
MSG_WriteString( &buf, XASH_VERSION );
|
MSG_WriteString( &buf, XASH_VERSION );
|
||||||
|
|
||||||
Netchan_OutOfBand( NS_SERVER, from, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ));
|
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ), from );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -87,7 +79,8 @@ static void SV_SourceQuery_Rules( netadr_t from )
|
|||||||
|
|
||||||
MSG_Init( &buf, "TSourceEngineQueryRules", answer, sizeof( answer ));
|
MSG_Init( &buf, "TSourceEngineQueryRules", answer, sizeof( answer ));
|
||||||
|
|
||||||
MSG_WriteByte( &buf, SOURCE_QUERY_RULES_RESPONSE );
|
MSG_WriteDword( &buf, 0xFFFFFFFFU );
|
||||||
|
MSG_WriteByte( &buf, S2A_GOLDSRC_RULES );
|
||||||
|
|
||||||
pos = MSG_GetNumBitsWritten( &buf );
|
pos = MSG_GetNumBitsWritten( &buf );
|
||||||
MSG_WriteShort( &buf, 0 );
|
MSG_WriteShort( &buf, 0 );
|
||||||
@ -117,7 +110,7 @@ static void SV_SourceQuery_Rules( netadr_t from )
|
|||||||
MSG_SeekToBit( &buf, pos, SEEK_SET );
|
MSG_SeekToBit( &buf, pos, SEEK_SET );
|
||||||
MSG_WriteShort( &buf, cvar_count );
|
MSG_WriteShort( &buf, cvar_count );
|
||||||
|
|
||||||
Netchan_OutOfBand( NS_SERVER, from, total, MSG_GetData( &buf ));
|
NET_SendPacket( NS_SERVER, total, MSG_GetData( &buf ), from );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +132,8 @@ static void SV_SourceQuery_Players( netadr_t from )
|
|||||||
|
|
||||||
MSG_Init( &buf, "TSourceEngineQueryPlayers", answer, sizeof( answer ));
|
MSG_Init( &buf, "TSourceEngineQueryPlayers", answer, sizeof( answer ));
|
||||||
|
|
||||||
MSG_WriteByte( &buf, SOURCE_QUERY_PLAYERS_RESPONSE );
|
MSG_WriteDword( &buf, 0xFFFFFFFFU );
|
||||||
|
MSG_WriteByte( &buf, S2A_GOLDSRC_PLAYERS );
|
||||||
|
|
||||||
pos = MSG_GetNumBitsWritten( &buf );
|
pos = MSG_GetNumBitsWritten( &buf );
|
||||||
MSG_WriteByte( &buf, 0 );
|
MSG_WriteByte( &buf, 0 );
|
||||||
@ -168,7 +162,7 @@ static void SV_SourceQuery_Players( netadr_t from )
|
|||||||
MSG_SeekToBit( &buf, pos, SEEK_SET );
|
MSG_SeekToBit( &buf, pos, SEEK_SET );
|
||||||
MSG_WriteByte( &buf, count );
|
MSG_WriteByte( &buf, count );
|
||||||
|
|
||||||
Netchan_OutOfBand( NS_SERVER, from, total, MSG_GetData( &buf ));
|
NET_SendPacket( NS_SERVER, total, MSG_GetData( &buf ), from );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,24 +171,18 @@ static void SV_SourceQuery_Players( netadr_t from )
|
|||||||
SV_SourceQuery_HandleConnnectionlessPacket
|
SV_SourceQuery_HandleConnnectionlessPacket
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
qboolean SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from )
|
void SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from )
|
||||||
{
|
{
|
||||||
switch( c[0] )
|
switch( c[0] )
|
||||||
{
|
{
|
||||||
case SOURCE_QUERY_DETAILS:
|
case A2S_GOLDSRC_INFO:
|
||||||
SV_SourceQuery_Details( from );
|
SV_SourceQuery_Details( from );
|
||||||
return true;
|
break;
|
||||||
|
case A2S_GOLDSRC_RULES:
|
||||||
case SOURCE_QUERY_RULES:
|
|
||||||
SV_SourceQuery_Rules( from );
|
SV_SourceQuery_Rules( from );
|
||||||
return true;
|
break;
|
||||||
|
case A2S_GOLDSRC_PLAYERS:
|
||||||
case SOURCE_QUERY_PLAYERS:
|
|
||||||
SV_SourceQuery_Players( from );
|
SV_SourceQuery_Players( from );
|
||||||
return true;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user