123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- #include "../game/q_shared.h"
- #include "qcommon.h"
- #define MAX_PACKETLEN 1400
- #define FRAGMENT_SIZE (MAX_PACKETLEN - 100)
- #define PACKET_HEADER 10
- #define FRAGMENT_BIT (1<<31)
- cvar_t *showpackets;
- cvar_t *showdrop;
- cvar_t *qport;
- static char *netsrcString[2] = {
- "client",
- "server"
- };
- /*
- ===============
- Netchan_Init
- ===============
- */
- void Netchan_Init( int port ) {
- port &= 0xffff;
- showpackets = Cvar_Get ("showpackets", "0", CVAR_TEMP );
- showdrop = Cvar_Get ("showdrop", "0", CVAR_TEMP );
- qport = Cvar_Get ("net_qport", va("%i", port), CVAR_INIT );
- }
- /*
- ==============
- 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 ) {
- Com_Memset (chan, 0, sizeof(*chan));
-
- chan->sock = sock;
- chan->remoteAddress = adr;
- chan->qport = qport;
- chan->incomingSequence = 0;
- chan->outgoingSequence = 1;
- }
- #if 0
- #define SCRAMBLE_START 6
- static void Netchan_ScramblePacket( msg_t *buf ) {
- unsigned seed;
- int i, j, c, mask, temp;
- int seq[MAX_PACKETLEN];
- seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
- c = buf->cursize;
- if ( c <= SCRAMBLE_START ) {
- return;
- }
- if ( c > MAX_PACKETLEN ) {
- Com_Error( ERR_DROP, "MAX_PACKETLEN" );
- }
-
- for (i = 0 ; i < c ; i++) {
- seed = (119 * seed + 1);
- seq[i] = seed;
- }
-
- for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
- }
- mask >>= 1;
- for (i = SCRAMBLE_START ; i < c ; i++) {
- j = SCRAMBLE_START + ( seq[i] & mask );
- temp = buf->data[j];
- buf->data[j] = buf->data[i];
- buf->data[i] = temp;
- }
-
- for (i = SCRAMBLE_START ; i < c ; i++) {
- buf->data[i] ^= seq[i];
- }
- }
- static void Netchan_UnScramblePacket( msg_t *buf ) {
- unsigned seed;
- int i, j, c, mask, temp;
- int seq[MAX_PACKETLEN];
- seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
- c = buf->cursize;
- if ( c <= SCRAMBLE_START ) {
- return;
- }
- if ( c > MAX_PACKETLEN ) {
- Com_Error( ERR_DROP, "MAX_PACKETLEN" );
- }
-
- for (i = 0 ; i < c ; i++) {
- seed = (119 * seed + 1);
- seq[i] = seed;
- }
-
- for (i = SCRAMBLE_START ; i < c ; i++) {
- buf->data[i] ^= seq[i];
- }
-
- for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
- }
- mask >>= 1;
- for (i = c-1 ; i >= SCRAMBLE_START ; i--) {
- j = SCRAMBLE_START + ( seq[i] & mask );
- temp = buf->data[j];
- buf->data[j] = buf->data[i];
- buf->data[i] = temp;
- }
- }
- #endif
- void Netchan_TransmitNextFragment( netchan_t *chan ) {
- msg_t send;
- byte send_buf[MAX_PACKETLEN];
- int fragmentLength;
-
- MSG_InitOOB (&send, send_buf, sizeof(send_buf));
- MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT );
-
- if ( chan->sock == NS_CLIENT ) {
- MSG_WriteShort( &send, qport->integer );
- }
-
- fragmentLength = FRAGMENT_SIZE;
- if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) {
- fragmentLength = chan->unsentLength - chan->unsentFragmentStart;
- }
- MSG_WriteShort( &send, chan->unsentFragmentStart );
- MSG_WriteShort( &send, fragmentLength );
- MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength );
-
- NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
- if ( showpackets->integer ) {
- Com_Printf ("%s send %4i : s=%i fragment=%i,%i\n"
- , netsrcString[ chan->sock ]
- , send.cursize
- , chan->outgoingSequence
- , chan->unsentFragmentStart, fragmentLength);
- }
- chan->unsentFragmentStart += fragmentLength;
-
-
-
-
- if ( chan->unsentFragmentStart == chan->unsentLength && fragmentLength != FRAGMENT_SIZE ) {
- chan->outgoingSequence++;
- chan->unsentFragments = qfalse;
- }
- }
- void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {
- msg_t send;
- byte send_buf[MAX_PACKETLEN];
- if ( length > MAX_MSGLEN ) {
- Com_Error( ERR_DROP, "Netchan_Transmit: length = %i", length );
- }
- chan->unsentFragmentStart = 0;
-
- if ( length >= FRAGMENT_SIZE ) {
- chan->unsentFragments = qtrue;
- chan->unsentLength = length;
- Com_Memcpy( chan->unsentBuffer, data, length );
-
- Netchan_TransmitNextFragment( chan );
- return;
- }
-
- MSG_InitOOB (&send, send_buf, sizeof(send_buf));
- MSG_WriteLong( &send, chan->outgoingSequence );
- chan->outgoingSequence++;
-
- if ( chan->sock == NS_CLIENT ) {
- MSG_WriteShort( &send, qport->integer );
- }
- MSG_WriteData( &send, data, length );
-
- NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
- if ( showpackets->integer ) {
- Com_Printf( "%s send %4i : s=%i ack=%i\n"
- , netsrcString[ chan->sock ]
- , send.cursize
- , chan->outgoingSequence - 1
- , chan->incomingSequence );
- }
- }
- qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
- int sequence;
- int qport;
- int fragmentStart, fragmentLength;
- qboolean fragmented;
-
-
- MSG_BeginReadingOOB( msg );
- sequence = MSG_ReadLong( msg );
-
- if ( sequence & FRAGMENT_BIT ) {
- sequence &= ~FRAGMENT_BIT;
- fragmented = qtrue;
- } else {
- fragmented = qfalse;
- }
-
- if ( chan->sock == NS_SERVER ) {
- qport = MSG_ReadShort( msg );
- }
-
- if ( fragmented ) {
- fragmentStart = MSG_ReadShort( msg );
- fragmentLength = MSG_ReadShort( msg );
- } else {
- fragmentStart = 0;
- fragmentLength = 0;
- }
- if ( showpackets->integer ) {
- if ( fragmented ) {
- Com_Printf( "%s recv %4i : s=%i fragment=%i,%i\n"
- , netsrcString[ chan->sock ]
- , msg->cursize
- , sequence
- , fragmentStart, fragmentLength );
- } else {
- Com_Printf( "%s recv %4i : s=%i\n"
- , netsrcString[ chan->sock ]
- , msg->cursize
- , sequence );
- }
- }
-
-
-
- if ( sequence <= chan->incomingSequence ) {
- if ( showdrop->integer || showpackets->integer ) {
- Com_Printf( "%s:Out of order packet %i at %i\n"
- , NET_AdrToString( chan->remoteAddress )
- , sequence
- , chan->incomingSequence );
- }
- return qfalse;
- }
-
-
-
- chan->dropped = sequence - (chan->incomingSequence+1);
- if ( chan->dropped > 0 ) {
- if ( showdrop->integer || showpackets->integer ) {
- Com_Printf( "%s:Dropped %i packets at %i\n"
- , NET_AdrToString( chan->remoteAddress )
- , chan->dropped
- , sequence );
- }
- }
-
-
-
-
-
- if ( fragmented ) {
-
-
-
-
-
- if ( sequence != chan->fragmentSequence ) {
- chan->fragmentSequence = sequence;
- chan->fragmentLength = 0;
- }
-
- if ( fragmentStart != chan->fragmentLength ) {
- if ( showdrop->integer || showpackets->integer ) {
- Com_Printf( "%s:Dropped a message fragment\n"
- , NET_AdrToString( chan->remoteAddress )
- , sequence);
- }
-
-
- return qfalse;
- }
-
- if ( fragmentLength < 0 || msg->readcount + fragmentLength > msg->cursize ||
- chan->fragmentLength + fragmentLength > sizeof( chan->fragmentBuffer ) ) {
- if ( showdrop->integer || showpackets->integer ) {
- Com_Printf ("%s:illegal fragment length\n"
- , NET_AdrToString (chan->remoteAddress ) );
- }
- return qfalse;
- }
- Com_Memcpy( chan->fragmentBuffer + chan->fragmentLength,
- msg->data + msg->readcount, fragmentLength );
- chan->fragmentLength += fragmentLength;
-
- if ( fragmentLength == FRAGMENT_SIZE ) {
- return qfalse;
- }
- if ( chan->fragmentLength > msg->maxsize ) {
- Com_Printf( "%s:fragmentLength %i > msg->maxsize\n"
- , NET_AdrToString (chan->remoteAddress ),
- chan->fragmentLength );
- return qfalse;
- }
-
-
- *(int *)msg->data = LittleLong( sequence );
- Com_Memcpy( msg->data + 4, chan->fragmentBuffer, chan->fragmentLength );
- msg->cursize = chan->fragmentLength + 4;
- chan->fragmentLength = 0;
- msg->readcount = 4;
- msg->bit = 32;
-
-
- chan->incomingSequence = sequence;
-
- return qtrue;
- }
-
-
-
- chan->incomingSequence = sequence;
- return qtrue;
- }
- qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
- {
- if (a.type != b.type)
- return qfalse;
- if (a.type == NA_LOOPBACK)
- return qtrue;
- if (a.type == NA_IP)
- {
- if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3])
- return qtrue;
- return qfalse;
- }
- if (a.type == NA_IPX)
- {
- if ((memcmp(a.ipx, b.ipx, 10) == 0))
- return qtrue;
- return qfalse;
- }
- Com_Printf ("NET_CompareBaseAdr: bad address type\n");
- return qfalse;
- }
- const char *NET_AdrToString (netadr_t a)
- {
- static char s[64];
- if (a.type == NA_LOOPBACK) {
- Com_sprintf (s, sizeof(s), "loopback");
- } else if (a.type == NA_BOT) {
- Com_sprintf (s, sizeof(s), "bot");
- } else if (a.type == NA_IP) {
- Com_sprintf (s, sizeof(s), "%i.%i.%i.%i:%hu",
- a.ip[0], a.ip[1], a.ip[2], a.ip[3], BigShort(a.port));
- } else {
- Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x.%02x%02x%02x%02x%02x%02x:%hu",
- a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9],
- BigShort(a.port));
- }
- return s;
- }
- qboolean NET_CompareAdr (netadr_t a, netadr_t b)
- {
- if (a.type != b.type)
- return qfalse;
- if (a.type == NA_LOOPBACK)
- return qtrue;
- if (a.type == NA_IP)
- {
- if (a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] && a.port == b.port)
- return qtrue;
- return qfalse;
- }
- if (a.type == NA_IPX)
- {
- if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port)
- return qtrue;
- return qfalse;
- }
- Com_Printf ("NET_CompareAdr: bad address type\n");
- return qfalse;
- }
- qboolean NET_IsLocalAddress( netadr_t adr ) {
- return adr.type == NA_LOOPBACK;
- }
- #define MAX_LOOPBACK 16
- typedef struct {
- byte data[MAX_PACKETLEN];
- int datalen;
- } loopmsg_t;
- typedef struct {
- loopmsg_t msgs[MAX_LOOPBACK];
- int get, send;
- } loopback_t;
- loopback_t loopbacks[2];
- qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, msg_t *net_message)
- {
- int i;
- loopback_t *loop;
- loop = &loopbacks[sock];
- if (loop->send - loop->get > MAX_LOOPBACK)
- loop->get = loop->send - MAX_LOOPBACK;
- if (loop->get >= loop->send)
- return qfalse;
- i = loop->get & (MAX_LOOPBACK-1);
- loop->get++;
- Com_Memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
- net_message->cursize = loop->msgs[i].datalen;
- Com_Memset (net_from, 0, sizeof(*net_from));
- net_from->type = NA_LOOPBACK;
- return qtrue;
- }
- void NET_SendLoopPacket (netsrc_t sock, int length, const void *data, netadr_t to)
- {
- int i;
- loopback_t *loop;
- loop = &loopbacks[sock^1];
- i = loop->send & (MAX_LOOPBACK-1);
- loop->send++;
- Com_Memcpy (loop->msgs[i].data, data, length);
- loop->msgs[i].datalen = length;
- }
- void NET_SendPacket( netsrc_t sock, int length, const void *data, netadr_t to ) {
-
- if ( showpackets->integer && *(int *)data == -1 ) {
- Com_Printf ("send packet %4i\n", length);
- }
- if ( to.type == NA_LOOPBACK ) {
- NET_SendLoopPacket (sock, length, data, to);
- return;
- }
- if ( to.type == NA_BOT ) {
- return;
- }
- if ( to.type == NA_BAD ) {
- return;
- }
- Sys_SendPacket( length, data, to );
- }
- void QDECL NET_OutOfBandPrint( netsrc_t sock, netadr_t adr, const char *format, ... ) {
- va_list argptr;
- char string[MAX_MSGLEN];
-
- string[0] = -1;
- string[1] = -1;
- string[2] = -1;
- string[3] = -1;
- va_start( argptr, format );
- vsprintf( string+4, format, argptr );
- va_end( argptr );
-
- NET_SendPacket( sock, strlen( string ), string, adr );
- }
- void QDECL NET_OutOfBandData( netsrc_t sock, netadr_t adr, byte *format, int len ) {
- byte string[MAX_MSGLEN*2];
- int i;
- msg_t mbuf;
-
- string[0] = 0xff;
- string[1] = 0xff;
- string[2] = 0xff;
- string[3] = 0xff;
- for(i=0;i<len;i++) {
- string[i+4] = format[i];
- }
- mbuf.data = string;
- mbuf.cursize = len+4;
- Huff_Compress( &mbuf, 12);
-
- NET_SendPacket( sock, mbuf.cursize, mbuf.data, adr );
- }
- qboolean NET_StringToAdr( const char *s, netadr_t *a ) {
- qboolean r;
- char base[MAX_STRING_CHARS];
- char *port;
- if (!strcmp (s, "localhost")) {
- Com_Memset (a, 0, sizeof(*a));
- a->type = NA_LOOPBACK;
- return qtrue;
- }
-
- Q_strncpyz( base, s, sizeof( base ) );
- port = strstr( base, ":" );
- if ( port ) {
- *port = 0;
- port++;
- }
- r = Sys_StringToAdr( base, a );
- if ( !r ) {
- a->type = NA_BAD;
- return qfalse;
- }
-
- if ( a->ip[0] == 255 && a->ip[1] == 255 && a->ip[2] == 255 && a->ip[3] == 255 ) {
- a->type = NA_BAD;
- return qfalse;
- }
- if ( port ) {
- a->port = BigShort( (short)atoi( port ) );
- } else {
- a->port = BigShort( PORT_SERVER );
- }
- return qtrue;
- }
|