mirror of
https://github.com/ioquake/ioq3.git
synced 2025-05-31 00:51:17 +00:00
- Greatly improve UDP downloading speed for clients
- Add download rate control cvar sv_dlRate - Don't send snapshots to downloading clients
This commit is contained in:
parent
1d880da777
commit
e52a492f61
6 changed files with 150 additions and 78 deletions
|
@ -345,7 +345,7 @@ void SV_DropClient( client_t *drop, const char *reason );
|
|||
void SV_ExecuteClientCommand( client_t *cl, const char *s, qboolean clientOK );
|
||||
void SV_ClientThink (client_t *cl, usercmd_t *cmd);
|
||||
|
||||
void SV_WriteDownloadToClient( client_t *cl , msg_t *msg );
|
||||
int SV_WriteDownloadToClient(client_t *cl , msg_t *msg);
|
||||
|
||||
#ifdef USE_VOIP
|
||||
void SV_WriteVoipToClient( client_t *cl, msg_t *msg );
|
||||
|
|
|
@ -852,21 +852,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)
|
||||
{
|
||||
|
@ -970,7 +968,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 );
|
||||
|
@ -1015,81 +1013,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;
|
||||
// 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 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_SendDownloadMessages
|
||||
|
||||
Send download messages to all clients
|
||||
==================
|
||||
*/
|
||||
|
||||
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
|
||||
return;
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send current block
|
||||
curindex = (cl->downloadXmitBlock % MAX_DOWNLOAD_WINDOW);
|
||||
|
||||
MSG_WriteByte( msg, svc_download );
|
||||
MSG_WriteShort( msg, cl->downloadXmitBlock );
|
||||
|
||||
// block zero is special, contains file size
|
||||
if ( cl->downloadXmitBlock == 0 )
|
||||
MSG_WriteLong( msg, cl->downloadSize );
|
||||
|
||||
MSG_WriteShort( msg, cl->downloadBlockSize[curindex] );
|
||||
|
||||
// Write the block
|
||||
if ( cl->downloadBlockSize[curindex] ) {
|
||||
MSG_WriteData( msg, cl->downloadBlocks[curindex], cl->downloadBlockSize[curindex] );
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -647,9 +647,6 @@ void SV_SendClientSnapshot( client_t *client ) {
|
|||
// and the playerState_t
|
||||
SV_WriteSnapshotToClient( client, &msg );
|
||||
|
||||
// Add any download data if the client is downloading
|
||||
SV_WriteDownloadToClient( client, &msg );
|
||||
|
||||
#ifdef USE_VOIP
|
||||
SV_WriteVoipToClient( client, &msg );
|
||||
#endif
|
||||
|
@ -683,6 +680,9 @@ void SV_SendClientMessages( void ) {
|
|||
continue; // not time yet
|
||||
}
|
||||
|
||||
if(*c->downloadName)
|
||||
continue; // Client is downloading, don't send snapshots
|
||||
|
||||
// send additional message fragments if the last message
|
||||
// was too large to send at once
|
||||
if ( c->netchan.unsentFragments ) {
|
||||
|
@ -696,4 +696,3 @@ void SV_SendClientMessages( void ) {
|
|||
SV_SendClientSnapshot( c );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue