Пример #1
0
void SV_NocPacket(netadr_t from, msg_t *msg) { //Not connected packet (Server is not running)
	char* s;
	char* c;
	if(msg->cursize >= 4) {
		if(*(int*)msg->data == -1) {
			#if 1
			int CSteamServer_HandleIncomingPacket(const void* pData, int cbData, unsigned int srcIP, unsigned short srcPort);
			if(!CSteamServer_HandleIncomingPacket((const void*)msg->data, msg->cursize, from._ip, from.port));
			#endif
		} else if(*(int*)msg->data == -2) {	
			MSG_BeginReading(msg);
			MSG_ReadLong(msg);
			
			s = MSG_ReadStringLine(msg);
			
			Cmd_TokenizeString(s);
			
			c = Cmd_Argv(0);
			
			if(!Q_stricmp(c, "serverversionresponse")) {
				if(!NET_CompareBaseAdr(from, x_master))
					return;
			} else if(!Q_stricmp(c, "clientversionresponse")) {
				if(!NET_CompareBaseAdr(from, x_master))
					return;
				clientversion = atoi( Cmd_Argv(1) );
			}
		}
	}
}
Пример #2
0
/*
 * =================
 * SV_ReadPackets
 * =================
 */
void SV_ReadPackets(void)
{
    int      i;
    client_t *cl;
    int      qport;

    while (NET_GetPacket(NS_SERVER, &net_from, &net_message))
    {
        // check for connectionless packet (0xffffffff) first
        if (*(int *)net_message.data == -1)
        {
            SV_ConnectionlessPacket();
            continue;
        }

        // read the qport out of the message so we can fix up
        // stupid address translating routers
        MSG_BeginReading(&net_message);
        MSG_ReadLong(&net_message);                     // sequence number
        MSG_ReadLong(&net_message);                     // sequence number
        qport = MSG_ReadShort(&net_message) & 0xffff;

        // check for packets from connected clients
        for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++)
        {
            if (cl->state == cs_free)
            {
                continue;
            }
            if (!NET_CompareBaseAdr(net_from, cl->netchan.remote_address))
            {
                continue;
            }
            if (cl->netchan.qport != qport)
            {
                continue;
            }
            if (cl->netchan.remote_address.port != net_from.port)
            {
                Com_Printf("SV_ReadPackets: fixing up a translated port\n");
                cl->netchan.remote_address.port = net_from.port;
            }

            if (Netchan_Process(&cl->netchan, &net_message))
            {                   // this is a valid, sequenced packet, so process it
                if (cl->state != cs_zombie)
                {
                    cl->lastmessage = svs.realtime;                     // don't timeout
                    SV_ExecuteClientMessage(cl);
                }
            }
            break;
        }

        if (i != maxclients->value)
        {
            continue;
        }
    }
}
Пример #3
0
/*
=================
SV_ConnectionlessPacket

A connectionless packet has four leading 0xff
characters to distinguish it from a game channel.
Clients that are in the game can still send
connectionless packets.
=================
*/
static void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
	char	*s;
	char	*c;

	MSG_BeginReading( msg );
	MSG_ReadLong( msg );		// skip the -1 marker

	s = MSG_ReadStringLine( msg );

	Cmd_TokenizeString( s );

	c = Cmd_Argv(0);
	Com_DPrintf ("SV packet %s : %s\n", NET_AdrToString(from), c);

	if (!strcmp(c,"getstatus")) {
		SVC_Status( from  );
	} else if (!strcmp(c,"getinfo")) {
		SVC_Info( from );
	} else if (!strcmp(c,"connect")) {
		SV_DirectConnect( from );
	} else if (!strcmp(c,"disconnect")) {
		// if a client starts up a local server, we may see some spurious
		// server disconnect messages when their new server sees our final
		// sequenced messages to the old client
	} else {
		Com_DPrintf ("bad connectionless packet from %s:\n%s\n"
		, NET_AdrToString (from), s);
	}
}
Пример #4
0
void NQD_ReadPackets (void)
{
	while (CL_GetNQDemoMessage()) {
		MSG_BeginReading ();
		CLNQ_ParseServerMessage();
	}
}
Пример #5
0
/*
* SV_ProcessPacket
*/
static qboolean SV_ProcessPacket( netchan_t *netchan, msg_t *msg )
{
	int zerror;

	if( !Netchan_Process( netchan, msg ) )
		return qfalse; // wasn't accepted for some reason

	// now if compressed, expand it
	MSG_BeginReading( msg );
	MSG_ReadLong( msg ); // sequence
	MSG_ReadLong( msg ); // sequence_ack
	MSG_ReadShort( msg ); // game_port
	if( msg->compressed )
	{
		zerror = Netchan_DecompressMessage( msg );
		if( zerror < 0 )
		{
			// compression error. Drop the packet
			Com_DPrintf( "SV_ProcessPacket: Compression error %i. Dropping packet\n", zerror );
			return qfalse;
		}
	}

	return qtrue;
}
Пример #6
0
/*
=================
SV_ConnectionlessPacket

A connectionless packet has four leading 0xff
characters to distinguish it from a game channel.
Clients that are in the game can still send
connectionless packets.
=================
*/
void SV_ConnectionlessPacket(void)
{
    const char * s;
    const char * c;

    MSG_BeginReading(&net_message);
    MSG_ReadLong(&net_message); // skip the -1 marker

    s = MSG_ReadStringLine(&net_message);

    Cmd_TokenizeString(s, false);

    c = Cmd_Argv(0);
    Com_DPrintf("Packet %s : %s\n", NET_AdrToString(net_from), c);

    if (!strcmp(c, "ping"))
        SVC_Ping();
    else if (!strcmp(c, "ack"))
        SVC_Ack();
    else if (!strcmp(c, "status"))
        SVC_Status();
    else if (!strcmp(c, "info"))
        SVC_Info();
    else if (!strcmp(c, "getchallenge"))
        SVC_GetChallenge();
    else if (!strcmp(c, "connect"))
        SVC_DirectConnect();
    else if (!strcmp(c, "rcon"))
        SVC_RemoteCommand();
    else
        Com_Printf("bad connectionless packet from %s:\n%s\n", NET_AdrToString(net_from), s);
}
Пример #7
0
/*
* SV_ConnectionlessPacket
* 
* A connectionless packet has four leading 0xff
* characters to distinguish it from a game channel.
* Clients that are in the game can still send
* connectionless packets.
*/
void SV_ConnectionlessPacket( const socket_t *socket, const netadr_t *address, msg_t *msg )
{
	connectionless_cmd_t *cmd;
	char *s, *c;

	MSG_BeginReading( msg );
	MSG_ReadLong( msg );    // skip the -1 marker

	s = MSG_ReadStringLine( msg );

	Cmd_TokenizeString( s );

	c = Cmd_Argv( 0 );
	Com_DPrintf( "Packet %s : %s\n", NET_AddressToString( address ), c );

	for( cmd = connectionless_cmds; cmd->name; cmd++ )
	{
		if( !strcmp( c, cmd->name ) )
		{
			cmd->func( socket, address );
			return;
		}
	}

	Com_DPrintf( "Bad connectionless packet from %s:\n%s\n", NET_AddressToString( address ), s );
}
Пример #8
0
/*
* TV_Downstream_UpstreamlessPacket
*/
void TV_Downstream_UpstreamlessPacket( const socket_t *socket, const netadr_t *address, msg_t *msg )
{
	upstreamless_cmd_t *cmd;
	char *s, *c;

	MSG_BeginReading( msg );
	MSG_ReadLong( msg );    // skip the -1 marker

	s = MSG_ReadStringLine( msg );

	if( TV_Downstream_SteamServerQuery( s, socket, address, msg ) )
		return;

	Cmd_TokenizeString( s );
	c = Cmd_Argv( 0 );

	for( cmd = upstreamless_cmds; cmd->name; cmd++ )
	{
		if( !strcmp( c, cmd->name ) )
		{
			cmd->func( socket, address );
			return;
		}
	}

	Com_DPrintf( "Bad downstream connectionless packet from %s:\n%s\n", NET_AddressToString( address ), s );
}
Пример #9
0
/*
=================
SV_ReadPackets
=================
*/
void SV_PacketEvent( netadr_t from, msg_t *msg ) {
	int			i;
	client_t	*cl;
	int			qport;

	// check for connectionless packet (0xffffffff) first
	if ( msg->cursize >= 4 && *(int *)msg->data == -1) {
		SV_ConnectionlessPacket( from, msg );
		return;
	}

	// read the qport out of the message so we can fix up
	// stupid address translating routers
	MSG_BeginReading( msg );
	MSG_ReadLong( msg );				// sequence number
	MSG_ReadLong( msg );				// sequence number
	qport = MSG_ReadShort( msg ) & 0xffff;

	// find which client the message is from
	for (i=0, cl=svs.clients ; i < 1 ; i++,cl++) {
		if (cl->state == CS_FREE) {
			continue;
		}
		if ( !NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) ) {
			continue;
		}
		// it is possible to have multiple clients from a single IP
		// address, so they are differentiated by the qport variable
		if (cl->netchan.qport != qport) {
			continue;
		}

		// the IP port can't be used to differentiate them, because
		// some address translating routers periodically change UDP
		// port assignments
		if (cl->netchan.remoteAddress.port != from.port) {
			Com_Printf( "SV_ReadPackets: fixing up a translated port\n" );
			cl->netchan.remoteAddress.port = from.port;
		}

		// make sure it is a valid, in sequence packet
		if (Netchan_Process(&cl->netchan, msg)) {
			// zombie clients stil neet to do the Netchan_Process
			// to make sure they don't need to retransmit the final
			// reliable message, but they don't do any other processing
			if (cl->state != CS_ZOMBIE) {
				cl->lastPacketTime = sv.time;	// don't timeout
				cl->frames[ cl->netchan.incomingAcknowledged & PACKET_MASK ]
					.messageAcked = sv.time;
				SV_ExecuteClientMessage( cl, msg );
			}
		}
		return;
	}
	
	// if we received a sequenced packet from an address we don't reckognize,
	// send an out of band disconnect packet to it
	NET_OutOfBandPrint( NS_SERVER, from, "disconnect" );
}
Пример #10
0
/*
 * =================
 * SV_ConnectionlessPacket
 *
 * A connectionless packet has four leading 0xff
 * characters to distinguish it from a game channel.
 * Clients that are in the game can still send
 * connectionless packets.
 * =================
 */
