From 189e8b33f31470ff4b0bef18634fc4332c99f776 Mon Sep 17 00:00:00 2001 From: "Tony J. White =" Date: Fri, 13 Oct 2006 19:44:52 +0000 Subject: [PATCH] * (bug 2784) help to prevent reliable command overflow in cases when 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. --- code/server/server.h | 2 + code/server/sv_client.c | 4 ++ code/server/sv_init.c | 111 +++++++++++++++++++++++++++++----------- code/server/sv_main.c | 7 +-- 4 files changed, 90 insertions(+), 34 deletions(-) diff --git a/code/server/server.h b/code/server/server.h index 94bde880..57a49f3a 100644 --- a/code/server/server.h +++ b/code/server/server.h @@ -168,6 +168,7 @@ typedef struct client_s { netchan_buffer_t **netchan_end_queue; int oldServerTime; + qboolean csUpdated[MAX_CONFIGSTRINGS+1]; } client_t; //============================================================================= @@ -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 ); diff --git a/code/server/sv_client.c b/code/server/sv_client.c index e9f1a2b7..6f9af5c7 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -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 ); diff --git a/code/server/sv_init.c b/code/server/sv_init.c index 986575ba..c7c5087b 100644 --- a/code/server/sv_init.c +++ b/code/server/sv_init.c @@ -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 @@ -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 ) { @@ -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 diff --git a/code/server/sv_main.c b/code/server/sv_main.c index a343c510..ed07b87b 100644 --- a/code/server/sv_main.c +++ b/code/server/sv_main.c @@ -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 @@ -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 ); } }