Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

sv_net_chan.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 #include "../game/q_shared.h"
00024 #include "../qcommon/qcommon.h"
00025 #include "server.h"
00026 
00027 /*
00028 ==============
00029 SV_Netchan_Encode
00030 
00031     // first four bytes of the data are always:
00032     long reliableAcknowledge;
00033 
00034 ==============
00035 */
00036 static void SV_Netchan_Encode( client_t *client, msg_t *msg ) {
00037     long reliableAcknowledge, i, index;
00038     byte key, *string;
00039         int srdc, sbit, soob;
00040         
00041     if ( msg->cursize < SV_ENCODE_START ) {
00042         return;
00043     }
00044 
00045         srdc = msg->readcount;
00046         sbit = msg->bit;
00047         soob = msg->oob;
00048         
00049         msg->bit = 0;
00050         msg->readcount = 0;
00051         msg->oob = 0;
00052         
00053     reliableAcknowledge = MSG_ReadLong(msg);
00054 
00055         msg->oob = soob;
00056         msg->bit = sbit;
00057         msg->readcount = srdc;
00058         
00059     string = (byte *)client->lastClientCommandString;
00060     index = 0;
00061     // xor the client challenge with the netchan sequence number
00062     key = client->challenge ^ client->netchan.outgoingSequence;
00063     for (i = SV_ENCODE_START; i < msg->cursize; i++) {
00064         // modify the key with the last received and with this message acknowledged client command
00065         if (!string[index])
00066             index = 0;
00067         if (string[index] > 127 || string[index] == '%') {
00068             key ^= '.' << (i & 1);
00069         }
00070         else {
00071             key ^= string[index] << (i & 1);
00072         }
00073         index++;
00074         // encode the data with this key
00075         *(msg->data + i) = *(msg->data + i) ^ key;
00076     }
00077 }
00078 
00079 /*
00080 ==============
00081 SV_Netchan_Decode
00082 
00083     // first 12 bytes of the data are always:
00084     long serverId;
00085     long messageAcknowledge;
00086     long reliableAcknowledge;
00087 
00088 ==============
00089 */
00090 static void SV_Netchan_Decode( client_t *client, msg_t *msg ) {
00091     int serverId, messageAcknowledge, reliableAcknowledge;
00092     int i, index, srdc, sbit, soob;
00093     byte key, *string;
00094 
00095         srdc = msg->readcount;
00096         sbit = msg->bit;
00097         soob = msg->oob;
00098         
00099         msg->oob = 0;
00100         
00101         serverId = MSG_ReadLong(msg);
00102     messageAcknowledge = MSG_ReadLong(msg);
00103     reliableAcknowledge = MSG_ReadLong(msg);
00104 
00105         msg->oob = soob;
00106         msg->bit = sbit;
00107         msg->readcount = srdc;
00108         
00109     string = (byte *)client->reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
00110     index = 0;
00111     //
00112     key = client->challenge ^ serverId ^ messageAcknowledge;
00113     for (i = msg->readcount + SV_DECODE_START; i < msg->cursize; i++) {
00114         // modify the key with the last sent and acknowledged server command
00115         if (!string[index])
00116             index = 0;
00117         if (string[index] > 127 || string[index] == '%') {
00118             key ^= '.' << (i & 1);
00119         }
00120         else {
00121             key ^= string[index] << (i & 1);
00122         }
00123         index++;
00124         // decode the data with this key
00125         *(msg->data + i) = *(msg->data + i) ^ key;
00126     }
00127 }
00128 
00129 /*
00130 =================
00131 SV_Netchan_TransmitNextFragment
00132 =================
00133 */
00134 void SV_Netchan_TransmitNextFragment( client_t *client ) {
00135     Netchan_TransmitNextFragment( &client->netchan );
00136     if (!client->netchan.unsentFragments)
00137     {
00138         // make sure the netchan queue has been properly initialized (you never know)
00139         if (!client->netchan_end_queue) {
00140             Com_Error(ERR_DROP, "netchan queue is not properly initialized in SV_Netchan_TransmitNextFragment\n");
00141         }
00142         // the last fragment was transmitted, check wether we have queued messages
00143         if (client->netchan_start_queue) {
00144             netchan_buffer_t *netbuf;
00145             Com_DPrintf("#462 Netchan_TransmitNextFragment: popping a queued message for transmit\n");
00146             netbuf = client->netchan_start_queue;
00147             SV_Netchan_Encode( client, &netbuf->msg );
00148             Netchan_Transmit( &client->netchan, netbuf->msg.cursize, netbuf->msg.data );
00149             // pop from queue
00150             client->netchan_start_queue = netbuf->next;
00151             if (!client->netchan_start_queue) {
00152                 Com_DPrintf("#462 Netchan_TransmitNextFragment: emptied queue\n");
00153                 client->netchan_end_queue = &client->netchan_start_queue;
00154             }
00155             else
00156                 Com_DPrintf("#462 Netchan_TransmitNextFragment: remaining queued message\n");
00157             Z_Free(netbuf);
00158         } 
00159     }   
00160 }
00161 
00162 
00163 /*
00164 ===============
00165 SV_Netchan_Transmit
00166 TTimo
00167 https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=462
00168 if there are some unsent fragments (which may happen if the snapshots
00169 and the gamestate are fragmenting, and collide on send for instance)
00170 then buffer them and make sure they get sent in correct order
00171 ================
00172 */
00173 
00174 void SV_Netchan_Transmit( client_t *client, msg_t *msg) {   //int length, const byte *data ) {
00175     MSG_WriteByte( msg, svc_EOF );
00176     if (client->netchan.unsentFragments) {
00177         netchan_buffer_t *netbuf;
00178         Com_DPrintf("#462 SV_Netchan_Transmit: unsent fragments, stacked\n");
00179         netbuf = (netchan_buffer_t *)Z_Malloc(sizeof(netchan_buffer_t));
00180         // store the msg, we can't store it encoded, as the encoding depends on stuff we still have to finish sending
00181         MSG_Copy(&netbuf->msg, netbuf->msgBuffer, sizeof( netbuf->msgBuffer ), msg);
00182         netbuf->next = NULL;
00183         // insert it in the queue, the message will be encoded and sent later
00184         *client->netchan_end_queue = netbuf;
00185         client->netchan_end_queue = &(*client->netchan_end_queue)->next;
00186         // emit the next fragment of the current message for now
00187         Netchan_TransmitNextFragment(&client->netchan);
00188     } else {
00189         SV_Netchan_Encode( client, msg );
00190         Netchan_Transmit( &client->netchan, msg->cursize, msg->data );
00191     }
00192 }
00193 
00194 /*
00195 =================
00196 Netchan_SV_Process
00197 =================
00198 */
00199 qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) {
00200     int ret;
00201     ret = Netchan_Process( &client->netchan, msg );
00202     if (!ret)
00203         return qfalse;
00204     SV_Netchan_Decode( client, msg );
00205     return qtrue;
00206 }
00207 

Generated on Thu Aug 25 12:37:57 2005 for Quake III Arena by  doxygen 1.3.9.1