void SV_ConnectionlessPacket(void)
{
    char *s;
    char *c;

    // r1ch fix: make sure we never talk to ourselves
//	if (NET_IsLocalAddress (net_from.ip[0] == 127) && !NET_IsLocalHost(net_from) && ShortSwap(net_from.port) == server_port)

/*	if ( (net_from.ip[0] == 127) && (net_from.type != NA_LOOPBACK) && (ShortSwap(net_from.port) == server_port) )
 *      {
 *              Com_DPrintf ("dropped %d byte connectionless packet from self! (spoofing attack?)\n", net_message.cursize);
 *              return;
 *      }*/

    MSG_BeginReading(&net_message);
    MSG_ReadLong(&net_message);                 // skip the -1 marker

    s = MSG_ReadStringLine(&net_message);

    Cmd_TokenizeString(s, false);

    c = Cmd_Argv(0);
    Com_DPrintf("Packet %s : %s\n", NET_AdrToString(net_from), c);

    if (!strcmp(c, "ping"))
    {
        SVC_Ping();
    }
    else if (!strcmp(c, "ack"))
    {
        SVC_Ack();
    }
    else if (!strcmp(c, "status"))
    {
        SVC_Status();
    }
    else if (!strcmp(c, "info"))
    {
        SVC_Info();
    }
    else if (!strcmp(c, "getchallenge"))
    {
        SVC_GetChallenge();
    }
    else if (!strcmp(c, "connect"))
    {
        SVC_DirectConnect();
    }
    else if (!strcmp(c, "rcon"))
    {
        SVC_RemoteCommand();
    }
    else
    {
        Com_Printf("bad connectionless packet from %s:\n%s\n"
                   , NET_AdrToString(net_from), s);
    }
}
Пример #11
0
static void Test_Poll(void)
{
    struct qsockaddr clientaddr;
    int		control;
    int		len;
    char	name[32];
    char	address[64];
    int		colors;
    int		frags;
    int		connectTime;
    byte	playerNumber;

    net_landriverlevel = testDriver;

    while (1) {
        len = dfunc.Read(testSocket, net_message.data, net_message.maxsize, &clientaddr);
        if (len < sizeof(int)) {
            break;
        }

        net_message.cursize = len;

        MSG_BeginReading();
        control = BigLong(*((int *)net_message.data));
        MSG_ReadLong();
        if (control == -1) {
            break;
        }
        if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL) {
            break;
        }
        if ((control & NETFLAG_LENGTH_MASK) != len) {
            break;
        }

        if (MSG_ReadByte() != CCREP_PLAYER_INFO) {
            Sys_Error("Unexpected repsonse to Player Info request\n");
        }

        playerNumber = MSG_ReadByte();
        Q_strcpy(name, MSG_ReadString());
        colors = MSG_ReadLong();
        frags = MSG_ReadLong();
        connectTime = MSG_ReadLong();
        Q_strcpy(address, MSG_ReadString());

        Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
    }

    testPollCount--;
    if (testPollCount) {
        SchedulePollProcedure(&testPollProcedure, 0.1);
    } else {
        dfunc.CloseSocket(testSocket);
        testInProgress = false;
    }
}
Пример #12
0
static void Test2_Poll(void)
{
	struct qsockaddr clientaddr;
	int		control;
	int		len;
	char	name[256];
	char	value[256];

	net_landriverlevel = test2Driver;
	name[0] = 0;

	len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
	if (len < sizeof(int))
		goto Reschedule;

	net_message.cursize = len;

	MSG_BeginReading ();
	control = BigLong(*((int *)net_message.data));
	MSG_ReadLong();
	if (control == -1)
		goto Error;
	if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
		goto Error;
	if ((control & NETFLAG_LENGTH_MASK) != len)
		goto Error;

	if (MSG_ReadByte() != CCREP_RULE_INFO)
		goto Error;

	Q_strcpy(name, MSG_ReadString());
	if (name[0] == 0)
		goto Done;
	Q_strcpy(value, MSG_ReadString());

	Con_Printf("%-16.16s  %-16.16s\n", name, value);

	SZ_Clear(&net_message);
	// save space for the header, filled in later
	MSG_WriteLong(&net_message, 0);
	MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
	MSG_WriteString(&net_message, name);
	*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
	dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
	SZ_Clear(&net_message);

Reschedule:
	SchedulePollProcedure(&test2PollProcedure, 0.05);
	return;

Error:
	Con_Printf("Unexpected repsonse to Rule Info request\n");
Done:
	dfunc.CloseSocket(test2Socket);
	test2InProgress = false;
	return;
}
Пример #13
0
unsigned char *W_ConvertWAD3TextureBGRA(sizebuf_t *sb)
{
	unsigned char *in, *data, *out, *pal;
	int d, p;
	unsigned char name[16];
	unsigned int mipoffset[4];

	MSG_BeginReading(sb);
	MSG_ReadBytes(sb, 16, name);
	image_width = MSG_ReadLittleLong(sb);
	image_height = MSG_ReadLittleLong(sb);
	mipoffset[0] = MSG_ReadLittleLong(sb);
	mipoffset[1] = MSG_ReadLittleLong(sb); // should be mipoffset[0] + image_width*image_height
	mipoffset[2] = MSG_ReadLittleLong(sb); // should be mipoffset[1] + image_width*image_height/4
	mipoffset[3] = MSG_ReadLittleLong(sb); // should be mipoffset[2] + image_width*image_height/16
	pal = sb->data + mipoffset[3] + (image_width / 8 * image_height / 8) + 2;

	// bail if any data looks wrong
	if (image_width < 0
	 || image_width > 4096
	 || image_height < 0
	 || image_height > 4096
	 || mipoffset[0] != 40
	 || mipoffset[1] != mipoffset[0] + image_width * image_height
	 || mipoffset[2] != mipoffset[1] + image_width / 2 * image_height / 2
	 || mipoffset[3] != mipoffset[2] + image_width / 4 * image_height / 4
	 || (unsigned int)sb->cursize < (mipoffset[3] + image_width / 8 * image_height / 8 + 2 + 768))
		return NULL;

	in = (unsigned char *)sb->data + mipoffset[0];
	data = out = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
	if (!data)
		return NULL;
	for (d = 0;d < image_width * image_height;d++)
	{
		p = *in++;
		if (name[0] == '{' && p == 255)
			out[0] = out[1] = out[2] = out[3] = 0;
		else
		{
			p *= 3;
			out[2] = pal[p];
			out[1] = pal[p+1];
			out[0] = pal[p+2];
			out[3] = 255;
		}
		out += 4;
	}
	return data;
}
Пример #14
0
/*
=================
SV_ConnectionlessPacket

A connectionless packet has four leading 0xff
characters to distinguish it from a game channel.
Clients that are in the game can still send
connectionless packets.
=================
*/
static void SV_ConnectionlessPacket (void)
{
	const char	*s;
	const char	*c;

	MSG_BeginReading ();
	MSG_ReadLong ();	// skip the -1 marker

	s = MSG_ReadStringLine ();

	Cmd_TokenizeString (s);

	c = Cmd_Argv(0);

	if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) )
	{
		SVC_Ping ();
		return;
	}
	if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') )
	{
		Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from));
		return;
	}
	else if (c[0] == A2S_ECHO)
	{
		NET_SendPacket (net_message.cursize, net_message.data, net_from);
		return;
	}
	else if (!strcmp(c,"status"))
	{
		SVC_Status ();
		return;
	}
	else if (!strcmp(c,"log"))
	{
		SVC_Log ();
		return;
	}
	else if (!strcmp(c,"connect"))
	{
		SVC_DirectConnect ();
		return;
	}
	else if (!strcmp(c, "rcon"))
		SVC_RemoteCommand ();
	else
		Con_Printf ("bad connectionless packet from %s:\n%s\n", NET_AdrToString (net_from), s);
}
Пример #15
0
/* <66786> ../engine/net_chan.c:1723 */
qboolean Netchan_CopyNormalFragments(netchan_t *chan)
{
	fragbuf_t *p, *n;

	if (!chan->incomingready[FRAG_NORMAL_STREAM])
		return FALSE;

	if (!chan->incomingbufs[FRAG_NORMAL_STREAM])
	{
		Con_Printf("Netchan_CopyNormalFragments:  Called with no fragments readied\n");
		chan->incomingready[FRAG_NORMAL_STREAM] = FALSE;
		return FALSE;
	}

	p = chan->incomingbufs[FRAG_NORMAL_STREAM];

	SZ_Clear(&net_message);
	MSG_BeginReading();

	while (p)
	{
		n = p->next;

		SZ_Write(&net_message, p->frag_message.data, p->frag_message.cursize);

		Mem_Free(p);
		p = n;
	}

	if (*(uint32 *)net_message.data == MAKEID('B', 'Z', '2', '\0'))
	{
		char uncompressed[65536];
		unsigned int uncompressedSize = 65536;
		BZ2_bzBuffToBuffDecompress(uncompressed, &uncompressedSize, (char*)net_message.data + 4, net_message.cursize - 4, 1, 0);
		Q_memcpy(net_message.data, uncompressed, uncompressedSize);
		net_message.cursize = uncompressedSize;
	}

	chan->incomingbufs[FRAG_NORMAL_STREAM] = NULL;
	chan->incomingready[FRAG_NORMAL_STREAM] = false;

	return TRUE;
}
Пример #16
0
/*
=================
SV_ConnectionlessPacket

A connectionless packet has four leading 0xff
characters to distinguish it from a game channel.
Clients that are in the game can still send
connectionless packets.
=================
*/
void SV_ConnectionlessPacket (void)
{
    char	*s;
    char	*c;
    int s_token = 0;
    // r1ch fix: make sure we never talk to ourselves
//	if (NET_IsLocalAddress (net_from.ip[0] == 127) && !NET_IsLocalHost(net_from) && ShortSwap(net_from.port) == server_port)
    /*	if ( (net_from.ip[0] == 127) && (net_from.type != NA_LOOPBACK) && (ShortSwap(net_from.port) == server_port) )
    	{
    		Com_DPrintf ("dropped %d byte connectionless packet from self! (spoofing attack?)\n", net_message.cursize);
    		return;
    	}*/

    MSG_BeginReading (&net_message);
    MSG_ReadLong (&net_message);		// skip the -1 marker

    s = MSG_ReadStringLine (&net_message);

    Cmd_TokenizeString (s, false);

    c = Cmd_Argv(0);
    Com_DPrintf ("Packet %s : %s\n", NET_AdrToString(net_from), c);

    if ((s_token = Q_STLookup(&packet_stable, c)) != -1) {
        if (s_token == s_ping)
            SVC_Ping ();
        else if (s_token == s_ack)
            SVC_Ack ();
        else if (s_token == s_status)
            SVC_Status ();
        else if (s_token == s_info)
            SVC_Info ();
        else if (s_token == s_getchallenge)
            SVC_GetChallenge ();
        else if (s_token == s_connect)
            SVC_DirectConnect ();
        else if (s_token == s_rcon)
            SVC_RemoteCommand ();
    } else
        Com_Printf ("bad connectionless packet from %s:\n%s\n"
                    , NET_AdrToString (net_from), s);
}
Пример #17
0
/*
* TV_Upstream_ConnectionlessPacket
*/
void TV_Upstream_ConnectionlessPacket( upstream_t *upstream, msg_t *msg ) {
	upstreamless_cmd_t *cmd;
	char *s, *c;

	MSG_BeginReading( msg );
	MSG_ReadInt32( msg );    // skip the -1 marker

	s = MSG_ReadStringLine( msg );
	Cmd_TokenizeString( s );
	c = Cmd_Argv( 0 );

	for( cmd = upstream_upstreamless_cmds; cmd->name; cmd++ ) {
		if( !strcmp( c, cmd->name ) ) {
			cmd->func( upstream, msg );
			return;
		}
	}

	Com_DPrintf( "%s" S_COLOR_WHITE ": Bad upstream connectionless packet: %s\n", upstream->name, c );
}
Пример #18
0
/* Detecting the clientside protocol and process the 1st chunk of data if it is a http client */
tcpclientstate_t HTTPServer_AuthEvent(netadr_t* from, msg_t* msg, int *connectionId)
{
	
	ftRequest_t* request;
	*connectionId = 0;
	
	char protocol[MAX_STRING_CHARS];
	char* line;
	
	MSG_BeginReading(msg);
	
	line = MSG_ReadStringLine(msg, protocol, sizeof(protocol));
	if (line != NULL) {
		if ( Q_strncmp(line, "GET", 3) && Q_strncmp(line, "POST", 4) && Q_strncmp(line, "HEAD", 4) ) {
			return TCP_AUTHNOTME;
		}
		if( strstr(line, "HTTP/1.0") == NULL && strstr(line, "HTTP/1.1") == NULL )
		{
			/* Is not a HTTP client */
			return TCP_AUTHNOTME;
		}
	}
	
	request = FT_CreateRequest(NULL, NULL);
	
	if(request == NULL)
		return TCP_AUTHBAD;
	
	*connectionId = (int)request;

	
	if (HTTPServer_Event(from, msg, *connectionId) == qtrue)
	{
		return TCP_AUTHBAD;
	}	

	return TCP_AUTHSUCCESSFULL;
}
Пример #19
0
static void demoPlayForwardFrame( demoPlay_t *play ) {
	int			blockSize;
	msg_t		msg;
	demoFrame_t *copyFrame;

	if (play->filePos + 4 > play->fileSize) {
		play->lastFrame = qtrue;
		return;
	}
	play->lastFrame = qfalse;
	play->filePos += 4;
	FS_Read( &blockSize, 4, play->fileHandle );
	blockSize = LittleLong( blockSize );
	FS_Read( demoBuffer, blockSize, play->fileHandle );
	play->filePos += blockSize;
	MSG_Init( &msg, demoBuffer, sizeof(demoBuffer) );
	MSG_BeginReading( &msg );
	msg.cursize = blockSize;
	copyFrame = play->frame;
	play->frame = play->nextFrame;
	play->nextFrame = copyFrame;
	demoFrameUnpack( &msg, play->frame, play->nextFrame );
	play->frameNumber++;
}
Пример #20
0
static void
qtv_connectionless_packet (void)
{
	const char *cmd, *str;

	MSG_BeginReading (net_message);
	MSG_ReadLong (net_message);			// skip the -1 marker

	str = MSG_ReadString (net_message);
	COM_TokenizeString (str, qtv_args);
	cmd_args = qtv_args;

	cmd = qtv_args->argv[0]->str;
	if (!strcmp (cmd, "ping")) {
		qtv_ping ();
	} else if (!strcmp (cmd, "status")) {
		qtv_status ();
	} else if (!strcmp (cmd, "getchallenge")) {
		Client_NewConnection ();
	} else if (cmd[0]) {
		switch (cmd[0]) {
			default:
				goto bad_packet;
			case A2C_PRINT:
				Sys_Printf ("%s", str + 1);
				break;
			case A2A_PING:
				qtv_ping ();
				break;
		}
	} else {
bad_packet:
		Sys_Printf ("bad connectionless packet from %s:\n%s\n",
					NET_AdrToString (net_from), str);
	}
}
Пример #21
0
/*
* Netchan_Process
* 
* Returns false 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.
*/
bool Netchan_Process( netchan_t *chan, msg_t *msg )
{
	int sequence, sequence_ack;
	int game_port = -1;
	int fragmentStart, fragmentLength;
	bool fragmented = false;
	int headerlength;
	bool compressed = false;
	bool lastfragment = false;

	// get sequence numbers
	MSG_BeginReading( msg );
	sequence = MSG_ReadLong( msg );
	sequence_ack = MSG_ReadLong( msg ); // wsw : jal : by now our header sends incoming ack too (q3 doesn't)

	// check for fragment information
	if( sequence & FRAGMENT_BIT )
	{
		sequence &= ~FRAGMENT_BIT;
		fragmented = true;

		if( net_showfragments->integer )
			Com_Printf( "Process fragmented packet (%s) (id:%i)\n", NET_SocketToString( chan->socket ), sequence );
	}
	else
	{
		fragmented = false;
	}

	// wsw : jal : check for compressed information
	if( sequence_ack & FRAGMENT_BIT )
	{
		sequence_ack &= ~FRAGMENT_BIT;
		compressed = true;
		if( !fragmented )
			msg->compressed = true;
	}

	// read the game port if we are a server
	if( chan->socket->server )
		game_port = MSG_ReadShort( msg );

	// read the fragment information
	if( fragmented )
	{
		fragmentStart = MSG_ReadShort( msg );
		fragmentLength = MSG_ReadShort( msg );
		if( fragmentLength & FRAGMENT_LAST )
		{
			lastfragment = true;
			fragmentLength &= ~FRAGMENT_LAST;
		}
	}
	else
	{
		fragmentStart = 0; // stop warning message
		fragmentLength = 0;
	}

	if( showpackets->integer )
	{
		if( fragmented )
		{
			Com_Printf( "%s recv %4i : s=%i fragment=%i,%i\n", NET_SocketToString( chan->socket ), msg->cursize,
				sequence, fragmentStart, fragmentLength );
		}
		else
		{
			Com_Printf( "%s recv %4i : s=%i\n", NET_SocketToString( chan->socket ), 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_AddressToString( &chan->remoteAddress ), sequence,
				chan->incomingSequence );
		}
		return false;
	}

	//
	// 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_AddressToString( &chan->remoteAddress ), chan->dropped,
				sequence );
		}
	}

	//
	// if this is the final framgent of a reliable message,
	// bump incoming_reliable_sequence
	//
	if( fragmented )
	{
		// TTimo
		// make sure we add the fragments in correct order
		// either a packet was dropped, or we received this one too soon
		// we don't reconstruct the fragments. we will wait till this fragment gets to us again
		// (NOTE: we could probably try to rebuild by out of order chunks if needed)
		if( sequence != chan->fragmentSequence )
		{
			chan->fragmentSequence = sequence;
			chan->fragmentLength = 0;
		}

		// if we missed a fragment, dump the message
		if( fragmentStart != (int) chan->fragmentLength )
		{
			if( showdrop->integer || showpackets->integer )
			{
				Com_Printf( "%s:Dropped a message fragment\n", NET_AddressToString( &chan->remoteAddress ), sequence );
			}
			// we can still keep the part that we have so far,
			// so we don't need to clear chan->fragmentLength
			return false;
		}

		// 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_AddressToString( &chan->remoteAddress ) );
			}
			return false;
		}

		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( !lastfragment )
		{
			return false;
		}

		if( chan->fragmentLength > msg->maxsize )
		{
			Com_Printf( "%s:fragmentLength %i > msg->maxsize\n", NET_AddressToString( &chan->remoteAddress ),
				chan->fragmentLength );
			return false;
		}

		// wsw : jal : reconstruct the message

		MSG_Clear( msg );
		MSG_WriteLong( msg, sequence );
		MSG_WriteLong( msg, sequence_ack );
		if( chan->socket->server )
			MSG_WriteShort( msg, game_port );

		msg->compressed = compressed;

		headerlength = msg->cursize;
		MSG_CopyData( msg, chan->fragmentBuffer, chan->fragmentLength );
		msg->readcount = headerlength; // put read pointer after header again
		chan->fragmentLength = 0;

		//let it be finished as standard packets
	}

	// the message can now be read from the current message pointer
	chan->incomingSequence = sequence;

	// wsw : jal[start] :  get the ack from the very first fragment
	chan->incoming_acknowledged = sequence_ack;
	// wsw : jal[end]

	return true;
}
Пример #22
0
/*
=================
SV_ConnectionlessPacket

A connectionless packet has four leading 0xff
characters to distinguish it from a game channel.
Clients that are in the game can still send
connectionless packets.
=================
*/
void SV_ConnectionlessPacket (void)
{
	char	*s;
	char	*c;

	MSG_BeginReading ();
	MSG_ReadLong ();		// skip the -1 marker

	s = MSG_ReadStringLine ();
	s[1023] = 0;

	Cmd_TokenizeString (s);

	c = Cmd_Argv(0);

	if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) )
	{
		SVC_Ping ();
		return;
	}
	if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') )
	{
		Com_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from));
		return;
	}
	else if (!strcmp(c,"status"))
	{
		SVC_Status ();
		return;
	}
	else if (!strcmp(c,"log"))
	{
		SVC_Log ();
		return;
	}
	else if (!strcmp(c,"connect"))
	{
		SVC_DirectConnect ();
		return;
	}
