summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
author/dev/humancontroller <devhc@example.com>2015-02-08 13:55:15 +0100
committer/dev/humancontroller <devhc@example.com>2017-03-09 13:51:18 +0100
commitb392b0d97f3ea048478059873ed6dec8afd9634b (patch)
treee3fb4a9ef70d89bfb70676fe33f9b493da7051ec /src/server
parent65bcf419d4b612b7d626447924fa0fe2079c18c2 (diff)
implement part 1 of the multi-protocol functionality: protocols
this contains support for connecting via, and serving simultaneously via, any of the three protocols: latest, GPP and 1.1 alternate-1 means protocol 70 (GPP), alternate-2 means protocol 69 (1.1) relevant cvars: - net_alternateProtocols - net_alt{1|2}port[6] - sv_alt{1|2}master{1|...|5} - sv_clAltProto{0|..|63}
Diffstat (limited to 'src/server')
-rw-r--r--src/server/server.h2
-rw-r--r--src/server/sv_ccmds.c6
-rw-r--r--src/server/sv_client.c90
-rw-r--r--src/server/sv_init.c10
-rw-r--r--src/server/sv_main.c78
-rw-r--r--src/server/sv_net_chan.c108
-rw-r--r--src/server/sv_snapshot.c24
7 files changed, 249 insertions, 69 deletions
diff --git a/src/server/server.h b/src/server/server.h
index 0d56ea11..591af854 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -259,7 +259,7 @@ extern cvar_t *sv_maxclients;
extern cvar_t *sv_privateClients;
extern cvar_t *sv_hostname;
-extern cvar_t *sv_master[MAX_MASTER_SERVERS];
+extern cvar_t *sv_masters[3][MAX_MASTER_SERVERS];
extern cvar_t *sv_reconnectlimit;
extern cvar_t *sv_showloss;
extern cvar_t *sv_padPackets;
diff --git a/src/server/sv_ccmds.c b/src/server/sv_ccmds.c
index 48b1eb65..56c73aa8 100644
--- a/src/server/sv_ccmds.c
+++ b/src/server/sv_ccmds.c
@@ -45,6 +45,7 @@ static void SV_Map_f( void ) {
qboolean killBots, cheat;
char expanded[MAX_QPATH];
char mapname[MAX_QPATH];
+ int a;
int i;
map = Cmd_Argv(1);
@@ -88,8 +89,9 @@ static void SV_Map_f( void ) {
// This forces the local master server IP address cache
// to be updated on sending the next heartbeat
- for( i = 0; i < MAX_MASTER_SERVERS; i++ )
- sv_master[ i ]->modified = qtrue;
+ for( a = 0; a < 3; ++a )
+ for( i = 0; i < MAX_MASTER_SERVERS; i++ )
+ sv_masters[ a ][ i ]->modified = qtrue;
}
/*
diff --git a/src/server/sv_client.c b/src/server/sv_client.c
index 5a60a271..91743f8e 100644
--- a/src/server/sv_client.c
+++ b/src/server/sv_client.c
@@ -60,8 +60,6 @@ void SV_GetChallenge(netadr_t from)
int clientChallenge;
challenge_t *challenge;
qboolean wasfound = qfalse;
- char *gameName;
- qboolean gameMismatch;
// Prevent using getchallenge as an amplifier
if ( SVC_RateLimitAddress( from, 10, 1000 ) ) {
@@ -77,18 +75,6 @@ void SV_GetChallenge(netadr_t from)
return;
}
- gameName = Cmd_Argv(2);
-
- gameMismatch = !*gameName || strcmp(gameName, com_gamename->string) != 0;
-
- // reject client if the gamename string sent by the client doesn't match ours
- if (gameMismatch)
- {
- NET_OutOfBandPrint(NS_SERVER, from, "print\nGame mismatch: This is a %s server\n",
- com_gamename->string);
- return;
- }
-
oldest = 0;
oldestClientTime = oldestTime = 0x7fffffff;
@@ -166,8 +152,8 @@ void SV_DirectConnect( netadr_t from ) {
Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
version = atoi( Info_ValueForKey( userinfo, "protocol" ) );
- if ( version != PROTOCOL_VERSION ) {
- NET_OutOfBandPrint(NS_SERVER, from, "print\nServer uses protocol version %i "
+ if ( version != PROTOCOL_VERSION && version != 70 && version != 69 ) {
+ NET_OutOfBandPrint(NS_SERVER, from, "print\nServer uses either protocol version %i, 70 or 69 "
"(yours is %i).\n", PROTOCOL_VERSION, version);
Com_DPrintf(" rejected connect from version %i\n", version);
return;
@@ -333,11 +319,13 @@ gotnewcl:
ent = SV_GentityNum( clientNum );
newcl->gentity = ent;
+ Cvar_Set( va( "sv_clAltProto%i", clientNum ), ( version == 69 ? "2" : version == 70 ? "1" : "0" ) );
+
// save the challenge
newcl->challenge = challenge;
// save the address
- Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge);
+ Netchan_Setup((version == 69 ? 2 : version == 70 ? 1 : 0), NS_SERVER, &newcl->netchan, from, qport, challenge);
// init the netchan queue
newcl->netchan_end_queue = &newcl->netchan_start_queue;
@@ -532,7 +520,7 @@ static void SV_SendClientGameState( client_t *client ) {
continue;
}
MSG_WriteByte( &msg, svc_baseline );
- MSG_WriteDeltaEntity( &msg, &nullstate, base, qtrue );
+ MSG_WriteDeltaEntity( client->netchan.alternateProtocol, &msg, &nullstate, base, qtrue );
}
MSG_WriteByte( &msg, svc_EOF );
@@ -1200,8 +1188,16 @@ void SV_UserinfoChanged( client_t *cl ) {
}
#ifdef USE_VOIP
- val = Info_ValueForKey(cl->userinfo, "cl_voipProtocol");
- cl->hasVoip = !Q_stricmp( val, "opus" );
+ if( cl->netchan.alternateProtocol == 0 )
+ {
+ val = Info_ValueForKey(cl->userinfo, "cl_voipProtocol");
+ cl->hasVoip = !Q_stricmp( val, "opus" );
+ }
+ else
+ {
+ val = Info_ValueForKey(cl->userinfo, "cl_voip");
+ cl->hasVoip = atoi(val);
+ }
#endif
// TTimo
@@ -1446,7 +1442,7 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) {
// also use the message acknowledge
key ^= cl->messageAcknowledge;
// also use the last acknowledged server command in the key
- key ^= MSG_HashKey(cl->reliableCommands[ cl->reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ], 32);
+ key ^= MSG_HashKey(cl->netchan.alternateProtocol, cl->reliableCommands[ cl->reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ], 32);
Com_Memset( &nullcmd, 0, sizeof(nullcmd) );
oldcmd = &nullcmd;
@@ -1539,7 +1535,8 @@ void SV_UserVoip(client_t *cl, msg_t *msg, qboolean ignoreData)
{
int sender, generation, sequence, frames, packetsize;
uint8_t recips[(MAX_CLIENTS + 7) / 8];
- int flags;
+ int recip1 = 0, recip2 = 0, recip3 = 0; // silence warning
+ int flags = 0;
byte encoded[sizeof(cl->voipPacket[0]->data)];
client_t *client = NULL;
voipServerPacket_t *packet = NULL;
@@ -1549,8 +1546,14 @@ void SV_UserVoip(client_t *cl, msg_t *msg, qboolean ignoreData)
generation = MSG_ReadByte(msg);
sequence = MSG_ReadLong(msg);
frames = MSG_ReadByte(msg);
- MSG_ReadData(msg, recips, sizeof(recips));
- flags = MSG_ReadByte(msg);
+ if (cl->netchan.alternateProtocol == 0) {
+ MSG_ReadData(msg, recips, sizeof(recips));
+ flags = MSG_ReadByte(msg);
+ } else {
+ recip1 = MSG_ReadLong(msg);
+ recip2 = MSG_ReadLong(msg);
+ recip3 = MSG_ReadLong(msg);
+ }
packetsize = MSG_ReadShort(msg);
if (msg->readcount > msg->cursize)
@@ -1593,10 +1596,21 @@ void SV_UserVoip(client_t *cl, msg_t *msg, qboolean ignoreData)
else if (*cl->downloadName) // !!! FIXME: possible to DoS?
continue; // no VoIP allowed if downloading, to save bandwidth.
- if(Com_IsVoipTarget(recips, sizeof(recips), i))
+ if (cl->netchan.alternateProtocol == 0) {
+ if(Com_IsVoipTarget(recips, sizeof(recips), i))
+ flags |= VOIP_DIRECT;
+ else
+ flags &= ~VOIP_DIRECT;
+ } else {
+ if (i < 31 && (recip1 & (1 << (i - 0))) == 0)
+ continue; // not addressed to this player.
+ else if (i >= 31 && i < 62 && (recip2 & (1 << (i - 31))) == 0)
+ continue; // not addressed to this player.
+ else if (i >= 62 && (recip3 & (1 << (i - 62))) == 0)
+ continue; // not addressed to this player.
+
flags |= VOIP_DIRECT;
- else
- flags &= ~VOIP_DIRECT;
+ }
if (!(flags & (VOIP_SPATIAL | VOIP_DIRECT)))
continue; // not addressed to this player.
@@ -1709,6 +1723,28 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
do {
c = MSG_ReadByte( msg );
+ if ( cl->netchan.alternateProtocol != 0 ) {
+ // See if this is an extension command after the EOF, which means we
+ // got data that a legacy server should ignore.
+ if ( c == clc_EOF && MSG_LookaheadByte( msg ) == clc_voipSpeex ) {
+ MSG_ReadByte( msg ); // throw the clc_extension byte away.
+ c = MSG_ReadByte( msg ); // something legacy servers can't do!
+ // sometimes you get a clc_extension at end of stream...dangling
+ // bits in the huffman decoder giving a bogus value?
+ if ( c == -1 ) {
+ c = clc_EOF;
+ }
+ }
+
+ if ( c == clc_voipOpus ) {
+ c = clc_voipSpeex;
+ } else if ( c == clc_voipOpus + 1 ) {
+ c = clc_voipOpus;
+ } else if ( c == clc_voipSpeex ) {
+ c = clc_voipOpus + 1;
+ }
+ }
+
if ( c == clc_EOF ) {
break;
}
diff --git a/src/server/sv_init.c b/src/server/sv_init.c
index 380a117e..16726b40 100644
--- a/src/server/sv_init.c
+++ b/src/server/sv_init.c
@@ -626,6 +626,7 @@ Only called at main exe startup, not for each game
*/
void SV_Init (void)
{
+ int a;
int index;
SV_AddOperatorCommands ();
@@ -668,9 +669,12 @@ void SV_Init (void)
sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO);
Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE);
- sv_master[0] = Cvar_Get("sv_master1", MASTER_SERVER_NAME, 0);
- for(index = 1; index < MAX_MASTER_SERVERS; index++)
- sv_master[index] = Cvar_Get(va("sv_master%d", index + 1), "", CVAR_ARCHIVE);
+ for (a = 0; a < 3; ++a)
+ {
+ sv_masters[a][0] = Cvar_Get(va("sv_%smaster1", (a == 2 ? "alt2" : a == 1 ? "alt1" : "")), MASTER_SERVER_NAME, 0);
+ for(index = 1; index < MAX_MASTER_SERVERS; index++)
+ sv_masters[a][index] = Cvar_Get(va("sv_%smaster%d", (a == 2 ? "alt2" : a == 1 ? "alt1" : ""), index + 1), "", CVAR_ARCHIVE);
+ }
sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0);
sv_showloss = Cvar_Get ("sv_showloss", "0", 0);
diff --git a/src/server/sv_main.c b/src/server/sv_main.c
index e5b260e5..19ec5cea 100644
--- a/src/server/sv_main.c
+++ b/src/server/sv_main.c
@@ -42,7 +42,7 @@ cvar_t *sv_maxclients;
cvar_t *sv_privateClients; // number of clients reserved for password
cvar_t *sv_hostname;
-cvar_t *sv_master[MAX_MASTER_SERVERS]; // master server ip address
+cvar_t *sv_masters[3][MAX_MASTER_SERVERS]; // master server IP addresses
cvar_t *sv_reconnectlimit; // minimum seconds between connect messages
cvar_t *sv_showloss; // report when usercmds are lost
cvar_t *sv_padPackets; // add nop bytes to messages
@@ -225,12 +225,15 @@ but not on every player enter or exit.
#define HEARTBEAT_MSEC 300*1000
void SV_MasterHeartbeat(const char *message)
{
- static netadr_t adr[MAX_MASTER_SERVERS][2]; // [2] for v4 and v6 address for the same address string.
+ static netadr_t adrs[3][MAX_MASTER_SERVERS][2]; // [2] for v4 and v6 address for the same address string.
+ int a;
int i;
int res;
int netenabled;
+ int netAlternateProtocols;
netenabled = Cvar_VariableIntegerValue("net_enabled");
+ netAlternateProtocols = Cvar_VariableIntegerValue("net_alternateProtocols");
// "dedicated 1" is for lan play, "dedicated 2" is for inet public play
if (!com_dedicated || com_dedicated->integer != 2 || !(netenabled & (NET_ENABLEV4 | NET_ENABLEV6)))
@@ -242,72 +245,86 @@ void SV_MasterHeartbeat(const char *message)
svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC;
+ for (a = 0; a < 3; ++a)
+ {
+ // indent
+ if(a == 0 && (netAlternateProtocols & NET_DISABLEPRIMPROTO))
+ continue;
+ if(a == 1 && !(netAlternateProtocols & NET_ENABLEALT1PROTO))
+ continue;
+ if(a == 2 && !(netAlternateProtocols & NET_ENABLEALT2PROTO))
+ continue;
+
// send to group masters
for (i = 0; i < MAX_MASTER_SERVERS; i++)
{
- if(!sv_master[i]->string[0])
+ if(!sv_masters[a][i]->string[0])
continue;
// see if we haven't already resolved the name
// resolving usually causes hitches on win95, so only
// do it when needed
- if(sv_master[i]->modified || (adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD))
+ if(sv_masters[a][i]->modified || (adrs[a][i][0].type == NA_BAD && adrs[a][i][1].type == NA_BAD))
{
- sv_master[i]->modified = qfalse;
+ sv_masters[a][i]->modified = qfalse;
if(netenabled & NET_ENABLEV4)
{
- Com_Printf("Resolving %s (IPv4)\n", sv_master[i]->string);
- res = NET_StringToAdr(sv_master[i]->string, &adr[i][0], NA_IP);
+ Com_Printf("Resolving %s (IPv4)\n", sv_masters[a][i]->string);
+ res = NET_StringToAdr(sv_masters[a][i]->string, &adrs[a][i][0], NA_IP);
+ adrs[a][i][0].alternateProtocol = a;
if(res == 2)
{
// if no port was specified, use the default master port
- adr[i][0].port = BigShort(PORT_MASTER);
+ adrs[a][i][0].port = BigShort(a == 2 ? ALT2PORT_MASTER : a == 1 ? ALT1PORT_MASTER : PORT_MASTER);
}
if(res)
- Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i][0]));
+ Com_Printf( "%s resolved to %s\n", sv_masters[a][i]->string, NET_AdrToStringwPort(adrs[a][i][0]));
else
- Com_Printf( "%s has no IPv4 address.\n", sv_master[i]->string);
+ Com_Printf( "%s has no IPv4 address.\n", sv_masters[a][i]->string);
}
if(netenabled & NET_ENABLEV6)
{
- Com_Printf("Resolving %s (IPv6)\n", sv_master[i]->string);
- res = NET_StringToAdr(sv_master[i]->string, &adr[i][1], NA_IP6);
+ Com_Printf("Resolving %s (IPv6)\n", sv_masters[a][i]->string);
+ res = NET_StringToAdr(sv_masters[a][i]->string, &adrs[a][i][1], NA_IP6);
+ adrs[a][i][1].alternateProtocol = a;
if(res == 2)
{
// if no port was specified, use the default master port
- adr[i][1].port = BigShort(PORT_MASTER);
+ adrs[a][i][1].port = BigShort(a == 2 ? ALT2PORT_MASTER : a == 1 ? ALT1PORT_MASTER : PORT_MASTER);
}
if(res)
- Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i][1]));
+ Com_Printf( "%s resolved to %s\n", sv_masters[a][i]->string, NET_AdrToStringwPort(adrs[a][i][1]));
else
- Com_Printf( "%s has no IPv6 address.\n", sv_master[i]->string);
+ Com_Printf( "%s has no IPv6 address.\n", sv_masters[a][i]->string);
}
- if(adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD)
+ if(adrs[a][i][0].type == NA_BAD && adrs[a][i][1].type == NA_BAD)
{
- Com_Printf("Couldn't resolve address: %s\n", sv_master[i]->string);
- Cvar_Set(sv_master[i]->name, "");
- sv_master[i]->modified = qfalse;
+ Com_Printf("Couldn't resolve address: %s\n", sv_masters[a][i]->string);
+ Cvar_Set(sv_masters[a][i]->name, "");
+ sv_masters[a][i]->modified = qfalse;
continue;
}
}
- Com_Printf ("Sending heartbeat to %s\n", sv_master[i]->string );
+ Com_Printf ("Sending%s heartbeat to %s\n", (a == 2 ? " alternate-2" : a == 1 ? " alternate-1" : ""), sv_masters[a][i]->string );
// this command should be changed if the server info / status format
// ever incompatably changes
- if(adr[i][0].type != NA_BAD)
- NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", message);
- if(adr[i][1].type != NA_BAD)
- NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", message);
+ if(adrs[a][i][0].type != NA_BAD)
+ NET_OutOfBandPrint( NS_SERVER, adrs[a][i][0], "heartbeat %s\n", message);
+ if(adrs[a][i][1].type != NA_BAD)
+ NET_OutOfBandPrint( NS_SERVER, adrs[a][i][1], "heartbeat %s\n", message);
+ }
+ // outdent
}
}
@@ -542,6 +559,9 @@ static void SVC_Status( netadr_t from ) {
// to prevent timed spoofed reply packets that add ghost servers
Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
+ if ( from.alternateProtocol != 0 )
+ Info_SetValueForKey( infostring, "protocol", from.alternateProtocol == 2 ? "69" : "70" );
+
status[0] = 0;
statusLength = 0;
@@ -612,7 +632,7 @@ void SVC_Info( netadr_t from ) {
// to prevent timed spoofed reply packets that add ghost servers
Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
- Info_SetValueForKey( infostring, "protocol", va("%i", PROTOCOL_VERSION) );
+ Info_SetValueForKey( infostring, "protocol", va("%i", from.alternateProtocol == 2 ? 69 : from.alternateProtocol == 1 ? 70 : PROTOCOL_VERSION) );
Info_SetValueForKey( infostring, "gamename", com_gamename->string );
Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
@@ -622,8 +642,12 @@ void SVC_Info( netadr_t from ) {
Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) );
#ifdef USE_VOIP
- if (sv_voipProtocol->string && *sv_voipProtocol->string) {
- Info_SetValueForKey( infostring, "voip", sv_voipProtocol->string );
+ if (from.alternateProtocol == 0) {
+ if (sv_voipProtocol->string && *sv_voipProtocol->string) {
+ Info_SetValueForKey( infostring, "voip", sv_voipProtocol->string );
+ }
+ } else {
+ Info_SetValueForKey( infostring, "voip", va("%i", sv_voip->integer) );
}
#endif
diff --git a/src/server/sv_net_chan.c b/src/server/sv_net_chan.c
index d7ac326c..7ec27cf9 100644
--- a/src/server/sv_net_chan.c
+++ b/src/server/sv_net_chan.c
@@ -26,6 +26,110 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "server.h"
/*
+==============
+SV_Netchan_Encode
+
+ // first four bytes of the data are always:
+ long reliableAcknowledge;
+
+==============
+*/
+static void SV_Netchan_Encode( client_t *client, msg_t *msg ) {
+ long i, index;
+ byte key, *string;
+ int srdc, sbit;
+ qboolean soob;
+
+ if ( msg->cursize < SV_ENCODE_START ) {
+ return;
+ }
+
+ srdc = msg->readcount;
+ sbit = msg->bit;
+ soob = msg->oob;
+
+ msg->bit = 0;
+ msg->readcount = 0;
+ msg->oob = qfalse;
+
+ /* reliableAcknowledge = */ MSG_ReadLong(msg);
+
+ msg->oob = soob;
+ msg->bit = sbit;
+ msg->readcount = srdc;
+
+ string = (byte *)client->lastClientCommandString;
+ index = 0;
+ // xor the client challenge with the netchan sequence number
+ key = client->challenge ^ client->netchan.outgoingSequence;
+ for (i = SV_ENCODE_START; i < msg->cursize; i++) {
+ // modify the key with the last received and with this message acknowledged client command
+ if (!string[index])
+ index = 0;
+ if (string[index] > 127 || (client->netchan.alternateProtocol == 2 && string[index] == '%')) {
+ key ^= '.' << (i & 1);
+ }
+ else {
+ key ^= string[index] << (i & 1);
+ }
+ index++;
+ // encode the data with this key
+ *(msg->data + i) = *(msg->data + i) ^ key;
+ }
+}
+
+/*
+==============
+SV_Netchan_Decode
+
+ // first 12 bytes of the data are always:
+ long serverId;
+ long messageAcknowledge;
+ long reliableAcknowledge;
+
+==============
+*/
+static void SV_Netchan_Decode( client_t *client, msg_t *msg ) {
+ int serverId, messageAcknowledge, reliableAcknowledge;
+ int i, index, srdc, sbit;
+ qboolean soob;
+ byte key, *string;
+
+ srdc = msg->readcount;
+ sbit = msg->bit;
+ soob = msg->oob;
+
+ msg->oob = qfalse;
+
+ serverId = MSG_ReadLong(msg);
+ messageAcknowledge = MSG_ReadLong(msg);
+ reliableAcknowledge = MSG_ReadLong(msg);
+
+ msg->oob = soob;
+ msg->bit = sbit;
+ msg->readcount = srdc;
+
+ string = (byte *)client->reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
+ index = 0;
+
+ key = client->challenge ^ serverId ^ messageAcknowledge;
+ for (i = msg->readcount + SV_DECODE_START; i < msg->cursize; i++) {
+ // modify the key with the last sent and acknowledged server command
+ if (!string[index])
+ index = 0;
+ if (string[index] > 127 || (client->netchan.alternateProtocol == 2 && string[index] == '%')) {
+ key ^= '.' << (i & 1);
+ }
+ else {
+ key ^= string[index] << (i & 1);
+ }
+ index++;
+ // decode the data with this key
+ *(msg->data + i) = *(msg->data + i) ^ key;
+ }
+}
+
+/*
=================
SV_Netchan_FreeQueue
=================
@@ -126,6 +230,8 @@ void SV_Netchan_Transmit( client_t *client, msg_t *msg)
}
else
{
+ if (client->netchan.alternateProtocol != 0)
+ SV_Netchan_Encode( client, msg );
Netchan_Transmit( &client->netchan, msg->cursize, msg->data );
}
}
@@ -140,6 +246,8 @@ qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) {
ret = Netchan_Process( &client->netchan, msg );
if (!ret)
return qfalse;
+ if (client->netchan.alternateProtocol != 0)
+ SV_Netchan_Decode( client, msg );
return qtrue;
}
diff --git a/src/server/sv_snapshot.c b/src/server/sv_snapshot.c
index e73e6138..09633eb7 100644
--- a/src/server/sv_snapshot.c
+++ b/src/server/sv_snapshot.c
@@ -53,7 +53,7 @@ SV_EmitPacketEntities
Writes a delta update of an entityState_t list to the message.
=============
*/
-static void SV_EmitPacketEntities( clientSnapshot_t *from, clientSnapshot_t *to, msg_t *msg ) {
+static void SV_EmitPacketEntities( int alternateProtocol, clientSnapshot_t *from, clientSnapshot_t *to, msg_t *msg ) {
entityState_t *oldent, *newent;
int oldindex, newindex;
int oldnum, newnum;
@@ -89,7 +89,7 @@ static void SV_EmitPacketEntities( clientSnapshot_t *from, clientSnapshot_t *to,
// delta update from old position
// because the force parm is qfalse, this will not result
// in any bytes being emited if the entity has not changed at all
- MSG_WriteDeltaEntity (msg, oldent, newent, qfalse );
+ MSG_WriteDeltaEntity (alternateProtocol, msg, oldent, newent, qfalse );
oldindex++;
newindex++;
continue;
@@ -97,14 +97,14 @@ static void SV_EmitPacketEntities( clientSnapshot_t *from, clientSnapshot_t *to,
if ( newnum < oldnum ) {
// this is a new entity, send it from the baseline
- MSG_WriteDeltaEntity (msg, &sv.svEntities[newnum].baseline, newent, qtrue );
+ MSG_WriteDeltaEntity (alternateProtocol, msg, &sv.svEntities[newnum].baseline, newent, qtrue );
newindex++;
continue;
}
if ( newnum > oldnum ) {
// the old entity isn't present in the new message
- MSG_WriteDeltaEntity (msg, oldent, NULL, qtrue );
+ MSG_WriteDeltaEntity (alternateProtocol, msg, oldent, NULL, qtrue );
oldindex++;
continue;
}
@@ -192,13 +192,13 @@ static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) {
// delta encode the playerstate
if ( oldframe ) {
- MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
+ MSG_WriteDeltaPlayerstate( client->netchan.alternateProtocol, msg, &oldframe->ps, &frame->ps );
} else {
- MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
+ MSG_WriteDeltaPlayerstate( client->netchan.alternateProtocol, msg, NULL, &frame->ps );
}
// delta encode the entities
- SV_EmitPacketEntities (oldframe, frame, msg);
+ SV_EmitPacketEntities (client->netchan.alternateProtocol, oldframe, frame, msg);
// padding for rate debugging
if ( sv_padPackets->integer ) {
@@ -551,13 +551,19 @@ static void SV_WriteVoipToClient(client_t *cl, msg_t *msg)
if (totalbytes > (msg->maxsize - msg->cursize) / 2)
break;
- MSG_WriteByte(msg, svc_voipOpus);
+ if(cl->netchan.alternateProtocol != 0)
+ {
+ MSG_WriteByte(msg, svc_EOF);
+ MSG_WriteByte(msg, svc_voipSpeex);
+ }
+ MSG_WriteByte(msg, svc_voipOpus);
MSG_WriteShort(msg, packet->sender);
MSG_WriteByte(msg, (byte) packet->generation);
MSG_WriteLong(msg, packet->sequence);
MSG_WriteByte(msg, packet->frames);
MSG_WriteShort(msg, packet->len);
- MSG_WriteBits(msg, packet->flags, VOIP_FLAGCNT);
+ if(cl->netchan.alternateProtocol == 0)
+ MSG_WriteBits(msg, packet->flags, VOIP_FLAGCNT);
MSG_WriteData(msg, packet->data, packet->len);
}