Skip to content

Commit

Permalink
- Improve snapshot rate and data rate control
Browse files Browse the repository at this point in the history
- Make server send packet fragments and queued packets when server is idle
- Voip protocol detection is tied to com_protocol making past-end-of-message reading unncessary
- Use Hunk_AllocateTempMemory() for buffering VOIP packets and fix buffering scheme that ryan hates so much
- Disable packet scrambling for new protocol as it is useless now
- Get rid of the old packet scrambling functions predating latest point release
- Use Hunk_AllocateTempMemory() for netchan packet queue to fix memory leak when client gets disconnected with packets in the queue
- Use Hunk_AllocateTempMemory() for download blocks to fix memory leak when client gets disconnected with download blocks in the queue
- Fix SV_RateMsec to account for udp/udp6 packet lengths
  • Loading branch information
Thilo Schulz committed Jul 13, 2011
1 parent a844c94 commit ac30d86
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 357 deletions.
14 changes: 0 additions & 14 deletions code/client/cl_input.c
Expand Up @@ -840,8 +840,6 @@ void CL_WritePacket( void ) {
cl_voipSendTarget->modified = qfalse;
}

MSG_WriteByte (&buf, clc_EOF); // placate legacy servers.
MSG_WriteByte (&buf, clc_extension);
MSG_WriteByte (&buf, clc_voip);
MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
MSG_WriteLong (&buf, clc.voipOutgoingSequence);
Expand All @@ -863,8 +861,6 @@ void CL_WritePacket( void ) {
MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
MSG_Bitstream (&fakemsg);
MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
MSG_WriteByte (&fakemsg, svc_EOF);
MSG_WriteByte (&fakemsg, svc_extension);
MSG_WriteByte (&fakemsg, svc_voip);
MSG_WriteShort (&fakemsg, clc.clientNum);
MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
Expand Down Expand Up @@ -928,16 +924,6 @@ void CL_WritePacket( void ) {
}

CL_Netchan_Transmit (&clc.netchan, &buf);

// clients never really should have messages large enough
// to fragment, but in case they do, fire them all off
// at once
// TTimo: this causes a packet burst, which is bad karma for winsock
// added a WARNING message, we'll see if there are legit situations where this happens
while ( clc.netchan.unsentFragments ) {
Com_DPrintf( "WARNING: #462 unsent fragments (not supposed to happen!)\n" );
CL_Netchan_TransmitNextFragment( &clc.netchan );
}
}

