Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

sv_main.c File Reference

#include "server.h"

Include dependency graph for sv_main.c:

Include dependency graph

Go to the source code of this file.

Defines

#define HEARTBEAT_GAME   "QuakeArena-1"
#define HEARTBEAT_MSEC   300*1000
#define SV_OUTPUTBUF_LENGTH   (1024 - 16)

Functions

void SV_AddServerCommand (client_t *client, const char *cmd)
void SV_CalcPings (void)
qboolean SV_CheckPaused (void)
void SV_CheckTimeouts (void)
void SV_ConnectionlessPacket (netadr_t from, msg_t *msg)
char * SV_ExpandNewlines (char *in)
void SV_FlushRedirect (char *outputbuf)
void SV_Frame (int msec)
void SV_MasterHeartbeat (void)
void SV_MasterShutdown (void)
void SV_PacketEvent (netadr_t from, msg_t *msg)
int SV_ReplacePendingServerCommands (client_t *client, const char *cmd)
void QDECL SV_SendServerCommand (client_t *cl, const char *fmt,...)
void SVC_Info (netadr_t from)
void SVC_RemoteCommand (netadr_t from, msg_t *msg)
void SVC_Status (netadr_t from)

Variables

vm_tgvm = NULL
server_t sv
cvar_tsv_allowDownload
cvar_tsv_floodProtect
cvar_tsv_fps
cvar_tsv_gametype
cvar_tsv_hostname
cvar_tsv_killserver
cvar_tsv_lanForceRate
cvar_tsv_mapChecksum
cvar_tsv_mapname
cvar_tsv_master [MAX_MASTER_SERVERS]
cvar_tsv_maxclients
cvar_tsv_maxPing
cvar_tsv_maxRate
cvar_tsv_minPing
cvar_tsv_padPackets
cvar_tsv_privateClients
cvar_tsv_privatePassword
cvar_tsv_pure
cvar_tsv_rconPassword
cvar_tsv_reconnectlimit
cvar_tsv_serverid
cvar_tsv_showloss
cvar_tsv_strictAuth
cvar_tsv_timeout
cvar_tsv_zombietime
serverStatic_t svs


Define Documentation

#define HEARTBEAT_GAME   "QuakeArena-1"
 

Definition at line 215 of file sv_main.c.

Referenced by SV_MasterHeartbeat().

#define HEARTBEAT_MSEC   300*1000
 

Definition at line 214 of file sv_main.c.

#define SV_OUTPUTBUF_LENGTH   (1024 - 16)
 

Referenced by SVC_RemoteCommand().


Function Documentation

void SV_AddServerCommand client_t client,
const char *  cmd
 

Definition at line 128 of file sv_main.c.

References client_t, Com_Printf(), i, MAX_RELIABLE_COMMANDS, Q_strncpyz(), client_s::reliableAcknowledge, client_s::reliableCommands, client_s::reliableSequence, and SV_DropClient().

Referenced by SV_MapRestart_f(), and SV_SendServerCommand().

00128                                                               {
00129     int     index, i;
00130 
00131     // this is very ugly but it's also a waste to for instance send multiple config string updates
00132     // for the same config string index in one snapshot
00133 //  if ( SV_ReplacePendingServerCommands( client, cmd ) ) {
00134 //      return;
00135 //  }
00136 
00137     client->reliableSequence++;
00138     // if we would be losing an old command that hasn't been acknowledged,
00139     // we must drop the connection
00140     // we check == instead of >= so a broadcast print added by SV_DropClient()
00141     // doesn't cause a recursive drop client
00142     if ( client->reliableSequence - client->reliableAcknowledge == MAX_RELIABLE_COMMANDS + 1 ) {
00143         Com_Printf( "===== pending server commands =====\n" );
00144         for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
00145             Com_Printf( "cmd %5d: %s\n", i, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
00146         }
00147         Com_Printf( "cmd %5d: %s\n", i, cmd );
00148         SV_DropClient( client, "Server command overflow" );
00149         return;
00150     }
00151     index = client->reliableSequence & ( MAX_RELIABLE_COMMANDS - 1 );
00152     Q_strncpyz( client->reliableCommands[ index ], cmd, sizeof( client->reliableCommands[ index ] ) );
00153 }