#ifdef MAUTH
	else if (c[0] == M2S_AUTH_TOK && (c[1] == 0 || c[1] == '\n') )
	{
        Com_Printf("MAUTH: Adding token from %s to auth queue\n", NET_AdrToString(net_from));
        // Provisionally add auth record...
        if (SV_AuthListAdd(&authtokq))
        {
            //SV_AuthListPrint(&authtokq);
            //SV_AuthListPrint(&authclientq);
            // Send S2M_AUTH_TOK_CHK as a spoofing check...
            Master_AuthTokChk(authtokq.start->name, authtokq.start->hash);
        }
        else
        {
            Com_Printf("MAUTH: Failure to add token from %s -- already added?\n", NET_AdrToString(net_from));
            // FIXME Send S2M_AUTH_TOK_NACK
        }
		return;
	}
	else if (c[0] == M2S_AUTH_TOK_ACK && (c[1] == 0 || c[1] == '\n') )
	{
        // The master is sending us the correct name and hash;
        // check that what we've got agrees with this.

        // FIXME do we trust this packet?
       
        char tok_ack = S2C_AUTH_TOK_ACK;
        authclient_t *newclient = NULL;
        qbool result;
        result = SV_AuthListValidate(&authtokq, &newclient);
        //SV_AuthListPrint(&authtokq);
        //SV_AuthListPrint(&authclientq);

        // Check the client is valid...
        if( !result )
        {
            Com_Printf("MAUTH: Client is not valid!\n");
            return;
        }
        
        // Tell client they can connect...
        Com_Printf("MAUTH: Telling client %s on %s to connect...\n", newclient->name, NET_AdrToString(newclient->client_addr));
		NET_SendPacket (NS_SERVER, 1, &tok_ack, newclient->client_addr);
		return;
	}
	/*else if (c[0] == M2S_AUTH_TOK_NACK && (c[1] == 0 || c[1] == '\n') )
    {
        // Master said this token not valid -- FIXME how can we trust this?
        // FIXME remove player details from auth queue.
        Com_Printf("MAUTH: Player invalid!\n");
    }*/
