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