Here is the call graph for this function:

void SV_CalcPings void   ) 
 

Definition at line 613 of file sv_main.c.

References cl, client_t, serverStatic_t::clients, count, i, cvar_s::integer, j, playerState_s::ping, playerState_t, SV_GameClientNum(), sv_maxclients, and svs.

Referenced by SV_Frame().

00613                           {
00614     int         i, j;
00615     client_t    *cl;
00616     int         total, count;
00617     int         delta;
00618     playerState_t   *ps;
00619 
00620     for (i=0 ; i < sv_maxclients->integer ; i++) {
00621         cl = &svs.clients[i];
00622         if ( cl->state != CS_ACTIVE ) {
00623             cl->ping = 999;
00624             continue;
00625         }
00626         if ( !cl->gentity ) {
00627             cl->ping = 999;
00628             continue;
00629         }
00630         if ( cl->gentity->r.svFlags & SVF_BOT ) {
00631             cl->ping = 0;
00632             continue;
00633         }
00634 
00635         total = 0;
00636         count = 0;
00637         for ( j = 0 ; j < PACKET_BACKUP ; j++ ) {
00638             if ( cl->frames[j].messageAcked <= 0 ) {
00639                 continue;
00640             }
00641             delta = cl->frames[j].messageAcked - cl->frames[j].messageSent;
00642             count++;
00643             total += delta;
00644         }
00645         if (!count) {
00646             cl->ping = 999;
00647         } else {
00648             cl->ping = total/count;
00649             if ( cl->ping > 999 ) {
00650                 cl->ping = 999;
00651             }
00652         }
00653 
00654         // let the game dll know about the ping
00655         ps = SV_GameClientNum( i );
00656         ps->ping = cl->ping;
00657     }
00658 }

Here is the call graph for this function:

qboolean SV_CheckPaused void   ) 
 

Definition at line 714 of file sv_main.c.

References cl, cl_paused, client_t, serverStatic_t::clients, count, CS_CONNECTED, Cvar_Set(), i, cvar_s::integer, qboolean, sv_maxclients, sv_paused, and svs.

Referenced by SV_Frame().

00714                                 {
00715     int     count;
00716     client_t    *cl;
00717     int     i;
00718 
00719     if ( !cl_paused->integer ) {
00720         return qfalse;
00721     }
00722 
00723     // only pause if there is just a single client connected
00724     count = 0;
00725     for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
00726         if ( cl->state >= CS_CONNECTED && cl->netchan.remoteAddress.type != NA_BOT ) {
00727             count++;
00728         }
00729     }
00730 
00731     if ( count > 1 ) {
00732         // don't pause
00733         if (sv_paused->integer)
00734             Cvar_Set("sv_paused", "0");
00735         return qfalse;
00736     }
00737 
00738     if (!sv_paused->integer)
00739         Cvar_Set("sv_paused", "1");
00740     return qtrue;
00741 }

Here is the call graph for this function:

void SV_CheckTimeouts void   ) 
 

Definition at line 673 of file sv_main.c.

References cl, client_t, serverStatic_t::clients, Com_DPrintf(), CS_CONNECTED, CS_ZOMBIE, i, cvar_s::integer, SV_DropClient(), sv_maxclients, sv_timeout, sv_zombietime, svs, and serverStatic_t::time.

Referenced by SV_Frame().

00673                               {
00674     int     i;
00675     client_t    *cl;
00676     int         droppoint;
00677     int         zombiepoint;
00678 
00679     droppoint = svs.time - 1000 * sv_timeout->integer;
00680     zombiepoint = svs.time - 1000 * sv_zombietime->integer;
00681 
00682     for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
00683         // message times may be wrong across a changelevel
00684         if (cl->lastPacketTime > svs.time) {
00685             cl->lastPacketTime = svs.time;
00686         }
00687 
00688         if (cl->state == CS_ZOMBIE
00689         && cl->lastPacketTime < zombiepoint) {
00690             // using the client id cause the cl->name is empty at this point
00691             Com_DPrintf( "Going from CS_ZOMBIE to CS_FREE for client %d\n", i );
00692             cl->state = CS_FREE;    // can now be reused
00693             continue;
00694         }
00695         if ( cl->state >= CS_CONNECTED && cl->lastPacketTime < droppoint) {
00696             // wait several frames so a debugger session doesn't
00697             // cause a timeout
00698             if ( ++cl->timeoutCount > 5 ) {
00699                 SV_DropClient (cl, "timed out"); 
00700                 cl->state = CS_FREE;    // don't bother with zombie state
00701             }
00702         } else {
00703             cl->timeoutCount = 0;
00704         }
00705     }
00706 }