#endif
	else if (!strcmp(c,"getchallenge"))
	{
		SVC_GetChallenge ();
		return;
	}
	else if (!strcmp(c, "rcon"))
		SVC_RemoteCommand ();
	else
		Com_Printf ("bad connectionless packet from %s:\n%s\n"
		, NET_AdrToString (net_from), s);
}
Пример #23
0
static qsocket_t *_Datagram_Connect (char *host)
{
	struct qsockaddr sendaddr;
	struct qsockaddr readaddr;
	qsocket_t	*sock;
	int			newsock;
	int			ret;
	int			reps;
	double		start_time;
	int			control;
	char		*reason;

	// see if we can resolve the host name
	if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
		return NULL;

	newsock = dfunc.OpenSocket (0);
	if (newsock == -1)
		return NULL;

	sock = NET_NewQSocket ();
	if (sock == NULL)
		goto ErrorReturn2;
	sock->socket = newsock;
	sock->landriver = net_landriverlevel;

	// connect to the host
	if (dfunc.Connect (newsock, &sendaddr) == -1)
		goto ErrorReturn;

	// send the connection request
	Con_Printf("trying...\n"); SCR_UpdateScreen ();
	start_time = net_time;

	for (reps = 0; reps < 3; reps++)
	{
		SZ_Clear(&net_message);
		// save space for the header, filled in later
		MSG_WriteLong(&net_message, 0);
		MSG_WriteByte(&net_message, CCREQ_CONNECT);
		MSG_WriteString(&net_message, "QUAKE");
		MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
		dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
		SZ_Clear(&net_message);
		do
		{
			ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
			// if we got something, validate it
			if (ret > 0)
			{
				// is it from the right place?
				if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
				{
#ifdef DEBUG
					Con_Printf("wrong reply address\n");
					Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
					Con_Printf("Received: %s\n", StrAddr (&readaddr));
					SCR_UpdateScreen ();
#endif
					ret = 0;
					continue;
				}

				if (ret < sizeof(int))
				{
					ret = 0;
					continue;
				}

				net_message.cursize = ret;
				MSG_BeginReading ();

				control = BigLong(*((int *)net_message.data));
				MSG_ReadLong();
				if (control == -1)
				{
					ret = 0;
					continue;
				}
				if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
				{
					ret = 0;
					continue;
				}
				if ((control & NETFLAG_LENGTH_MASK) != ret)
				{
					ret = 0;
					continue;
				}
			}
		}
		while (ret == 0 && (SetNetTime() - start_time) < 2.5);
		if (ret)
			break;
		Con_Printf("still trying...\n"); SCR_UpdateScreen ();
		start_time = SetNetTime();
	}

	if (ret == 0)
	{
		reason = "No Response";
		Con_Printf("%s\n", reason);
		Q_strcpy(m_return_reason, reason);
		goto ErrorReturn;
	}

	if (ret == -1)
	{
		reason = "Network Error";
		Con_Printf("%s\n", reason);
		Q_strcpy(m_return_reason, reason);
		goto ErrorReturn;
	}

	ret = MSG_ReadByte();
	if (ret == CCREP_REJECT)
	{
		reason = MSG_ReadString();
		Con_Printf(reason);
		Q_strncpy(m_return_reason, reason, 31);
		goto ErrorReturn;
	}

	if (ret == CCREP_ACCEPT)
	{
		Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
		dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
	}
	else
	{
		reason = "Bad Response";
		Con_Printf("%s\n", reason);
		Q_strcpy(m_return_reason, reason);
		goto ErrorReturn;
	}

	dfunc.GetNameFromAddr (&sendaddr, sock->address);

	Con_Printf ("Connection accepted\n");
	sock->lastMessageTime = SetNetTime();

	// switch the connection to the specified address
	if (dfunc.Connect (newsock, &sock->addr) == -1)
	{
		reason = "Connect to Game failed";
		Con_Printf("%s\n", reason);
		Q_strcpy(m_return_reason, reason);
		goto ErrorReturn;
	}

	m_return_onerror = false;
	return sock;

ErrorReturn:
	NET_FreeQSocket(sock);
ErrorReturn2:
	dfunc.CloseSocket(newsock);
	if (m_return_onerror)
	{
		key_dest = key_menu;
		m_state = m_return_state;
		m_return_onerror = false;
	}
	return NULL;
}
Пример #24
0
/*
=====================
CL_ParseServerMessage
=====================
*/
void
CL_ParseServerMessage(void)
{
    unsigned int bits;
    int i, cmd, prevcmd;
    int playernum, version, stylenum, signon, statnum;
    int stopsound, entitynum, channel;
    byte colors;
    player_info_t *player;
    lightstyle_t *style;
    const char *stylemap, *name;

//
// if recording demos, copy the message out
//
    if (cl_shownet.value == 1)
	Con_Printf("%i ", net_message.cursize);
    else if (cl_shownet.value == 2)
	Con_Printf("------------------\n");

    cl.onground = false;	// unless the server says otherwise
//
// parse the message
//
    prevcmd = svc_bad;
    MSG_BeginReading();

    while (1) {
	if (msg_badread)
	    Host_Error("%s: Bad server message", __func__);

	cmd = MSG_ReadByte();

	if (cmd == -1) {
	    SHOWNET("END OF MESSAGE");
	    return;		// end of message
	}
	// if the high bit of the command byte is set, it is a fast update
	if (cmd & 128) {
	    SHOWNET("fast update");
	    CL_ParseUpdate(cmd & 127);
	    continue;
	}

	SHOWNET(svc_strings[cmd]);

	// other commands
	switch (cmd) {
	case svc_nop:
	    break;

	case svc_time:
	    cl.mtime[1] = cl.mtime[0];
	    cl.mtime[0] = MSG_ReadFloat();
	    break;

	case svc_clientdata:
	    CL_ParseClientdata();
	    break;

	case svc_version:
	    version = MSG_ReadLong();
	    if (!Protocol_Known(version))
		Host_Error("%s: Server returned unknown protocol version %i",
			   __func__, version);
	    cl.protocol = version;
	    break;

	case svc_disconnect:
	    Host_EndGame("Server disconnected\n");

	case svc_print:
	    Con_Printf("%s", MSG_ReadString());
	    break;

	case svc_centerprint:
	    SCR_CenterPrint(MSG_ReadString());
	    break;

	case svc_stufftext:
	    Cbuf_AddText("%s", MSG_ReadString());
	    break;

	case svc_damage:
	    V_ParseDamage();
	    break;

	case svc_serverinfo:
	    CL_ParseServerInfo();
	    vid.recalc_refdef = true;	// leave intermission full screen
	    break;

	case svc_setangle:
	    for (i = 0; i < 3; i++)
		cl.viewangles[i] = MSG_ReadAngle();
	    break;

	case svc_setview:
	    cl.viewentity = MSG_ReadShort();
	    break;

	case svc_lightstyle:
	    stylenum = MSG_ReadByte();
	    if (stylenum >= MAX_LIGHTSTYLES)
		Sys_Error("svc_lightstyle > MAX_LIGHTSTYLES");
	    stylemap = MSG_ReadString();
	    style = cl_lightstyle + stylenum;
	    snprintf(style->map, MAX_STYLESTRING, "%s", stylemap);
	    style->length = strlen(style->map);
	    break;

	case svc_sound:
	    CL_ParseStartSoundPacket();
	    break;

	case svc_stopsound:
	    stopsound = MSG_ReadShort(); /* 3-bit channel encoded in lsb */
	    entitynum = stopsound >> 3;
	    channel = stopsound & 7;
	    S_StopSound(entitynum, channel);
	    break;

	case svc_updatename:
	    Sbar_Changed();
	    playernum = MSG_ReadByte();
	    if (playernum >= cl.maxclients)
		Host_Error("%s: svc_updatename > MAX_SCOREBOARD", __func__);
	    name = MSG_ReadString();
	    player = cl.players + playernum;
	    snprintf(player->name, MAX_SCOREBOARDNAME, "%s", name);
	    break;

	case svc_updatefrags:
	    Sbar_Changed();
	    playernum = MSG_ReadByte();
	    if (playernum >= cl.maxclients)
		Host_Error("%s: svc_updatefrags > MAX_SCOREBOARD", __func__);
	    player = cl.players + playernum;
	    player->frags = MSG_ReadShort();
	    break;

	case svc_updatecolors:
	    Sbar_Changed();
	    playernum = MSG_ReadByte();
	    if (playernum >= cl.maxclients)
		Host_Error("%s: svc_updatecolors > MAX_SCOREBOARD", __func__);
	    colors = MSG_ReadByte();
	    player = cl.players + playernum;
	    player->topcolor = (colors & 0xf0) >> 4;
	    player->bottomcolor = colors & 0x0f;
	    /* FIXME - is this the right check for current player? */
	    if (playernum == cl.viewentity)
		cl_color.value = colors;
	    CL_NewTranslation(playernum);
	    break;

	case svc_particle:
	    R_ParseParticleEffect();
	    break;

	case svc_spawnbaseline:
	    entitynum = MSG_ReadShort();
	    // must use CL_EntityNum() to force cl.num_entities up
	    CL_ParseBaseline(CL_EntityNum(entitynum), 0);
	    break;

	case svc_fitz_spawnbaseline2:
	    /* FIXME - check here that protocol is FITZ? => Host_Error() */
	    entitynum = MSG_ReadShort();
	    bits = MSG_ReadByte();
	    // must use CL_EntityNum() to force cl.num_entities up
	    CL_ParseBaseline(CL_EntityNum(entitynum), bits);
	    break;

	case svc_spawnstatic:
	    CL_ParseStatic(0);
	    break;

	case svc_fitz_spawnstatic2:
	    /* FIXME - check here that protocol is FITZ? => Host_Error() */
	    bits = MSG_ReadByte();
	    CL_ParseStatic(bits);
	    break;

	case svc_temp_entity:
	    CL_ParseTEnt();
	    break;

	case svc_setpause:
	    cl.paused = MSG_ReadByte();
	    if (cl.paused)
		CDAudio_Pause();
	    else
		CDAudio_Resume();
	    break;

	case svc_signonnum:
	    signon = MSG_ReadByte();
	    if (signon <= cls.signon)
		Host_Error("Received signon %d when at %d", signon, cls.signon);
	    cls.signon = signon;
	    CL_SignonReply();
	    break;

	case svc_killedmonster:
	    cl.stats[STAT_MONSTERS]++;
	    break;

	case svc_foundsecret:
	    cl.stats[STAT_SECRETS]++;
	    break;

	case svc_updatestat:
	    statnum = MSG_ReadByte();
	    if (statnum < 0 || statnum >= MAX_CL_STATS)
		Sys_Error("svc_updatestat: %d is invalid", statnum);
	    cl.stats[statnum] = MSG_ReadLong();
	    break;

	case svc_spawnstaticsound:
	    CL_ParseStaticSound();
	    break;

	case svc_fitz_spawnstaticsound2:
	    /* FIXME - check here that protocol is FITZ? => Host_Error() */
	    CL_ParseFitzStaticSound2();
	    break;

	case svc_cdtrack:
	    cl.cdtrack = MSG_ReadByte();
	    cl.looptrack = MSG_ReadByte();
	    if ((cls.demoplayback || cls.demorecording)
		&& (cls.forcetrack != -1))
		CDAudio_Play((byte)cls.forcetrack, true);
	    else
		CDAudio_Play((byte)cl.cdtrack, true);
	    break;

	case svc_intermission:
	    cl.intermission = 1;
	    cl.completed_time = cl.time;
	    vid.recalc_refdef = true;	// go to full screen
	    break;

	case svc_finale:
	    cl.intermission = 2;
	    cl.completed_time = cl.time;
	    vid.recalc_refdef = true;	// go to full screen
	    SCR_CenterPrint(MSG_ReadString());
	    break;

	case svc_cutscene:
	    cl.intermission = 3;
	    cl.completed_time = cl.time;
	    vid.recalc_refdef = true;	// go to full screen
	    SCR_CenterPrint(MSG_ReadString());
	    break;

	case svc_sellscreen:
	    Cmd_ExecuteString("help", src_command);
	    break;

	/* Various FITZ protocol messages - FIXME - !protocol => Host_Error */
	case svc_fitz_skybox:
	    MSG_ReadString(); // FIXME - TODO
	    break;

	case svc_fitz_bf:
	    Cmd_ExecuteString("bf", src_command);
	    break;

	case svc_fitz_fog:
	    /* FIXME - TODO */
	    MSG_ReadByte(); // density
	    MSG_ReadByte(); // red
	    MSG_ReadByte(); // green
	    MSG_ReadByte(); // blue
	    MSG_ReadShort(); // time
	    break;

	default:
	    Host_Error("%s: Illegible server message. Previous was %s",
		       __func__, svc_strings[prevcmd]);
	}
	prevcmd = cmd;
    }
}
Пример #25
0
/*
=================
SV_ReadPackets
=================
*/
void SV_ReadPackets (void)
{
	int			i;
	client_t	*cl;
	int			qport;

	// first deal with delayed packets from connected clients
	for (i = 0, cl=svs.clients; i < MAX_CLIENTS; i++, cl++) {
		if (cl->state == cs_free)
			continue;

		net_from = cl->netchan.remote_address;

		while (cl->packets && svs.realtime - cl->packets->time >= cl->delay) {
			SZ_Clear(&net_message);
			SZ_Write(&net_message, cl->packets->msg.data, cl->packets->msg.cursize);
			SV_ExecuteClientMessage(cl);
			SV_FreeHeadDelayedPacket(cl);
		}		
	}

	// now deal with new packets
	while (NET_GetPacket(NS_SERVER))
	{
		if (SV_FilterPacket ())
		{
			SV_SendBan ();	// tell them we aren't listening...
			continue;
		}

		// check for connectionless packet (0xffffffff) first
		if (*(int *)net_message.data == -1)
		{
			SV_ConnectionlessPacket ();
			continue;
		}
		
		// read the qport out of the message so we can fix up
		// stupid address translating routers
		MSG_BeginReading ();
		MSG_ReadLong ();		// sequence number
		MSG_ReadLong ();		// sequence number
		qport = MSG_ReadShort () & 0xffff;

		// check which client sent this packet
		for (i=0, cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
		{
			if (cl->state == cs_free)
				continue;
			if (!NET_CompareBaseAdr (net_from, cl->netchan.remote_address))
				continue;
			if (cl->netchan.qport != qport)
				continue;
			if (cl->netchan.remote_address.port != net_from.port)
			{
				Com_DPrintf ("SV_ReadPackets: fixing up a translated port\n");
				cl->netchan.remote_address.port = net_from.port;
			}

			break;
		}

		if (i == MAX_CLIENTS)
			continue;

		// ok, we know who sent this packet, but do we need to delay executing it?
		if (cl->delay > 0) {
			if (!svs.free_packets) // packet has to be dropped..
				break;

			// insert at end of list
			if (!cl->packets) {
				cl->last_packet = cl->packets = svs.free_packets;
			} else {
				// this works because '=' associates from right to left
				cl->last_packet = cl->last_packet->next = svs.free_packets;
			}

			svs.free_packets = svs.free_packets->next;
			cl->last_packet->next = NULL;
			
			cl->last_packet->time = svs.realtime;
			SZ_Clear(&cl->last_packet->msg);
			SZ_Write(&cl->last_packet->msg, net_message.data, net_message.cursize);
		} else {
			SV_ExecuteClientMessage (cl);
		}
	}
}
Пример #26
0
/*
=================
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 fragmentStart, fragmentLength;
	qboolean fragmented;
	// get sequence numbers
	MSG_BeginReading( msg );
	sequence = MSG_ReadLong( msg );

	// check for fragment information
	if ( sequence & FRAGMENT_BIT ) {
		sequence &= ~FRAGMENT_BIT;
		fragmented = qtrue;
	} else {
		fragmented = qfalse;
	}

	// Pop off the qport if we are a server
	if ( chan->sock == NS_SERVER ) {
		MSG_ReadShort( msg );
	}

	// read the fragment information
	if ( fragmented ) {
		fragmentStart = MSG_ReadLong( msg );
		fragmentLength = MSG_ReadShort( msg );

	} else {
		fragmentStart = 0;      // stop warning message
		fragmentLength = 0;
	}

	if ( showpackets->boolean ) {
		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->boolean || showpackets->boolean ) {
			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->boolean || showpackets->boolean ) {
			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 ) {
		// TTimo
		// make sure we add the fragments in correct order
		// either a packet was dropped, or we received this one too soon
		// we don't reconstruct the fragments. we will wait till this fragment gets to us again
		// (NOTE: we could probably try to rebuild by out of order chunks if needed)

		if ( sequence != chan->fragmentSequence ) {
			chan->fragmentSequence = sequence;
			chan->fragmentLength = 0;
		}

		// if we missed a fragment, dump the message
		if ( fragmentStart != chan->fragmentLength ) {
			if ( showdrop->boolean || showpackets->boolean ) {
				Com_Printf( "%s:Dropped a message fragment seq: %d\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 > chan->fragmentBufferSize)
		{
			if ( showdrop->boolean || showpackets->boolean ) {
				Com_Printf( "%s:illegal fragment length: Current %i Fragment length %i Max %i\n",
						NET_AdrToString( &chan->remoteAddress ), chan->fragmentLength,
						fragmentLength, chan->fragmentBufferSize);
			}
			return qfalse;
		}

		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 > msg->maxsize ) {
			Com_Printf( "%s:fragmentLength %i > msg->maxsize\n", NET_AdrToString( &chan->remoteAddress ), chan->fragmentLength );
			return qfalse;
		}

		// copy the full message over the partial fragment

		// make sure the sequence number is still there
		*(int *)msg->data = LittleLong( sequence );

		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


		// TTimo
		// clients were not acking fragmented messages
		chan->incomingSequence = sequence;

		return qtrue;
	}

	//
	// the message can now be read from the current message pointer
	//
	chan->incomingSequence = sequence;

	return qtrue;
}
Пример #27
0
qboolean
Netchan_Process (netchan_t *chan)
{
	unsigned int reliable_ack, reliable_message, sequence, sequence_ack;

	if (!net_blocksend)
		if (!NET_CompareAdr (net_from, chan->remote_address))
			return false;

	/// Get the sequence numbers.
	MSG_BeginReading (net_message);
	sequence = MSG_ReadLong (net_message);
	sequence_ack = MSG_ReadLong (net_message);

	/// Read the qport if appropriate (we are a server), but ignore it.
	if (chan->flags & NC_QPORT_READ)
		MSG_ReadShort (net_message);

	reliable_message = sequence >> 31;
	reliable_ack = sequence_ack >> 31;

	sequence &= ~(1 << 31);
	sequence_ack &= ~(1 << 31);

	if (showpackets->int_val & 2)
		Sys_Printf ("<-- s=%i(%i) a=%i(%i) %i\n", sequence, reliable_message,
					sequence_ack, reliable_ack, net_message->message->cursize);

	// get a rate estimation
#if 0 // FIXME: Dead code
	if (chan->outgoing_sequence - sequence_ack < MAX_LATENT) {
		int         i;
		double      time, rate;

		i = sequence_ack & (MAX_LATENT - 1);
		time = *net_realtime - chan->outgoing_time[i];
		time -= 0.1;					// subtract 100 ms
		if (time <= 0) {				// gotta be a digital link for <100
										// ms ping
			if (chan->rate > 1.0 / 5000)
				chan->rate = 1.0 / 5000;
		} else {
			if (chan->outgoing_size[i] < 512) {	// deal with only small
												// messages
				rate = chan->outgoing_size[i] / time;
				if (rate > 5000)
					rate = 5000;
				rate = 1.0 / rate;
				if (chan->rate > rate)
					chan->rate = rate;
			}
		}
	}
#endif

	/// Discard stale or duplicated packets.
	if (sequence < (unsigned int) chan->incoming_sequence + 1) {
		if (showdrop->int_val)
			Sys_Printf ("%s:Out of order packet %i at %i\n",
						NET_AdrToString (chan->remote_address), sequence,
						chan->incoming_sequence);
		return false;
	}

	/// Dropped packets don't keep the message from being used.
	chan->net_drop = sequence - (chan->incoming_sequence + 1);
	if (chan->net_drop > 0) {
		chan->drop_count += 1;

		if (showdrop->int_val)
			Sys_Printf ("%s:Dropped %i packets at %i\n",
						NET_AdrToString (chan->remote_address),
						sequence - (chan->incoming_sequence + 1), sequence);
	}

	/// If the current outgoing reliable message has been acknowledged,
	/// clear the buffer to make way for the next.
	if (reliable_ack == (unsigned int) chan->reliable_sequence)
		chan->reliable_length = 0;		// it has been received

	/// If this message contains a reliable message, bump
	/// incoming_reliable_sequence
	chan->incoming_sequence = sequence;
	chan->incoming_acknowledged = sequence_ack;
	chan->incoming_reliable_acknowledged = reliable_ack;
	if (reliable_message)
		chan->incoming_reliable_sequence ^= 1;

	// The message can now be read from the current message pointer.
	/// Update statistics counters.
	chan->frame_latency = chan->frame_latency * OLD_AVG
		+ (chan->outgoing_sequence - sequence_ack) * (1.0 - OLD_AVG);
	chan->frame_rate = chan->frame_rate * OLD_AVG
		+ (*net_realtime - chan->last_received) * (1.0 - OLD_AVG);
	chan->good_count += 1;

	chan->last_received = *net_realtime;

	return true;
}
Пример #28
0
/*
====================
CL_ReadDemoMessage

Handles playback of demos
====================
*/
void CL_ReadDemoMessage(void)
{
	int i;
	float f;

	if (!cls.demoplayback)
		return;

	// LordHavoc: pausedemo
	if (cls.demopaused)
		return;

	for (;;)
	{
		// decide if it is time to grab the next message
		// always grab until fully connected
		if (cls.signon == SIGNONS)
		{
			if (cls.timedemo)
			{
				cls.td_frames++;
				cls.td_onesecondframes++;
				// if this is the first official frame we can now grab the real
				// td_starttime so the bogus time on the first frame doesn't
				// count against the final report
				if (cls.td_frames == 0)
				{
					cls.td_starttime = realtime;
					cls.td_onesecondnexttime = cl.time + 1;
					cls.td_onesecondrealtime = realtime;
					cls.td_onesecondframes = 0;
					cls.td_onesecondminfps = 0;
					cls.td_onesecondmaxfps = 0;
					cls.td_onesecondavgfps = 0;
					cls.td_onesecondavgcount = 0;
				}
				if (cl.time >= cls.td_onesecondnexttime)
				{
					double fps = cls.td_onesecondframes / (realtime - cls.td_onesecondrealtime);
					if (cls.td_onesecondavgcount == 0)
					{
						cls.td_onesecondminfps = fps;
						cls.td_onesecondmaxfps = fps;
					}
					cls.td_onesecondrealtime = realtime;
					cls.td_onesecondminfps = min(cls.td_onesecondminfps, fps);
					cls.td_onesecondmaxfps = max(cls.td_onesecondmaxfps, fps);
					cls.td_onesecondavgfps += fps;
					cls.td_onesecondavgcount++;
					cls.td_onesecondframes = 0;
					cls.td_onesecondnexttime++;
				}
			}
			else if (cl.time <= cl.mtime[0])
			{
				// don't need another message yet
				return;
			}
		}

		// get the next message
		FS_Read(cls.demofile, &cl_message.cursize, 4);
		cl_message.cursize = LittleLong(cl_message.cursize);
		if(cl_message.cursize & DEMOMSG_CLIENT_TO_SERVER) // This is a client->server message! Ignore for now!
		{
			// skip over demo packet
			FS_Seek(cls.demofile, 12 + (cl_message.cursize & (~DEMOMSG_CLIENT_TO_SERVER)), SEEK_CUR);
			continue;
		}
		if (cl_message.cursize > cl_message.maxsize)
		{
			Con_Printf("Demo message (%i) > cl_message.maxsize (%i)", cl_message.cursize, cl_message.maxsize);
			cl_message.cursize = 0;
			CL_Disconnect();
			return;
		}
		VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
		for (i = 0;i < 3;i++)
		{
			FS_Read(cls.demofile, &f, 4);
			cl.mviewangles[0][i] = LittleFloat(f);
		}

		if (FS_Read(cls.demofile, cl_message.data, cl_message.cursize) == cl_message.cursize)
		{
			MSG_BeginReading(&cl_message);
			CL_ParseServerMessage();

			if (cls.signon != SIGNONS)
				Cbuf_Execute(); // immediately execute svc_stufftext if in the demo before connect!

			// In case the demo contains a "svc_disconnect" message
			if (!cls.demoplayback)
				return;

			if (cls.timedemo)
				return;
		}
		else
		{
			CL_Disconnect();
			return;
		}
	}
}
Пример #29
0
/*
* CL_ParseGetServersResponseMessage
* Handle a reply from getservers message to master server
*/
static void CL_ParseGetServersResponseMessage( msg_t *msg, qboolean extended )
{
	const char *header;
	char adrString[64];
	qbyte addr[16];
	unsigned short port;
	netadr_t adr;

	MSG_BeginReading( msg );
	MSG_ReadLong( msg ); // skip the -1

	//jump over the command name
	header = ( extended ? "getserversExtResponse" : "getserversResponse" );
	if( !MSG_SkipData( msg, strlen( header ) ) )
	{
		Com_Printf( "Invalid master packet ( missing %s )\n", header );
		return;
	}

	while( msg->readcount + 7 <= msg->cursize )
	{
		char prefix = MSG_ReadChar( msg );

		switch( prefix )
		{
		case '\\':
			MSG_ReadData( msg, addr, 4 );
			port = ShortSwap( MSG_ReadShort( msg ) ); // both endians need this swapped.
			Q_snprintfz( adrString, sizeof( adrString ), "%u.%u.%u.%u:%u", addr[0], addr[1], addr[2], addr[3], port );
			break;

		case '/':
			if( extended )
			{
				MSG_ReadData( msg, addr, 16 );
				port = ShortSwap( MSG_ReadShort( msg ) ); // both endians need this swapped.
				Q_snprintfz( adrString, sizeof( adrString ), "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%hu",
								addr[ 0], addr[ 1], addr[ 2], addr[ 3], addr[ 4], addr[ 5], addr[ 6], addr[ 7],
								addr[ 8], addr[ 9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15],
								port );
			}
			else
			{
				Com_Printf( "Invalid master packet ( IPv6 prefix in a non-extended response )\n" );
				return;
			}

			break;

		default:
			Com_Printf( "Invalid master packet ( missing separator )\n" );
			return;
		}

		if( port == 0 )  // last server seen
			return;

		Com_DPrintf( "%s\n", adrString );
		if( !NET_StringToAddress( adrString, &adr ) )
		{
			Com_Printf( "Bad address: %s\n", adrString );
			continue;
		}

		CL_AddServerToList( &masterList, adrString, 0 );
	}
}
Пример #30
0
static qsocket_t *_Datagram_CheckNewConnections (void)
{
	struct qsockaddr clientaddr;
	struct qsockaddr newaddr;
	int			newsock;
	int			acceptsock;
	qsocket_t	*sock;
	qsocket_t	*s;
	int			len;
	int			command;
	int			control;
	int			ret;

	acceptsock = dfunc.CheckNewConnections();
	if (acceptsock == -1)
		return NULL;

	SZ_Clear(&net_message);

	len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
	if (len < sizeof(int))
		return NULL;
	net_message.cursize = len;

	MSG_BeginReading ();
	control = BigLong(*((int *)net_message.data));
	MSG_ReadLong();
	if (control == -1)
		return NULL;
	if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
		return NULL;
	if ((control & NETFLAG_LENGTH_MASK) != len)
		return NULL;

	command = MSG_ReadByte();
	if (command == CCREQ_SERVER_INFO)
	{
		if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
			return NULL;

		SZ_Clear(&net_message);
		// save space for the header, filled in later
		MSG_WriteLong(&net_message, 0);
		MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
		dfunc.GetSocketAddr(acceptsock, &newaddr);
		MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
		MSG_WriteString(&net_message, hostname.string);
		MSG_WriteString(&net_message, sv.name);
		MSG_WriteByte(&net_message, net_activeconnections);
		MSG_WriteByte(&net_message, svs.maxclients);
		MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
		SZ_Clear(&net_message);
		return NULL;
	}

	if (command == CCREQ_PLAYER_INFO)
	{
		int			playerNumber;
		int			activeNumber;
		int			clientNumber;
		client_t	*client;
		
		playerNumber = MSG_ReadByte();
		activeNumber = -1;
		for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
		{
			if (client->active)
			{
				activeNumber++;
				if (activeNumber == playerNumber)
					break;
			}
		}
		if (clientNumber == svs.maxclients)
			return NULL;

		SZ_Clear(&net_message);
		// save space for the header, filled in later
		MSG_WriteLong(&net_message, 0);
		MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
		MSG_WriteByte(&net_message, playerNumber);
		MSG_WriteString(&net_message, client->name);
		MSG_WriteLong(&net_message, client->colors);
		MSG_WriteLong(&net_message, (int)client->edict->v.frags);
		MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
		MSG_WriteString(&net_message, client->netconnection->address);
		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
		SZ_Clear(&net_message);

		return NULL;
	}

	if (command == CCREQ_RULE_INFO)
	{
		char	*prevCvarName;
		cvar_t	*var;

		// find the search start location
		prevCvarName = MSG_ReadString();
		if (*prevCvarName)
		{
			var = Cvar_FindVar (prevCvarName);
			if (!var)
				return NULL;
			var = var->next;
		}
		else
			var = cvar_vars;

		// search for the next server cvar
		while (var)
		{
			if (var->server)
				break;
			var = var->next;
		}

		// send the response

		SZ_Clear(&net_message);
		// save space for the header, filled in later
		MSG_WriteLong(&net_message, 0);
		MSG_WriteByte(&net_message, CCREP_RULE_INFO);
		if (var)
		{
			MSG_WriteString(&net_message, var->name);
			MSG_WriteString(&net_message, var->string);
		}
		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
		SZ_Clear(&net_message);

		return NULL;
	}

	if (command != CCREQ_CONNECT)
		return NULL;

	if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
		return NULL;

	if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
	{
		SZ_Clear(&net_message);
		// save space for the header, filled in later
		MSG_WriteLong(&net_message, 0);
		MSG_WriteByte(&net_message, CCREP_REJECT);
		MSG_WriteString(&net_message, "Incompatible version.\n");
		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
		SZ_Clear(&net_message);
		return NULL;
	}

#ifdef BAN_TEST
	// check for a ban
	if (clientaddr.sa_family == AF_INET)
	{
		unsigned long testAddr;
		testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
		if ((testAddr & banMask) == banAddr)
		{
			SZ_Clear(&net_message);
			// save space for the header, filled in later
			MSG_WriteLong(&net_message, 0);
			MSG_WriteByte(&net_message, CCREP_REJECT);
			MSG_WriteString(&net_message, "You have been banned.\n");
			*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
			dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
			SZ_Clear(&net_message);
			return NULL;
		}
	}
#endif

	// see if this guy is already connected
	for (s = net_activeSockets; s; s = s->next)
	{
		if (s->driver != net_driverlevel)
			continue;
		ret = dfunc.AddrCompare(&clientaddr, &s->addr);
		if (ret >= 0)
		{
			// is this a duplicate connection reqeust?
			if (ret == 0 && net_time - s->connecttime < 2.0)
			{
				// yes, so send a duplicate reply
				SZ_Clear(&net_message);
				// save space for the header, filled in later
				MSG_WriteLong(&net_message, 0);
				MSG_WriteByte(&net_message, CCREP_ACCEPT);
				dfunc.GetSocketAddr(s->socket, &newaddr);
				MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
				*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
				dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
				SZ_Clear(&net_message);
				return NULL;
			}
			// it's somebody coming back in from a crash/disconnect
			// so close the old qsocket and let their retry get them back in
			NET_Close(s);
			return NULL;
		}
	}

	// allocate a QSocket
	sock = NET_NewQSocket ();
	if (sock == NULL)
	{
		// no room; try to let him know
		SZ_Clear(&net_message);
		// save space for the header, filled in later
		MSG_WriteLong(&net_message, 0);
		MSG_WriteByte(&net_message, CCREP_REJECT);
		MSG_WriteString(&net_message, "Server is full.\n");
		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
		SZ_Clear(&net_message);
		return NULL;
	}

	// allocate a network socket
	newsock = dfunc.OpenSocket(0);
	if (newsock == -1)
	{
		NET_FreeQSocket(sock);
		return NULL;
	}

	// connect to the client
	if (dfunc.Connect (newsock, &clientaddr) == -1)
	{
		dfunc.CloseSocket(newsock);
		NET_FreeQSocket(sock);
		return NULL;
	}

	// everything is allocated, just fill in the details	
	sock->socket = newsock;
	sock->landriver = net_landriverlevel;
	sock->addr = clientaddr;
	Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr));

	// send him back the info about the server connection he has been allocated
	SZ_Clear(&net_message);
	// save space for the header, filled in later
	MSG_WriteLong(&net_message, 0);
	MSG_WriteByte(&net_message, CCREP_ACCEPT);
	dfunc.GetSocketAddr(newsock, &newaddr);
	MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
//	MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
	*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
	dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
	SZ_Clear(&net_message);

	return sock;
}