Move rate limiting / queued packet sending logic from Com_Frame() to sv_main.c

This commit is contained in:
Thilo Schulz 2011-07-15 16:51:54 +00:00
parent 58a5d3d383
commit e6ba500164
6 changed files with 121 additions and 87 deletions

View file

@ -77,7 +77,6 @@ cvar_t *cl_paused;
cvar_t *sv_paused; cvar_t *sv_paused;
cvar_t *cl_packetdelay; cvar_t *cl_packetdelay;
cvar_t *sv_packetdelay; cvar_t *sv_packetdelay;
cvar_t *sv_dlRate;
cvar_t *com_cameraMode; cvar_t *com_cameraMode;
cvar_t *com_ansiColor; cvar_t *com_ansiColor;
cvar_t *com_unfocused; cvar_t *com_unfocused;
@ -2781,7 +2780,6 @@ void Com_Init( char *commandLine ) {
sv_paused = Cvar_Get ("sv_paused", "0", CVAR_ROM); sv_paused = Cvar_Get ("sv_paused", "0", CVAR_ROM);
cl_packetdelay = Cvar_Get ("cl_packetdelay", "0", CVAR_CHEAT); cl_packetdelay = Cvar_Get ("cl_packetdelay", "0", CVAR_CHEAT);
sv_packetdelay = Cvar_Get ("sv_packetdelay", "0", CVAR_CHEAT); sv_packetdelay = Cvar_Get ("sv_packetdelay", "0", CVAR_CHEAT);
sv_dlRate = Cvar_Get ("sv_dlRate", "100", CVAR_ARCHIVE);
com_sv_running = Cvar_Get ("sv_running", "0", CVAR_ROM); com_sv_running = Cvar_Get ("sv_running", "0", CVAR_ROM);
com_cl_running = Cvar_Get ("cl_running", "0", CVAR_ROM); com_cl_running = Cvar_Get ("cl_running", "0", CVAR_ROM);
com_buildScript = Cvar_Get( "com_buildScript", "0", 0 ); com_buildScript = Cvar_Get( "com_buildScript", "0", 0 );
@ -3029,6 +3027,26 @@ int Com_ModifyMsec( int msec ) {
return msec; return msec;
} }
/*
=================
Com_TimeVal
=================
*/
int Com_TimeVal(int minMsec)
{
int timeVal;
timeVal = Sys_Milliseconds() - com_frameTime;
if(timeVal >= minMsec)
timeVal = 0;
else
timeVal = minMsec - timeVal;
return timeVal;
}
/* /*
================= =================
Com_Frame Com_Frame
@ -3037,10 +3055,7 @@ Com_Frame
void Com_Frame( void ) { void Com_Frame( void ) {
int msec, minMsec; int msec, minMsec;
int timeVal; int timeVal, timeValSV;
int numBlocks = 1;
int dlStart, deltaT, delayT;
static int dlNextRound = 0;
static int lastTime = 0, bias = 0; static int lastTime = 0, bias = 0;
int timeBeforeFirstEvents; int timeBeforeFirstEvents;
@ -3100,94 +3115,26 @@ void Com_Frame( void ) {
else else
minMsec = 1; minMsec = 1;
msec = Sys_Milliseconds() - com_frameTime; timeVal = 0;
if(msec >= minMsec)
timeVal = 0;
else
timeVal = minMsec - msec;
do do
{ {
if(com_sv_running->integer) if(com_sv_running->integer)
{ {
// Send out fragmented packets now that we're idle timeValSV = SV_SendQueuedPackets();
delayT = SV_SendQueuedMessages();
if(delayT >= 0 && delayT < timeVal) timeVal = Com_TimeVal(minMsec);
timeVal = delayT;
if(sv_dlRate->integer) if(timeValSV < timeVal)
{ timeVal = timeValSV;
// Rate limiting. This is very imprecise for high
// download rates due to millisecond timedelta resolution
dlStart = Sys_Milliseconds();
deltaT = dlNextRound - dlStart;
if(deltaT > 0)
{
if(deltaT < timeVal)
timeVal = deltaT + 1;
}
else
{
numBlocks = SV_SendDownloadMessages();
if(numBlocks)
{
// There are active downloads
deltaT = Sys_Milliseconds() - dlStart;
delayT = 1000 * numBlocks * MAX_DOWNLOAD_BLKSIZE;
delayT /= sv_dlRate->integer * 1024;
if(delayT <= deltaT + 1)
{
// Sending the last round of download messages
// took too long for given rate, don't wait for
// next round, but always enforce a 1ms delay
// between DL message rounds so we don't hog
// all of the bandwidth. This will result in an
// effective maximum rate of 1MB/s per user, but the
// low download window size limits this anyways.
if(timeVal > 2)
timeVal = 2;
dlNextRound = dlStart + deltaT + 1;
}
else
{
dlNextRound = dlStart + delayT;
delayT -= deltaT;
if(delayT < timeVal)
timeVal = delayT;
}
}
}
}
else
{
if(SV_SendDownloadMessages())
timeVal = 1;
}
} }
else
if(timeVal == 0) timeVal = Com_TimeVal(minMsec);
timeVal = 1;
if(com_busyWait->integer || timeVal < 1)
if(com_busyWait->integer)
NET_Sleep(0); NET_Sleep(0);
else else
NET_Sleep(timeVal - 1); NET_Sleep(timeVal - 1);
} while(Com_TimeVal(minMsec));
msec = Sys_Milliseconds() - com_frameTime;
if(msec >= minMsec)
timeVal = 0;
else
timeVal = minMsec - msec;
} while(timeVal > 0);
lastTime = com_frameTime; lastTime = com_frameTime;
com_frameTime = Com_EventLoop(); com_frameTime = Com_EventLoop();

View file

@ -1675,6 +1675,9 @@ void NET_Sleep(int msec)
fd_set fdr; fd_set fdr;
int highestfd = -1, retval; int highestfd = -1, retval;
if(msec < 0)
msec = 0;
FD_ZERO(&fdr); FD_ZERO(&fdr);
if(ip_socket != INVALID_SOCKET) if(ip_socket != INVALID_SOCKET)

View file

@ -1039,8 +1039,7 @@ void SV_Frame( int msec );
void SV_PacketEvent( netadr_t from, msg_t *msg ); void SV_PacketEvent( netadr_t from, msg_t *msg );
int SV_FrameMsec(void); int SV_FrameMsec(void);
qboolean SV_GameCommand( void ); qboolean SV_GameCommand( void );
int SV_SendDownloadMessages(void); int SV_SendQueuedPackets(void);
int SV_SendQueuedMessages(void);
// //
// UI interface // UI interface

View file

@ -279,6 +279,7 @@ extern cvar_t *sv_mapChecksum;
extern cvar_t *sv_serverid; extern cvar_t *sv_serverid;
extern cvar_t *sv_minRate; extern cvar_t *sv_minRate;
extern cvar_t *sv_maxRate; extern cvar_t *sv_maxRate;
extern cvar_t *sv_dlRate;
extern cvar_t *sv_minPing; extern cvar_t *sv_minPing;
extern cvar_t *sv_maxPing; extern cvar_t *sv_maxPing;
extern cvar_t *sv_gametype; extern cvar_t *sv_gametype;
@ -355,6 +356,8 @@ void SV_ExecuteClientCommand( client_t *cl, const char *s, qboolean clientOK );
void SV_ClientThink (client_t *cl, usercmd_t *cmd); void SV_ClientThink (client_t *cl, usercmd_t *cmd);
int SV_WriteDownloadToClient(client_t *cl , msg_t *msg); int SV_WriteDownloadToClient(client_t *cl , msg_t *msg);
int SV_SendDownloadMessages(void);
int SV_SendQueuedMessages(void);
#ifdef USE_VOIP #ifdef USE_VOIP
void SV_WriteVoipToClient( client_t *cl, msg_t *msg ); void SV_WriteVoipToClient( client_t *cl, msg_t *msg );

View file

@ -643,6 +643,7 @@ void SV_Init (void)
sv_minRate = Cvar_Get ("sv_minRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); sv_minRate = Cvar_Get ("sv_minRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_maxRate = Cvar_Get ("sv_maxRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); sv_maxRate = Cvar_Get ("sv_maxRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_dlRate = Cvar_Get("sv_dlRate", "100", CVAR_ARCHIVE | CVAR_SERVERINFO);
sv_minPing = Cvar_Get ("sv_minPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); sv_minPing = Cvar_Get ("sv_minPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_maxPing = Cvar_Get ("sv_maxPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); sv_maxPing = Cvar_Get ("sv_maxPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO );
sv_floodProtect = Cvar_Get ("sv_floodProtect", "1", CVAR_ARCHIVE | CVAR_SERVERINFO ); sv_floodProtect = Cvar_Get ("sv_floodProtect", "1", CVAR_ARCHIVE | CVAR_SERVERINFO );

View file

@ -50,6 +50,7 @@ cvar_t *sv_mapChecksum;
cvar_t *sv_serverid; cvar_t *sv_serverid;
cvar_t *sv_minRate; cvar_t *sv_minRate;
cvar_t *sv_maxRate; cvar_t *sv_maxRate;
cvar_t *sv_dlRate;
cvar_t *sv_minPing; cvar_t *sv_minPing;
cvar_t *sv_maxPing; cvar_t *sv_maxPing;
cvar_t *sv_gametype; cvar_t *sv_gametype;
@ -1205,3 +1206,83 @@ int SV_RateMsec(client_t *client)
else else
return rateMsec - rate; return rateMsec - rate;
} }
/*
====================
SV_SendQueuedPackets
Send download messages and queued packets in the time that we're idle, i.e.
not computing a server frame or sending client snapshots.
Return the time in msec until we expect to be called next
====================
*/
int SV_SendQueuedPackets()
{
int numBlocks;
int dlStart, deltaT, delayT;
static int dlNextRound = 0;
int timeVal = INT_MAX;
// Send out fragmented packets now that we're idle
delayT = SV_SendQueuedMessages();
if(delayT >= 0)
timeVal = delayT;
if(sv_dlRate->integer)
{
// Rate limiting. This is very imprecise for high
// download rates due to millisecond timedelta resolution
dlStart = Sys_Milliseconds();
deltaT = dlNextRound - dlStart;
if(deltaT > 0)
{
if(deltaT < timeVal)
timeVal = deltaT + 1;
}
else
{
numBlocks = SV_SendDownloadMessages();
if(numBlocks)
{
// There are active downloads
deltaT = Sys_Milliseconds() - dlStart;
delayT = 1000 * numBlocks * MAX_DOWNLOAD_BLKSIZE;
delayT /= sv_dlRate->integer * 1024;
if(delayT <= deltaT + 1)
{
// Sending the last round of download messages
// took too long for given rate, don't wait for
// next round, but always enforce a 1ms delay
// between DL message rounds so we don't hog
// all of the bandwidth. This will result in an
// effective maximum rate of 1MB/s per user, but the
// low download window size limits this anyways.
if(timeVal > 2)
timeVal = 2;
dlNextRound = dlStart + deltaT + 1;
}
else
{
dlNextRound = dlStart + delayT;
delayT -= deltaT;
if(delayT < timeVal)
timeVal = delayT;
}
}
}
}
else
{
if(SV_SendDownloadMessages())
timeVal = 0;
}
return timeVal;
}