- Added selective compression of network packets. Interestingly, most packets

don't actually compress all that well, even the ones that aren't too short
  to possibly compress. (Maybe make the whole thing one long, never-ending
  zlib data stream with Z_SYNC_FLUSH used to chunk things at packet
  boundaries? That would probably help the compression ratio, but it would
  require changing the way the netcode determines sequence, which would be
  a much more invasive change.)


SVN r1438 (trunk)
This commit is contained in:
Randy Heit 2009-02-22 05:05:58 +00:00
parent b246d79c8b
commit 10c31b82cb
4 changed files with 108 additions and 38 deletions

View file

@ -1,4 +1,13 @@
February 21, 2009 (Changes by Graf Zahl)
February 21, 2009
- Added selective compression of network packets. Interestingly, most packets
don't actually compress all that well, even the ones that aren't too short
to possibly compress. (Maybe make the whole thing one long, never-ending
zlib data stream with Z_SYNC_FLUSH used to chunk things at packet
boundaries? That would probably help the compression ratio, but it would
require changing the way the netcode determines sequence, which would be
a much more invasive change.)
February 21, 2009 (Changes by Graf Zahl)
- Fixed: Heretic's fullscreen HUD crashed when the player had armor without
a valid icon.
- Fixed: The StrifePlayer was missing a RunHealth setting.

View file

@ -67,35 +67,6 @@ EXTERN_CVAR (Int, autosavecount)
//#define SIMULATEERRORS (RAND_MAX/3)
#define SIMULATEERRORS 0
#define NCMD_EXIT 0x80
#define NCMD_RETRANSMIT 0x40
#define NCMD_SETUP 0x20
#define NCMD_MULTI 0x10 // multiple players in this packet
#define NCMD_QUITTERS 0x08 // one or more players just quit (packet server only)
#define NCMD_XTICS 0x03 // packet contains >2 tics
#define NCMD_2TICS 0x02 // packet contains 2 tics
#define NCMD_1TICS 0x01 // packet contains 1 tic
#define NCMD_0TICS 0x00 // packet contains 0 tics
// [RH]
// New generic packet structure:
//
// Header:
// One byte with above flags.
// One byte with starttic
// One byte with master's maketic (master -> slave only!)
// If NCMD_RETRANSMIT set, one byte with retransmitfrom
// If NCMD_XTICS set, one byte with number of tics (minus 3, so theoretically up to 258 tics in one packet)
// If NCMD_QUITTERS, one byte with number of players followed by one byte with each player's consolenum
// If NCMD_MULTI, one byte with number of players followed by one byte with each player's consolenum
// - The first player's consolenum is not included in this list, because it always matches the sender
//
// For each tic:
// Two bytes with consistancy check, followed by tic data
//
// Setup packets are different, and are described just before D_ArbitrateNetStart().
extern BYTE *demo_p; // [RH] Special "ticcmds" get recorded in demos
extern char savedescription[SAVESTRINGSIZE];
extern FString savegamefile;

View file

@ -48,7 +48,7 @@
// Probably not enough.
#define MAX_MSGLEN (BACKUPTICS*10)
#else
#define MAX_MSGLEN 1400
#define MAX_MSGLEN 14000
#endif
#define CMD_SEND 1
@ -144,4 +144,34 @@ extern int nettics[MAXNETNODES];
extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
extern int ticdup;
// [RH]
// New generic packet structure:
//
// Header:
// One byte with following flags.
// One byte with starttic
// One byte with master's maketic (master -> slave only!)
// If NCMD_RETRANSMIT set, one byte with retransmitfrom
// If NCMD_XTICS set, one byte with number of tics (minus 3, so theoretically up to 258 tics in one packet)
// If NCMD_QUITTERS, one byte with number of players followed by one byte with each player's consolenum
// If NCMD_MULTI, one byte with number of players followed by one byte with each player's consolenum
// - The first player's consolenum is not included in this list, because it always matches the sender
//
// For each tic:
// Two bytes with consistancy check, followed by tic data
//
// Setup packets are different, and are described just before D_ArbitrateNetStart().
#define NCMD_EXIT 0x80
#define NCMD_RETRANSMIT 0x40
#define NCMD_SETUP 0x20
#define NCMD_MULTI 0x10 // multiple players in this packet
#define NCMD_QUITTERS 0x08 // one or more players just quit (packet server only)
#define NCMD_COMPRESSED 0x04 // remainder of packet is compressed
#define NCMD_XTICS 0x03 // packet contains >2 tics
#define NCMD_2TICS 0x02 // packet contains 2 tics
#define NCMD_1TICS 0x01 // packet contains 1 tic
#define NCMD_0TICS 0x00 // packet contains 0 tics
#endif

