summaryrefslogtreecommitdiff
path: root/src/server/sv_client.c
diff options
context:
space:
mode:
authorThilo Schulz <arny@ats.s.bawue.de>2011-07-12 11:01:20 +0000
committerTim Angus <tim@ngus.net>2013-01-10 21:57:40 +0000
commit3bd2ba9e590cb882b684b1eb4b2650b1a4c94f7f (patch)
tree277a7efa735dfa9854d5e41199b65ef48f0043c2 /src/server/sv_client.c
parentc22cbd3e5552c0599dad9d60c1ea80a56b48f883 (diff)
- Greatly improve UDP downloading speed for clients - Add download rate control cvar sv_dlRate - Don't send snapshots to downloading clients
Diffstat (limited to 'src/server/sv_client.c')
-rw-r--r--src/server/sv_client.c134
1 files changed, 68 insertions, 66 deletions
diff --git a/src/server/sv_client.c b/src/server/sv_client.c
index 082c0417..8ff3f0a1 100644
--- a/src/server/sv_client.c
+++ b/src/server/sv_client.c
@@ -646,21 +646,19 @@ static void SV_BeginDownload_f( client_t *cl ) {
SV_WriteDownloadToClient
Check to see if the client wants a file, open it if needed and start pumping the client
-Fill up msg with data
+Fill up msg with data, return number of download blocks added
==================
*/
-void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
+int SV_WriteDownloadToClient(client_t *cl, msg_t *msg)
{
int curindex;
- int rate;
- int blockspersnap;
int unreferenced = 1;
char errorMessage[1024];
char pakbuf[MAX_QPATH], *pakptr;
int numRefPaks;
if (!*cl->downloadName)
- return; // Nothing being downloaded
+ return 0; // Nothing being downloaded
if(!cl->download)
{
@@ -736,7 +734,7 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
if(cl->download)
FS_FCloseFile(cl->download);
- return;
+ return 0;
}
Com_Printf( "clientDownload: %d : beginning \"%s\"\n", (int) (cl - svs.clients), cl->downloadName );
@@ -781,81 +779,85 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
cl->downloadEOF = qtrue; // We have added the EOF block
}
- // Loop up to window size times based on how many blocks we can fit in the
- // client snapMsec and rate
+ if (cl->downloadClientBlock == cl->downloadCurrentBlock)
+ return 0; // Nothing to transmit
- // based on the rate, how many bytes can we fit in the snapMsec time of the client
- // normal rate / snapshotMsec calculation
- rate = cl->rate;
- if ( sv_maxRate->integer ) {
- if ( sv_maxRate->integer < 1000 ) {
- Cvar_Set( "sv_MaxRate", "1000" );
- }
- if ( sv_maxRate->integer < rate ) {
- rate = sv_maxRate->integer;
- }
- }
- if ( sv_minRate->integer ) {
- if ( sv_minRate->integer < 1000 )
- Cvar_Set( "sv_minRate", "1000" );
- if ( sv_minRate->integer > rate )
- rate = sv_minRate->integer;
+ // Write out the next section of the file, if we have already reached our window,
+ // automatically start retransmitting
+ if (cl->downloadXmitBlock == cl->downloadCurrentBlock)
+ {
+ // We have transmitted the complete window, should we start resending?
+ if (svs.time - cl->downloadSendTime > 1000)
+ cl->downloadXmitBlock = cl->downloadClientBlock;
+ else
+ return 0;
}
- if (!rate) {
- blockspersnap = 1;
- } else {
- blockspersnap = ( (rate * cl->snapshotMsec) / 1000 + MAX_DOWNLOAD_BLKSIZE ) /
- MAX_DOWNLOAD_BLKSIZE;
- }
+ // Send current block
+ curindex = (cl->downloadXmitBlock % MAX_DOWNLOAD_WINDOW);
- if (blockspersnap < 0)
- blockspersnap = 1;
+ MSG_WriteByte( msg, svc_download );
+ MSG_WriteShort( msg, cl->downloadXmitBlock );
- while (blockspersnap--) {
+ // block zero is special, contains file size
+ if ( cl->downloadXmitBlock == 0 )
+ MSG_WriteLong( msg, cl->downloadSize );
- // Write out the next section of the file, if we have already reached our window,
- // automatically start retransmitting
+ MSG_WriteShort( msg, cl->downloadBlockSize[curindex] );
- if (cl->downloadClientBlock == cl->downloadCurrentBlock)
- return; // Nothing to transmit
+ // Write the block
+ if(cl->downloadBlockSize[curindex])
+ MSG_WriteData(msg, cl->downloadBlocks[curindex], cl->downloadBlockSize[curindex]);
- if (cl->downloadXmitBlock == cl->downloadCurrentBlock) {
- // We have transmitted the complete window, should we start resending?
+ Com_DPrintf( "clientDownload: %d : writing block %d\n", (int) (cl - svs.clients), cl->downloadXmitBlock );
- //FIXME: This uses a hardcoded one second timeout for lost blocks
- //the timeout should be based on client rate somehow
- if (svs.time - cl->downloadSendTime > 1000)
- cl->downloadXmitBlock = cl->downloadClientBlock;
- else
- return;
- }
+ // Move on to the next block
+ // It will get sent with next snap shot. The rate will keep us in line.
+ cl->downloadXmitBlock++;
+ cl->downloadSendTime = svs.time;
- // Send current block
- curindex = (cl->downloadXmitBlock % MAX_DOWNLOAD_WINDOW);
+ return 1;
+}
- MSG_WriteByte( msg, svc_download );
- MSG_WriteShort( msg, cl->downloadXmitBlock );
+/*
+==================
+SV_SendDownloadMessages
- // block zero is special, contains file size
- if ( cl->downloadXmitBlock == 0 )
- MSG_WriteLong( msg, cl->downloadSize );
-
- MSG_WriteShort( msg, cl->downloadBlockSize[curindex] );
+Send download messages to all clients
+==================
+*/
- // Write the block
- if ( cl->downloadBlockSize[curindex] ) {
- MSG_WriteData( msg, cl->downloadBlocks[curindex], cl->downloadBlockSize[curindex] );
+int SV_SendDownloadMessages(void)
+{
+ int i, numDLs = 0, retval;
+ client_t *cl;
+ msg_t msg;
+ byte msgBuffer[MAX_MSGLEN];
+
+ for(i=0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++)
+ {
+ if(cl->state && *cl->downloadName)
+ {
+ if(cl->netchan.unsentFragments)
+ SV_Netchan_TransmitNextFragment(cl);
+ else
+ {
+ MSG_Init(&msg, msgBuffer, sizeof(msgBuffer));
+ MSG_WriteLong(&msg, cl->lastClientCommand);
+
+ retval = SV_WriteDownloadToClient(cl, &msg);
+
+ if(retval)
+ {
+ MSG_WriteByte(&msg, svc_EOF);
+ SV_Netchan_Transmit(cl, &msg);
+ numDLs += retval;
+ }
+ }
}
-
- Com_DPrintf( "clientDownload: %d : writing block %d\n", (int) (cl - svs.clients), cl->downloadXmitBlock );
-
- // Move on to the next block
- // It will get sent with next snap shot. The rate will keep us in line.
- cl->downloadXmitBlock++;
-
- cl->downloadSendTime = svs.time;
}
+
+ return numDLs;
}
#ifdef USE_VOIP