From 425decdf7e9284d15aa726e3ae96b9942fb0e3ea Mon Sep 17 00:00:00 2001 From: IronClawTrem Date: Sun, 16 Feb 2020 03:40:06 +0000 Subject: create tremded branch --- src/server/sv_net_chan.cpp | 259 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 src/server/sv_net_chan.cpp (limited to 'src/server/sv_net_chan.cpp') diff --git a/src/server/sv_net_chan.cpp b/src/server/sv_net_chan.cpp new file mode 100644 index 0000000..f8d9b7e --- /dev/null +++ b/src/server/sv_net_chan.cpp @@ -0,0 +1,259 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2013 Darklegion Development +Copyright (C) 2015-2019 GrangerHub + +This file is part of Tremulous. + +Tremulous is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +Tremulous is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Tremulous; if not, see + +=========================================================================== +*/ + +#include "server.h" + +#include "qcommon/q_shared.h" +#include "qcommon/msg.h" +#include "qcommon/net.h" +#include "qcommon/qcommon.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; + bool 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 = false; + + /* 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; + bool soob; + byte key, *string; + + srdc = msg->readcount; + sbit = msg->bit; + soob = msg->oob; + + msg->oob = false; + + 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 +================= +*/ +void SV_Netchan_FreeQueue(client_t *client) +{ + netchan_buffer_t *netbuf, *next; + + for(netbuf = client->netchan_start_queue; netbuf; netbuf = next) + { + next = netbuf->next; + Z_Free(netbuf); + } + + client->netchan_start_queue = NULL; + client->netchan_end_queue = &client->netchan_start_queue; +} + +/* +================= +SV_Netchan_TransmitNextInQueue +================= +*/ +void SV_Netchan_TransmitNextInQueue(client_t *client) +{ + netchan_buffer_t *netbuf; + + Com_DPrintf("#462 Netchan_TransmitNextFragment: popping a queued message for transmit\n"); + netbuf = client->netchan_start_queue; + + Netchan_Transmit(&client->netchan, netbuf->msg.cursize, netbuf->msg.data); + + // pop from queue + client->netchan_start_queue = netbuf->next; + if(!client->netchan_start_queue) + { + Com_DPrintf("#462 Netchan_TransmitNextFragment: emptied queue\n"); + client->netchan_end_queue = &client->netchan_start_queue; + } + else + Com_DPrintf("#462 Netchan_TransmitNextFragment: remaining queued message\n"); + + Z_Free(netbuf); +} + +/* +================= +SV_Netchan_TransmitNextFragment +Transmit the next fragment and the next queued packet +Return number of ms until next message can be sent based on throughput given by client rate, +-1 if no packet was sent. +================= +*/ + +int SV_Netchan_TransmitNextFragment(client_t *client) +{ + if(client->netchan.unsentFragments) + { + Netchan_TransmitNextFragment(&client->netchan); + return SV_RateMsec(client); + } + else if(client->netchan_start_queue) + { + SV_Netchan_TransmitNextInQueue(client); + return SV_RateMsec(client); + } + + return -1; +} + + +/* +=============== +SV_Netchan_Transmit +TTimo +https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=462 +if there are some unsent fragments (which may happen if the snapshots +and the gamestate are fragmenting, and collide on send for instance) +then buffer them and make sure they get sent in correct order +================ +*/ + +void SV_Netchan_Transmit( client_t *client, msg_t *msg) +{ + MSG_WriteByte( msg, svc_EOF ); + + if(client->netchan.unsentFragments || client->netchan_start_queue) + { + netchan_buffer_t *netbuf; + Com_DPrintf("#462 SV_Netchan_Transmit: unsent fragments, stacked\n"); + netbuf = (netchan_buffer_t *) Z_Malloc(sizeof(netchan_buffer_t)); + // store the msg, we can't store it encoded, as the encoding depends on stuff we still have to finish sending + MSG_Copy(&netbuf->msg, netbuf->msgBuffer, sizeof( netbuf->msgBuffer ), msg); + netbuf->next = NULL; + // insert it in the queue, the message will be encoded and sent later + *client->netchan_end_queue = netbuf; + client->netchan_end_queue = &(*client->netchan_end_queue)->next; + } + else + { + if (client->netchan.alternateProtocol != 0) + SV_Netchan_Encode( client, msg ); + Netchan_Transmit( &client->netchan, msg->cursize, msg->data ); + } +} + +/* +================= +Netchan_SV_Process +================= +*/ +bool SV_Netchan_Process( client_t *client, msg_t *msg ) +{ + bool ret = Netchan_Process( &client->netchan, msg ); + if (!ret) return false; + + if (client->netchan.alternateProtocol != 0) + SV_Netchan_Decode( client, msg ); + + return true; +} -- cgit