* (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.
This commit is contained in:
Tony J. White = 2006-10-13 19:44:52 +00:00
parent 41add6c01f
commit 189e8b33f3
4 changed files with 90 additions and 34 deletions

View file

@ -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 );

View file

@ -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 );

View file

@ -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

View file

@ -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 );
}
}