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/sv_net_chan.c | |
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/sv_net_chan.c')
-rw-r--r-- | src/server/sv_net_chan.c | 108 |
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; } |