1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 // cl_parse.c  -- parse a message received from the server
23 
24 #include "client.h"
25 
26 char *svc_strings[256] = {
27 	"svc_bad",
28 
29 	"svc_nop",
30 	"svc_gamestate",
31 	"svc_configstring",
32 	"svc_baseline",
33 	"svc_serverCommand",
34 	"svc_download",
35 	"svc_snapshot",
36 	"svc_EOF",
37 	"svc_extension",
38 	"svc_voip",
39 };
40 
SHOWNET(msg_t * msg,char * s)41 void SHOWNET( msg_t *msg, char *s) {
42 	if ( cl_shownet->integer >= 2) {
43 		Com_Printf ("%3i:%s\n", msg->readcount-1, s);
44 	}
45 }
46 
47 
48 /*
49 =========================================================================
50 
51 MESSAGE PARSING
52 
53 =========================================================================
54 */
55 
56 /*
57 ==================
58 CL_DeltaEntity
59 
60 Parses deltas from the given base and adds the resulting entity
61 to the current frame
62 ==================
63 */
CL_DeltaEntity(msg_t * msg,clSnapshot_t * frame,int newnum,entityState_t * old,qboolean unchanged)64 void CL_DeltaEntity (msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t *old,
65 					 qboolean unchanged) {
66 	entityState_t	*state;
67 
68 	// save the parsed entity state into the big circular buffer so
69 	// it can be used as the source for a later delta
70 	state = &cl.parseEntities[cl.parseEntitiesNum & (MAX_PARSE_ENTITIES-1)];
71 
72 	if ( unchanged ) {
73 		*state = *old;
74 	} else {
75 		MSG_ReadDeltaEntity( msg, old, state, newnum );
76 	}
77 
78 	if ( state->number == (MAX_GENTITIES-1) ) {
79 		return;		// entity was delta removed
80 	}
81 	cl.parseEntitiesNum++;
82 	frame->numEntities++;
83 }
84 
85 /*
86 ==================
87 CL_ParsePacketEntities
88 
89 ==================
90 */
CL_ParsePacketEntities(msg_t * msg,clSnapshot_t * oldframe,clSnapshot_t * newframe)91 void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *newframe) {
92 	int			newnum;
93 	entityState_t	*oldstate;
94 	int			oldindex, oldnum;
95 
96 	newframe->parseEntitiesNum = cl.parseEntitiesNum;
97 	newframe->numEntities = 0;
98 
99 	// delta from the entities present in oldframe
100 	oldindex = 0;
101 	oldstate = NULL;
102 	if (!oldframe) {
103 		oldnum = 99999;
104 	} else {
105 		if ( oldindex >= oldframe->numEntities ) {
106 			oldnum = 99999;
107 		} else {
108 			oldstate = &cl.parseEntities[
109 				(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
110 			oldnum = oldstate->number;
111 		}
112 	}
113 
114 	while ( 1 ) {
115 		// read the entity index number
116 		newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
117 
118 		if ( newnum == (MAX_GENTITIES-1) ) {
119 			break;
120 		}
121 
122 		if ( msg->readcount > msg->cursize ) {
123 			Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
124 		}
125 
126 		while ( oldnum < newnum ) {
127 			// one or more entities from the old packet are unchanged
128 			if ( cl_shownet->integer == 3 ) {
129 				Com_Printf ("%3i:  unchanged: %i\n", msg->readcount, oldnum);
130 			}
131 			CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
132 
133 			oldindex++;
134 
135 			if ( oldindex >= oldframe->numEntities ) {
136 				oldnum = 99999;
137 			} else {
138 				oldstate = &cl.parseEntities[
139 					(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
140 				oldnum = oldstate->number;
141 			}
142 		}
143 		if (oldnum == newnum) {
144 			// delta from previous state
145 			if ( cl_shownet->integer == 3 ) {
146 				Com_Printf ("%3i:  delta: %i\n", msg->readcount, newnum);
147 			}
148 			CL_DeltaEntity( msg, newframe, newnum, oldstate, qfalse );
149 
150 			oldindex++;
151 
152 			if ( oldindex >= oldframe->numEntities ) {
153 				oldnum = 99999;
154 			} else {
155 				oldstate = &cl.parseEntities[
156 					(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
157 				oldnum = oldstate->number;
158 			}
159 			continue;
160 		}
161 
162 		if ( oldnum > newnum ) {
163 			// delta from baseline
164 			if ( cl_shownet->integer == 3 ) {
165 				Com_Printf ("%3i:  baseline: %i\n", msg->readcount, newnum);
166 			}
167 			CL_DeltaEntity( msg, newframe, newnum, &cl.entityBaselines[newnum], qfalse );
168 			continue;
169 		}
170 
171 	}
172 
173 	// any remaining entities in the old frame are copied over
174 	while ( oldnum != 99999 ) {
175 		// one or more entities from the old packet are unchanged
176 		if ( cl_shownet->integer == 3 ) {
177 			Com_Printf ("%3i:  unchanged: %i\n", msg->readcount, oldnum);
178 		}
179 		CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
180 
181 		oldindex++;
182 
183 		if ( oldindex >= oldframe->numEntities ) {
184 			oldnum = 99999;
185 		} else {
186 			oldstate = &cl.parseEntities[
187 				(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
188 			oldnum = oldstate->number;
189 		}
190 	}
191 }
192 
193 
194 /*
195 ================
196 CL_ParseSnapshot
197 
198 If the snapshot is parsed properly, it will be copied to
199 cl.snap and saved in cl.snapshots[].  If the snapshot is invalid
200 for any reason, no changes to the state will be made at all.
201 ================
202 */
CL_ParseSnapshot(msg_t * msg)203 void CL_ParseSnapshot( msg_t *msg ) {
204 	int			len;
205 	clSnapshot_t	*old;
206 	clSnapshot_t	newSnap;
207 	int			deltaNum;
208 	int			oldMessageNum;
209 	int			i, packetNum;
210 
211 	// get the reliable sequence acknowledge number
212 	// NOTE: now sent with all server to client messages
213 	//clc.reliableAcknowledge = MSG_ReadLong( msg );
214 
215 	// read in the new snapshot to a temporary buffer
216 	// we will only copy to cl.snap if it is valid
217 	Com_Memset (&newSnap, 0, sizeof(newSnap));
218 
219 	// we will have read any new server commands in this
220 	// message before we got to svc_snapshot
221 	newSnap.serverCommandNum = clc.serverCommandSequence;
222 
223 	newSnap.serverTime = MSG_ReadLong( msg );
224 
225 	// if we were just unpaused, we can only *now* really let the
226 	// change come into effect or the client hangs.
227 	cl_paused->modified = 0;
228 
229 	newSnap.messageNum = clc.serverMessageSequence;
230 
231 	deltaNum = MSG_ReadByte( msg );
232 	if ( !deltaNum ) {
233 		newSnap.deltaNum = -1;
234 	} else {
235 		newSnap.deltaNum = newSnap.messageNum - deltaNum;
236 	}
237 	newSnap.snapFlags = MSG_ReadByte( msg );
238 
239 	// If the frame is delta compressed from data that we
240 	// no longer have available, we must suck up the rest of
241 	// the frame, but not use it, then ask for a non-compressed
242 	// message
243 	if ( newSnap.deltaNum <= 0 ) {
244 		newSnap.valid = qtrue;		// uncompressed frame
245 		old = NULL;
246 		clc.demowaiting = qfalse;	// we can start recording now
247 	} else {
248 		old = &cl.snapshots[newSnap.deltaNum & PACKET_MASK];
249 		if ( !old->valid ) {
250 			// should never happen
251 			Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
252 		} else if ( old->messageNum != newSnap.deltaNum ) {
253 			// The frame that the server did the delta from
254 			// is too old, so we can't reconstruct it properly.
255 			Com_Printf ("Delta frame too old.\n");
256 		} else if ( cl.parseEntitiesNum - old->parseEntitiesNum > MAX_PARSE_ENTITIES-128 ) {
257 			Com_Printf ("Delta parseEntitiesNum too old.\n");
258 		} else {
259 			newSnap.valid = qtrue;	// valid delta parse
260 		}
261 	}
262 
263 	// read areamask
264 	len = MSG_ReadByte( msg );
265 
266 	if(len > sizeof(newSnap.areamask))
267 	{
268 		Com_Error (ERR_DROP,"CL_ParseSnapshot: Invalid size %d for areamask.", len);
269 		return;
270 	}
271 
272 	MSG_ReadData( msg, &newSnap.areamask, len);
273 
274 	// read playerinfo
275 	SHOWNET( msg, "playerstate" );
276 	if ( old ) {
277 		MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps );
278 	} else {
279 		MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps );
280 	}
281 
282 	// read packet entities
283 	SHOWNET( msg, "packet entities" );
284 	CL_ParsePacketEntities( msg, old, &newSnap );
285 
286 	// if not valid, dump the entire thing now that it has
287 	// been properly read
288 	if ( !newSnap.valid ) {
289 		return;
290 	}
291 
292 	// clear the valid flags of any snapshots between the last
293 	// received and this one, so if there was a dropped packet
294 	// it won't look like something valid to delta from next
295 	// time we wrap around in the buffer
296 	oldMessageNum = cl.snap.messageNum + 1;
297 
298 	if ( newSnap.messageNum - oldMessageNum >= PACKET_BACKUP ) {
299 		oldMessageNum = newSnap.messageNum - ( PACKET_BACKUP - 1 );
300 	}
301 	for ( ; oldMessageNum < newSnap.messageNum ; oldMessageNum++ ) {
302 		cl.snapshots[oldMessageNum & PACKET_MASK].valid = qfalse;
303 	}
304 
305 	// copy to the current good spot
306 	cl.snap = newSnap;
307 	cl.snap.ping = 999;
308 	// calculate ping time
309 	for ( i = 0 ; i < PACKET_BACKUP ; i++ ) {
310 		packetNum = ( clc.netchan.outgoingSequence - 1 - i ) & PACKET_MASK;
311 		if ( cl.snap.ps.commandTime >= cl.outPackets[ packetNum ].p_serverTime ) {
312 			cl.snap.ping = cls.realtime - cl.outPackets[ packetNum ].p_realtime;
313 			break;
314 		}
315 	}
316 	// save the frame off in the backup array for later delta comparisons
317 	cl.snapshots[cl.snap.messageNum & PACKET_MASK] = cl.snap;
318 
319 	if (cl_shownet->integer == 3) {
320 		Com_Printf( "   snapshot:%i  delta:%i  ping:%i\n", cl.snap.messageNum,
321 		cl.snap.deltaNum, cl.snap.ping );
322 	}
323 
324 	cl.newSnapshots = qtrue;
325 }
326 
327 
328 //=====================================================================
329 
330 int cl_connectedToPureServer;
331 int cl_connectedToCheatServer;
332 
333 #ifdef USE_VOIP
334 int cl_connectedToVoipServer;
335 #endif
336 
337 /*
338 ==================
339 CL_SystemInfoChanged
340 
341 The systeminfo configstring has been changed, so parse
342 new information out of it.  This will happen at every
343 gamestate, and possibly during gameplay.
344 ==================
345 */
CL_SystemInfoChanged(void)346 void CL_SystemInfoChanged( void ) {
347 	char			*systemInfo;
348 	const char		*s, *t;
349 	char			key[BIG_INFO_KEY];
350 	char			value[BIG_INFO_VALUE];
351 	qboolean		gameSet;
352 
353 	systemInfo = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SYSTEMINFO ];
354 	// NOTE TTimo:
355 	// when the serverId changes, any further messages we send to the server will use this new serverId
356 	// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475
357 	// in some cases, outdated cp commands might get sent with this news serverId
358 	cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) );
359 
360 	// don't set any vars when playing a demo
361 	if ( clc.demoplaying ) {
362 		return;
363 	}
364 
365 #ifdef USE_VOIP
366 	// in the future, (val) will be a protocol version string, so only
367 	//  accept explicitly 1, not generally non-zero.
368 	s = Info_ValueForKey( systemInfo, "sv_voip" );
369 	if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive"))
370 		cl_connectedToVoipServer = qfalse;
371 	else
372 		cl_connectedToVoipServer = (atoi( s ) == 1);
373 
374 #endif
375 
376 	s = Info_ValueForKey( systemInfo, "sv_cheats" );
377 	cl_connectedToCheatServer = atoi( s );
378 	if ( !cl_connectedToCheatServer ) {
379 		Cvar_SetCheatState();
380 	}
381 
382 	// check pure server string
383 	s = Info_ValueForKey( systemInfo, "sv_paks" );
384 	t = Info_ValueForKey( systemInfo, "sv_pakNames" );
385 	FS_PureServerSetLoadedPaks( s, t );
386 
387 	s = Info_ValueForKey( systemInfo, "sv_referencedPaks" );
388 	t = Info_ValueForKey( systemInfo, "sv_referencedPakNames" );
389 	FS_PureServerSetReferencedPaks( s, t );
390 
391 	gameSet = qfalse;
392 	// scan through all the variables in the systeminfo and locally set cvars to match
393 	s = systemInfo;
394 	while ( s ) {
395 		int cvar_flags;
396 
397 		Info_NextPair( &s, key, value );
398 		if ( !key[0] ) {
399 			break;
400 		}
401 
402 		// ehw!
403 		if (!Q_stricmp(key, "fs_game"))
404 		{
405 			if(FS_CheckDirTraversal(value))
406 			{
407 				Com_Printf(S_COLOR_YELLOW "WARNING: Server sent invalid fs_game value %s\n", value);
408 				continue;
409 			}
410 
411 			gameSet = qtrue;
412 		}
413 
414 		if((cvar_flags = Cvar_Flags(key)) == CVAR_NONEXISTENT)
415 			Cvar_Get(key, value, CVAR_SERVER_CREATED | CVAR_ROM);
416 		else
417 		{
418 			// If this cvar may not be modified by a server discard the value.
419 			// I have added exceptions for sv_fps, pmove_fixed and pmove_msec. These should relly be corrected in the game logic code, but they are required\
420 				for a lot of mods and not all can be changed. vq3 uses pmove_fixed, pmove_msec and g_synchronousClients. Most unlagged mods uses sv_fps too.
421 			if(!(cvar_flags & (CVAR_SYSTEMINFO | CVAR_SERVER_CREATED)) && Q_stricmp(key, "sv_fps") && Q_stricmp(key, "pmove_fixed") &&\
422 				 Q_stricmp(key, "pmove_msec") && Q_stricmp(key, "g_synchronousClients"))
423 			{
424 				Com_Printf(S_COLOR_YELLOW "WARNING: server is not allowed to set %s=%s\n", key, value);
425 				continue;
426 			}
427 
428 			Cvar_Set(key, value);
429 		}
430 	}
431 	// if game folder should not be set and it is set at the client side
432 	if ( !gameSet && *Cvar_VariableString("fs_game") ) {
433 		Cvar_Set( "fs_game", "" );
434 	}
435 	cl_connectedToPureServer = Cvar_VariableValue( "sv_pure" );
436 }
437 
438 /*
439 ==================
440 CL_ParseServerInfo
441 ==================
442 */
CL_ParseServerInfo(void)443 static void CL_ParseServerInfo(void)
444 {
445 	const char *serverInfo;
446 
447 	serverInfo = cl.gameState.stringData
448 		+ cl.gameState.stringOffsets[ CS_SERVERINFO ];
449 
450 	clc.sv_allowDownload = atoi(Info_ValueForKey(serverInfo,
451 		"sv_allowDownload"));
452 	Q_strncpyz(clc.sv_dlURL,
453 		Info_ValueForKey(serverInfo, "sv_dlURL"),
454 		sizeof(clc.sv_dlURL));
455 }
456 
457 /*
458 ==================
459 CL_ParseGamestate
460 ==================
461 */
CL_ParseGamestate(msg_t * msg)462 void CL_ParseGamestate( msg_t *msg ) {
463 	int				i;
464 	entityState_t	*es;
465 	int				newnum;
466 	entityState_t	nullstate;
467 	int				cmd;
468 	char			*s;
469 
470 	Con_Close();
471 
472 	clc.connectPacketCount = 0;
473 
474 	// wipe local client state
475 	CL_ClearState();
476 
477 	// a gamestate always marks a server command sequence
478 	clc.serverCommandSequence = MSG_ReadLong( msg );
479 
480 	// parse all the configstrings and baselines
481 	cl.gameState.dataCount = 1;	// leave a 0 at the beginning for uninitialized configstrings
482 	while ( 1 ) {
483 		cmd = MSG_ReadByte( msg );
484 
485 		if ( cmd == svc_EOF ) {
486 			break;
487 		}
488 
489 		if ( cmd == svc_configstring ) {
490 			int		len;
491 
492 			i = MSG_ReadShort( msg );
493 			if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
494 				Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
495 			}
496 			s = MSG_ReadBigString( msg );
497 			len = strlen( s );
498 
499 			if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
500 				Com_Error( ERR_DROP, "MAX_GAMESTATE_CHARS exceeded" );
501 			}
502 
503 			// append it to the gameState string buffer
504 			cl.gameState.stringOffsets[ i ] = cl.gameState.dataCount;
505 			Com_Memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
506 			cl.gameState.dataCount += len + 1;
507 		} else if ( cmd == svc_baseline ) {
508 			newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
509 			if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
510 				Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
511 			}
512 			Com_Memset (&nullstate, 0, sizeof(nullstate));
513 			es = &cl.entityBaselines[ newnum ];
514 			MSG_ReadDeltaEntity( msg, &nullstate, es, newnum );
515 		} else {
516 			Com_Error( ERR_DROP, "CL_ParseGamestate: bad command byte" );
517 		}
518 	}
519 
520 	clc.clientNum = MSG_ReadLong(msg);
521 	// read the checksum feed
522 	clc.checksumFeed = MSG_ReadLong( msg );
523 
524 	// parse useful values out of CS_SERVERINFO
525 	CL_ParseServerInfo();
526 
527 	// parse serverId and other cvars
528 	CL_SystemInfoChanged();
529 
530 	// stop recording now so the demo won't have an unnecessary level load at the end.
531 	if(cl_autoRecordDemo->integer && clc.demorecording)
532 		CL_StopRecord_f();
533 
534 	// reinitialize the filesystem if the game directory has changed
535 	FS_ConditionalRestart( clc.checksumFeed );
536 
537 	if (dangerousPaksFound) {
538 		char PakList[MAX_STRING_CHARS];
539 		for (i = 0; i < dangerousPaksFound; i++) {
540 			Q_strcat(PakList, sizeof(PakList), va("%s.pk3, ", dangerousPakNames[i]));
541 		}
542 
543 		PakList[strlen(PakList) - 2] = 0;
544 
545 		Cvar_Set("com_errorMessage", va(
546 			"^1WARNING! ^7Dangerous file(s) found in downloaded pk3%s:\n\n%s\n\n"
547 			"You should go delete %s immediately. %s could lead to malicious code execution.",
548 			dangerousPaksFound == 1 ? "" : "s",
549 			PakList,
550 			dangerousPaksFound == 1 ? "that file" : "those files",
551 			dangerousPaksFound == 1 ? "It" : "They"));
552 
553 		VM_Call(uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN);
554 		return;
555 	}
556 
557 	// This used to call CL_StartHunkUsers, but now we enter the download state before loading the
558 	// cgame
559 	CL_InitDownloads();
560 
561 	// make sure the game starts
562 	Cvar_Set( "cl_paused", "0" );
563 }
564 
565 
566 //=====================================================================
567 
568 /*
569 =====================
570 CL_ParseDownload
571 
572 A download message has been received from the server
573 =====================
574 */
CL_ParseDownload(msg_t * msg)575 void CL_ParseDownload ( msg_t *msg ) {
576 	int		size;
577 	unsigned char data[MAX_MSGLEN];
578 	int block;
579 
580 	if (!*clc.downloadTempName) {
581 		Com_Printf("Server sending download, but no download was requested\n");
582 		CL_AddReliableCommand("stopdl", qfalse);
583 		return;
584 	}
585 
586 	// read the data
587 	block = MSG_ReadShort ( msg );
588 
589 	if ( !block )
590 	{
591 		// block zero is special, contains file size
592 		clc.downloadSize = MSG_ReadLong ( msg );
593 
594 		Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
595 
596 		if (clc.downloadSize < 0)
597 		{
598 			Com_Error( ERR_DROP, "%s", MSG_ReadString( msg ) );
599 			return;
600 		}
601 	}
602 
603 	size = MSG_ReadShort ( msg );
604 	if (size < 0 || size > sizeof(data))
605 	{
606 		Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk.", size);
607 		return;
608 	}
609 
610 	MSG_ReadData(msg, data, size);
611 
612 	if (clc.downloadBlock != block) {
613 		Com_DPrintf( "CL_ParseDownload: Expected block %d, got %d\n", clc.downloadBlock, block);
614 		return;
615 	}
616 
617 	// open the file if not opened yet
618 	if (!clc.download)
619 	{
620 		clc.download = FS_SV_FOpenFileWrite( clc.downloadTempName );
621 
622 		if (!clc.download) {
623 			Com_Printf( "Could not create %s\n", clc.downloadTempName );
624 			CL_AddReliableCommand("stopdl", qfalse);
625 			CL_NextDownload();
626 			return;
627 		}
628 	}
629 
630 	if (size)
631 		FS_Write( data, size, clc.download );
632 
633 	CL_AddReliableCommand(va("nextdl %d", clc.downloadBlock), qfalse);
634 	clc.downloadBlock++;
635 
636 	clc.downloadCount += size;
637 
638 	// So UI gets access to it
639 	Cvar_SetValue( "cl_downloadCount", clc.downloadCount );
640 
641 	if (!size) { // A zero length block means EOF
642 		if (clc.download) {
643 			FS_FCloseFile( clc.download );
644 			clc.download = 0;
645 
646 			// rename the file
647 			FS_SV_Rename ( clc.downloadTempName, clc.downloadName, qfalse );
648 		}
649 
650 		// send intentions now
651 		// We need this because without it, we would hold the last nextdl and then start
652 		// loading right away.  If we take a while to load, the server is happily trying
653 		// to send us that last block over and over.
654 		// Write it twice to help make sure we acknowledge the download
655 		CL_WritePacket();
656 		CL_WritePacket();
657 
658 		// get another file if needed
659 		CL_NextDownload ();
660 	}
661 }
662 
663 #ifdef USE_VOIP
664 static
CL_ShouldIgnoreVoipSender(int sender)665 qboolean CL_ShouldIgnoreVoipSender(int sender)
666 {
667 	if (!cl_voip->integer)
668 		return qtrue;  // VoIP is disabled.
669 	else if ((sender == clc.clientNum) && (!clc.demoplaying))
670 		return qtrue;  // ignore own voice (unless playing back a demo).
671 	else if (clc.voipMuteAll)
672 		return qtrue;  // all channels are muted with extreme prejudice.
673 	else if (clc.voipIgnore[sender])
674 		return qtrue;  // just ignoring this guy.
675 	else if (clc.voipGain[sender] == 0.0f)
676 		return qtrue;  // too quiet to play.
677 
678 	return qfalse;
679 }
680 
681 /*
682 =====================
683 CL_ParseVoip
684 
685 A VoIP message has been received from the server
686 =====================
687 */
688 static
CL_ParseVoip(msg_t * msg)689 void CL_ParseVoip ( msg_t *msg ) {
690 	static short decoded[4096];  // !!! FIXME: don't hardcode.
691 
692 	const int sender = MSG_ReadShort(msg);
693 	const int generation = MSG_ReadByte(msg);
694 	const int sequence = MSG_ReadLong(msg);
695 	const int frames = MSG_ReadByte(msg);
696 	const int packetsize = MSG_ReadShort(msg);
697 	char encoded[1024];
698 	int seqdiff = sequence - clc.voipIncomingSequence[sender];
699 	int written = 0;
700 	int i;
701 
702 	Com_DPrintf("VoIP: %d-byte packet from client %d\n", packetsize, sender);
703 
704 	if (sender < 0)
705 		return;   // short/invalid packet, bail.
706 	else if (generation < 0)
707 		return;   // short/invalid packet, bail.
708 	else if (sequence < 0)
709 		return;   // short/invalid packet, bail.
710 	else if (frames < 0)
711 		return;   // short/invalid packet, bail.
712 	else if (packetsize < 0)
713 		return;   // short/invalid packet, bail.
714 
715 	if (packetsize > sizeof (encoded)) {  // overlarge packet?
716 		int bytesleft = packetsize;
717 		while (bytesleft) {
718 			int br = bytesleft;
719 			if (br > sizeof (encoded))
720 				br = sizeof (encoded);
721 			MSG_ReadData(msg, encoded, br);
722 			bytesleft -= br;
723 		}
724 		return;   // overlarge packet, bail.
725 	}
726 
727 	if (!clc.speexInitialized) {
728 		MSG_ReadData(msg, encoded, packetsize);  // skip payload.
729 		return;   // can't handle VoIP without libspeex!
730 	} else if (sender >= MAX_CLIENTS) {
731 		MSG_ReadData(msg, encoded, packetsize);  // skip payload.
732 		return;   // bogus sender.
733 	} else if (CL_ShouldIgnoreVoipSender(sender)) {
734 		MSG_ReadData(msg, encoded, packetsize);  // skip payload.
735 		return;   // Channel is muted, bail.
736 	}
737 
738 	// !!! FIXME: make sure data is narrowband? Does decoder handle this?
739 
740 	Com_DPrintf("VoIP: packet accepted!\n");
741 
742 	// This is a new "generation" ... a new recording started, reset the bits.
743 	if (generation != clc.voipIncomingGeneration[sender]) {
744 		Com_DPrintf("VoIP: new generation %d!\n", generation);
745 		speex_bits_reset(&clc.speexDecoderBits[sender]);
746 		clc.voipIncomingGeneration[sender] = generation;
747 		seqdiff = 0;
748 	} else if (seqdiff < 0) {   // we're ahead of the sequence?!
749 		// This shouldn't happen unless the packet is corrupted or something.
750 		Com_DPrintf("VoIP: misordered sequence! %d < %d!\n",
751 		            sequence, clc.voipIncomingSequence[sender]);
752 		// reset the bits just in case.
753 		speex_bits_reset(&clc.speexDecoderBits[sender]);
754 		seqdiff = 0;
755 	} else if (seqdiff > 100) { // more than 2 seconds of audio dropped?
756 		// just start over.
757 		Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n",
758 		            seqdiff, sender);
759 		speex_bits_reset(&clc.speexDecoderBits[sender]);
760 		seqdiff = 0;
761 	}
762 
763 	if (seqdiff != 0) {
764 		Com_DPrintf("VoIP: Dropped %d frames from client #%d\n",
765 		            seqdiff, sender);
766 		// tell speex that we're missing frames...
767 		for (i = 0; i < seqdiff; i++) {
768 			assert((written + clc.speexFrameSize) * 2 < sizeof (decoded));
769 			speex_decode_int(clc.speexDecoder[sender], NULL, decoded + written);
770 			written += clc.speexFrameSize;
771 		}
772 	}
773 
774 	for (i = 0; i < frames; i++) {
775 		char encoded[256];
776 		const int len = MSG_ReadByte(msg);
777 		if (len < 0) {
778 			Com_DPrintf("VoIP: Short packet!\n");
779 			break;
780 		}
781 		MSG_ReadData(msg, encoded, len);
782 
783 		// shouldn't happen, but just in case...
784 		if ((written + clc.speexFrameSize) * 2 > sizeof (decoded)) {
785 			Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
786 			            written * 2, written, i);
787 			S_RawSamples(sender + 1, written, clc.speexSampleRate, 2, 1,
788 			             (const byte *) decoded, clc.voipGain[sender]);
789 			written = 0;
790 		}
791 
792 		speex_bits_read_from(&clc.speexDecoderBits[sender], encoded, len);
793 		speex_decode_int(clc.speexDecoder[sender],
794 		                 &clc.speexDecoderBits[sender], decoded + written);
795 
796 		#if 0
797 		static FILE *encio = NULL;
798 		if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb");
799 		if (encio != NULL) { fwrite(encoded, len, 1, encio); fflush(encio); }
800 		static FILE *decio = NULL;
801 		if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb");
802 		if (decio != NULL) { fwrite(decoded+written, clc.speexFrameSize*2, 1, decio); fflush(decio); }
803 		#endif
804 
805 		written += clc.speexFrameSize;
806 	}
807 
808 	Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
809 	            written * 2, written, i);
810 
811 	if (written > 0) {
812 		S_RawSamples(sender + 1, written, clc.speexSampleRate, 2, 1,
813 		             (const byte *) decoded, clc.voipGain[sender]);
814 	}
815 
816 	clc.voipIncomingSequence[sender] = sequence + frames;
817 }
818 #endif
819 
820 
821 /*
822 =====================
823 CL_ParseCommandString
824 
825 Command strings are just saved off until cgame asks for them
826 when it transitions a snapshot
827 =====================
828 */
CL_ParseCommandString(msg_t * msg)829 void CL_ParseCommandString( msg_t *msg ) {
830 	char	*s;
831 	int		seq;
832 	int		index;
833 
834 	seq = MSG_ReadLong( msg );
835 	s = MSG_ReadString( msg );
836 
837 	// see if we have already executed stored it off
838 	if ( clc.serverCommandSequence >= seq ) {
839 		return;
840 	}
841 	clc.serverCommandSequence = seq;
842 
843 	index = seq & (MAX_RELIABLE_COMMANDS-1);
844 	Q_strncpyz( clc.serverCommands[ index ], s, sizeof( clc.serverCommands[ index ] ) );
845 }
846 
847 
848 /*
849 =====================
850 CL_ParseServerMessage
851 =====================
852 */
CL_ParseServerMessage(msg_t * msg)853 void CL_ParseServerMessage( msg_t *msg ) {
854 	int			cmd;
855 
856 	if ( cl_shownet->integer == 1 ) {
857 		Com_Printf ("%i ",msg->cursize);
858 	} else if ( cl_shownet->integer >= 2 ) {
859 		Com_Printf ("------------------\n");
860 	}
861 
862 	MSG_Bitstream(msg);
863 
864 	// get the reliable sequence acknowledge number
865 	clc.reliableAcknowledge = MSG_ReadLong( msg );
866 	//
867 	if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
868 		clc.reliableAcknowledge = clc.reliableSequence;
869 	}
870 
871 	//
872 	// parse the message
873 	//
874 	while ( 1 ) {
875 		if ( msg->readcount > msg->cursize ) {
876 			Com_Error (ERR_DROP,"CL_ParseServerMessage: read past end of server message");
877 			break;
878 		}
879 
880 		cmd = MSG_ReadByte( msg );
881 
882 		// See if this is an extension command after the EOF, which means we
883 		//  got data that a legacy client should ignore.
884 		if ((cmd == svc_EOF) && (MSG_LookaheadByte( msg ) == svc_extension)) {
885 			SHOWNET( msg, "EXTENSION" );
886 			MSG_ReadByte( msg );  // throw the svc_extension byte away.
887 			cmd = MSG_ReadByte( msg );  // something legacy clients can't do!
888 			// sometimes you get a svc_extension at end of stream...dangling
889 			//  bits in the huffman decoder giving a bogus value?
890 			if (cmd == -1) {
891 				cmd = svc_EOF;
892 			}
893 		}
894 
895 		if (cmd == svc_EOF) {
896 			SHOWNET( msg, "END OF MESSAGE" );
897 			break;
898 		}
899 
900 		if ( cl_shownet->integer >= 2 ) {
901 			if ( (cmd < 0) || (!svc_strings[cmd]) ) {
902 				Com_Printf( "%3i:BAD CMD %i\n", msg->readcount-1, cmd );
903 			} else {
904 				SHOWNET( msg, svc_strings[cmd] );
905 			}
906 		}
907 
908 	// other commands
909 		switch ( cmd ) {
910 		default:
911 			Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message\n");
912 			break;
913 		case svc_nop:
914 			break;
915 		case svc_serverCommand:
916 			CL_ParseCommandString( msg );
917 			break;
918 		case svc_gamestate:
919 			CL_ParseGamestate( msg );
920 			break;
921 		case svc_snapshot:
922 			CL_ParseSnapshot( msg );
923 			break;
924 		case svc_download:
925 			CL_ParseDownload( msg );
926 			break;
927 		case svc_voip:
928 #ifdef USE_VOIP
929 			CL_ParseVoip( msg );
930 #endif
931 			break;
932 		}
933 	}
934 }
935 
936 
937