Here is the call graph for this function:

void SV_ConnectionlessPacket netadr_t  from,
msg_t msg
 

Definition at line 502 of file sv_main.c.

References c, Cmd_Argv(), Cmd_TokenizeString(), Com_DPrintf(), msg_t::data, Huff_Decompress(), MSG_BeginReadingOOB(), MSG_ReadLong(), MSG_ReadStringLine(), NET_AdrToString(), Q_stricmp(), Q_strncmp(), s, SV_AuthorizeIpPacket(), SV_DirectConnect(), SV_GetChallenge(), SVC_Info(), SVC_RemoteCommand(), and SVC_Status().

Referenced by SV_PacketEvent().

00502                                                           {
00503     char    *s;
00504     char    *c;
00505 
00506     MSG_BeginReadingOOB( msg );
00507     MSG_ReadLong( msg );        // skip the -1 marker
00508 
00509     if (!Q_strncmp("connect", &msg->data[4], 7)) {
00510         Huff_Decompress(msg, 12);
00511     }
00512 
00513     s = MSG_ReadStringLine( msg );
00514     Cmd_TokenizeString( s );
00515 
00516     c = Cmd_Argv(0);
00517     Com_DPrintf ("SV packet %s : %s\n", NET_AdrToString(from), c);
00518 
00519     if (!Q_stricmp(c, "getstatus")) {
00520         SVC_Status( from  );
00521   } else if (!Q_stricmp(c, "getinfo")) {
00522         SVC_Info( from );
00523     } else if (!Q_stricmp(c, "getchallenge")) {
00524         SV_GetChallenge( from );
00525     } else if (!Q_stricmp(c, "connect")) {
00526         SV_DirectConnect( from );
00527     } else if (!Q_stricmp(c, "ipAuthorize")) {
00528         SV_AuthorizeIpPacket( from );
00529     } else if (!Q_stricmp(c, "rcon")) {
00530         SVC_RemoteCommand( from, msg );
00531     } else if (!Q_stricmp(c, "disconnect")) {
00532         // if a client starts up a local server, we may see some spurious
00533         // server disconnect messages when their new server sees our final
00534         // sequenced messages to the old client
00535     } else {
00536         Com_DPrintf ("bad connectionless packet from %s:\n%s\n"
00537         , NET_AdrToString (from), s);
00538     }
00539 }

Here is the call graph for this function:

char* SV_ExpandNewlines char *  in  ) 
 

Definition at line 71 of file sv_main.c.

References in, l, and string().

Referenced by SV_SendServerCommand().

00071                                        {
00072     static  char    string[1024];
00073     int     l;
00074 
00075     l = 0;
00076     while ( *in && l < sizeof(string) - 3 ) {
00077         if ( *in == '\n' ) {
00078             string[l++] = '\\';
00079             string[l++] = 'n';
00080         } else {
00081             string[l++] = *in;
00082         }
00083         in++;
00084     }
00085     string[l] = 0;
00086 
00087     return string;
00088 }

Here is the call graph for this function:

void SV_FlushRedirect char *  outputbuf  ) 
 

Definition at line 419 of file sv_main.c.

References NET_OutOfBandPrint(), NS_SERVER, serverStatic_t::redirectAddress, and svs.

Referenced by SVC_RemoteCommand().

00419                                          {
00420     NET_OutOfBandPrint( NS_SERVER, svs.redirectAddress, "print\n%s", outputbuf );
00421 }

Here is the call graph for this function:

void SV_Frame int  msec  ) 
 

Definition at line 751 of file sv_main.c.