/*
Expand Down
8 changes: 4 additions & 4 deletions code/client/cl_main.c
Expand Up @@ -235,7 +235,7 @@ void CL_Voip_f( void )
reason = "Not connected to a server";
else if (!clc.speexInitialized)
reason = "Speex not initialized";
else if (!cl_connectedToVoipServer)
else if (!clc.voipEnabled)
reason = "Server doesn't support VoIP";
else if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive"))
reason = "running in single-player mode";
Expand Down Expand Up @@ -331,7 +331,7 @@ void CL_CaptureVoip(void)
qboolean dontCapture = qfalse;
if (clc.state != CA_ACTIVE)
dontCapture = qtrue; // not connected to a server.
else if (!cl_connectedToVoipServer)
else if (!clc.voipEnabled)
dontCapture = qtrue; // server doesn't support VoIP.
else if (clc.demoplaying)
dontCapture = qtrue; // playing back a demo.
Expand Down Expand Up @@ -1375,7 +1375,7 @@ void CL_Disconnect( qboolean showMainMenu ) {

#ifdef USE_VOIP
// not connected to voip server anymore.
cl_connectedToVoipServer = qfalse;
clc.voipEnabled = qfalse;
#endif

// Stop recording any video
Expand Down Expand Up @@ -4397,7 +4397,7 @@ void CL_ShowIP_f(void) {

/*
=================
bool CL_CDKeyValidate
CL_CDKeyValidate
=================
*/
qboolean CL_CDKeyValidate( const char *key, const char *checksum ) {
Expand Down
32 changes: 27 additions & 5 deletions code/client/cl_net_chan.c
Expand Up @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/qcommon.h"
#include "client.h"

#ifdef LEGACY_PROTOCOL
/*
==============
CL_Netchan_Encode
Expand Down Expand Up @@ -125,14 +126,22 @@ static void CL_Netchan_Decode( msg_t *msg ) {
*(msg->data + i) = *(msg->data + i) ^ key;
}
}
#endif

/*
=================
CL_Netchan_TransmitNextFragment
=================
*/
void CL_Netchan_TransmitNextFragment( netchan_t *chan ) {
Netchan_TransmitNextFragment( chan );
qboolean CL_Netchan_TransmitNextFragment(netchan_t *chan)
{
if(chan->unsentFragments)
{
Netchan_TransmitNextFragment(chan);
return qtrue;
}

return qfalse;
}

/*
Expand All @@ -143,8 +152,18 @@ CL_Netchan_Transmit
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
MSG_WriteByte( msg, clc_EOF );

CL_Netchan_Encode( msg );
Netchan_Transmit( chan, msg->cursize, msg->data );
#ifdef LEGACY_PROTOCOL
if(chan->compat)
CL_Netchan_Encode(msg);
#endif

Netchan_Transmit(chan, msg->cursize, msg->data);

// Transmit all fragments without delay
while(CL_Netchan_TransmitNextFragment(chan))
{
Com_DPrintf("WARNING: #462 unsent fragments (not supposed to happen!)\n");
}
}

/*
Expand All @@ -159,7 +178,10 @@ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
if (!ret)
return qfalse;

CL_Netchan_Decode( msg );
#ifdef LEGACY_PROTOCOL
if(chan->compat)
CL_Netchan_Decode(msg);
#endif

return qtrue;
}
36 changes: 11 additions & 25 deletions code/client/cl_parse.c
Expand Up @@ -34,7 +34,6 @@ char *svc_strings[256] = {
"svc_download",
"svc_snapshot",
"svc_EOF",
"svc_extension",
"svc_voip",
};

Expand Down Expand Up @@ -330,10 +329,6 @@ void CL_ParseSnapshot( msg_t *msg ) {
int cl_connectedToPureServer;
int cl_connectedToCheatServer;

#ifdef USE_VOIP
int cl_connectedToVoipServer;
#endif

/*
==================
CL_SystemInfoChanged
Expand Down Expand Up @@ -363,14 +358,18 @@ void CL_SystemInfoChanged( void ) {
}

#ifdef USE_VOIP
// in the future, (val) will be a protocol version string, so only
// accept explicitly 1, not generally non-zero.
s = Info_ValueForKey( systemInfo, "sv_voip" );
if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive"))
cl_connectedToVoipServer = qfalse;
#ifdef LEGACY_PROTOCOL
if(clc.compat)
clc.voipEnabled = qfalse;
else
cl_connectedToVoipServer = (atoi( s ) == 1);

#endif
{
s = Info_ValueForKey( systemInfo, "sv_voip" );
if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive"))
clc.voipEnabled = qfalse;
else
clc.voipEnabled = atoi(s);
}
#endif

s = Info_ValueForKey( systemInfo, "sv_cheats" );
Expand Down Expand Up @@ -865,19 +864,6 @@ void CL_ParseServerMessage( msg_t *msg ) {

cmd = MSG_ReadByte( msg );

// See if this is an extension command after the EOF, which means we
// got data that a legacy client should ignore.
if ((cmd == svc_EOF) && (MSG_LookaheadByte( msg ) == svc_extension)) {
SHOWNET( msg, "EXTENSION" );
MSG_ReadByte( msg ); // throw the svc_extension byte away.
cmd = MSG_ReadByte( msg ); // something legacy clients can't do!
// sometimes you get a svc_extension at end of stream...dangling
// bits in the huffman decoder giving a bogus value?
if (cmd == -1) {
cmd = svc_EOF;
}
}

if (cmd == svc_EOF) {
SHOWNET( msg, "END OF MESSAGE" );
break;
Expand Down
2 changes: 1 addition & 1 deletion code/client/cl_scrn.c
Expand Up @@ -362,7 +362,7 @@ void SCR_DrawVoipMeter( void ) {
return; // not recording at the moment.
else if (clc.state != CA_ACTIVE)
return; // not connected to a server.
else if (!cl_connectedToVoipServer)
else if (!clc.voipEnabled)
return; // server doesn't support VoIP.
else if (clc.demoplaying)
return; // playing back a demo.
Expand Down
3 changes: 1 addition & 2 deletions code/client/client.h
Expand Up @@ -234,6 +234,7 @@ typedef struct {
unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations

#ifdef USE_VOIP
qboolean voipEnabled;
qboolean speexInitialized;
int speexFrameSize;
int speexSampleRate;
Expand Down Expand Up @@ -517,7 +518,6 @@ extern int cl_connectedToPureServer;
extern int cl_connectedToCheatServer;

#ifdef USE_VOIP
extern int cl_connectedToVoipServer;
void CL_Voip_f( void );
#endif

Expand Down Expand Up @@ -622,7 +622,6 @@ void LAN_SaveServersToCache( void );
// cl_net_chan.c
//
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg); //int length, const byte *data );
void CL_Netchan_TransmitNextFragment( netchan_t *chan );
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg );

//
Expand Down
21 changes: 18 additions & 3 deletions code/qcommon/common.c
Expand Up @@ -3111,7 +3111,11 @@ void Com_Frame( void ) {
{
if(com_sv_running->integer)
{
// Send out download messages now that we're idle
// Send out fragmented packets now that we're idle
delayT = SV_SendQueuedMessages();
if(delayT >= 0 && delayT < timeVal)
timeVal = delayT;

if(sv_dlRate->integer)
{
// Rate limiting. This is very imprecise for high
Expand Down Expand Up @@ -3145,21 +3149,32 @@ void Com_Frame( void ) {
// 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.
timeVal = 2;
if(timeVal > 2)
timeVal = 2;

dlNextRound = dlStart + deltaT + 1;
}
else
{
dlNextRound = dlStart + delayT;
timeVal = delayT - deltaT;
delayT -= deltaT;

if(delayT < timeVal)
timeVal = delayT;
}
}
}
}
else
{
SV_SendDownloadMessages();
timeVal = 1;
}
}

if(timeVal == 0)
timeVal = 1;

if(com_busyWait->integer)
NET_Sleep(0);
else
Expand Down
96 changes: 9 additions & 87 deletions code/qcommon/net_chan.c
Expand Up @@ -99,92 +99,6 @@ void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int
#endif
}

// TTimo: unused, commenting out to make gcc happy
#if 0
/*
==============
Netchan_ScramblePacket
A probably futile attempt to make proxy hacking somewhat
more difficult.
==============
*/
#define SCRAMBLE_START 6
static void Netchan_ScramblePacket( msg_t *buf ) {
unsigned seed;
int i, j, c, mask, temp;
int seq[MAX_PACKETLEN];

seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
c = buf->cursize;
if ( c <= SCRAMBLE_START ) {
return;
}
if ( c > MAX_PACKETLEN ) {
Com_Error( ERR_DROP, "MAX_PACKETLEN" );
}

// generate a sequence of "random" numbers
for (i = 0 ; i < c ; i++) {
seed = (119 * seed + 1);
seq[i] = seed;
}

// transpose each character
for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
}
mask >>= 1;
for (i = SCRAMBLE_START ; i < c ; i++) {
j = SCRAMBLE_START + ( seq[i] & mask );
temp = buf->data[j];
buf->data[j] = buf->data[i];
buf->data[i] = temp;
}

// byte xor the data after the header
for (i = SCRAMBLE_START ; i < c ; i++) {
buf->data[i] ^= seq[i];
}
}

static void Netchan_UnScramblePacket( msg_t *buf ) {
unsigned seed;
int i, j, c, mask, temp;
int seq[MAX_PACKETLEN];

seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
c = buf->cursize;
if ( c <= SCRAMBLE_START ) {
return;
}
if ( c > MAX_PACKETLEN ) {
Com_Error( ERR_DROP, "MAX_PACKETLEN" );
}

// generate a sequence of "random" numbers
for (i = 0 ; i < c ; i++) {
seed = (119 * seed + 1);
seq[i] = seed;
}

// byte xor the data after the header
for (i = SCRAMBLE_START ; i < c ; i++) {
buf->data[i] ^= seq[i];
}

// transpose each character in reverse order
for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
}
mask >>= 1;
for (i = c-1 ; i >= SCRAMBLE_START ; i--) {
j = SCRAMBLE_START + ( seq[i] & mask );
temp = buf->data[j];
buf->data[j] = buf->data[i];
buf->data[i] = temp;
}
}
#endif

/*
=================
Netchan_TransmitNextFragment
Expand Down Expand Up @@ -225,7 +139,11 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) {
MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength );

// send the datagram
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
NET_SendPacket(chan->sock, send.cursize, send.data, chan->remoteAddress);

// Store send time and size of this packet for rate control
chan->lastSentTime = Sys_Milliseconds();
chan->lastSentSize = send.cursize;

if ( showpackets->integer ) {
Com_Printf ("%s send %4i : s=%i fragment=%i,%i\n"
Expand Down Expand Up @@ -298,6 +216,10 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {
// send the datagram
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );

// Store send time and size of this packet for rate control
chan->lastSentTime = Sys_Milliseconds();
chan->lastSentSize = send.cursize;

if ( showpackets->integer ) {
Com_Printf( "%s send %4i : s=%i ack=%i\n"
, netsrcString[ chan->sock ]
Expand Down

0 comments on commit ac30d86

Please sign in to comment.