Merge pull request #22 from FWGS/netsplit

Extended netsplit, network extensions
This commit is contained in:
Alibek Omarov
2019-03-21 17:23:49 +03:00
committed by GitHub
9 changed files with 188 additions and 61 deletions

View File

@@ -302,7 +302,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 * ))
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ))
{
Netchan_Clear( chan );
@@ -710,7 +710,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
return;
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
wait = (fragbufwaiting_t *)Mem_Calloc( net_mempool, sizeof( fragbufwaiting_t ));
@@ -871,7 +871,7 @@ void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, const char *filenam
if( !size ) return;
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
if( !LZSS_IsCompressed( pbuf ))
@@ -969,7 +969,7 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename )
}
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
Q_strncpy( compressedfilename, filename, sizeof( compressedfilename ));
@@ -1458,9 +1458,15 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
if( send_from_regular && ( send_from_frag[FRAG_NORMAL_STREAM] ))
{
send_from_regular = false;
int maxsize = MAX_RELIABLE_PAYLOAD;
if( chan->pfnBlockSize )
maxsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
if( maxsize == 0 )
maxsize = MAX_RELIABLE_PAYLOAD;
// if the reliable buffer has gotten too big, queue it at the end of everything and clear out buffer
if( MSG_GetNumBytesWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD )
if( MSG_GetNumBytesWritten( &chan->message ) + (((uint)length) >> 3) > maxsize )
{
Netchan_CreateFragments_( chan, &chan->message );
MSG_Clear( &chan->message );
@@ -1627,9 +1633,16 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
chan->last_reliable_sequence = chan->outgoing_sequence - 1;
}
if( MSG_GetNumBitsLeft( &send ) >= length )
MSG_WriteBits( &send, data, length );
else Con_Printf( S_WARN "Netchan_Transmit: unreliable message overflow\n" );
if( length )
{
int maxsize = NET_MAX_MESSAGE;
if( chan->pfnBlockSize )
maxsize = chan->pfnBlockSize( chan->client, FRAGSIZE_UNRELIABLE );
if( MSG_GetNumBytesWritten( &send ) + length >> 3 <= maxsize )
MSG_WriteBits( &send, data, length );
else Con_Printf( S_WARN "Netchan_Transmit: unreliable message overflow: %d\n", MSG_GetNumBytesWritten( &send ) );
}
// deal with packets that are too small for some networks
if( MSG_GetNumBytesWritten( &send ) < 16 && !NET_IsLocalAddress( chan->remote_address )) // packet too small for some networks
@@ -1658,7 +1671,10 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// send the datagram
if( !CL_IsPlaybackDemo( ))
{
NET_SendPacket( chan->sock, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), chan->remote_address );
int splitsize = 0;
if( chan->pfnBlockSize )
splitsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
NET_SendPacketEx( chan->sock, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), chan->remote_address, splitsize );
}
if( SV_Active() && sv_lan.value && sv_lan_rate.value > 1000.0 )

View File