References Cbuf_AddText(), com_dedicated, com_speeds, com_sv_running, CS_SERVERINFO, CS_SYSTEMINFO, Cvar_InfoString(), Cvar_InfoString_Big(), cvar_modifiedFlags, CVAR_SERVERINFO, Cvar_Set(), CVAR_SYSTEMINFO, GAME_RUN_FRAME, gvm, cvar_s::integer, NET_Sleep(), serverStatic_t::nextSnapshotEntities, serverStatic_t::numSnapshotEntities, server_t::restartTime, startTime, sv, SV_BotFrame(), SV_CalcPings(), SV_CheckPaused(), SV_CheckTimeouts(), sv_fps, sv_killserver, SV_MasterHeartbeat(), SV_SendClientMessages(), SV_SetConfigstring(), SV_Shutdown(), svs, Sys_Milliseconds(), serverStatic_t::time, time_game, server_t::timeResidual, and VM_Call().

Referenced by CL_Connect_f(), and Com_Frame().

00751                           {
00752     int     frameMsec;
00753     int     startTime;
00754 
00755     // the menu kills the server with this cvar
00756     if ( sv_killserver->integer ) {
00757         SV_Shutdown ("Server was killed.\n");
00758         Cvar_Set( "sv_killserver", "0" );
00759         return;
00760     }
00761 
00762     if ( !com_sv_running->integer ) {
00763         return;
00764     }
00765 
00766     // allow pause if only the local client is connected
00767     if ( SV_CheckPaused() ) {
00768         return;
00769     }
00770 
00771     // if it isn't time for the next frame, do nothing
00772     if ( sv_fps->integer < 1 ) {
00773         Cvar_Set( "sv_fps", "10" );
00774     }
00775     frameMsec = 1000 / sv_fps->integer ;
00776 
00777     sv.timeResidual += msec;
00778 
00779     if (!com_dedicated->integer) SV_BotFrame( svs.time + sv.timeResidual );
00780 
00781     if ( com_dedicated->integer && sv.timeResidual < frameMsec ) {
00782         // NET_Sleep will give the OS time slices until either get a packet
00783         // or time enough for a server frame has gone by
00784         NET_Sleep(frameMsec - sv.timeResidual);
00785         return;
00786     }
00787 
00788     // if time is about to hit the 32nd bit, kick all clients
00789     // and clear sv.time, rather
00790     // than checking for negative time wraparound everywhere.
00791     // 2giga-milliseconds = 23 days, so it won't be too often
00792     if ( svs.time > 0x70000000 ) {
00793         SV_Shutdown( "Restarting server due to time wrapping" );
00794         Cbuf_AddText( "vstr nextmap\n" );
00795         return;
00796     }
00797     // this can happen considerably earlier when lots of clients play and the map doesn't change
00798     if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
00799         SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" );
00800         Cbuf_AddText( "vstr nextmap\n" );
00801         return;
00802     }
00803 
00804     if( sv.restartTime && svs.time >= sv.restartTime ) {
00805         sv.restartTime = 0;
00806         Cbuf_AddText( "map_restart 0\n" );
00807         return;
00808     }
00809 
00810     // update infostrings if anything has been changed
00811     if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
00812         SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
00813         cvar_modifiedFlags &= ~CVAR_SERVERINFO;
00814     }
00815     if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
00816         SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );
00817         cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
00818     }
00819 
00820     if ( com_speeds->integer ) {
00821         startTime = Sys_Milliseconds ();
00822     } else {
00823         startTime = 0;  // quite a compiler warning
00824     }
00825 
00826     // update ping based on the all received frames
00827     SV_CalcPings();
00828 
00829     if (com_dedicated->integer) SV_BotFrame( svs.time );
00830 
00831     // run the game simulation in chunks
00832     while ( sv.timeResidual >= frameMsec ) {
00833         sv.timeResidual -= frameMsec;
00834         svs.time += frameMsec;
00835 
00836         // let everything in the world think and move
00837         VM_Call( gvm, GAME_RUN_FRAME, svs.time );
00838     }
00839 
00840     if ( com_speeds->integer ) {
00841         time_game = Sys_Milliseconds () - startTime;
00842     }
00843 
00844     // check timeouts
00845     SV_CheckTimeouts();
00846 
00847     // send messages back to the clients
00848     SV_SendClientMessages();
00849 
00850     // send a heartbeat to the master if needed
00851     SV_MasterHeartbeat();
00852 }

Here is the call graph for this function:

void SV_MasterHeartbeat void   ) 
 

