diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index b4e22f91..3a8790b0 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -708,7 +708,7 @@ static void CL_DemoStartPlayback( int mode ) demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message - Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize ); + Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, 0 ); memset( demo.cmds, 0, sizeof( demo.cmds )); demo.angle_position = 1; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 018da453..d564cdb1 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1483,16 +1483,19 @@ static void CL_Reconnect( qboolean setup_netchan ) { if( setup_netchan ) { - Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize ); + uint flags = 0; - if( cls.legacymode ) + if( cls.legacymode == PROTO_GOLDSRC ) + { + SetBits( flags, NETCHAN_USE_MUNGE | NETCHAN_USE_BZIP2 | NETCHAN_GOLDSRC ); + } + else if( cls.legacymode == PROTO_LEGACY ) { unsigned int extensions = Q_atoi( Cmd_Argv( 1 ) ); - if( extensions & NET_LEGACY_EXT_SPLIT ) + if( FBitSet( extensions, NET_LEGACY_EXT_SPLIT )) { - // only enable incoming split for legacy mode - cls.netchan.split = true; + SetBits( flags, NETCHAN_USE_LEGACY_SPLIT ); Con_Reportf( "^2NET_EXT_SPLIT enabled^7 (packet sizes is %d/%d)\n", (int)cl_dlmax.value, 65536 ); } } @@ -1500,12 +1503,11 @@ static void CL_Reconnect( qboolean setup_netchan ) { cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" )); - if( cls.extensions & NET_EXT_SPLITSIZE ) - { + if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE )) Con_Reportf( "^2NET_EXT_SPLITSIZE enabled^7 (packet size is %d)\n", (int)cl_dlmax.value ); - } } + Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, flags ); } else { diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 7c1a4985..f3582496 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -18,6 +18,9 @@ GNU General Public License for more details. #include "xash3d_mathlib.h" #include "net_encode.h" #include "protocol.h" +#if !XASH_DEDICATED +#include +#endif // !XASH_DEDICATED #define MAKE_FRAGID( id, count ) ((( id & 0xffff ) << 16 ) | ( count & 0xffff )) #define FRAG_GETID( fragid ) (( fragid >> 16 ) & 0xffff ) @@ -265,7 +268,7 @@ Netchan_Setup called to open a channel to a remote system ============== */ -void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode )) +void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ), uint flags ) { Netchan_Clear( chan ); @@ -281,6 +284,10 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi chan->qport = qport; chan->client = client; chan->pfnBlockSize = pfnBlockSize; + chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false; + chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false; + chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false; + chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false; MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf )); } @@ -687,7 +694,19 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg ) wait = (fragbufwaiting_t *)Mem_Calloc( net_mempool, sizeof( fragbufwaiting_t )); - if( !LZSS_IsCompressed( MSG_GetData( msg ))) + if( chan->use_bz2 && memcmp( MSG_GetData( msg ), "BZ2", 4 )) + { + byte pbOut[0x10000]; + uint uCompressedSize = MSG_GetNumBytesWritten( msg ) - 4; + if( !BZ2_bzBuffToBuffCompress( pbOut, &uCompressedSize, MSG_GetData( msg ), MSG_GetNumBytesWritten( msg ), 9, 0, 30 )) + { + Con_Reportf( "Compressing split packet with BZip2 (%d -> %d bytes)\n", MSG_GetNumBytesWritten( msg ), uCompressedSize ); + memcpy( msg->pData, "BZ2", 4 ); + memcpy( msg->pData + 4, pbOut, uCompressedSize ); + MSG_SeekToBit( msg, uCompressedSize << 3, SEEK_SET ); + } + } + else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ))) { uint uCompressedSize = 0; uint uSourceSize = MSG_GetNumBytesWritten( msg ); @@ -695,7 +714,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg ) if( pbOut && uCompressedSize > 0 && uCompressedSize < uSourceSize ) { - Con_Reportf( "Compressing split packet (%d -> %d bytes)\n", uSourceSize, uCompressedSize ); + Con_Reportf( "Compressing split packet with LZSS (%d -> %d bytes)\n", uSourceSize, uCompressedSize ); memcpy( msg->pData, pbOut, uCompressedSize ); MSG_SeekToBit( msg, uCompressedSize << 3, SEEK_SET ); } @@ -1098,7 +1117,16 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l p = n; } - if( LZSS_IsCompressed( MSG_GetData( msg ))) + if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ) ) + { + byte buf[0x10000]; + uint uDecompressedLen = sizeof( buf ); + + BZ2_bzBuffToBuffDecompress( buf, &uDecompressedLen, MSG_GetData( msg ) + 4, MSG_GetNumBytesWritten( msg ) - 4, 1, 0 ); + memcpy( msg->pData, buf, uDecompressedLen ); + size = uDecompressedLen; + } + else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg ))) { uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg )); byte buf[NET_MAX_MESSAGE]; @@ -1135,7 +1163,8 @@ Netchan_CopyFileFragments */ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ) { - char filename[MAX_OSPATH]; + char filename[MAX_OSPATH], compressor[32]; + uint uncompressedSize; int nsize, pos; byte *buffer; fragbuf_t *p, *n; @@ -1158,6 +1187,12 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ) MSG_Clear( msg ); Q_strncpy( filename, MSG_ReadString( msg ), sizeof( filename )); + compressor[0] = 0; + if( chan->gs_netchan ) + { + Q_strncpy( compressor, MSG_ReadString( msg ), sizeof( compressor )); + uncompressedSize = MSG_ReadLong( msg ); + } if( !COM_CheckString( filename )) { @@ -1228,10 +1263,25 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ) p = n; } - if( LZSS_IsCompressed( buffer )) + if( chan->gs_netchan && chan->use_bz2 ) { - uint uncompressedSize = LZSS_GetActualSize( buffer ) + 1; - byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize ); + if( !Q_stricmp( compressor, "bz2" )) + { + byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize ); + + Con_DPrintf( "Decompressing file %s (%d -> %d bytes)\n", filename, nsize, uncompressedSize ); + BZ2_bzBuffToBuffDecompress( uncompressedBuffer, &uncompressedSize, buffer, nsize, 1, 0 ); + Mem_Free( buffer ); + nsize = uncompressedSize; + buffer = uncompressedBuffer; + } + } + else if( LZSS_IsCompressed( buffer )) + { + byte *uncompressedBuffer; + + uncompressedSize = LZSS_GetActualSize( buffer ) + 1; + uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize ); nsize = LZSS_Decompress( buffer, uncompressedBuffer ); Mem_Free( buffer ); @@ -1593,7 +1643,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) MSG_WriteLong( &send, w2 ); // send the qport if we are a client - if( chan->sock == NS_CLIENT ) + if( chan->sock == NS_CLIENT && !chan->gs_netchan ) { MSG_WriteWord( &send, (int)net_qport.value ); } @@ -1606,8 +1656,16 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) { MSG_WriteByte( &send, 1 ); MSG_WriteLong( &send, chan->reliable_fragid[i] ); - MSG_WriteLong( &send, chan->frag_startpos[i] ); - MSG_WriteLong( &send, chan->frag_length[i] ); + if( chan->gs_netchan ) + { + MSG_WriteShort( &send, chan->frag_startpos[i] >> 3 ); + MSG_WriteShort( &send, chan->frag_length[i] >> 3 ); + } + else + { + MSG_WriteLong( &send, chan->frag_startpos[i] ); + MSG_WriteLong( &send, chan->frag_length[i] ); + } } else { @@ -1664,6 +1722,10 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) int splitsize = 0; if( chan->pfnBlockSize ) splitsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT ); + + if( chan->use_munge ) + COM_Munge2( send.pData + 8, MSG_GetNumBytesWritten( &send ) - 8, (byte)( chan->outgoing_sequence - 1 )); + NET_SendPacketEx( chan->sock, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), chan->remote_address, splitsize ); } @@ -1712,6 +1774,9 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg ) sequence = MSG_ReadLong( msg ); sequence_ack = MSG_ReadLong( msg ); + if( chan->use_munge ) + COM_UnMunge2( msg->pData + 8, ( msg->nDataBits >> 3 ) - 8, sequence & 0xFF ); + // read the qport if we are a server if( chan->sock == NS_SERVER ) qport = MSG_ReadShort( msg ); @@ -1729,8 +1794,16 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg ) { frag_message[i] = true; fragid[i] = MSG_ReadLong( msg ); - frag_offset[i] = MSG_ReadLong( msg ); - frag_length[i] = MSG_ReadLong( msg ); + if( chan->gs_netchan ) + { + frag_offset[i] = MSG_ReadShort( msg ) << 3; + frag_length[i] = MSG_ReadShort( msg ) << 3; + } + else + { + frag_offset[i] = MSG_ReadLong( msg ); + frag_length[i] = MSG_ReadLong( msg ); + } } } diff --git a/engine/common/netchan.h b/engine/common/netchan.h index d6335341..22e01770 100644 --- a/engine/common/netchan.h +++ b/engine/common/netchan.h @@ -208,6 +208,14 @@ typedef enum fragsize_e FRAGSIZE_UNRELIABLE } fragsize_t; +typedef enum netchan_flags_e +{ + NETCHAN_USE_LEGACY_SPLIT = BIT( 0 ), + NETCHAN_USE_MUNGE = BIT( 1 ), + NETCHAN_USE_BZIP2 = BIT( 2 ), + NETCHAN_GOLDSRC = BIT( 3 ), +} netchan_flags_t; + // Network Connection Channel typedef struct netchan_s { @@ -270,10 +278,14 @@ typedef struct netchan_s // added for net_speeds size_t total_sended; size_t total_received; - qboolean split; unsigned int maxpacket; unsigned int splitid; - netsplit_t netsplit; + netsplit_t netsplit; + + qboolean split; + qboolean use_munge; + qboolean use_bz2; + qboolean gs_netchan; } netchan_t; extern netadr_t net_from; @@ -287,7 +299,7 @@ extern int net_drop; void Netchan_Init( void ); void Netchan_Shutdown( void ); -void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ) ); +void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ), uint flags ); void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, const char *filename, byte *pbuf, int size ); qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *length ); qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ); diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index b7951c9d..81fdef67 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -444,7 +444,7 @@ static void SV_ConnectClient( netadr_t from ) newcl->listeners = -1; // initailize netchan - Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize ); + Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, 0 ); MSG_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 );