@@ -35,15 +35,16 @@ GNU General Public License for more details.
#include "netchan.h"
#include "mathlib.h"
// #define NET_USE_FRAGMENTS
#define NET_USE_FRAGMENTS
#define PORT_ANY -1
#define MAX_LOOPBACK 4
#define MASK_LOOPBACK (MAX_LOOPBACK - 1)
#define MAX_ROUTEABLE_PACKET 1400
#define SPLIT_SIZE ( MAX_ROUTEABLE_PACKET - sizeof( SPLITPACKET ))
#define NET_MAX_FRAGMENTS ( NET_MAX_FRAGMENT / SPLIT_SIZE )
#define SPLITPACKET_MIN_SIZE 508 // RFC 791: 576(min ip packet) - 60 (ip header) - 8 (udp header)
#define SPLITPACKET_MAX_SIZE 64000
#define NET_MAX_FRAGMENTS ( NET_MAX_FRAGMENT / (SPLITPACKET_MIN_SIZE - sizeof( SPLITPACKET )) )
#ifndef _WIN32 // it seems we need to use WS2 to support it
#define HAVE_GETADDRINFO
@@ -1105,13 +1106,17 @@ NET_GetLong
receive long packet from network
==================
*/
qboolean NET_GetLong( byte *pData, int size, int *outSize )
qboolean NET_GetLong( byte *pData, int size, int *outSize, int splitsize )
{
int i, sequence_number, offset;
SPLITPACKET *pHeader = (SPLITPACKET *)pData;
int packet_number;
int packet_count;
short packet_id;
int body_size = splitsize - sizeof( SPLITPACKET );
if( body_size < 0 )
return false;
if( size < sizeof( SPLITPACKET ))
{
@@ -1149,7 +1154,7 @@ qboolean NET_GetLong( byte *pData, int size, int *outSize )
if( net.split_flags[packet_number] != sequence_number )
{
if( packet_number == ( packet_count - 1 ))
net.split.total_size = size + SPLIT_SIZE * ( packet_count - 1 );
net.split.total_size = size + body_size * ( packet_count - 1 );
net.split.split_count--;
net.split_flags[packet_number] = sequence_number;
@@ -1162,7 +1167,7 @@ qboolean NET_GetLong( byte *pData, int size, int *outSize )
Con_DPrintf( "NET_GetLong: Ignoring duplicated split packet %i of %i ( %i bytes )\n", packet_number + 1, packet_count, size );
}
offset = (packet_number * SPLIT_SIZE);
offset = (packet_number * body_size);
memcpy( net.split.buffer + offset, pData + sizeof( SPLITPACKET ), size );
// have we received all of the pieces to the packet?
@@ -1221,13 +1226,13 @@ qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size_t *len
#ifndef XASH_DEDICATED
if( CL_LegacyMode() )
return NET_LagPacket( true, sock, from, length, data );
#endif
// check for split message
if( *(int *)data == NET_HEADER_SPLITPACKET )
{
return NET_GetLong( data, ret, length );
}
// check for split message
if( sock == NS_CLIENT && *(int *)data == NET_HEADER_SPLITPACKET )
{
return NET_GetLong( data, ret, length, CL_GetSplitSize() );
}
#endif
// lag the packet, if needed
return NET_LagPacket( true, sock, from, length, data );
}
@@ -1288,15 +1293,16 @@ NET_SendLong
Fragment long packets, send short directly
==================
*/
int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int flags, const struct sockaddr *to, int tolen )
int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t len, int flags, const struct sockaddr *to, size_t tolen, size_t splitsize )
{
#ifdef NET_USE_FRAGMENTS
// do we need to break this packet up?
if( sock == NS_SERVER && len > MAX_ROUTEABLE_PACKET )
if( splitsize > sizeof( SPLITPACKET ) && sock == NS_SERVER && len > splitsize )
{
char packet[MAX_ROUTEABLE_PACKET];
char packet[SPLITPACKET_MAX_SIZE];
int total_sent, size, packet_count;
int ret, packet_number;
int body_size = splitsize - sizeof( SPLITPACKET );
SPLITPACKET *pPacket;
net.sequence_number++;
@@ -1308,13 +1314,13 @@ int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int f
pPacket->net_id = NET_HEADER_SPLITPACKET;
packet_number = 0;
total_sent = 0;
packet_count = (len + SPLIT_SIZE - 1) / SPLIT_SIZE;
packet_count = (len + body_size - 1) / body_size;
while( len > 0 )
{
size = Q_min( SPLIT_SIZE, len );
size = Q_min( body_size, len );
pPacket->packet_id = (packet_number << 8) + packet_count;
memcpy( packet + sizeof( SPLITPACKET ), buf + ( packet_number * SPLIT_SIZE ), size );
memcpy( packet + sizeof( SPLITPACKET ), buf + ( packet_number * body_size ), size );
if( net_showpackets && net_showpackets->value == 3.0f )
{
@@ -1349,10 +1355,10 @@ int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int f
/*
==================
NET_SendPacket
NET_SendPacketEx
==================
*/
void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to )
void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t to, size_t splitsize )
{
int ret;
struct sockaddr addr;
@@ -1382,7 +1388,7 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to
NET_NetadrToSockadr( &to, &addr );
ret = NET_SendLong( sock, net_socket, data, length, 0, &addr, sizeof( addr ));
ret = NET_SendLong( sock, net_socket, data, length, 0, &addr, sizeof( addr ), splitsize );
if( NET_IsSocketError( ret ))
{
@@ -1412,6 +1418,16 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to
}
/*
==================
NET_SendPacket
==================
*/
void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to )
{
return NET_SendPacketEx( sock, length, data, to, 0 );
}
/*
====================
NET_BufferToBufferCompress

View File

@@ -61,10 +61,12 @@ qboolean NET_GetPacket( netsrc_t sock, netadr_t *from, byte *data, size_t *lengt
qboolean NET_BufferToBufferCompress( char *dest, uint *destLen, char *source, uint sourceLen );
qboolean NET_BufferToBufferDecompress( char *dest, uint *destLen, char *source, uint sourceLen );
void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to );
void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t to, size_t splitsize );
void NET_ClearLagData( qboolean bClient, qboolean bServer );
#ifndef XASH_DEDICATED
qboolean CL_LegacyMode( void );
int CL_GetSplitSize( void );
#endif
void HTTP_AddCustomServer( const char *url );

View File

@@ -59,10 +59,10 @@ GNU General Public License for more details.
// {
// byte (on/off)
// int (fragment id)
// short (startpos)
// short (length)
// int (startpos)
// int (length)
// }
#define HEADER_BYTES ( 8 + MAX_STREAMS * 9 )
#define HEADER_BYTES ( 8 + MAX_STREAMS * 13 )
// Pad this to next higher 16 byte boundary
// This is the largest packet that can come in/out over the wire, before processing the header
@@ -84,7 +84,7 @@ GNU General Public License for more details.
#define NUM_PACKET_ENTITIES 256 // 170 Mb for multiplayer with 32 players
#define MAX_CUSTOM_BASELINES 64
#define NET_EXT_SPLIT (1U<<1)
#define NET_LEGACY_EXT_SPLIT (1U<<1)
#define NETSPLIT_BACKUP 8
#define NETSPLIT_BACKUP_MASK (NETSPLIT_BACKUP - 1)
#define NETSPLIT_HEADER_SIZE 18
@@ -182,6 +182,13 @@ typedef struct fbufqueue_s
fragbuf_t *fragbufs; // the actual buffers
} fragbufwaiting_t;
typedef enum fragsize_e
{
FRAGSIZE_FRAG,
FRAGSIZE_SPLIT,
FRAGSIZE_UNRELIABLE
} fragsize_t;
// Network Connection Channel
typedef struct netchan_s
{
@@ -205,7 +212,7 @@ typedef struct netchan_s
// callback to get actual framgment size
void *client;
int (*pfnBlockSize)( void *cl );
int (*pfnBlockSize)( void *cl, fragsize_t mode );
// staging and holding areas
sizebuf_t message;
@@ -261,7 +268,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 * ) );
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ) );
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 );

View File

@@ -174,8 +174,8 @@ GNU General Public License for more details.
#define MAX_RESOURCES (MAX_MODELS+MAX_SOUNDS+MAX_CUSTOM+MAX_EVENTS)
#define MAX_RESOURCE_BITS 13 // 13 bits 8192 resource (4096 models + 2048 sounds + 1024 events + 1024 files)
#define FRAGMENT_MIN_SIZE 1200 // default MTU
#define FRAGMENT_MIN_SIZE 508 // RFC 791: 576(min ip packet) - 60 (ip header) - 8 (udp header)
#define FRAGMENT_DEFAULT_SIZE 1200 // default MTU
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
@@ -243,6 +243,9 @@ GNU General Public License for more details.
extern const char *svc_strings[svc_lastmsg+1];
extern const char *clc_strings[clc_lastmsg+1];
// FWGS extensions
#define NET_EXT_SPLITSIZE (1U<<0) // set splitsize by cl_dlmax
// legacy protocol definitons
#define PROTOCOL_LEGACY_VERSION 48
#define svc_legacy_modelindex 31 // [index][modelpath]