Definition at line 216 of file sv_main.c.

References BigShort(), com_dedicated, Com_Printf(), Cvar_Set(), HEARTBEAT_GAME, i, cvar_s::integer, cvar_s::modified, name, NET_OutOfBandPrint(), NET_StringToAdr(), serverStatic_t::nextHeartbeatTime, NS_SERVER, netadr_t::port, PORT_MASTER, string(), cvar_s::string, strstr(), sv_master, svs, and serverStatic_t::time.

Referenced by SV_Frame(), and SV_MasterShutdown().

00216                                 {
00217     static netadr_t adr[MAX_MASTER_SERVERS];
00218     int         i;
00219 
00220     // "dedicated 1" is for lan play, "dedicated 2" is for inet public play
00221     if ( !com_dedicated || com_dedicated->integer != 2 ) {
00222         return;     // only dedicated servers send heartbeats
00223     }
00224 
00225     // if not time yet, don't send anything
00226     if ( svs.time < svs.nextHeartbeatTime ) {
00227         return;
00228     }
00229     svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC;
00230 
00231 
00232     // send to group masters
00233     for ( i = 0 ; i < MAX_MASTER_SERVERS ; i++ ) {
00234         if ( !sv_master[i]->string[0] ) {
00235             continue;
00236         }
00237 
00238         // see if we haven't already resolved the name
00239         // resolving usually causes hitches on win95, so only
00240         // do it when needed
00241         if ( sv_master[i]->modified ) {
00242             sv_master[i]->modified = qfalse;
00243     
00244             Com_Printf( "Resolving %s\n", sv_master[i]->string );
00245             if ( !NET_StringToAdr( sv_master[i]->string, &adr[i] ) ) {
00246                 // if the address failed to resolve, clear it
00247                 // so we don't take repeated dns hits
00248                 Com_Printf( "Couldn't resolve address: %s\n", sv_master[i]->string );
00249                 Cvar_Set( sv_master[i]->name, "" );
00250                 sv_master[i]->modified = qfalse;
00251                 continue;
00252             }
00253             if ( !strstr( ":", sv_master[i]->string ) ) {
00254                 adr[i].port = BigShort( PORT_MASTER );
00255             }
00256             Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", sv_master[i]->string,
00257                 adr[i].ip[0], adr[i].ip[1], adr[i].ip[2], adr[i].ip[3],
00258                 BigShort( adr[i].port ) );
00259         }
00260 
00261 
00262         Com_Printf ("Sending heartbeat to %s\n", sv_master[i]->string );
00263         // this command should be changed if the server info / status format
00264         // ever incompatably changes
00265         NET_OutOfBandPrint( NS_SERVER, adr[i], "heartbeat %s\n", HEARTBEAT_GAME );
00266     }
00267 }

Here is the call graph for this function:

void SV_MasterShutdown void   ) 
 

Definition at line 276 of file sv_main.c.

References serverStatic_t::nextHeartbeatTime, SV_MasterHeartbeat(), and svs.

Referenced by SV_Shutdown().

00276                                {
00277     // send a hearbeat right now
00278     svs.nextHeartbeatTime = -9999;
00279     SV_MasterHeartbeat();
00280 
00281     // send it again to minimize chance of drops
00282     svs.nextHeartbeatTime = -9999;
00283     SV_MasterHeartbeat();
00284 
00285     // when the master tries to poll the server, it won't respond, so
00286     // it will be removed from the list
00287 }

Here is the call graph for this function:

void SV_PacketEvent netadr_t  from,
msg_t msg
 

Definition at line 548 of file sv_main.c.

References cl, client_t, serverStatic_t::clients, Com_Printf(), msg_t::cursize, msg_t::data, i, cvar_s::integer, MSG_BeginReadingOOB(), MSG_ReadLong(), MSG_ReadShort(), NET_CompareBaseAdr(), NET_OutOfBandPrint(), NS_SERVER, netadr_t::port, qport, SV_ConnectionlessPacket(), SV_ExecuteClientMessage(), sv_maxclients, SV_Netchan_Process(), svs, and serverStatic_t::time.

Referenced by Com_RunAndTimeServerPacket().

