From cb0159014de59e7234cf834fe7b81113c8f9dd21 Mon Sep 17 00:00:00 2001 From: Yamagi Burmeister Date: Fri, 26 Nov 2010 08:12:50 +0000 Subject: [PATCH] Connectionless server commands in eine eigene Datei --- Makefile | 8 + src/server/sv_conless.c | 427 ++++++++++++++++++++++++++++++++++++++++ src/server/sv_main.c | 396 +------------------------------------ 3 files changed, 436 insertions(+), 395 deletions(-) create mode 100644 src/server/sv_conless.c diff --git a/Makefile b/Makefile index 5c139cb6..1ee08673 100644 --- a/Makefile +++ b/Makefile @@ -241,6 +241,7 @@ GAME_ABI_OBJS = \ # Server objects SERVER_OBJS = \ build/server/sv_cmd.o \ + build/server/sv_conless.o \ build/server/sv_entities.o \ build/server/sv_game.o \ build/server/sv_init.o \ @@ -273,6 +274,7 @@ SDL_OBJS= \ # Dedicated server object DEDICATED_SERVER_OBJS = \ build/dedicated_server/sv_cmd.o \ + build/dedicated_server/sv_conless.o \ build/dedicated_server/sv_entities.o \ build/dedicated_server/sv_game.o \ build/dedicated_server/sv_init.o \ @@ -607,6 +609,9 @@ build/gameabi/q_shared.o : src/game/baseq2/q_shared.c build/server/sv_cmd.o : src/server/sv_cmd.c $(CC) $(CFLAGS_CLIENT) -o $@ -c $< +build/server/sv_conless.o : src/server/sv_conless.c + $(CC) $(CFLAGS_CLIENT) -o $@ -c $< + build/server/sv_entities.o : src/server/sv_entities.c $(CC) $(CFLAGS_CLIENT) -o $@ -c $< @@ -666,6 +671,9 @@ build/sdl/sound.o : src/sdl/sound.c build/dedicated_server/sv_cmd.o : src/server/sv_cmd.c $(CC) $(CFLAGS_DEDICATED_SERVER) -o $@ -c $< +build/dedicated_server/sv_conless.o : src/server/sv_conless.c + $(CC) $(CFLAGS_DEDICATED_SERVER) -o $@ -c $< + build/dedicated_server/sv_entities.o : src/server/sv_entities.c $(CC) $(CFLAGS_DEDICATED_SERVER) -o $@ -c $< diff --git a/src/server/sv_conless.c b/src/server/sv_conless.c new file mode 100644 index 00000000..5b760bdb --- /dev/null +++ b/src/server/sv_conless.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 1997-2001 Id Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * ======================================================================= + * + * Connectionless server commands. + * + * ======================================================================= + */ + +#include "header/server.h" + +extern cvar_t *hostname; +extern cvar_t *rcon_password; + +cvar_t *sv_reconnect_limit; /* minimum seconds between connect messages */ + +char * SV_StatusString ( void ); + +/* + * Responds with all the info that qplug or qspy can see + */ +void +SVC_Status ( void ) +{ + Netchan_OutOfBandPrint( NS_SERVER, net_from, "print\n%s", SV_StatusString() ); +} + +void +SVC_Ack ( void ) +{ + Com_Printf( "Ping acknowledge from %s\n", NET_AdrToString( net_from ) ); +} + +/* + * Responds with short info for broadcast scans + * The second parameter should be the current protocol version number. + */ +void +SVC_Info ( void ) +{ + char string [ 64 ]; + int i, count; + int version; + + if ( maxclients->value == 1 ) + { + return; /* ignore in single player */ + } + + version = atoi( Cmd_Argv( 1 ) ); + + if ( version != PROTOCOL_VERSION ) + { + Com_sprintf( string, sizeof ( string ), "%s: wrong version\n", hostname->string, sizeof ( string ) ); + } + else + { + count = 0; + + for ( i = 0; i < maxclients->value; i++ ) + { + if ( svs.clients [ i ].state >= cs_connected ) + { + count++; + } + } + + Com_sprintf( string, sizeof ( string ), "%16s %8s %2i/%2i\n", hostname->string, sv.name, count, (int) maxclients->value ); + } + + Netchan_OutOfBandPrint( NS_SERVER, net_from, "info\n%s", string ); +} + +/* + * SVC_Ping + */ +void +SVC_Ping ( void ) +{ + Netchan_OutOfBandPrint( NS_SERVER, net_from, "ack" ); +} + +/* + * Returns a challenge number that can be used + * in a subsequent client_connect command. + * We do this to prevent denial of service attacks that + * flood the server with invalid connection IPs. With a + * challenge, they must give a valid IP address. + */ +void +SVC_GetChallenge ( void ) +{ + int i; + int oldest; + int oldestTime; + + oldest = 0; + oldestTime = 0x7fffffff; + + /* see if we already have a challenge for this ip */ + for ( i = 0; i < MAX_CHALLENGES; i++ ) + { + if ( NET_CompareBaseAdr( net_from, svs.challenges [ i ].adr ) ) + { + break; + } + + if ( svs.challenges [ i ].time < oldestTime ) + { + oldestTime = svs.challenges [ i ].time; + oldest = i; + } + } + + if ( i == MAX_CHALLENGES ) + { + /* overwrite the oldest */ + svs.challenges [ oldest ].challenge = rand() & 0x7fff; + svs.challenges [ oldest ].adr = net_from; + svs.challenges [ oldest ].time = curtime; + i = oldest; + } + + /* send it back */ + Netchan_OutOfBandPrint( NS_SERVER, net_from, "challenge %i", svs.challenges [ i ].challenge ); +} + +/* + * A connection request that did not come from the master + */ +void +SVC_DirectConnect ( void ) +{ + char userinfo [ MAX_INFO_STRING ]; + netadr_t adr; + int i; + client_t *cl, *newcl; + client_t temp; + edict_t *ent; + int edictnum; + int version; + int qport; + int challenge; + + adr = net_from; + + Com_DPrintf( "SVC_DirectConnect ()\n" ); + + version = atoi( Cmd_Argv( 1 ) ); + + if ( version != PROTOCOL_VERSION ) + { + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nServer is version %4.2f.\n", VERSION ); + Com_DPrintf( " rejected connect from version %i\n", version ); + return; + } + + qport = atoi( Cmd_Argv( 2 ) ); + + challenge = atoi( Cmd_Argv( 3 ) ); + + strncpy( userinfo, Cmd_Argv( 4 ), sizeof ( userinfo ) - 1 ); + userinfo [ sizeof ( userinfo ) - 1 ] = 0; + + /* force the IP key/value pair so the game can filter based on ip */ + Info_SetValueForKey( userinfo, "ip", NET_AdrToString( net_from ) ); + + /* attractloop servers are ONLY for local clients */ + if ( sv.attractloop ) + { + if ( !NET_IsLocalAddress( adr ) ) + { + Com_Printf( "Remote connect in attract loop. Ignored.\n" ); + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nConnection refused.\n" ); + return; + } + } + + /* see if the challenge is valid */ + if ( !NET_IsLocalAddress( adr ) ) + { + for ( i = 0; i < MAX_CHALLENGES; i++ ) + { + if ( NET_CompareBaseAdr( net_from, svs.challenges [ i ].adr ) ) + { + if ( challenge == svs.challenges [ i ].challenge ) + { + break; /* good */ + } + + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nBad challenge.\n" ); + return; + } + } + + if ( i == MAX_CHALLENGES ) + { + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nNo challenge for address.\n" ); + return; + } + } + + newcl = &temp; + memset( newcl, 0, sizeof ( client_t ) ); + + /* if there is already a slot for this ip, reuse it */ + for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ ) + { + if ( cl->state < cs_connected ) + { + continue; + } + + if ( NET_CompareBaseAdr( adr, cl->netchan.remote_address ) && + ( ( cl->netchan.qport == qport ) || + ( adr.port == cl->netchan.remote_address.port ) ) ) + { + if ( !NET_IsLocalAddress( adr ) && ( ( svs.realtime - cl->lastconnect ) < ( (int) sv_reconnect_limit->value * 1000 ) ) ) + { + Com_DPrintf( "%s:reconnect rejected : too soon\n", NET_AdrToString( adr ) ); + return; + } + + Com_Printf( "%s:reconnect\n", NET_AdrToString( adr ) ); + newcl = cl; + goto gotnewcl; + } + } + + /* find a client slot */ + newcl = NULL; + + for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ ) + { + if ( cl->state == cs_free ) + { + newcl = cl; + break; + } + } + + if ( !newcl ) + { + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nServer is full.\n" ); + Com_DPrintf( "Rejected a connection.\n" ); + return; + } + +gotnewcl: + /* build a new connection + accept the new client + this is the only place a client_t is ever initialized */ + *newcl = temp; + sv_client = newcl; + edictnum = ( newcl - svs.clients ) + 1; + ent = EDICT_NUM( edictnum ); + newcl->edict = ent; + newcl->challenge = challenge; /* save challenge for checksumming */ + + /* get the game a chance to reject this connection or modify the userinfo */ + if ( !( ge->ClientConnect( ent, userinfo ) ) ) + { + if ( *Info_ValueForKey( userinfo, "rejmsg" ) ) + { + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\n%s\nConnection refused.\n", + Info_ValueForKey( userinfo, "rejmsg" ) ); + } + else + { + Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nConnection refused.\n" ); + } + + Com_DPrintf( "Game rejected a connection.\n" ); + return; + } + + /* parse some info from the info strings */ + strncpy( newcl->userinfo, userinfo, sizeof ( newcl->userinfo ) - 1 ); + SV_UserinfoChanged( newcl ); + + /* send the connect packet to the client */ + Netchan_OutOfBandPrint( NS_SERVER, adr, "client_connect" ); + + Netchan_Setup( NS_SERVER, &newcl->netchan, adr, qport ); + + newcl->state = cs_connected; + + SZ_Init( &newcl->datagram, newcl->datagram_buf, sizeof ( newcl->datagram_buf ) ); + newcl->datagram.allowoverflow = true; + newcl->lastmessage = svs.realtime; /* don't timeout */ + newcl->lastconnect = svs.realtime; +} + +int +Rcon_Validate ( void ) +{ + if ( !strlen( rcon_password->string ) ) + { + return ( 0 ); + } + + if ( strcmp( Cmd_Argv( 1 ), rcon_password->string ) ) + { + return ( 0 ); + } + + return ( 1 ); +} + +/* + * A client issued an rcon command. + * Shift down the remaining args + * Redirect all printfs + */ +void +SVC_RemoteCommand ( void ) +{ + int i; + char remaining [ 1024 ]; + + i = Rcon_Validate(); + + if ( i == 0 ) + { + Com_Printf( "Bad rcon from %s:\n%s\n", NET_AdrToString( net_from ), net_message.data + 4 ); + } + else + { + Com_Printf( "Rcon from %s:\n%s\n", NET_AdrToString( net_from ), net_message.data + 4 ); + } + + Com_BeginRedirect( RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect ); + + if ( !Rcon_Validate() ) + { + Com_Printf( "Bad rcon_password.\n" ); + } + else + { + remaining [ 0 ] = 0; + + for ( i = 2; i < Cmd_Argc(); i++ ) + { + strcat( remaining, Cmd_Argv( i ) ); + strcat( remaining, " " ); + } + + Cmd_ExecuteString( remaining ); + } + + Com_EndRedirect(); +} + +/* + * A connectionless packet has four leading 0xff + * characters to distinguish it from a game channel. + * Clients that are in the game can still send + * connectionless packets. + */ +void +SV_ConnectionlessPacket ( void ) +{ + char *s; + char *c; + + MSG_BeginReading( &net_message ); + MSG_ReadLong( &net_message ); /* skip the -1 marker */ + + s = MSG_ReadStringLine( &net_message ); + + Cmd_TokenizeString( s, false ); + + c = Cmd_Argv( 0 ); + Com_DPrintf( "Packet %s : %s\n", NET_AdrToString( net_from ), c ); + + if ( !strcmp( c, "ping" ) ) + { + SVC_Ping(); + } + else if ( !strcmp( c, "ack" ) ) + { + SVC_Ack(); + } + else if ( !strcmp( c, "status" ) ) + { + SVC_Status(); + } + else if ( !strcmp( c, "info" ) ) + { + SVC_Info(); + } + else if ( !strcmp( c, "getchallenge" ) ) + { + SVC_GetChallenge(); + } + else if ( !strcmp( c, "connect" ) ) + { + SVC_DirectConnect(); + } + else if ( !strcmp( c, "rcon" ) ) + { + SVC_RemoteCommand(); + } + else + { + Com_Printf( "bad connectionless packet from %s:\n%s\n", + NET_AdrToString( net_from ), s ); + } +} + diff --git a/src/server/sv_main.c b/src/server/sv_main.c index 3c681e14..b920d955 100644 --- a/src/server/sv_main.c +++ b/src/server/sv_main.c @@ -49,9 +49,9 @@ cvar_t *maxclients; /* FIXME: rename sv_maxclients */ cvar_t *sv_showclamp; cvar_t *hostname; cvar_t *public_server; /* should heartbeats be sent */ -cvar_t *sv_reconnect_limit; /* minimum seconds between connect messages */ void Master_Shutdown ( void ); +void SV_ConnectionlessPacket ( void ); /* * Called when the player is totally leaving the server, either willingly @@ -121,400 +121,6 @@ SV_StatusString ( void ) return ( status ); } -/* - * Responds with all the info that qplug or qspy can see - */ -void -SVC_Status ( void ) -{ - Netchan_OutOfBandPrint( NS_SERVER, net_from, "print\n%s", SV_StatusString() ); -} - -void -SVC_Ack ( void ) -{ - Com_Printf( "Ping acknowledge from %s\n", NET_AdrToString( net_from ) ); -} - -/* - * Responds with short info for broadcast scans - * The second parameter should be the current protocol version number. - */ -void -SVC_Info ( void ) -{ - char string [ 64 ]; - int i, count; - int version; - - if ( maxclients->value == 1 ) - { - return; /* ignore in single player */ - } - - version = atoi( Cmd_Argv( 1 ) ); - - if ( version != PROTOCOL_VERSION ) - { - Com_sprintf( string, sizeof ( string ), "%s: wrong version\n", hostname->string, sizeof ( string ) ); - } - else - { - count = 0; - - for ( i = 0; i < maxclients->value; i++ ) - { - if ( svs.clients [ i ].state >= cs_connected ) - { - count++; - } - } - - Com_sprintf( string, sizeof ( string ), "%16s %8s %2i/%2i\n", hostname->string, sv.name, count, (int) maxclients->value ); - } - - Netchan_OutOfBandPrint( NS_SERVER, net_from, "info\n%s", string ); -} - -/* - * SVC_Ping - */ -void -SVC_Ping ( void ) -{ - Netchan_OutOfBandPrint( NS_SERVER, net_from, "ack" ); -} - -/* - * Returns a challenge number that can be used - * in a subsequent client_connect command. - * We do this to prevent denial of service attacks that - * flood the server with invalid connection IPs. With a - * challenge, they must give a valid IP address. - */ -void -SVC_GetChallenge ( void ) -{ - int i; - int oldest; - int oldestTime; - - oldest = 0; - oldestTime = 0x7fffffff; - - /* see if we already have a challenge for this ip */ - for ( i = 0; i < MAX_CHALLENGES; i++ ) - { - if ( NET_CompareBaseAdr( net_from, svs.challenges [ i ].adr ) ) - { - break; - } - - if ( svs.challenges [ i ].time < oldestTime ) - { - oldestTime = svs.challenges [ i ].time; - oldest = i; - } - } - - if ( i == MAX_CHALLENGES ) - { - /* overwrite the oldest */ - svs.challenges [ oldest ].challenge = rand() & 0x7fff; - svs.challenges [ oldest ].adr = net_from; - svs.challenges [ oldest ].time = curtime; - i = oldest; - } - - /* send it back */ - Netchan_OutOfBandPrint( NS_SERVER, net_from, "challenge %i", svs.challenges [ i ].challenge ); -} - -/* - * A connection request that did not come from the master - */ -void -SVC_DirectConnect ( void ) -{ - char userinfo [ MAX_INFO_STRING ]; - netadr_t adr; - int i; - client_t *cl, *newcl; - client_t temp; - edict_t *ent; - int edictnum; - int version; - int qport; - int challenge; - - adr = net_from; - - Com_DPrintf( "SVC_DirectConnect ()\n" ); - - version = atoi( Cmd_Argv( 1 ) ); - - if ( version != PROTOCOL_VERSION ) - { - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nServer is version %4.2f.\n", VERSION ); - Com_DPrintf( " rejected connect from version %i\n", version ); - return; - } - - qport = atoi( Cmd_Argv( 2 ) ); - - challenge = atoi( Cmd_Argv( 3 ) ); - - strncpy( userinfo, Cmd_Argv( 4 ), sizeof ( userinfo ) - 1 ); - userinfo [ sizeof ( userinfo ) - 1 ] = 0; - - /* force the IP key/value pair so the game can filter based on ip */ - Info_SetValueForKey( userinfo, "ip", NET_AdrToString( net_from ) ); - - /* attractloop servers are ONLY for local clients */ - if ( sv.attractloop ) - { - if ( !NET_IsLocalAddress( adr ) ) - { - Com_Printf( "Remote connect in attract loop. Ignored.\n" ); - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nConnection refused.\n" ); - return; - } - } - - /* see if the challenge is valid */ - if ( !NET_IsLocalAddress( adr ) ) - { - for ( i = 0; i < MAX_CHALLENGES; i++ ) - { - if ( NET_CompareBaseAdr( net_from, svs.challenges [ i ].adr ) ) - { - if ( challenge == svs.challenges [ i ].challenge ) - { - break; /* good */ - } - - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nBad challenge.\n" ); - return; - } - } - - if ( i == MAX_CHALLENGES ) - { - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nNo challenge for address.\n" ); - return; - } - } - - newcl = &temp; - memset( newcl, 0, sizeof ( client_t ) ); - - /* if there is already a slot for this ip, reuse it */ - for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ ) - { - if ( cl->state < cs_connected ) - { - continue; - } - - if ( NET_CompareBaseAdr( adr, cl->netchan.remote_address ) && - ( ( cl->netchan.qport == qport ) || - ( adr.port == cl->netchan.remote_address.port ) ) ) - { - if ( !NET_IsLocalAddress( adr ) && ( ( svs.realtime - cl->lastconnect ) < ( (int) sv_reconnect_limit->value * 1000 ) ) ) - { - Com_DPrintf( "%s:reconnect rejected : too soon\n", NET_AdrToString( adr ) ); - return; - } - - Com_Printf( "%s:reconnect\n", NET_AdrToString( adr ) ); - newcl = cl; - goto gotnewcl; - } - } - - /* find a client slot */ - newcl = NULL; - - for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ ) - { - if ( cl->state == cs_free ) - { - newcl = cl; - break; - } - } - - if ( !newcl ) - { - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nServer is full.\n" ); - Com_DPrintf( "Rejected a connection.\n" ); - return; - } - -gotnewcl: - /* build a new connection - accept the new client - this is the only place a client_t is ever initialized */ - *newcl = temp; - sv_client = newcl; - edictnum = ( newcl - svs.clients ) + 1; - ent = EDICT_NUM( edictnum ); - newcl->edict = ent; - newcl->challenge = challenge; /* save challenge for checksumming */ - - /* get the game a chance to reject this connection or modify the userinfo */ - if ( !( ge->ClientConnect( ent, userinfo ) ) ) - { - if ( *Info_ValueForKey( userinfo, "rejmsg" ) ) - { - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\n%s\nConnection refused.\n", - Info_ValueForKey( userinfo, "rejmsg" ) ); - } - else - { - Netchan_OutOfBandPrint( NS_SERVER, adr, "print\nConnection refused.\n" ); - } - - Com_DPrintf( "Game rejected a connection.\n" ); - return; - } - - /* parse some info from the info strings */ - strncpy( newcl->userinfo, userinfo, sizeof ( newcl->userinfo ) - 1 ); - SV_UserinfoChanged( newcl ); - - /* send the connect packet to the client */ - Netchan_OutOfBandPrint( NS_SERVER, adr, "client_connect" ); - - Netchan_Setup( NS_SERVER, &newcl->netchan, adr, qport ); - - newcl->state = cs_connected; - - SZ_Init( &newcl->datagram, newcl->datagram_buf, sizeof ( newcl->datagram_buf ) ); - newcl->datagram.allowoverflow = true; - newcl->lastmessage = svs.realtime; /* don't timeout */ - newcl->lastconnect = svs.realtime; -} - -int -Rcon_Validate ( void ) -{ - if ( !strlen( rcon_password->string ) ) - { - return ( 0 ); - } - - if ( strcmp( Cmd_Argv( 1 ), rcon_password->string ) ) - { - return ( 0 ); - } - - return ( 1 ); -} - -/* - * A client issued an rcon command. - * Shift down the remaining args - * Redirect all printfs - */ -void -SVC_RemoteCommand ( void ) -{ - int i; - char remaining [ 1024 ]; - - i = Rcon_Validate(); - - if ( i == 0 ) - { - Com_Printf( "Bad rcon from %s:\n%s\n", NET_AdrToString( net_from ), net_message.data + 4 ); - } - else - { - Com_Printf( "Rcon from %s:\n%s\n", NET_AdrToString( net_from ), net_message.data + 4 ); - } - - Com_BeginRedirect( RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect ); - - if ( !Rcon_Validate() ) - { - Com_Printf( "Bad rcon_password.\n" ); - } - else - { - remaining [ 0 ] = 0; - - for ( i = 2; i < Cmd_Argc(); i++ ) - { - strcat( remaining, Cmd_Argv( i ) ); - strcat( remaining, " " ); - } - - Cmd_ExecuteString( remaining ); - } - - Com_EndRedirect(); -} - -/* - * A connectionless packet has four leading 0xff - * characters to distinguish it from a game channel. - * Clients that are in the game can still send - * connectionless packets. - */ -void -SV_ConnectionlessPacket ( void ) -{ - char *s; - char *c; - - MSG_BeginReading( &net_message ); - MSG_ReadLong( &net_message ); /* skip the -1 marker */ - - s = MSG_ReadStringLine( &net_message ); - - Cmd_TokenizeString( s, false ); - - c = Cmd_Argv( 0 ); - Com_DPrintf( "Packet %s : %s\n", NET_AdrToString( net_from ), c ); - - if ( !strcmp( c, "ping" ) ) - { - SVC_Ping(); - } - else if ( !strcmp( c, "ack" ) ) - { - SVC_Ack(); - } - else if ( !strcmp( c, "status" ) ) - { - SVC_Status(); - } - else if ( !strcmp( c, "info" ) ) - { - SVC_Info(); - } - else if ( !strcmp( c, "getchallenge" ) ) - { - SVC_GetChallenge(); - } - else if ( !strcmp( c, "connect" ) ) - { - SVC_DirectConnect(); - } - else if ( !strcmp( c, "rcon" ) ) - { - SVC_RemoteCommand(); - } - else - { - Com_Printf( "bad connectionless packet from %s:\n%s\n", - NET_AdrToString( net_from ), s ); - } -} - -/* ============================================================================ */ - /* * Updates the cl->ping variables */