Initial commit.
This commit is contained in:
703
codemp/qcommon/net_chan.cpp
Normal file
703
codemp/qcommon/net_chan.cpp
Normal file
@@ -0,0 +1,703 @@
|
||||
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../client/cl_data.h"
|
||||
#endif
|
||||
/*
|
||||
|
||||
packet header
|
||||
-------------
|
||||
4 outgoing sequence. high bit will be set if this is a fragmented message
|
||||
[2 qport (only for client to server)]
|
||||
[2 fragment start byte]
|
||||
[2 fragment length. if < FRAGMENT_SIZE, this is the last fragment]
|
||||
|
||||
if the sequence number is -1, the packet should be handled as an out-of-band
|
||||
message instead of as part of a netcon.
|
||||
|
||||
All fragments will have the same sequence numbers.
|
||||
|
||||
The qport field is a workaround for bad address translating routers that
|
||||
sometimes remap the client's source port on a packet during gameplay.
|
||||
|
||||
If the base part of the net address matches and the qport matches, then the
|
||||
channel matches even if the IP port differs. The IP port should be updated
|
||||
to the new value before sending out any replies.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef _XBOX
|
||||
#define MAX_PACKETLEN 1359 // UDP total packet size
|
||||
#define FRAGMENT_SIZE (MAX_PACKETLEN - 55 - 10) // 55 is packet overhead ||| 10 is fudge factor - needed due to huffman?
|
||||
#else
|
||||
#define MAX_PACKETLEN 1400 // max size of a network packet
|
||||
#define FRAGMENT_SIZE (MAX_PACKETLEN - 100)
|
||||
#define PACKET_HEADER 10 // two ints and a short
|
||||
#endif
|
||||
|
||||
#define FRAGMENT_BIT (1<<31)
|
||||
|
||||
cvar_t *showpackets;
|
||||
cvar_t *showdrop;
|
||||
cvar_t *qport;
|
||||
cvar_t *net_killdroppedfragments;
|
||||
|
||||
static char *netsrcString[2] = {
|
||||
"client",
|
||||
"server"
|
||||
};
|
||||
|
||||
/*
|
||||
===============
|
||||
Netchan_Init
|
||||
|
||||
===============
|
||||
*/
|
||||
void Netchan_Init( int port ) {
|
||||
#ifdef _XBOX
|
||||
CM_START_LOOP();
|
||||
if (!ClientManager::ActiveClient().loopbacks)
|
||||
{
|
||||
Z_PushNewDeleteTag( TAG_CLIENT_MANAGER );
|
||||
|
||||
ClientManager::ActiveClient().loopbacks = new loopback_t[2];
|
||||
memset(ClientManager::ActiveClient().loopbacks, 0, sizeof(loopback_t) * 2);
|
||||
|
||||
Z_PopNewDeleteTag();
|
||||
}
|
||||
CM_END_LOOP();
|
||||
#endif
|
||||
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 );
|
||||
net_killdroppedfragments = Cvar_Get ("net_killdroppedfragments", "0", CVAR_TEMP);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Netchan_TransmitNextFragment
|
||||
|
||||
Send one fragment of the current message
|
||||
=================
|
||||
*/
|
||||
bool Netchan_TransmitNextFragment( netchan_t *chan ) {
|
||||
msg_t send;
|
||||
byte send_buf[MAX_PACKETLEN];
|
||||
int fragmentLength;
|
||||
|
||||
// write the packet header
|
||||
MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here
|
||||
|
||||
MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT );
|
||||
|
||||
// send the qport if we are a client
|
||||
if ( chan->sock == NS_CLIENT ) {
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
MSG_WriteShort( &send, ClientManager::ActivePort() );
|
||||
else
|
||||
MSG_WriteShort( &send, qport->integer );
|
||||
}
|
||||
|
||||
// copy the reliable message to the packet first
|
||||
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 );
|
||||
|
||||
// send the datagram
|
||||
bool retVal = NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
|
||||
|
||||
chan->unsentFragmentStart += fragmentLength;
|
||||
|
||||
// this exit condition is a little tricky, because a packet
|
||||
// that is exactly the fragment length still needs to send
|
||||
// a second packet of zero length so that the other side
|
||||
// can tell there aren't more to follow
|
||||
if ( chan->unsentFragmentStart == chan->unsentLength && fragmentLength != FRAGMENT_SIZE ) {
|
||||
chan->outgoingSequence++;
|
||||
chan->unsentFragments = qfalse;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Netchan_Transmit
|
||||
|
||||
Sends a message to a connection, fragmenting if necessary
|
||||
A 0 length will still generate a packet.
|
||||
================
|
||||
*/
|
||||
bool 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 (chan->unsentFragments)
|
||||
{
|
||||
Com_Printf("[ISM] Stomping Unsent Fragments %s\n",netsrcString[ chan->sock ]);
|
||||
}
|
||||
// fragment large reliable messages
|
||||
if ( length >= FRAGMENT_SIZE )
|
||||
{
|
||||
chan->unsentFragments = qtrue;
|
||||
chan->unsentLength = length;
|
||||
Com_Memcpy( chan->unsentBuffer, data, length );
|
||||
|
||||
// only send the first fragment now
|
||||
return Netchan_TransmitNextFragment( chan );
|
||||
}
|
||||
|
||||
// write the packet header
|
||||
MSG_InitOOB (&send, send_buf, sizeof(send_buf));
|
||||
|
||||
MSG_WriteLong( &send, chan->outgoingSequence );
|
||||
chan->outgoingSequence++;
|
||||
|
||||
// send the qport if we are a client
|
||||
if ( chan->sock == NS_CLIENT ) {
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
MSG_WriteShort( &send, ClientManager::ActivePort() );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
MSG_WriteShort( &send, qport->integer );
|
||||
}
|
||||
|
||||
MSG_WriteData( &send, data, length );
|
||||
|
||||
// send the datagram
|
||||
return 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 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Netchan_Process
|
||||
|
||||
Returns qfalse if the message should not be processed due to being
|
||||
out of order or a fragment.
|
||||
|
||||
Msg must be large enough to hold MAX_MSGLEN, because if this is the
|
||||
final fragment of a multi-part message, the entire thing will be
|
||||
copied out.
|
||||
=================
|
||||
*/
|
||||
qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
|
||||
int sequence;
|
||||
int qport;
|
||||
int fragmentStart, fragmentLength;
|
||||
qboolean fragmented;
|
||||
|
||||
// get sequence numbers
|
||||
MSG_BeginReadingOOB( msg );
|
||||
sequence = MSG_ReadLong( msg );
|
||||
|
||||
// check for fragment information
|
||||
if ( sequence & FRAGMENT_BIT ) {
|
||||
sequence &= ~FRAGMENT_BIT;
|
||||
fragmented = qtrue;
|
||||
} else {
|
||||
fragmented = qfalse;
|
||||
}
|
||||
|
||||
// read the qport if we are a server
|
||||
if ( chan->sock == NS_SERVER ) {
|
||||
qport = MSG_ReadShort( msg );
|
||||
}
|
||||
|
||||
// read the fragment information
|
||||
if ( fragmented ) {
|
||||
fragmentStart = (unsigned short)MSG_ReadShort( msg );
|
||||
fragmentLength = (unsigned short)MSG_ReadShort( msg );
|
||||
} else {
|
||||
fragmentStart = 0; // stop warning message
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// discard out of order or duplicated packets
|
||||
//
|
||||
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;
|
||||
}
|
||||
|
||||
//
|
||||
// dropped packets don't keep the message from being used
|
||||
//
|
||||
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 this is the final framgent of a reliable message,
|
||||
// bump incoming_reliable_sequence
|
||||
//
|
||||
if ( fragmented ) {
|
||||
// make sure we
|
||||
if ( sequence != chan->fragmentSequence ) {
|
||||
chan->fragmentSequence = sequence;
|
||||
chan->fragmentLength = 0;
|
||||
}
|
||||
|
||||
// if we missed a fragment, dump the message
|
||||
if ( fragmentStart != chan->fragmentLength ) {
|
||||
if ( showdrop->integer || showpackets->integer ) {
|
||||
Com_Printf( "%s:Dropped a message fragment\n"
|
||||
, NET_AdrToString( chan->remoteAddress )
|
||||
, sequence);
|
||||
}
|
||||
// we can still keep the part that we have so far,
|
||||
// so we don't need to clear chan->fragmentLength
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// copy the fragment to the fragment buffer
|
||||
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 this wasn't the last fragment, don't process anything
|
||||
if ( fragmentLength == FRAGMENT_SIZE ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if ( chan->fragmentLength+4 > msg->maxsize ) {
|
||||
Com_Printf( "%s:fragmentLength %i > msg->maxsize\n"
|
||||
, NET_AdrToString (chan->remoteAddress ),
|
||||
chan->fragmentLength+4 );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// copy the full message over the partial fragment
|
||||
|
||||
// make sure the sequence number is still there
|
||||
*(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; // past the sequence number
|
||||
msg->bit = 32; // past the sequence number
|
||||
|
||||
// but I am a wuss -mw
|
||||
// chan->incomingSequence = sequence; // lets not accept any more with this sequence number -gil
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
//
|
||||
// the message can now be read from the current message pointer
|
||||
//
|
||||
chan->incomingSequence = sequence;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
===================
|
||||
NET_CompareBaseAdr
|
||||
|
||||
Compares without the port
|
||||
===================
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef _XBOX // No IPX
|
||||
if (a.type == NA_IPX)
|
||||
{
|
||||
if ((memcmp(a.ipx, b.ipx, 10) == 0))
|
||||
return qtrue;
|
||||
return qfalse;
|
||||
}
|
||||
#endif
|
||||
|
||||
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:%i",
|
||||
a.ip[0], a.ip[1], a.ip[2], a.ip[3], BigShort(a.port));
|
||||
} else if (a.type == NA_BAD) {
|
||||
Com_sprintf (s, sizeof(s), "BAD");
|
||||
} else {
|
||||
Com_sprintf (s, sizeof(s), "%02x%02x%02x%02x.%02x%02x%02x%02x%02x%02x:%i",
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef _XBOX // No IPX
|
||||
if (a.type == NA_IPX)
|
||||
{
|
||||
if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port)
|
||||
return qtrue;
|
||||
return qfalse;
|
||||
}
|
||||
#endif
|
||||
|
||||
Com_Printf ("NET_CompareAdr: bad address type\n");
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
qboolean NET_IsLocalAddress( netadr_t adr ) {
|
||||
return (qboolean)(adr.type == NA_LOOPBACK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LOOPBACK BUFFERS FOR LOCAL PLAYER
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
// there needs to be enough loopback messages to hold a complete
|
||||
// gamestate of maximum size
|
||||
//#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 = (loopback_t*)&ClientManager::ActiveClient().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;
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
if (sock == NS_CLIENT)
|
||||
net_from->port = 0;// // server is on port 0;
|
||||
else if (sock == NS_SERVER)
|
||||
net_from->port = ClientManager::ActiveClientNum();
|
||||
else
|
||||
assert(0 && "what happened????");
|
||||
}
|
||||
#endif
|
||||
return qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void NET_SendLoopPacket (netsrc_t sock, int length, const void *data, netadr_t to)
|
||||
{
|
||||
int i;
|
||||
loopback_t *loop;
|
||||
|
||||
loop = (loopback_t*)&ClientManager::ActiveClient().loopbacks[sock^1];
|
||||
|
||||
i = loop->send & (MAX_LOOPBACK-1);
|
||||
loop->send++;
|
||||
|
||||
Com_Memcpy (loop->msgs[i].data, data, length);
|
||||
loop->msgs[i].datalen = length;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
bool NET_SendPacket( netsrc_t sock, int length, const void *data, netadr_t to ) {
|
||||
|
||||
// sequenced packets are shown in netchan, so just show oob
|
||||
if ( showpackets->integer && *(int *)data == -1 ) {
|
||||
Com_Printf ("send packet %4i\n", length);
|
||||
}
|
||||
|
||||
if ( to.type == NA_LOOPBACK ) {
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue)
|
||||
to.port = ClientManager::ActiveClientNum();
|
||||
#endif
|
||||
NET_SendLoopPacket (sock, length, data, to);
|
||||
return true;
|
||||
}
|
||||
if ( to.type == NA_BOT ) {
|
||||
return true;
|
||||
}
|
||||
if ( to.type == NA_BAD ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Sys_SendPacket( length, data, to );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
NET_OutOfBandPrint
|
||||
|
||||
Sends a text message in an out-of-band datagram
|
||||
================
|
||||
*/
|
||||
void QDECL NET_OutOfBandPrint( netsrc_t sock, netadr_t adr, const char *format, ... ) {
|
||||
va_list argptr;
|
||||
char string[MAX_MSGLEN];
|
||||
|
||||
|
||||
// set the header
|
||||
string[0] = -1;
|
||||
string[1] = -1;
|
||||
string[2] = -1;
|
||||
string[3] = -1;
|
||||
|
||||
va_start( argptr, format );
|
||||
vsprintf( string+4, format, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
// send the datagram
|
||||
NET_SendPacket( sock, strlen( string ), string, adr );
|
||||
}
|
||||
|
||||
// Used for packets that need to be broadcast. The only such
|
||||
// packets are "infoResponse"
|
||||
void QDECL NET_BroadcastPrint( netsrc_t sock, const char *format, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char string[MAX_MSGLEN];
|
||||
|
||||
// set the header
|
||||
string[0] = -1;
|
||||
string[1] = -1;
|
||||
string[2] = -1;
|
||||
string[3] = -1;
|
||||
|
||||
va_start( argptr, format );
|
||||
vsprintf( string+4, format, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
// send the datagram
|
||||
Sys_SendBroadcastPacket( strlen( string ), string );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
NET_OutOfBandPrint
|
||||
|
||||
Sends a data message in an out-of-band datagram (only used for "connect")
|
||||
================
|
||||
*/
|
||||
bool QDECL NET_OutOfBandData( netsrc_t sock, netadr_t adr, byte *format, int len ) {
|
||||
byte string[MAX_MSGLEN+4];
|
||||
int i;
|
||||
msg_t mbuf;
|
||||
|
||||
// set the header
|
||||
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);
|
||||
// send the datagram
|
||||
return NET_SendPacket( sock, mbuf.cursize, mbuf.data, adr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
NET_StringToAdr
|
||||
|
||||
Traps "localhost" for loopback, passes everything else to system
|
||||
=============
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
// look for a port number
|
||||
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;
|
||||
}
|
||||
|
||||
// inet_addr returns this if out of range
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user