00548                                                  {
00549     int         i;
00550     client_t    *cl;
00551     int         qport;
00552 
00553     // check for connectionless packet (0xffffffff) first
00554     if ( msg->cursize >= 4 && *(int *)msg->data == -1) {
00555         SV_ConnectionlessPacket( from, msg );
00556         return;
00557     }
00558 
00559     // read the qport out of the message so we can fix up
00560     // stupid address translating routers
00561     MSG_BeginReadingOOB( msg );
00562     MSG_ReadLong( msg );                // sequence number
00563     qport = MSG_ReadShort( msg ) & 0xffff;
00564 
00565     // find which client the message is from
00566     for (i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
00567         if (cl->state == CS_FREE) {
00568             continue;
00569         }
00570         if ( !NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) ) {
00571             continue;
00572         }
00573         // it is possible to have multiple clients from a single IP
00574         // address, so they are differentiated by the qport variable
00575         if (cl->netchan.qport != qport) {
00576             continue;
00577         }
00578 
00579         // the IP port can't be used to differentiate them, because
00580         // some address translating routers periodically change UDP
00581         // port assignments
00582         if (cl->netchan.remoteAddress.port != from.port) {
00583             Com_Printf( "SV_PacketEvent: fixing up a translated port\n" );
00584             cl->netchan.remoteAddress.port = from.port;
00585         }
00586 
00587         // make sure it is a valid, in sequence packet
00588         if (SV_Netchan_Process(cl, msg)) {
00589             // zombie clients still need to do the Netchan_Process
00590             // to make sure they don't need to retransmit the final
00591             // reliable message, but they don't do any other processing
00592             if (cl->state != CS_ZOMBIE) {
00593                 cl->lastPacketTime = svs.time;  // don't timeout
00594                 SV_ExecuteClientMessage( cl, msg );
00595             }
00596         }
00597         return;
00598     }
00599     
00600     // if we received a sequenced packet from an address we don't recognize,
00601     // send an out of band disconnect packet to it
00602     NET_OutOfBandPrint( NS_SERVER, from, "disconnect" );
00603 }

Here is the call graph for this function:

int SV_ReplacePendingServerCommands client_t client,
const char *  cmd
 

Definition at line 97 of file sv_main.c.

References client_t, i, MAX_RELIABLE_COMMANDS, Q_strncmp(), Q_strncpyz(), client_s::reliableCommands, client_s::reliableSent, client_s::reliableSequence, sscanf(), and strlen().

00097                                                                          {
00098     int i, index, csnum1, csnum2;
00099 
00100     for ( i = client->reliableSent+1; i <= client->reliableSequence; i++ ) {
00101         index = i & ( MAX_RELIABLE_COMMANDS - 1 );
00102         //
00103         if ( !Q_strncmp(cmd, client->reliableCommands[ index ], strlen("cs")) ) {
00104             sscanf(cmd, "cs %i", &csnum1);
00105             sscanf(client->reliableCommands[ index ], "cs %i", &csnum2);
00106             if ( csnum1 == csnum2 ) {
00107                 Q_strncpyz( client->reliableCommands[ index ], cmd, sizeof( client->reliableCommands[ index ] ) );
00108                 /*
00109                 if ( client->netchan.remoteAddress.type != NA_BOT ) {
00110                     Com_Printf( "WARNING: client %i removed double pending config string %i: %s\n", client-svs.clients, csnum1, cmd );
00111                 }
00112                 */
00113                 return qtrue;
00114             }
00115         }
00116     }
00117     return qfalse;
00118 }

Here is the call graph for this function:

void QDECL SV_SendServerCommand client_t cl,
const char *  fmt,
  ...
 

Definition at line 165 of file sv_main.c.

References byte, cl, client_t, serverStatic_t::clients, com_dedicated, Com_Printf(), cvar_s::integer, j, Q_vsnprintf, QDECL, client_s::state, strncmp(), SV_AddServerCommand(), SV_ExpandNewlines(), sv_maxclients, svs, va_end, va_list, and va_start.

Referenced by SV_Ban_f(), SV_BanNum_f(), SV_ConSay_f(), SV_DropClient(), SV_FinalMessage(), SV_GameSendServerCommand(), SV_Kick_f(), SV_KickNum_f(), and SV_SetConfigstring().

