2
0
mirror of https://github.com/FWGS/xash3d-fwgs synced 2024-11-28 13:02:13 +01:00
xash3d-fwgs/engine/common/netchan.h
a1batross fc7fb8b62d engine: masterlist: replace master server domain by mentality.rip
It is essentially the same as ms.xash.su but due to current situation, it is known to be blocked on some Ukrainian ISPs.

ms2.xash.su is retired for now.
2022-03-19 01:58:10 +03:00

310 lines
10 KiB
C

/*
netchan.h - net channel abstraction layer
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef NET_MSG_H
#define NET_MSG_H
/*
==========================================================
ELEMENTS COMMUNICATED ACROSS THE NET
==========================================================
*/
#include "crtlib.h"
#include "net_buffer.h"
// 0 == regular, 1 == file stream
#define MAX_STREAMS 2
// flow control bytes per second limits
#define MAX_RATE 100000.0f
#define MIN_RATE 1000.0f
// default data rate
#define DEFAULT_RATE (9999.0f)
// NETWORKING INFO
// This is the packet payload without any header bytes (which are attached for actual sending)
#define NET_MAX_PAYLOAD MAX_INIT_MSG
// Theoretically maximum size of UDP-packet without header and hardware-specific data
#define NET_MAX_FRAGMENT 65535
// because encoded as highpart of uint32
#define NET_MAX_BUFFER_ID 32767
// because encoded as lowpart of uint32
#define NET_MAX_BUFFERS_COUNT 32767
// This is the payload plus any header info (excluding UDP header)
// Packet header is:
// 4 bytes of outgoing seq
// 4 bytes of incoming seq
// and for each stream
// {
// byte (on/off)
// int (fragment id)
// int (startpos)
// int (length)
// }
#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
// bytes will be stripped by the networking channel layer
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
#define MASTERSERVER_ADR "mentality.rip:27010"
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
#define PORT_MASTER 27010
#define PORT_CLIENT 27005
#define PORT_SERVER 27015
#define MULTIPLAYER_BACKUP 64 // how many data slots to use when in multiplayer (must be power of 2)
#define SINGLEPLAYER_BACKUP 16 // same for single player
#define CMD_BACKUP 64 // allow a lot of command backups for very fast systems
#define CMD_MASK (CMD_BACKUP - 1)
#define NUM_PACKET_ENTITIES 256 // 170 Mb for multiplayer with 32 players
#define MAX_CUSTOM_BASELINES 64
#define NET_LEGACY_EXT_SPLIT (1U<<1)
#define NETSPLIT_BACKUP 8
#define NETSPLIT_BACKUP_MASK (NETSPLIT_BACKUP - 1)
#define NETSPLIT_HEADER_SIZE 18
#if XASH_LOW_MEMORY == 2
#undef MULTIPLAYER_BACKUP
#undef SINGLEPLAYER_BACKUP
#undef NUM_PACKET_ENTITIES
#undef MAX_CUSTOM_BASELINES
#undef NET_MAX_FRAGMENT
#define MULTIPLAYER_BACKUP 4 // breaks protocol in legacy mode, new protocol status unknown
#define SINGLEPLAYER_BACKUP 4
#define NUM_PACKET_ENTITIES 32
#define MAX_CUSTOM_BASELINES 8
#define NET_MAX_FRAGMENT 32768
#elif XASH_LOW_MEMORY == 1
#undef SINGLEPLAYER_BACKUP
#undef NUM_PACKET_ENTITIES
#undef MAX_CUSTOM_BASELINES
#undef NET_MAX_FRAGMENT
#define SINGLEPLAYER_BACKUP 4
#define NUM_PACKET_ENTITIES 64
#define MAX_CUSTOM_BASELINES 8
#define NET_MAX_FRAGMENT 32768
#endif
typedef struct netsplit_chain_packet_s
{
// bool vector
uint32_t recieved_v[8];
// serial number
uint32_t id;
byte data[NET_MAX_PAYLOAD];
byte received;
byte count;
} netsplit_chain_packet_t;
// raw packet format
typedef struct netsplit_packet_s
{
uint32_t signature; // 0xFFFFFFFE
uint32_t length;
uint32_t part;
uint32_t id;
// max 256 parts
byte count;
byte index;
byte data[NET_MAX_PAYLOAD - NETSPLIT_HEADER_SIZE];
} netsplit_packet_t;
typedef struct netsplit_s
{
netsplit_chain_packet_t packets[NETSPLIT_BACKUP];
uint64_t total_received;
uint64_t total_received_uncompressed;
} netsplit_t;
// packet splitting
qboolean NetSplit_GetLong( netsplit_t *ns, netadr_t *from, byte *data, size_t *length );
/*
==============================================================
NET
==============================================================
*/
#define MAX_FLOWS 2
#define FLOW_OUTGOING 0
#define FLOW_INCOMING 1
#define MAX_LATENT 32
#define MASK_LATENT ( MAX_LATENT - 1 )
#define FRAG_NORMAL_STREAM 0
#define FRAG_FILE_STREAM 1
// message data
typedef struct
{
int size; // size of message sent/received
double time; // time that message was sent/received
} flowstats_t;
typedef struct
{
flowstats_t stats[MAX_LATENT]; // data for last MAX_LATENT messages
int current; // current message position
double nextcompute; // time when we should recompute k/sec data
float kbytespersec; // average data
float avgkbytespersec;
int totalbytes;
} flow_t;
// generic fragment structure
typedef struct fragbuf_s
{
struct fragbuf_s *next; // next buffer in chain
int bufferid; // id of this buffer
sizebuf_t frag_message; // message buffer where raw data is stored
byte frag_message_buf[NET_MAX_FRAGMENT]; // the actual data sits here
qboolean isfile; // is this a file buffer?
qboolean isbuffer; // is this file buffer from memory ( custom decal, etc. ).
qboolean iscompressed; // is compressed file, we should using filename.ztmp
char filename[MAX_OSPATH]; // name of the file to save out on remote host
int foffset; // offset in file from which to read data
int size; // size of data to read at that offset
} fragbuf_t;
// Waiting list of fragbuf chains
typedef struct fbufqueue_s
{
struct fbufqueue_s *next; // next chain in waiting list
int fragbufcount; // number of buffers in this chain
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
{
netsrc_t sock; // NS_SERVER or NS_CLIENT, depending on channel.
netadr_t remote_address; // address this channel is talking to.
int qport; // qport value to write when transmitting
double last_received; // for timeouts
double connect_time; // Usage: host.realtime - netchan.connect_time
double rate; // bandwidth choke. bytes per second
double cleartime; // if realtime > cleartime, free to send next packet
// Sequencing variables
unsigned int incoming_sequence; // increasing count of sequence numbers
unsigned int incoming_acknowledged; // # of last outgoing message that has been ack'd.
unsigned int incoming_reliable_acknowledged; // toggles T/F as reliable messages are received.
unsigned int incoming_reliable_sequence; // single bit, maintained local
unsigned int outgoing_sequence; // message we are sending to remote
unsigned int reliable_sequence; // whether the message contains reliable payload, single bit
unsigned int last_reliable_sequence; // outgoing sequence number of last send that had reliable data
// callback to get actual framgment size
void *client;
int (*pfnBlockSize)( void *cl, fragsize_t mode );
// staging and holding areas
sizebuf_t message;
byte message_buf[NET_MAX_MESSAGE];
// reliable message buffer.
// we keep adding to it until reliable is acknowledged. Then we clear it.
int reliable_length;
byte reliable_buf[NET_MAX_MESSAGE]; // unacked reliable message (max size for loopback connection)
// Waiting list of buffered fragments to go onto queue.
// Multiple outgoing buffers can be queued in succession
fragbufwaiting_t *waitlist[MAX_STREAMS];
int reliable_fragment[MAX_STREAMS]; // is reliable waiting buf a fragment?
uint reliable_fragid[MAX_STREAMS]; // buffer id for each waiting fragment
fragbuf_t *fragbufs[MAX_STREAMS]; // the current fragment being set
int fragbufcount[MAX_STREAMS]; // the total number of fragments in this stream
int frag_startpos[MAX_STREAMS]; // position in outgoing buffer where frag data starts
int frag_length[MAX_STREAMS]; // length of frag data in the buffer
fragbuf_t *incomingbufs[MAX_STREAMS]; // incoming fragments are stored here
qboolean incomingready[MAX_STREAMS]; // set to true when incoming data is ready
// Only referenced by the FRAG_FILE_STREAM component
char incomingfilename[MAX_OSPATH]; // Name of file being downloaded
void *tempbuffer; // download file buffer
int tempbuffersize; // current size
// incoming and outgoing flow metrics
flow_t flow[MAX_FLOWS];
// added for net_speeds
size_t total_sended;
size_t total_received;
qboolean split;
unsigned int maxpacket;
unsigned int splitid;
netsplit_t netsplit;
} netchan_t;
extern netadr_t net_from;
extern netadr_t net_local;
extern sizebuf_t net_message;
extern byte net_message_buffer[NET_MAX_MESSAGE];
extern convar_t sv_lan;
extern convar_t sv_lan_rate;
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_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 );
void Netchan_CreateFragments( netchan_t *chan, sizebuf_t *msg );
int Netchan_CreateFileFragments( netchan_t *chan, const char *filename );
void Netchan_Transmit( netchan_t *chan, int lengthInBytes, byte *data );
void Netchan_TransmitBits( netchan_t *chan, int lengthInBits, byte *data );
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data );
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, const char *format, ... ) _format( 3 );
qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg );
void Netchan_UpdateProgress( netchan_t *chan );
qboolean Netchan_IncomingReady( netchan_t *chan );
qboolean Netchan_CanPacket( netchan_t *chan, qboolean choke );
qboolean Netchan_IsLocal( netchan_t *chan );
void Netchan_ReportFlow( netchan_t *chan );
void Netchan_FragSend( netchan_t *chan );
void Netchan_Clear( netchan_t *chan );
#endif//NET_MSG_H