summaryrefslogtreecommitdiff
path: root/src/server/sv_net_chan.c
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/sv_net_chan.c
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/sv_net_chan.c')
-rw-r--r--src/server/sv_net_chan.c108
1 files changed, 108 insertions, 0 deletions
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;
}