00165                                                                     {
00166     va_list     argptr;
00167     byte        message[MAX_MSGLEN];
00168     client_t    *client;
00169     int         j;
00170     
00171     va_start (argptr,fmt);
00172     Q_vsnprintf ((char *)message, sizeof(message), fmt,argptr);
00173     va_end (argptr);
00174 
00175     if ( cl != NULL ) {
00176         SV_AddServerCommand( cl, (char *)message );
00177         return;
00178     }
00179 
00180     // hack to echo broadcast prints to console
00181     if ( com_dedicated->integer && !strncmp( (char *)message, "print", 5) ) {
00182         Com_Printf ("broadcast: %s\n", SV_ExpandNewlines((char *)message) );
00183     }
00184 
00185     // send the data to all relevent clients
00186     for (j = 0, client = svs.clients; j < sv_maxclients->integer ; j++, client++) {
00187         if ( client->state < CS_PRIMED ) {
00188             continue;
00189         }
00190         SV_AddServerCommand( client, (char *)message );
00191     }
00192 }

Here is the call graph for this function:

void SVC_Info netadr_t  from  ) 
 

Definition at line 366 of file sv_main.c.

References serverStatic_t::clients, Cmd_Argv(), count, Cvar_VariableString(), Cvar_VariableValue(), gamedir, GT_SINGLE_PLAYER, i, Info_SetValueForKey(), cvar_s::integer, NET_OutOfBandPrint(), NS_SERVER, PROTOCOL_VERSION, client_s::state, cvar_s::string, sv_gametype, sv_hostname, sv_mapname, sv_maxclients, sv_maxPing, sv_minPing, sv_privateClients, sv_pure, svs, and va().

Referenced by SV_ConnectionlessPacket().

00366                                {
00367     int     i, count;
00368     char    *gamedir;
00369     char    infostring[MAX_INFO_STRING];
00370 
00371     // ignore if we are in single player
00372     if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
00373         return;
00374     }
00375 
00376     // don't count privateclients
00377     count = 0;
00378     for ( i = sv_privateClients->integer ; i < sv_maxclients->integer ; i++ ) {
00379         if ( svs.clients[i].state >= CS_CONNECTED ) {
00380             count++;
00381         }
00382     }
00383 
00384     infostring[0] = 0;
00385 
00386     // echo back the parameter to status. so servers can use it as a challenge
00387     // to prevent timed spoofed reply packets that add ghost servers
00388     Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
00389 
00390     Info_SetValueForKey( infostring, "protocol", va("%i", PROTOCOL_VERSION) );
00391     Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
00392     Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
00393     Info_SetValueForKey( infostring, "clients", va("%i", count) );
00394     Info_SetValueForKey( infostring, "sv_maxclients", 
00395         va("%i", sv_maxclients->integer - sv_privateClients->integer ) );
00396     Info_SetValueForKey( infostring, "gametype", va("%i", sv_gametype->integer ) );
00397     Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) );
00398 
00399     if( sv_minPing->integer ) {
00400         Info_SetValueForKey( infostring, "minPing", va("%i", sv_minPing->integer) );
00401     }
00402     if( sv_maxPing->integer ) {
00403         Info_SetValueForKey( infostring, "maxPing", va("%i", sv_maxPing->integer) );
00404     }
00405     gamedir = Cvar_VariableString( "fs_game" );
00406     if( *gamedir ) {
00407         Info_SetValueForKey( infostring, "game", gamedir );
00408     }
00409 
00410     NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring );
00411 }

Here is the call graph for this function:

void SVC_RemoteCommand netadr_t  from,
msg_t msg
 

Definition at line 432 of file sv_main.c.

References Cmd_Argv(), Cmd_Cmd(), Cmd_ExecuteString(), Com_BeginRedirect(), Com_EndRedirect(), Com_Milliseconds(), Com_Printf(), NET_AdrToString(), Q_strcat(), qboolean, serverStatic_t::redirectAddress, strcmp(), cvar_s::string, strlen(), SV_FlushRedirect(), SV_OUTPUTBUF_LENGTH, sv_rconPassword, svs, and time().

Referenced by SV_ConnectionlessPacket().

