diff options
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 |
commit | b392b0d97f3ea048478059873ed6dec8afd9634b (patch) | |
tree | e3fb4a9ef70d89bfb70676fe33f9b493da7051ec /src/server | |
parent | 65bcf419d4b612b7d626447924fa0fe2079c18c2 (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.h | 2 | ||||
-rw-r--r-- | src/server/sv_ccmds.c | 6 | ||||
-rw-r--r-- | src/server/sv_client.c | 90 | ||||
-rw-r--r-- | src/server/sv_init.c | 10 | ||||
-rw-r--r-- | src/server/sv_main.c | 78 | ||||
-rw-r--r-- | src/server/sv_net_chan.c | 108 | ||||
-rw-r--r-- | src/server/sv_snapshot.c | 24 |
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); } |