aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--code/client/cl_input.c2
-rw-r--r--code/client/cl_parse.c27
-rw-r--r--code/qcommon/huffman.c10
-rw-r--r--code/qcommon/msg.c11
-rw-r--r--code/qcommon/qcommon.h21
-rw-r--r--code/server/sv_client.c24
6 files changed, 79 insertions, 16 deletions
diff --git a/code/client/cl_input.c b/code/client/cl_input.c
index a972536..ff0e5b1 100644
--- a/code/client/cl_input.c
+++ b/code/client/cl_input.c
@@ -760,6 +760,8 @@ void CL_WritePacket( void ) {
#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);
diff --git a/code/client/cl_parse.c b/code/client/cl_parse.c
index d80d7d2..294e46e 100644
--- a/code/client/cl_parse.c
+++ b/code/client/cl_parse.c
@@ -34,10 +34,8 @@ char *svc_strings[256] = {
"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 @@ void CL_ParseServerMessage( msg_t *msg ) {
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 @@ void CL_ParseServerMessage( msg_t *msg ) {
case svc_download:
CL_ParseDownload( msg );
break;
-#if USE_VOIP
case svc_voip:
+#if USE_VOIP
CL_ParseVoip( msg );
- break;
#endif
+ break;
}
}
}
diff --git a/code/qcommon/huffman.c b/code/qcommon/huffman.c
index b230b5b..2ff4ae5 100644
--- a/code/qcommon/huffman.c
+++ b/code/qcommon/huffman.c
@@ -39,6 +39,16 @@ void Huff_putBit( int bit, byte *fout, int *offset) {
*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;
diff --git a/code/qcommon/msg.c b/code/qcommon/msg.c
index b26cf8f..3840a8c 100644
--- a/code/qcommon/msg.c
+++ b/code/qcommon/msg.c
@@ -389,6 +389,17 @@ int MSG_ReadByte( msg_t *msg ) {
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;
diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h
index f535d68..58b0a29 100644
--- a/code/qcommon/qcommon.h
+++ b/code/qcommon/qcommon.h
@@ -92,7 +92,7 @@ char *MSG_ReadBigString (msg_t *sb);
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 @@ enum svc_ops_e {
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 @@ enum clc_ops_e {
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_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset);
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
diff --git a/code/server/sv_client.c b/code/server/sv_client.c
index 2528e64..180bbf3 100644
--- a/code/server/sv_client.c
+++ b/code/server/sv_client.c
@@ -1108,6 +1108,14 @@ void SV_WriteVoipToClient( client_t *cl, msg_t *msg )
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 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
// 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 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
SV_UserMove( cl, msg, qtrue );
} else if ( c == clc_moveNoDelta ) {
SV_UserMove( cl, msg, qfalse );
-#if USE_VOIP
} else if ( c == clc_voip ) {
+#if USE_VOIP
SV_UserVoip( cl, msg );
#endif
} else if ( c != clc_EOF ) {