Skip to content

Commit

Permalink
server: cache sv_maxclients value to avoid potential crashes caused b…
Browse files Browse the repository at this point in the history
…y VMs changing it at runtime
  • Loading branch information
ec- committed Jun 27, 2024
1 parent 8d1636c commit 413e2fb
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 121 deletions.
4 changes: 2 additions & 2 deletions code/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ typedef struct snapshotFrame_s {
typedef struct {
serverState_t state;
qboolean restarting; // if true, send configstring changes during SS_LOADING
int pure;
int pure; // fixed at level spawn
int maxclients; // fixed at level spawn
int serverId; // changes each server start
int restartedServerId; // changes each map restart
int checksumFeed; // the feed key that we use to compute the pure checksum strings
Expand Down Expand Up @@ -340,7 +341,6 @@ void SV_UpdateConfigstrings( client_t *client );
void SV_SetUserinfo( int index, const char *val );
void SV_GetUserinfo( int index, char *buffer, int bufferSize );

void SV_ChangeMaxClients( void );
void SV_SpawnServer( const char *mapname, qboolean killBots );


Expand Down
12 changes: 6 additions & 6 deletions code/server/sv_bot.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ int SV_BotAllocateClient( void ) {
client_t *cl;

// find a client slot
for ( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) {
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state == CS_FREE ) {
break;
}
}

if ( i == sv_maxclients->integer ) {
if ( i == sv.maxclients ) {
return -1;
}

Expand All @@ -82,7 +82,7 @@ SV_BotFreeClient
void SV_BotFreeClient( int clientNum ) {
client_t *cl;

if ( (unsigned) clientNum >= sv_maxclients->integer ) {
if ( (unsigned) clientNum >= sv.maxclients ) {
Com_Error( ERR_DROP, "SV_BotFreeClient: bad clientNum: %i", clientNum );
}

Expand Down Expand Up @@ -440,7 +440,7 @@ SV_BotClientCommand
==================
*/
static void BotClientCommand( int client, const char *command ) {
if ( (unsigned) client < sv_maxclients->integer ) {
if ( (unsigned) client < sv.maxclients ) {
SV_ExecuteClientCommand( &svs.clients[client], command );
}
}
Expand Down Expand Up @@ -592,7 +592,7 @@ SV_BotGetConsoleMessage
*/
int SV_BotGetConsoleMessage( int client, char *buf, int size )
{
if ( (unsigned) client < sv_maxclients->integer ) {
if ( (unsigned) client < sv.maxclients ) {
client_t* cl;
int index;

Expand Down Expand Up @@ -647,7 +647,7 @@ SV_BotGetSnapshotEntity
==================
*/
int SV_BotGetSnapshotEntity( int client, int sequence ) {
if ( (unsigned) client < sv_maxclients->integer ) {
if ( (unsigned) client < sv.maxclients ) {
const client_t* cl = &svs.clients[client];
const clientSnapshot_t* frame = &cl->frames[cl->netchan.outgoingSequence & PACKET_MASK];
if ( (unsigned) sequence >= frame->num_entities ) {
Expand Down
42 changes: 21 additions & 21 deletions code/server/sv_ccmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ client_t *SV_GetPlayerByHandle( void ) {
int plid = atoi(s);

// Check for numeric playerid match
if(plid >= 0 && plid < sv_maxclients->integer)
if(plid >= 0 && plid < sv.maxclients)
{
cl = &svs.clients[plid];

if(cl->state)
if (cl->state >= CS_CONNECTED)
return cl;
}
}

// check for a name match
for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state < CS_CONNECTED ) {
continue;
}
Expand Down Expand Up @@ -128,7 +128,7 @@ static client_t *SV_GetPlayerByNum( void ) {
}
}
idnum = atoi( s );
if ( idnum < 0 || idnum >= sv_maxclients->integer ) {
if ( idnum < 0 || idnum >= sv.maxclients ) {
Com_Printf( "Bad client slot: %i\n", idnum );
return NULL;
}
Expand Down Expand Up @@ -294,7 +294,7 @@ static void SV_MapRestart_f( void ) {
// if a map_restart occurs while a client is changing maps, we need
// to give them the correct time so that when they finish loading
// they don't violate the backwards time check in cl_cgame.c
for ( i = 0; i < sv_maxclients->integer; i++ ) {
for ( i = 0; i < sv.maxclients; i++ ) {
if ( svs.clients[i].state == CS_PRIMED ) {
svs.clients[i].oldServerTime = sv.restartTime;
}
Expand Down Expand Up @@ -322,7 +322,7 @@ static void SV_MapRestart_f( void ) {
sv.restarting = qfalse;

// connect and begin all the clients
for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
for ( i = 0; i < sv.maxclients; i++ ) {
client = &svs.clients[i];

// send the new gamestate to all connected clients
Expand Down Expand Up @@ -359,7 +359,7 @@ static void SV_MapRestart_f( void ) {
VM_Call( gvm, 1, GAME_RUN_FRAME, sv.time );
svs.time += 100;

for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
for ( i = 0; i < sv.maxclients; i++ ) {
client = &svs.clients[i];
if ( client->state >= CS_PRIMED ) {
// accept usercmds starting from current server time only
Expand Down Expand Up @@ -395,24 +395,24 @@ static void SV_Kick_f( void ) {

cl = SV_GetPlayerByHandle();
if ( !cl ) {
if ( !Q_stricmp(Cmd_Argv(1), "all") ) {
for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
if ( !cl->state ) {
if ( !Q_stricmp( Cmd_Argv( 1 ), "all" ) ) {
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state < CS_CONNECTED ) {
continue;
}
if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) {
if ( cl->netchan.remoteAddress.type == NA_LOOPBACK ) {
continue;
}
SV_DropClient( cl, "was kicked" );
cl->lastPacketTime = svs.time; // in case there is a funny zombie
}
}
else if ( !Q_stricmp(Cmd_Argv(1), "allbots") ) {
for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
if ( !cl->state ) {
else if ( !Q_stricmp( Cmd_Argv( 1 ), "allbots" ) ) {
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state < CS_CONNECTED ) {
continue;
}
if( cl->netchan.remoteAddress.type != NA_BOT ) {
if ( cl->netchan.remoteAddress.type != NA_BOT ) {
continue;
}
SV_DropClient( cl, "was kicked" );
Expand All @@ -421,8 +421,8 @@ static void SV_Kick_f( void ) {
}
return;
}
if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) {
Com_Printf("Cannot kick host player\n");
if ( cl->netchan.remoteAddress.type == NA_LOOPBACK ) {
Com_Printf( "Cannot kick host player\n" );
return;
}

Expand All @@ -447,7 +447,7 @@ static void SV_KickBots_f( void ) {
return;
}

for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) {
for( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state < CS_CONNECTED ) {
continue;
}
Expand Down Expand Up @@ -477,7 +477,7 @@ static void SV_KickAll_f( void ) {
return;
}

for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) {
for( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state < CS_CONNECTED ) {
continue;
}
Expand Down Expand Up @@ -1216,7 +1216,7 @@ static void SV_Status_f( void ) {
Com_Memset( al, 0, sizeof( al ) );

// first pass: save and determine max.lengths of name/address fields
for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++ )
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ )
{
if ( cl->state == CS_FREE )
continue;
Expand Down Expand Up @@ -1260,7 +1260,7 @@ static void SV_Status_f( void ) {
Com_Printf( " -----\n" );
#endif

for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++ )
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ )
{
if ( cl->state == CS_FREE )
continue;
Expand Down
36 changes: 18 additions & 18 deletions code/server/sv_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ static int seqs[ MAX_CLIENTS ];

static void SV_SaveSequences( void ) {
int i;
for ( i = 0; i < sv_maxclients->integer; i++ ) {
for ( i = 0; i < sv.maxclients; i++ ) {
seqs[i] = svs.clients[i].reliableSequence;
}
}
Expand All @@ -390,7 +390,7 @@ static void SV_InjectLocation( const char *tld, const char *country ) {
const char *cmd;
char *str;
int i, n;
for ( i = 0; i < sv_maxclients->integer; i++ ) {
for ( i = 0; i < sv.maxclients; i++ ) {
if ( seqs[i] != svs.clients[i].reliableSequence ) {
for ( n = seqs[i]; n != svs.clients[i].reliableSequence + 1; n++ ) {
cmd = svs.clients[i].reliableCommands[n & (MAX_RELIABLE_COMMANDS-1)];
Expand Down Expand Up @@ -503,7 +503,7 @@ void SV_DirectConnect( const netadr_t *from ) {
}

// check for concurrent connections
for ( i = 0, n = 0; i < sv_maxclients->integer; i++ ) {
for ( i = 0, n = 0; i < sv.maxclients; i++ ) {
const netadr_t *addr = &svs.clients[ i ].netchan.remoteAddress;
if ( addr->type != NA_BOT && NET_CompareBaseAdr( addr, from ) ) {
if ( svs.clients[ i ].state >= CS_CONNECTED && !svs.clients[ i ].justConnected ) {
Expand Down Expand Up @@ -643,7 +643,7 @@ void SV_DirectConnect( const netadr_t *from ) {

// quick reject
newcl = NULL;
for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++ ) {
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( NET_CompareAdr( from, &cl->netchan.remoteAddress ) ) {
int elapsed = svs.time - cl->lastConnectTime;
if ( elapsed < ( sv_reconnectlimit->integer * 1000 ) && elapsed >= 0 ) {
Expand All @@ -664,7 +664,7 @@ void SV_DirectConnect( const netadr_t *from ) {
}

// if there is already a slot for this ip, reuse it
for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++ ) {
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ ) {
if ( cl->state == CS_FREE ) {
continue;
}
Expand Down Expand Up @@ -713,7 +713,7 @@ void SV_DirectConnect( const netadr_t *from ) {
// select least used free slot
n = 0;
newcl = NULL;
for ( i = startIndex; i < sv_maxclients->integer ; i++ ) {
for ( i = startIndex; i < sv.maxclients; i++ ) {
cl = &svs.clients[i];
if ( cl->state == CS_FREE && ( newcl == NULL || svs.time - cl->lastDisconnectTime > n ) ) {
n = svs.time - cl->lastDisconnectTime;
Expand All @@ -724,16 +724,16 @@ void SV_DirectConnect( const netadr_t *from ) {
if ( !newcl ) {
if ( NET_IsLocalAddress( from ) ) {
count = 0;
for ( i = startIndex; i < sv_maxclients->integer ; i++ ) {
for ( i = startIndex; i < sv.maxclients; i++ ) {
cl = &svs.clients[i];
if (cl->netchan.remoteAddress.type == NA_BOT) {
count++;
}
}
// if they're all bots
if (count >= sv_maxclients->integer - startIndex) {
SV_DropClient(&svs.clients[sv_maxclients->integer - 1], "only bots on server");
newcl = &svs.clients[sv_maxclients->integer - 1];
if (count >= sv.maxclients - startIndex) {
SV_DropClient(&svs.clients[sv.maxclients - 1], "only bots on server");
newcl = &svs.clients[sv.maxclients - 1];
}
else {
Com_Error( ERR_DROP, "server is full on local connect" );
Expand Down Expand Up @@ -824,12 +824,12 @@ void SV_DirectConnect( const netadr_t *from ) {
// if this was the first client on the server, or the last client
// the server can hold, send a heartbeat to the master.
count = 0;
for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
for ( i = 0, cl = svs.clients ; i < sv.maxclients; i++, cl++) {
if ( svs.clients[i].state >= CS_CONNECTED ) {
count++;
}
}
if ( count == 1 || count == sv_maxclients->integer ) {
if ( count == 1 || count == sv.maxclients ) {
SV_Heartbeat_f();
}
}
Expand Down Expand Up @@ -915,12 +915,12 @@ void SV_DropClient( client_t *drop, const char *reason ) {
// if this was the last client on the server, send a heartbeat
// to the master so it is known the server is empty
// send a heartbeat now so the master will get up to date info
for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
for ( i = 0; i < sv.maxclients; i++ ) {
if ( svs.clients[i].state >= CS_CONNECTED ) {
break;
}
}
if ( i == sv_maxclients->integer ) {
if ( i == sv.maxclients ) {
SV_Heartbeat_f();
}
}
Expand Down Expand Up @@ -1506,7 +1506,7 @@ int SV_SendQueuedMessages( void )
int i, retval = -1, nextFragT;
client_t *cl;

for( i = 0; i < sv_maxclients->integer; i++ )
for( i = 0; i < sv.maxclients; i++ )
{
cl = &svs.clients[i];

Expand Down Expand Up @@ -1538,7 +1538,7 @@ int SV_SendDownloadMessages( void )
int i, numDLs = 0;
client_t *cl;

for( i = 0; i < sv_maxclients->integer; i++ )
for( i = 0; i < sv.maxclients; i++ )
{
cl = &svs.clients[ i ];
if ( cl->state >= CS_CONNECTED && *cl->downloadName )
Expand Down Expand Up @@ -1878,7 +1878,7 @@ void SV_PrintLocations_f( client_t *client ) {
max_ctrylength = 7; // strlen( "country" )

// first pass: save and determine max.lengths of name/address fields
for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++ )
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ )
{
if ( cl->state == CS_FREE )
continue;
Expand All @@ -1902,7 +1902,7 @@ void SV_PrintLocations_f( client_t *client ) {
Com_sprintf( line, sizeof( line ), "-- %s -- %s\n", filln, fillc );
s = Q_stradd( s, line );

for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++ )
for ( i = 0, cl = svs.clients; i < sv.maxclients; i++, cl++ )
{
if ( cl->state == CS_FREE )
continue;
Expand Down
Loading

0 comments on commit 413e2fb

Please sign in to comment.