00432                                                     {
00433     qboolean    valid;
00434     unsigned int time;
00435     char        remaining[1024];
00436     // TTimo - scaled down to accumulate, but not overflow anything network wise, print wise etc.
00437     // (OOB messages are the bottleneck here)
00438 #define SV_OUTPUTBUF_LENGTH (1024 - 16)
00439     char        sv_outputbuf[SV_OUTPUTBUF_LENGTH];
00440     static unsigned int lasttime = 0;
00441     char *cmd_aux;
00442 
00443     // TTimo - https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=534
00444     time = Com_Milliseconds();
00445     if (time<(lasttime+500)) {
00446         return;
00447     }
00448     lasttime = time;
00449 
00450     if ( !strlen( sv_rconPassword->string ) ||
00451         strcmp (Cmd_Argv(1), sv_rconPassword->string) ) {
00452         valid = qfalse;
00453         Com_Printf ("Bad rcon from %s:\n%s\n", NET_AdrToString (from), Cmd_Argv(2) );
00454     } else {
00455         valid = qtrue;
00456         Com_Printf ("Rcon from %s:\n%s\n", NET_AdrToString (from), Cmd_Argv(2) );
00457     }
00458 
00459     // start redirecting all print outputs to the packet
00460     svs.redirectAddress = from;
00461     Com_BeginRedirect (sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
00462 
00463     if ( !strlen( sv_rconPassword->string ) ) {
00464         Com_Printf ("No rconpassword set on the server.\n");
00465     } else if ( !valid ) {
00466         Com_Printf ("Bad rconpassword.\n");
00467     } else {
00468         remaining[0] = 0;
00469         
00470         // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543
00471         // get the command directly, "rcon <pass> <command>" to avoid quoting issues
00472         // extract the command by walking
00473         // since the cmd formatting can fuckup (amount of spaces), using a dumb step by step parsing
00474         cmd_aux = Cmd_Cmd();
00475         cmd_aux+=4;
00476         while(cmd_aux[0]==' ')
00477             cmd_aux++;
00478         while(cmd_aux[0] && cmd_aux[0]!=' ') // password
00479             cmd_aux++;
00480         while(cmd_aux[0]==' ')
00481             cmd_aux++;
00482         
00483         Q_strcat( remaining, sizeof(remaining), cmd_aux);
00484         
00485         Cmd_ExecuteString (remaining);
00486 
00487     }
00488 
00489     Com_EndRedirect ();
00490 }

Here is the call graph for this function:

void SVC_Status netadr_t  from  ) 
 

Definition at line 307 of file sv_main.c.

References cl, client_t, serverStatic_t::clients, Cmd_Argv(), Com_sprintf(), Cvar_InfoString(), CVAR_SERVERINFO, Cvar_VariableValue(), i, Info_SetValueForKey(), Info_ValueForKey(), cvar_s::integer, NET_OutOfBandPrint(), NS_SERVER, PERS_SCORE, playerState_s::persistant, playerState_t, strcpy(), strlen(), SV_GameClientNum(), sv_maxclients, and svs.

Referenced by SV_ConnectionlessPacket().

00307                                  {
00308     char    player[1024];
00309     char    status[MAX_MSGLEN];
00310     int     i;
00311     client_t    *cl;
00312     playerState_t   *ps;
00313     int     statusLength;
00314     int     playerLength;
00315     char    infostring[MAX_INFO_STRING];
00316 
00317     // ignore if we are in single player
00318     if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER ) {
00319         return;
00320     }
00321 
00322     strcpy( infostring, Cvar_InfoString( CVAR_SERVERINFO ) );
00323 
00324     // echo back the parameter to status. so master servers can use it as a challenge
00325     // to prevent timed spoofed reply packets that add ghost servers
00326     Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
00327 
00328     // add "demo" to the sv_keywords if restricted
00329     if ( Cvar_VariableValue( "fs_restrict" ) ) {
00330         char    keywords[MAX_INFO_STRING];
00331 
00332         Com_sprintf( keywords, sizeof( keywords ), "demo %s",
00333             Info_ValueForKey( infostring, "sv_keywords" ) );
00334         Info_SetValueForKey( infostring, "sv_keywords", keywords );
00335     }
00336 
00337     status[0] = 0;
00338     statusLength = 0;
00339 
00340     for (i=0 ; i < sv_maxclients->integer ; i++) {
00341         cl = &svs.