View file

@ -64,7 +64,9 @@
#include "i_net.h"
// As per http://support.microsoft.com/kb/q192599/ the standard
// size for network buffers is 8k.
#define TRANSMIT_SIZE 8000
/* [Petteri] Get more portable: */
#ifndef __WIN32__
@ -133,6 +135,8 @@ struct PreGamePacket
} machines[MAXNETNODES];
};
BYTE TransmitBuffer[TRANSMIT_SIZE];
//
// UDPsocket
//
@ -191,11 +195,47 @@ void PacketSend (void)
{
int c;
//printf ("sending %i\n",gametic);
c = sendto (mysocket , (const char*)doomcom.data, doomcom.datalength
,0,(sockaddr *)&sendaddress[doomcom.remotenode]
,sizeof(sendaddress[doomcom.remotenode]));
// FIXME: Catch this before we've overflown the buffer. With long chat
// text and lots of backup tics, it could conceivably happen. (Though
// apparently it hasn't yet, which is good.)
if (doomcom.datalength > MAX_MSGLEN)
{
I_FatalError("Netbuffer overflow!");
}
uLong size = TRANSMIT_SIZE - 1;
if (doomcom.datalength >= 10)
{
assert(!(doomcom.data[0] & NCMD_COMPRESSED));
TransmitBuffer[0] = doomcom.data[0] | NCMD_COMPRESSED;
c = compress2(TransmitBuffer + 1, &size, doomcom.data + 1, doomcom.datalength - 1, 9);
size += 1;
}
else
{
c = -1; // Just some random error code to avoid sending the compressed buffer.
}
if (c == Z_OK && size < (uLong)doomcom.datalength)
{
// Printf("send %lu/%d\n", size, doomcom.datalength);
c = sendto(mysocket, (char *)TransmitBuffer, size,
0, (sockaddr *)&sendaddress[doomcom.remotenode],
sizeof(sendaddress[doomcom.remotenode]));
}
else
{
if (doomcom.datalength > TRANSMIT_SIZE)
{
I_Error("Net compression failed (zlib error %d)", c);
}
else
{
// Printf("send %d\n", doomcom.datalength);
c = sendto(mysocket, (char *)doomcom.data, doomcom.datalength,
0, (sockaddr *)&sendaddress[doomcom.remotenode],
sizeof(sendaddress[doomcom.remotenode]));
}
}
// if (c == -1)
// I_Error ("SendPacket error: %s",strerror(errno));
}
@ -212,8 +252,8 @@ void PacketGet (void)
int node;
fromlen = sizeof(fromaddress);
c = recvfrom (mysocket, (char*)doomcom.data, MAX_MSGLEN, 0
, (sockaddr *)&fromaddress, &fromlen);
c = recvfrom (mysocket, (char*)TransmitBuffer, TRANSMIT_SIZE, 0,
(sockaddr *)&fromaddress, &fromlen);
node = FindNode (&fromaddress);
if (node >= 0 && c == SOCKET_ERROR)
@ -239,6 +279,26 @@ void PacketGet (void)
return;
}
}
else if (c > 0)
{
doomcom.data[0] = TransmitBuffer[0] & ~NCMD_COMPRESSED;
if (TransmitBuffer[0] & NCMD_COMPRESSED)
{
uLongf msgsize = MAX_MSGLEN - 1;
int err = uncompress(doomcom.data + 1, &msgsize, TransmitBuffer + 1, c - 1);
// Printf("recv %d/%lu\n", c, msgsize + 1);
if (err != Z_OK)
{
I_Error("Net decompression failed (zlib error %d)\n", err);
}
c = msgsize + 1;
}
else
{
// Printf("recv %d\n", c);
memcpy(doomcom.data + 1, TransmitBuffer + 1, c - 1);
}
}
doomcom.remotenode = node;
doomcom.datalength = (short)c;