1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
8
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29
30 #include "../qcommon/q_shared.h"
31 #include "../qcommon/qcommon.h"
32 #include "client.h"
33
34 #ifdef LEGACY_PROTOCOL
35 /*
36 ==============
37 CL_Netchan_Encode
38
39 // first 12 bytes of the data are always:
40 long serverId;
41 long messageAcknowledge;
42 long reliableAcknowledge;
43
44 ==============
45 */
CL_Netchan_Encode(msg_t * msg)46 static void CL_Netchan_Encode( msg_t *msg ) {
47 int serverId, messageAcknowledge, reliableAcknowledge;
48 int i, index, srdc, sbit, soob;
49 byte key, *string;
50
51 if ( msg->cursize <= CL_ENCODE_START ) {
52 return;
53 }
54
55 srdc = msg->readcount;
56 sbit = msg->bit;
57 soob = msg->oob;
58
59 msg->bit = 0;
60 msg->readcount = 0;
61 msg->oob = 0;
62
63 serverId = MSG_ReadLong( msg );
64 messageAcknowledge = MSG_ReadLong( msg );
65 reliableAcknowledge = MSG_ReadLong( msg );
66
67 msg->oob = soob;
68 msg->bit = sbit;
69 msg->readcount = srdc;
70
71 string = (byte *)clc.serverCommands[ reliableAcknowledge & ( MAX_RELIABLE_COMMANDS - 1 ) ];
72 index = 0;
73 //
74 key = clc.challenge ^ serverId ^ messageAcknowledge;
75 for ( i = CL_ENCODE_START; i < msg->cursize; i++ ) {
76 // modify the key with the last received now acknowledged server command
77 if ( !string[index] ) {
78 index = 0;
79 }
80 if ( string[index] > 127 || string[index] == '%' ) {
81 key ^= '.' << ( i & 1 );
82 } else {
83 key ^= string[index] << ( i & 1 );
84 }
85 index++;
86 // encode the data with this key
87 *( msg->data + i ) = ( *( msg->data + i ) ) ^ key;
88 }
89 }
90 #endif
91
92 /*
93 ==============
94 CL_Netchan_Decode
95
96 // first four bytes of the data are always:
97 long reliableAcknowledge;
98
99 ==============
100 */
CL_Netchan_Decode(msg_t * msg)101 static void CL_Netchan_Decode( msg_t *msg ) {
102 long reliableAcknowledge, i, index;
103 byte key, *string;
104 int srdc, sbit, soob;
105
106 srdc = msg->readcount;
107 sbit = msg->bit;
108 soob = msg->oob;
109
110 msg->oob = 0;
111
112 reliableAcknowledge = MSG_ReadLong( msg );
113
114 msg->oob = soob;
115 msg->bit = sbit;
116 msg->readcount = srdc;
117
118 string = (byte *) clc.reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
119 index = 0;
120 // xor the client challenge with the netchan sequence number (need something that changes every message)
121 key = clc.challenge ^ LittleLong( *(unsigned *)msg->data );
122 for ( i = msg->readcount + CL_DECODE_START; i < msg->cursize; i++ ) {
123 // modify the key with the last sent and with this message acknowledged client command
124 if ( !string[index] ) {
125 index = 0;
126 }
127 if ( string[index] > 127 || string[index] == '%' ) {
128 key ^= '.' << ( i & 1 );
129 } else {
130 key ^= string[index] << ( i & 1 );
131 }
132 index++;
133 // decode the data with this key
134 *( msg->data + i ) = *( msg->data + i ) ^ key;
135 }
136 }
137
138 /*
139 =================
140 CL_Netchan_TransmitNextFragment
141 =================
142 */
CL_Netchan_TransmitNextFragment(netchan_t * chan)143 qboolean CL_Netchan_TransmitNextFragment(netchan_t *chan)
144 {
145 if(chan->unsentFragments)
146 {
147 Netchan_TransmitNextFragment(chan);
148 return qtrue;
149 }
150
151 return qfalse;
152 }
153
154 /*
155 ================
156 CL_Netchan_Transmit
157 ================
158 */
CL_Netchan_Transmit(netchan_t * chan,msg_t * msg)159 void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
160 MSG_WriteByte( msg, clc_EOF );
161
162 #ifdef LEGACY_PROTOCOL
163 if(chan->compat)
164 CL_Netchan_Encode(msg);
165 #endif
166
167 Netchan_Transmit(chan, msg->cursize, msg->data);
168
169 // Transmit all fragments without delay
170 while(CL_Netchan_TransmitNextFragment(chan))
171 {
172 Com_DPrintf("WARNING: #462 unsent fragments (not supposed to happen!)\n");
173 }
174 }
175
176 /*
177 =================
178 CL_Netchan_Process
179 =================
180 */
CL_Netchan_Process(netchan_t * chan,msg_t * msg)181 qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
182 int ret;
183
184 ret = Netchan_Process( chan, msg );
185 if ( !ret ) {
186 return qfalse;
187 }
188
189 #ifdef LEGACY_PROTOCOL
190 if(chan->compat)
191 CL_Netchan_Decode(msg);
192 #endif
193
194 return qtrue;
195 }
196