r1361 - in trunk/code: client qcommon server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Jun 2 22:32:55 EDT 2008


Author: icculus
Date: 2008-06-02 22:32:52 -0400 (Mon, 02 Jun 2008)
New Revision: 1361

Modified:
   trunk/code/client/cl_input.c
   trunk/code/client/cl_parse.c
   trunk/code/qcommon/huffman.c
   trunk/code/qcommon/msg.c
   trunk/code/qcommon/qcommon.h
   trunk/code/server/sv_client.c
Log:
Changed the protocol for VoIP packets to support legacy clients.

Previously, a legacy client wouldn't get a VoIP packet, but if they did,
 they'd panic and disconnect. Now they ignore them and continue on. This also
 gives us the framework to add other features legacy clients can ignore.

Oh, this also has the benefit of allowing us to store incoming VoIP for
 playback in recorded demos. They'll play the chatter on VoIP clients, and
 be ignored on legacy ones. Huge win.


Modified: trunk/code/client/cl_input.c
===================================================================
--- trunk/code/client/cl_input.c	2008-06-03 02:28:03 UTC (rev 1360)
+++ trunk/code/client/cl_input.c	2008-06-03 02:32:52 UTC (rev 1361)
@@ -760,6 +760,8 @@
 
 	#if USE_VOIP
 	if (clc.voipOutgoingDataSize > 0) {  // only send if data.
+		MSG_WriteByte (&buf, clc_EOF);  // placate legacy servers.
+		MSG_WriteByte (&buf, clc_extension);
 		MSG_WriteByte (&buf, clc_voip);
 		MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
 		MSG_WriteLong (&buf, clc.voipOutgoingSequence);

Modified: trunk/code/client/cl_parse.c
===================================================================
--- trunk/code/client/cl_parse.c	2008-06-03 02:28:03 UTC (rev 1360)
+++ trunk/code/client/cl_parse.c	2008-06-03 02:32:52 UTC (rev 1361)
@@ -34,10 +34,8 @@
 	"svc_download",
 	"svc_snapshot",
 	"svc_EOF",
-
-#if USE_VOIP
-	"svc_voip"
-#endif
+	"svc_extension",
+	"svc_voip",
 };
 
 void SHOWNET( msg_t *msg, char *s) {
@@ -854,13 +852,26 @@
 
 		cmd = MSG_ReadByte( msg );
 
-		if ( cmd == svc_EOF) {
+		// See if this is an extension command after the EOF, which means we
+		//  got data that a legacy client should ignore.
+		if ((cmd == svc_EOF) && (MSG_LookaheadByte( msg ) == svc_extension)) {
+			SHOWNET( msg, "EXTENSION" );
+			MSG_ReadByte( msg );  // throw the svc_extension byte away.
+			cmd = MSG_ReadByte( msg );  // something legacy clients can't do!
+			// sometimes you get a svc_extension at end of stream...dangling
+			//  bits in the huffman decoder giving a bogus value?
+			if (cmd == -1) {
+				cmd = svc_EOF;
+			}
+		}
+
+		if (cmd == svc_EOF) {
 			SHOWNET( msg, "END OF MESSAGE" );
 			break;
 		}
 
 		if ( cl_shownet->integer >= 2 ) {
-			if ( !svc_strings[cmd] ) {
+			if ( (cmd < 0) || (!svc_strings[cmd]) ) {
 				Com_Printf( "%3i:BAD CMD %i\n", msg->readcount-1, cmd );
 			} else {
 				SHOWNET( msg, svc_strings[cmd] );
@@ -886,11 +897,11 @@
 		case svc_download:
 			CL_ParseDownload( msg );
 			break;
+		case svc_voip:
 #if USE_VOIP
-		case svc_voip:
 			CL_ParseVoip( msg );
+#endif
 			break;
-#endif
 		}
 	}
 }

Modified: trunk/code/qcommon/huffman.c
===================================================================
--- trunk/code/qcommon/huffman.c	2008-06-03 02:28:03 UTC (rev 1360)
+++ trunk/code/qcommon/huffman.c	2008-06-03 02:32:52 UTC (rev 1361)
@@ -39,6 +39,16 @@
 	*offset = bloc;
 }
 
+int		Huff_getBloc(void)
+{
+	return bloc;
+}
+
+void	Huff_setBloc(int _bloc)
+{
+	bloc = _bloc;
+}
+
 int		Huff_getBit( byte *fin, int *offset) {
 	int t;
 	bloc = *offset;

Modified: trunk/code/qcommon/msg.c
===================================================================
--- trunk/code/qcommon/msg.c	2008-06-03 02:28:03 UTC (rev 1360)
+++ trunk/code/qcommon/msg.c	2008-06-03 02:32:52 UTC (rev 1361)
@@ -389,6 +389,17 @@
 	return c;
 }
 
+int MSG_LookaheadByte( msg_t *msg ) {
+	const int bloc = Huff_getBloc();
+	const int readcount = msg->readcount;
+	const int bit = msg->bit;
+	int c = MSG_ReadByte(msg);
+	Huff_setBloc(bloc);
+	msg->readcount = readcount;
+	msg->bit = bit;
+	return c;
+}
+
 int MSG_ReadShort( msg_t *msg ) {
 	int	c;
 	

Modified: trunk/code/qcommon/qcommon.h
===================================================================
--- trunk/code/qcommon/qcommon.h	2008-06-03 02:28:03 UTC (rev 1360)
+++ trunk/code/qcommon/qcommon.h	2008-06-03 02:32:52 UTC (rev 1361)
@@ -92,8 +92,8 @@
 char	*MSG_ReadStringLine (msg_t *sb);
 float	MSG_ReadAngle16 (msg_t *sb);
 void	MSG_ReadData (msg_t *sb, void *buffer, int size);
+int		MSG_LookaheadByte (msg_t *msg);
 
-
 void MSG_WriteDeltaUsercmd( msg_t *msg, struct usercmd_s *from, struct usercmd_s *to );
 void MSG_ReadDeltaUsercmd( msg_t *msg, struct usercmd_s *from, struct usercmd_s *to );
 
@@ -276,9 +276,10 @@
 	svc_snapshot,
 	svc_EOF,
 
-#if USE_VOIP
-	svc_voip
-#endif
+	// svc_extension follows a svc_EOF, followed by another svc_* ...
+	//  this keeps legacy clients compatible.
+	svc_extension,
+	svc_voip,     // not wrapped in USE_VOIP, so this value is reserved.
 };
 
 
@@ -293,9 +294,10 @@
 	clc_clientCommand,		// [string] message
 	clc_EOF,
 
-#if USE_VOIP
-	clc_voip,   // packet of voice data.
-#endif
+	// clc_extension follows a clc_EOF, followed by another clc_* ...
+	//  this keeps legacy servers compatible.
+	clc_extension,
+	clc_voip,   // not wrapped in USE_VOIP, so this value is reserved.
 };
 
 /*
@@ -1112,6 +1114,11 @@
 void	Huff_putBit( int bit, byte *fout, int *offset);
 int		Huff_getBit( byte *fout, int *offset);
 
+// don't use if you don't know what you're doing.
+int		Huff_getBloc(void);
+void	Huff_setBloc(int _bloc);
+
+
 extern huffman_t clientHuffTables;
 
 #define	SV_ENCODE_START		4

Modified: trunk/code/server/sv_client.c
===================================================================
--- trunk/code/server/sv_client.c	2008-06-03 02:28:03 UTC (rev 1360)
+++ trunk/code/server/sv_client.c	2008-06-03 02:32:52 UTC (rev 1361)
@@ -1108,6 +1108,14 @@
 		if (totalbytes > MAX_DOWNLOAD_BLKSIZE)
 			break;
 
+		// You have to start with a svc_EOF, so legacy clients drop the
+		//  rest of this packet. Otherwise, those without VoIP support will
+		//  see the svc_voip command, then panic and disconnect.
+		// Generally we don't send VoIP packets to legacy clients, but this
+		//  serves as both a safety measure and a means to keep demo files
+		//  compatible.
+		MSG_WriteByte( msg, svc_EOF );
+		MSG_WriteByte( msg, svc_extension );
 		MSG_WriteByte( msg, svc_voip );
 		MSG_WriteShort( msg, packet->sender );
 		MSG_WriteByte( msg, (byte) packet->generation );
@@ -1880,9 +1888,23 @@
 	// read optional clientCommand strings
 	do {
 		c = MSG_ReadByte( msg );
+
+		// See if this is an extension command after the EOF, which means we
+		//  got data that a legacy server should ignore.
+		if ((c == clc_EOF) && (MSG_LookaheadByte( msg ) == clc_extension)) {
+			MSG_ReadByte( msg );  // throw the clc_extension byte away.
+			c = MSG_ReadByte( msg );  // something legacy servers can't do!
+			// sometimes you get a clc_extension at end of stream...dangling
+			//  bits in the huffman decoder giving a bogus value?
+			if (c == -1) {
+				c = clc_EOF;
+			}
+		}
+
 		if ( c == clc_EOF ) {
 			break;
 		}
+
 		if ( c != clc_clientCommand ) {
 			break;
 		}
@@ -1899,8 +1921,8 @@
 		SV_UserMove( cl, msg, qtrue );
 	} else if ( c == clc_moveNoDelta ) {
 		SV_UserMove( cl, msg, qfalse );
+	} else if ( c == clc_voip ) {
 #if USE_VOIP
-	} else if ( c == clc_voip ) {
 		SV_UserVoip( cl, msg );
 #endif
 	} else if ( c != clc_EOF ) {




More information about the quake3-commits mailing list