Skip to content

Commit

Permalink
* (bug 2784) help to prevent reliable command overflow in cases when …
Browse files Browse the repository at this point in the history
…a slow

  client is loading the map on a busy server. Specifically, hold back all
  configstring update commands while the client is CS_PRIMED.  Once the
  client goes from CS_PRIMED to CS_ACTIVE, send the cleint commands for
  updating each of the configstring indexes which were updated while the 
  client was CS_PRIMED.
  • Loading branch information
tjdub committed Oct 13, 2006
1 parent 41add6c commit 189e8b3
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 34 deletions.
2 changes: 2 additions & 0 deletions code/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ typedef struct client_s {
netchan_buffer_t **netchan_end_queue;

int oldServerTime;
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
} client_t;

//=============================================================================
Expand Down Expand Up @@ -272,6 +273,7 @@ void SV_MasterShutdown (void);
//
void SV_SetConfigstring( int index, const char *val );
void SV_GetConfigstring( int index, char *buffer, int bufferSize );
void SV_UpdateConfigstrings( client_t *client );

void SV_SetUserinfo( int index, const char *val );
void SV_GetUserinfo( int index, char *buffer, int bufferSize );
Expand Down
4 changes: 4 additions & 0 deletions code/server/sv_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,10 @@ void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ) {
Com_DPrintf( "Going from CS_PRIMED to CS_ACTIVE for %s\n", client->name );
client->state = CS_ACTIVE;

// resend all configstrings using the cs commands since these are
// no longer sent when the client is CS_PRIMED
SV_UpdateConfigstrings( client );

// set up the entity for the client
clientNum = client - svs.clients;
ent = SV_GentityNum( clientNum );
Expand Down
111 changes: 80 additions & 31 deletions code/server/sv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,81 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "server.h"


/*
===============
SV_SendConfigstring
Creates and sends the server command necessary to update the CS index for the
given client
===============
*/
static void SV_SendConfigstring(client_t *client, int index)
{
int maxChunkSize = MAX_STRING_CHARS - 24;
int len;

len = strlen(sv.configstrings[index]);

if( len >= maxChunkSize ) {
int sent = 0;
int remaining = len;
char *cmd;
char buf[MAX_STRING_CHARS];

while (remaining > 0 ) {
if ( sent == 0 ) {
cmd = "bcs0";
}
else if( remaining < maxChunkSize ) {
cmd = "bcs2";
}
else {
cmd = "bcs1";
}
Q_strncpyz( buf, &sv.configstrings[index][sent],
maxChunkSize );

SV_SendServerCommand( client, "%s %i \"%s\"\n", cmd,
index, buf );

sent += (maxChunkSize - 1);
remaining -= (maxChunkSize - 1);
}
} else {
// standard cs, just send it
SV_SendServerCommand( client, "cs %i \"%s\"\n", index,
sv.configstrings[index] );
}
}

/*
===============
SV_UpdateConfigstrings
Called when a client goes from CS_PRIMED to CS_ACTIVE. Updates all
Configstring indexes that have changed while the client was in CS_PRIMED
===============
*/
void SV_UpdateConfigstrings(client_t *client)
{
int index;

for( index = 0; index <= MAX_CONFIGSTRINGS; index++ ) {
// if the CS hasn't changed since we went to CS_PRIMED, ignore
if(!client->csUpdated[index])
continue;

// do not always send server info to all clients
if ( index == CS_SERVERINFO && client->gentity &&
(client->gentity->r.svFlags & SVF_NOSERVERINFO) ) {
continue;
}
SV_SendConfigstring(client, index);
client->csUpdated[index] = qfalse;
}
}

/*
===============
SV_SetConfigstring
Expand All @@ -30,7 +105,6 @@ SV_SetConfigstring
*/
void SV_SetConfigstring (int index, const char *val) {
int len, i;
int maxChunkSize = MAX_STRING_CHARS - 24;
client_t *client;

if ( index < 0 || index >= MAX_CONFIGSTRINGS ) {
Expand All @@ -56,48 +130,23 @@ void SV_SetConfigstring (int index, const char *val) {

// send the data to all relevent clients
for (i = 0, client = svs.clients; i < sv_maxclients->integer ; i++, client++) {
if ( client->state < CS_PRIMED ) {
if ( client->state < CS_ACTIVE ) {
if ( client->state == CS_PRIMED )
client->csUpdated[ index ] = qtrue;
continue;
}
// do not always send server info to all clients
if ( index == CS_SERVERINFO && client->gentity && (client->gentity->r.svFlags & SVF_NOSERVERINFO) ) {
continue;
}


len = strlen( val );
if( len >= maxChunkSize ) {
int sent = 0;
int remaining = len;
char *cmd;
char buf[MAX_STRING_CHARS];

while (remaining > 0 ) {
if ( sent == 0 ) {
cmd = "bcs0";
}
else if( remaining < maxChunkSize ) {
cmd = "bcs2";
}
else {
cmd = "bcs1";
}
Q_strncpyz( buf, &val[sent], maxChunkSize );

SV_SendServerCommand( client, "%s %i \"%s\"\n", cmd, index, buf );

sent += (maxChunkSize - 1);
remaining -= (maxChunkSize - 1);
}
} else {
// standard cs, just send it
SV_SendServerCommand( client, "cs %i \"%s\"\n", index, val );
}
SV_SendConfigstring(client, index);
}
}
}



/*
===============
SV_GetConfigstring
Expand Down
7 changes: 4 additions & 3 deletions code/server/sv_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ void SV_AddServerCommand( client_t *client, const char *cmd ) {
// return;
// }

// do not send commands until the gamestate has been sent
if( client->state < CS_PRIMED )
return;

client->reliableSequence++;
// if we would be losing an old command that hasn't been acknowledged,
// we must drop the connection
Expand Down Expand Up @@ -193,9 +197,6 @@ void QDECL SV_SendServerCommand(client_t *cl, const char *fmt, ...) {

// send the data to all relevent clients
for (j = 0, client = svs.clients; j < sv_maxclients->integer ; j++, client++) {
if ( client->state < CS_PRIMED ) {
continue;
}
SV_AddServerCommand( client, (char *)message );
}
}
Expand Down

0 comments on commit 189e8b3

Please sign in to comment.