Home | History | Annotate | Download | only in jni
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // net_dgrm.c
     21 
     22 // This is enables a simple IP banning mechanism
     23 #define BAN_TEST
     24 
     25 #ifdef BAN_TEST
     26 #if defined(_WIN32)
     27 #include <windows.h>
     28 #elif defined (NeXT)
     29 #include <sys/socket.h>
     30 #include <arpa/inet.h>
     31 #else
     32 
     33 #include <sys/types.h>
     34 #include <sys/socket.h>
     35 #include <netinet/in.h>
     36 #include <arpa/inet.h>
     37 #endif
     38 #endif	// BAN_TEST
     39 
     40 #include "quakedef.h"
     41 #include "net_dgrm.h"
     42 
     43 // these two macros are to make the code more readable
     44 #define sfunc	net_landrivers[sock->landriver]
     45 #define dfunc	net_landrivers[net_landriverlevel]
     46 
     47 static int net_landriverlevel;
     48 
     49 /* statistic counters */
     50 int	packetsSent = 0;
     51 int	packetsReSent = 0;
     52 int packetsReceived = 0;
     53 int receivedDuplicateCount = 0;
     54 int shortPacketCount = 0;
     55 int droppedDatagrams;
     56 
     57 static int myDriverLevel;
     58 
     59 struct packetBuffer_t
     60 {
     61 	unsigned int	length;
     62 	unsigned int	sequence;
     63 	byte			data[MAX_DATAGRAM];
     64 } packetBuffer;
     65 
     66 extern int m_return_state;
     67 extern int m_state;
     68 extern qboolean m_return_onerror;
     69 extern char m_return_reason[32];
     70 
     71 
     72 #ifdef DEBUG
     73 char *StrAddr (struct qsockaddr *addr)
     74 {
     75 	static char buf[34];
     76 	byte *p = (byte *)addr;
     77 	int n;
     78 
     79 	for (n = 0; n < 16; n++)
     80 		sprintf (buf + n * 2, "%02x", *p++);
     81 	return buf;
     82 }
     83 #endif
     84 
     85 
     86 #ifdef BAN_TEST
     87 typedef union {
     88     unsigned long ul;
     89     struct in_addr addr;
     90 } ulongaddr;
     91 
     92 typedef union {
     93     qsockaddr q;
     94     sockaddr_in i;
     95 } qsockaddr2sockaddr_in;
     96 
     97 unsigned long banAddr = 0x00000000;
     98 unsigned long banMask = 0xffffffff;
     99 
    100 void NET_Ban_f (void)
    101 {
    102 	char	addrStr [32];
    103 	char	maskStr [32];
    104 	void	(*print) (const char *fmt, ...);
    105 
    106 	if (cmd_source == src_command)
    107 	{
    108 		if (!sv.active)
    109 		{
    110 			Cmd_ForwardToServer ();
    111 			return;
    112 		}
    113 		print = Con_Printf;
    114 	}
    115 	else
    116 	{
    117 		if (pr_global_struct->deathmatch && !host_client->privileged)
    118 			return;
    119 		print = SV_ClientPrintf;
    120 	}
    121 
    122 	switch (Cmd_Argc ())
    123 	{
    124 		case 1:
    125 		{
    126 		    ulongaddr addrTemp;
    127 		    addrTemp.ul = banAddr;
    128 		    ulongaddr maskTemp;
    129 		    maskTemp.ul - banMask;
    130 
    131 			if (addrTemp.addr.s_addr)
    132 			{
    133 				Q_strcpy(addrStr, inet_ntoa(addrTemp.addr));
    134 				Q_strcpy(maskStr, inet_ntoa(maskTemp.addr));
    135 				print("Banning %s [%s]\n", addrStr, maskStr);
    136 			}
    137 			else
    138 				print("Banning not active\n");
    139 		}
    140         break;
    141 
    142 		case 2:
    143 			if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
    144 				banAddr = 0x00000000;
    145 			else
    146 				banAddr = inet_addr(Cmd_Argv(1));
    147 			banMask = 0xffffffff;
    148 			break;
    149 
    150 		case 3:
    151 			banAddr = inet_addr(Cmd_Argv(1));
    152 			banMask = inet_addr(Cmd_Argv(2));
    153 			break;
    154 
    155 		default:
    156 			print("BAN ip_address [mask]\n");
    157 			break;
    158 	}
    159 }
    160 #endif
    161 
    162 
    163 int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
    164 {
    165 	unsigned int	packetLen;
    166 	unsigned int	dataLen;
    167 	unsigned int	eom;
    168 
    169 #ifdef DEBUG
    170 	if (data->cursize == 0)
    171 		Sys_Error("Datagram_SendMessage: zero length message\n");
    172 
    173 	if (data->cursize > NET_MAXMESSAGE)
    174 		Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
    175 
    176 	if (sock->canSend == false)
    177 		Sys_Error("SendMessage: called with canSend == false\n");
    178 #endif
    179 
    180 	Q_memcpy(sock->sendMessage, data->data, data->cursize);
    181 	sock->sendMessageLength = data->cursize;
    182 
    183 	if (data->cursize <= MAX_DATAGRAM)
    184 	{
    185 		dataLen = data->cursize;
    186 		eom = NETFLAG_EOM;
    187 	}
    188 	else
    189 	{
    190 		dataLen = MAX_DATAGRAM;
    191 		eom = 0;
    192 	}
    193 	packetLen = NET_HEADERSIZE + dataLen;
    194 
    195 	packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
    196 	packetBuffer.sequence = BigLong(sock->sendSequence++);
    197 	Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
    198 
    199 	sock->canSend = false;
    200 
    201 	if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
    202 		return -1;
    203 
    204 	sock->lastSendTime = net_time;
    205 	packetsSent++;
    206 	return 1;
    207 }
    208 
    209 
    210 int SendMessageNext (qsocket_t *sock)
    211 {
    212 	unsigned int	packetLen;
    213 	unsigned int	dataLen;
    214 	unsigned int	eom;
    215 
    216 	if (sock->sendMessageLength <= MAX_DATAGRAM)
    217 	{
    218 		dataLen = sock->sendMessageLength;
    219 		eom = NETFLAG_EOM;
    220 	}
    221 	else
    222 	{
    223 		dataLen = MAX_DATAGRAM;
    224 		eom = 0;
    225 	}
    226 	packetLen = NET_HEADERSIZE + dataLen;
    227 
    228 	packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
    229 	packetBuffer.sequence = BigLong(sock->sendSequence++);
    230 	Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
    231 
    232 	sock->sendNext = false;
    233 
    234 	if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
    235 		return -1;
    236 
    237 	sock->lastSendTime = net_time;
    238 	packetsSent++;
    239 	return 1;
    240 }
    241 
    242 
    243 int ReSendMessage (qsocket_t *sock)
    244 {
    245 	unsigned int	packetLen;
    246 	unsigned int	dataLen;
    247 	unsigned int	eom;
    248 
    249 	if (sock->sendMessageLength <= MAX_DATAGRAM)
    250 	{
    251 		dataLen = sock->sendMessageLength;
    252 		eom = NETFLAG_EOM;
    253 	}
    254 	else
    255 	{
    256 		dataLen = MAX_DATAGRAM;
    257 		eom = 0;
    258 	}
    259 	packetLen = NET_HEADERSIZE + dataLen;
    260 
    261 	packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
    262 	packetBuffer.sequence = BigLong(sock->sendSequence - 1);
    263 	Q_memcpy (packetBuffer.data, sock->sendMessage, dataLen);
    264 
    265 	sock->sendNext = false;
    266 
    267 	if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
    268 		return -1;
    269 
    270 	sock->lastSendTime = net_time;
    271 	packetsReSent++;
    272 	return 1;
    273 }
    274 
    275 
    276 qboolean Datagram_CanSendMessage (qsocket_t *sock)
    277 {
    278 	if (sock->sendNext)
    279 		SendMessageNext (sock);
    280 
    281 	return sock->canSend;
    282 }
    283 
    284 
    285 qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
    286 {
    287 	return true;
    288 }
    289 
    290 
    291 int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
    292 {
    293 	int 	packetLen;
    294 
    295 #ifdef DEBUG
    296 	if (data->cursize == 0)
    297 		Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
    298 
    299 	if (data->cursize > MAX_DATAGRAM)
    300 		Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
    301 #endif
    302 
    303 	packetLen = NET_HEADERSIZE + data->cursize;
    304 
    305 	packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE);
    306 	packetBuffer.sequence = BigLong(sock->unreliableSendSequence++);
    307 	Q_memcpy (packetBuffer.data, data->data, data->cursize);
    308 
    309 	if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
    310 		return -1;
    311 
    312 	packetsSent++;
    313 	return 1;
    314 }
    315 
    316 
    317 int	Datagram_GetMessage (qsocket_t *sock)
    318 {
    319 	unsigned int	length;
    320 	unsigned int	flags;
    321 	int				ret = 0;
    322 	struct qsockaddr readaddr;
    323 	unsigned int	sequence;
    324 	unsigned int	count;
    325 
    326 	if (!sock->canSend)
    327 		if ((net_time - sock->lastSendTime) > 1.0)
    328 			ReSendMessage (sock);
    329 
    330 	while(1)
    331 	{
    332 		length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
    333 
    334 //	if ((rand() & 255) > 220)
    335 //		continue;
    336 
    337 		if (length == 0)
    338 			break;
    339 
    340 		if (length == (unsigned int) -1)
    341 		{
    342 			Con_Printf("Read error\n");
    343 			return -1;
    344 		}
    345 
    346 		if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
    347 		{
    348 #ifdef DEBUG
    349 			Con_DPrintf("Forged packet received\n");
    350 			Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
    351 			Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
    352 #endif
    353 			continue;
    354 		}
    355 
    356 		if (length < NET_HEADERSIZE)
    357 		{
    358 			shortPacketCount++;
    359 			continue;
    360 		}
    361 
    362 		length = BigLong(packetBuffer.length);
    363 		flags = length & (~NETFLAG_LENGTH_MASK);
    364 		length &= NETFLAG_LENGTH_MASK;
    365 
    366 		if (flags & NETFLAG_CTL)
    367 			continue;
    368 
    369 		sequence = BigLong(packetBuffer.sequence);
    370 		packetsReceived++;
    371 
    372 		if (flags & NETFLAG_UNRELIABLE)
    373 		{
    374 			if (sequence < sock->unreliableReceiveSequence)
    375 			{
    376 				Con_DPrintf("Got a stale datagram\n");
    377 				ret = 0;
    378 				break;
    379 			}
    380 			if (sequence != sock->unreliableReceiveSequence)
    381 			{
    382 				count = sequence - sock->unreliableReceiveSequence;
    383 				droppedDatagrams += count;
    384 				Con_DPrintf("Dropped %u datagram(s)\n", count);
    385 			}
    386 			sock->unreliableReceiveSequence = sequence + 1;
    387 
    388 			length -= NET_HEADERSIZE;
    389 
    390 			SZ_Clear (&net_message);
    391 			SZ_Write (&net_message, packetBuffer.data, length);
    392 
    393 			ret = 2;
    394 			break;
    395 		}
    396 
    397 		if (flags & NETFLAG_ACK)
    398 		{
    399 			if (sequence != (sock->sendSequence - 1))
    400 			{
    401 				Con_DPrintf("Stale ACK received\n");
    402 				continue;
    403 			}
    404 			if (sequence == sock->ackSequence)
    405 			{
    406 				sock->ackSequence++;
    407 				if (sock->ackSequence != sock->sendSequence)
    408 					Con_DPrintf("ack sequencing error\n");
    409 			}
    410 			else
    411 			{
    412 				Con_DPrintf("Duplicate ACK received\n");
    413 				continue;
    414 			}
    415 			sock->sendMessageLength -= MAX_DATAGRAM;
    416 			if (sock->sendMessageLength > 0)
    417 			{
    418 				Q_memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
    419 				sock->sendNext = true;
    420 			}
    421 			else
    422 			{
    423 				sock->sendMessageLength = 0;
    424 				sock->canSend = true;
    425 			}
    426 			continue;
    427 		}
    428 
    429 		if (flags & NETFLAG_DATA)
    430 		{
    431 			packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
    432 			packetBuffer.sequence = BigLong(sequence);
    433 			sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
    434 
    435 			if (sequence != sock->receiveSequence)
    436 			{
    437 				receivedDuplicateCount++;
    438 				continue;
    439 			}
    440 			sock->receiveSequence++;
    441 
    442 			length -= NET_HEADERSIZE;
    443 
    444 			if (flags & NETFLAG_EOM)
    445 			{
    446 				SZ_Clear(&net_message);
    447 				SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
    448 				SZ_Write(&net_message, packetBuffer.data, length);
    449 				sock->receiveMessageLength = 0;
    450 
    451 				ret = 1;
    452 				break;
    453 			}
    454 
    455 			Q_memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
    456 			sock->receiveMessageLength += length;
    457 			continue;
    458 		}
    459 	}
    460 
    461 	if (sock->sendNext)
    462 		SendMessageNext (sock);
    463 
    464 	return ret;
    465 }
    466 
    467 
    468 void PrintStats(qsocket_t *s)
    469 {
    470 	Con_Printf("canSend = %4u   \n", s->canSend);
    471 	Con_Printf("sendSeq = %4u   ", s->sendSequence);
    472 	Con_Printf("recvSeq = %4u   \n", s->receiveSequence);
    473 	Con_Printf("\n");
    474 }
    475 
    476 void NET_Stats_f (void)
    477 {
    478 	qsocket_t	*s;
    479 
    480 	if (Cmd_Argc () == 1)
    481 	{
    482 		Con_Printf("unreliable messages sent   = %i\n", unreliableMessagesSent);
    483 		Con_Printf("unreliable messages recv   = %i\n", unreliableMessagesReceived);
    484 		Con_Printf("reliable messages sent     = %i\n", messagesSent);
    485 		Con_Printf("reliable messages received = %i\n", messagesReceived);
    486 		Con_Printf("packetsSent                = %i\n", packetsSent);
    487 		Con_Printf("packetsReSent              = %i\n", packetsReSent);
    488 		Con_Printf("packetsReceived            = %i\n", packetsReceived);
    489 		Con_Printf("receivedDuplicateCount     = %i\n", receivedDuplicateCount);
    490 		Con_Printf("shortPacketCount           = %i\n", shortPacketCount);
    491 		Con_Printf("droppedDatagrams           = %i\n", droppedDatagrams);
    492 	}
    493 	else if (Q_strcmp(Cmd_Argv(1), "*") == 0)
    494 	{
    495 		for (s = net_activeSockets; s; s = s->next)
    496 			PrintStats(s);
    497 		for (s = net_freeSockets; s; s = s->next)
    498 			PrintStats(s);
    499 	}
    500 	else
    501 	{
    502 		for (s = net_activeSockets; s; s = s->next)
    503 			if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
    504 				break;
    505 		if (s == NULL)
    506 			for (s = net_freeSockets; s; s = s->next)
    507 				if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
    508 					break;
    509 		if (s == NULL)
    510 			return;
    511 		PrintStats(s);
    512 	}
    513 }
    514 
    515 
    516 static qboolean testInProgress = false;
    517 static int		testPollCount;
    518 static int		testDriver;
    519 static int		testSocket;
    520 
    521 static void Test_Poll(void* arg);
    522 PollProcedure	testPollProcedure = {NULL, 0.0, Test_Poll, NULL};
    523 
    524 static void Test_Poll(void* /* arg */)
    525 {
    526 	struct qsockaddr clientaddr;
    527 	int		control;
    528 	int		len;
    529 	char	name[32];
    530 	char	address[64];
    531 	int		colors;
    532 	int		frags;
    533 	int		connectTime;
    534 	byte	playerNumber;
    535 
    536 	net_landriverlevel = testDriver;
    537 
    538 	while (1)
    539 	{
    540 		len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
    541 		if (len < (int) sizeof(int))
    542 			break;
    543 
    544 		net_message.cursize = len;
    545 
    546 		MSG_BeginReading ();
    547 		control = BigLong(*((int *)net_message.data));
    548 		MSG_ReadLong();
    549 		if (control == -1)
    550 			break;
    551 		if ((control & (~NETFLAG_LENGTH_MASK)) !=  (int) NETFLAG_CTL)
    552 			break;
    553 		if ((control & NETFLAG_LENGTH_MASK) != len)
    554 			break;
    555 
    556 		if (MSG_ReadByte() != CCREP_PLAYER_INFO)
    557 			Sys_Error("Unexpected repsonse to Player Info request\n");
    558 
    559 		playerNumber = MSG_ReadByte();
    560 		Q_strcpy(name, MSG_ReadString());
    561 		colors = MSG_ReadLong();
    562 		frags = MSG_ReadLong();
    563 		connectTime = MSG_ReadLong();
    564 		Q_strcpy(address, MSG_ReadString());
    565 
    566 		Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
    567 	}
    568 
    569 	testPollCount--;
    570 	if (testPollCount)
    571 	{
    572 		SchedulePollProcedure(&testPollProcedure, 0.1);
    573 	}
    574 	else
    575 	{
    576 		dfunc.CloseSocket(testSocket);
    577 		testInProgress = false;
    578 	}
    579 }
    580 
    581 static void Test_f (void)
    582 {
    583 	char	*host;
    584 	int		n;
    585 	int		max = MAX_SCOREBOARD;
    586 	struct qsockaddr sendaddr;
    587 
    588 	if (testInProgress)
    589 		return;
    590 
    591 	host = Cmd_Argv (1);
    592 
    593 	if (host && hostCacheCount)
    594 	{
    595 		for (n = 0; n < hostCacheCount; n++)
    596 			if (Q_strcasecmp (host, hostcache[n].name) == 0)
    597 			{
    598 				if (hostcache[n].driver != myDriverLevel)
    599 					continue;
    600 				net_landriverlevel = hostcache[n].ldriver;
    601 				max = hostcache[n].maxusers;
    602 				Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
    603 				break;
    604 			}
    605 		if (n < hostCacheCount)
    606 			goto JustDoIt;
    607 	}
    608 
    609 	for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
    610 	{
    611 		if (!net_landrivers[net_landriverlevel].initialized)
    612 			continue;
    613 
    614 		// see if we can resolve the host name
    615 		if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
    616 			break;
    617 	}
    618 	if (net_landriverlevel == net_numlandrivers)
    619 		return;
    620 
    621 JustDoIt:
    622 	testSocket = dfunc.OpenSocket(0);
    623 	if (testSocket == -1)
    624 		return;
    625 
    626 	testInProgress = true;
    627 	testPollCount = 20;
    628 	testDriver = net_landriverlevel;
    629 
    630 	for (n = 0; n < max; n++)
    631 	{
    632 		SZ_Clear(&net_message);
    633 		// save space for the header, filled in later
    634 		MSG_WriteLong(&net_message, 0);
    635 		MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
    636 		MSG_WriteByte(&net_message, n);
    637 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | 	(net_message.cursize & NETFLAG_LENGTH_MASK));
    638 		dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
    639 	}
    640 	SZ_Clear(&net_message);
    641 	SchedulePollProcedure(&testPollProcedure, 0.1);
    642 }
    643 
    644 
    645 static qboolean test2InProgress = false;
    646 static int		test2Driver;
    647 static int		test2Socket;
    648 
    649 static void Test2_Poll(void*);
    650 PollProcedure	test2PollProcedure = {NULL, 0.0, Test2_Poll, NULL};
    651 
    652 static void Test2_Poll(void* /* arg */)
    653 {
    654 	struct qsockaddr clientaddr;
    655 	int		control;
    656 	int		len;
    657 	char	name[256];
    658 	char	value[256];
    659 
    660 	net_landriverlevel = test2Driver;
    661 	name[0] = 0;
    662 
    663 	len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
    664 	if (len < (int) sizeof(int))
    665 		goto Reschedule;
    666 
    667 	net_message.cursize = len;
    668 
    669 	MSG_BeginReading ();
    670 	control = BigLong(*((int *)net_message.data));
    671 	MSG_ReadLong();
    672 	if (control == -1)
    673 		goto Error;
    674 	if ((control & (~NETFLAG_LENGTH_MASK)) !=  (int) NETFLAG_CTL)
    675 		goto Error;
    676 	if ((control & NETFLAG_LENGTH_MASK) != len)
    677 		goto Error;
    678 
    679 	if (MSG_ReadByte() != CCREP_RULE_INFO)
    680 		goto Error;
    681 
    682 	Q_strcpy(name, MSG_ReadString());
    683 	if (name[0] == 0)
    684 		goto Done;
    685 	Q_strcpy(value, MSG_ReadString());
    686 
    687 	Con_Printf("%-16.16s  %-16.16s\n", name, value);
    688 
    689 	SZ_Clear(&net_message);
    690 	// save space for the header, filled in later
    691 	MSG_WriteLong(&net_message, 0);
    692 	MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
    693 	MSG_WriteString(&net_message, name);
    694 	*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
    695 	dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
    696 	SZ_Clear(&net_message);
    697 
    698 Reschedule:
    699 	SchedulePollProcedure(&test2PollProcedure, 0.05);
    700 	return;
    701 
    702 Error:
    703 	Con_Printf("Unexpected repsonse to Rule Info request\n");
    704 Done:
    705 	dfunc.CloseSocket(test2Socket);
    706 	test2InProgress = false;
    707 	return;
    708 }
    709 
    710 static void Test2_f (void)
    711 {
    712 	char	*host;
    713 	int		n;
    714 	struct qsockaddr sendaddr;
    715 
    716 	if (test2InProgress)
    717 		return;
    718 
    719 	host = Cmd_Argv (1);
    720 
    721 	if (host && hostCacheCount)
    722 	{
    723 		for (n = 0; n < hostCacheCount; n++)
    724 			if (Q_strcasecmp (host, hostcache[n].name) == 0)
    725 			{
    726 				if (hostcache[n].driver != myDriverLevel)
    727 					continue;
    728 				net_landriverlevel = hostcache[n].ldriver;
    729 				Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
    730 				break;
    731 			}
    732 		if (n < hostCacheCount)
    733 			goto JustDoIt;
    734 	}
    735 
    736 	for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
    737 	{
    738 		if (!net_landrivers[net_landriverlevel].initialized)
    739 			continue;
    740 
    741 		// see if we can resolve the host name
    742 		if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
    743 			break;
    744 	}
    745 	if (net_landriverlevel == net_numlandrivers)
    746 		return;
    747 
    748 JustDoIt:
    749 	test2Socket = dfunc.OpenSocket(0);
    750 	if (test2Socket == -1)
    751 		return;
    752 
    753 	test2InProgress = true;
    754 	test2Driver = net_landriverlevel;
    755 
    756 	SZ_Clear(&net_message);
    757 	// save space for the header, filled in later
    758 	MSG_WriteLong(&net_message, 0);
    759 	MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
    760 	MSG_WriteString(&net_message, "");
    761 	*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
    762 	dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
    763 	SZ_Clear(&net_message);
    764 	SchedulePollProcedure(&test2PollProcedure, 0.05);
    765 }
    766 
    767 
    768 int Datagram_Init (void)
    769 {
    770 	int i;
    771 	int csock;
    772 
    773 	myDriverLevel = net_driverlevel;
    774 	Cmd_AddCommand ("net_stats", NET_Stats_f);
    775 
    776 	if (COM_CheckParm("-nolan"))
    777 		return -1;
    778 
    779 	for (i = 0; i < net_numlandrivers; i++)
    780 		{
    781 		csock = net_landrivers[i].Init ();
    782 		if (csock == -1)
    783 			continue;
    784 		net_landrivers[i].initialized = true;
    785 		net_landrivers[i].controlSock = csock;
    786 		}
    787 
    788 #ifdef BAN_TEST
    789 	Cmd_AddCommand ("ban", NET_Ban_f);
    790 #endif
    791 	Cmd_AddCommand ("test", Test_f);
    792 	Cmd_AddCommand ("test2", Test2_f);
    793 
    794 	return 0;
    795 }
    796 
    797 
    798 void Datagram_Shutdown (void)
    799 {
    800 	int i;
    801 
    802 //
    803 // shutdown the lan drivers
    804 //
    805 	for (i = 0; i < net_numlandrivers; i++)
    806 	{
    807 		if (net_landrivers[i].initialized)
    808 		{
    809 			net_landrivers[i].Shutdown ();
    810 			net_landrivers[i].initialized = false;
    811 		}
    812 	}
    813 }
    814 
    815 
    816 void Datagram_Close (qsocket_t *sock)
    817 {
    818 	sfunc.CloseSocket(sock->socket);
    819 }
    820 
    821 
    822 void Datagram_Listen (qboolean state)
    823 {
    824 	int i;
    825 
    826 	for (i = 0; i < net_numlandrivers; i++)
    827 		if (net_landrivers[i].initialized)
    828 			net_landrivers[i].Listen (state);
    829 }
    830 
    831 
    832 static qsocket_t *_Datagram_CheckNewConnections (void)
    833 {
    834 	struct qsockaddr clientaddr;
    835 	struct qsockaddr newaddr;
    836 	int			newsock;
    837 	int			acceptsock;
    838 	qsocket_t	*sock;
    839 	qsocket_t	*s;
    840 	int			len;
    841 	int			command;
    842 	int			control;
    843 	int			ret;
    844 
    845 	acceptsock = dfunc.CheckNewConnections();
    846 	if (acceptsock == -1)
    847 		return NULL;
    848 
    849 	SZ_Clear(&net_message);
    850 
    851 	len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
    852 	if (len < (int) sizeof(int))
    853 		return NULL;
    854 	net_message.cursize = len;
    855 
    856 	MSG_BeginReading ();
    857 	control = BigLong(*((int *)net_message.data));
    858 	MSG_ReadLong();
    859 	if (control == -1)
    860 		return NULL;
    861 	if ((control & (~NETFLAG_LENGTH_MASK)) !=  (int) NETFLAG_CTL)
    862 		return NULL;
    863 	if ((control & NETFLAG_LENGTH_MASK) != len)
    864 		return NULL;
    865 
    866 	command = MSG_ReadByte();
    867 	if (command == CCREQ_SERVER_INFO)
    868 	{
    869 		if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
    870 			return NULL;
    871 
    872 		SZ_Clear(&net_message);
    873 		// save space for the header, filled in later
    874 		MSG_WriteLong(&net_message, 0);
    875 		MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
    876 		dfunc.GetSocketAddr(acceptsock, &newaddr);
    877 		MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
    878 		MSG_WriteString(&net_message, hostname.string);
    879 		MSG_WriteString(&net_message, sv.name);
    880 		MSG_WriteByte(&net_message, net_activeconnections);
    881 		MSG_WriteByte(&net_message, svs.maxclients);
    882 		MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
    883 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
    884 		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
    885 		SZ_Clear(&net_message);
    886 		return NULL;
    887 	}
    888 
    889 	if (command == CCREQ_PLAYER_INFO)
    890 	{
    891 		int			playerNumber;
    892 		int			activeNumber;
    893 		int			clientNumber;
    894 		client_t	*client;
    895 
    896 		playerNumber = MSG_ReadByte();
    897 		activeNumber = -1;
    898 		for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
    899 		{
    900 			if (client->active)
    901 			{
    902 				activeNumber++;
    903 				if (activeNumber == playerNumber)
    904 					break;
    905 			}
    906 		}
    907 		if (clientNumber == svs.maxclients)
    908 			return NULL;
    909 
    910 		SZ_Clear(&net_message);
    911 		// save space for the header, filled in later
    912 		MSG_WriteLong(&net_message, 0);
    913 		MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
    914 		MSG_WriteByte(&net_message, playerNumber);
    915 		MSG_WriteString(&net_message, client->name);
    916 		MSG_WriteLong(&net_message, client->colors);
    917 		MSG_WriteLong(&net_message, (int)client->edict->u.v.frags);
    918 		MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
    919 		MSG_WriteString(&net_message, client->netconnection->address);
    920 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
    921 		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
    922 		SZ_Clear(&net_message);
    923 
    924 		return NULL;
    925 	}
    926 
    927 	if (command == CCREQ_RULE_INFO)
    928 	{
    929 		char	*prevCvarName;
    930 		cvar_t	*var;
    931 
    932 		// find the search start location
    933 		prevCvarName = MSG_ReadString();
    934 		if (*prevCvarName)
    935 		{
    936 			var = Cvar_FindVar (prevCvarName);
    937 			if (!var)
    938 				return NULL;
    939 			var = var->next;
    940 		}
    941 		else
    942 			var = cvar_vars;
    943 
    944 		// search for the next server cvar
    945 		while (var)
    946 		{
    947 			if (var->server)
    948 				break;
    949 			var = var->next;
    950 		}
    951 
    952 		// send the response
    953 
    954 		SZ_Clear(&net_message);
    955 		// save space for the header, filled in later
    956 		MSG_WriteLong(&net_message, 0);
    957 		MSG_WriteByte(&net_message, CCREP_RULE_INFO);
    958 		if (var)
    959 		{
    960 			MSG_WriteString(&net_message, var->name);
    961 			MSG_WriteString(&net_message, var->string);
    962 		}
    963 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
    964 		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
    965 		SZ_Clear(&net_message);
    966 
    967 		return NULL;
    968 	}
    969 
    970 	if (command != CCREQ_CONNECT)
    971 		return NULL;
    972 
    973 	if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
    974 		return NULL;
    975 
    976 	if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
    977 	{
    978 		SZ_Clear(&net_message);
    979 		// save space for the header, filled in later
    980 		MSG_WriteLong(&net_message, 0);
    981 		MSG_WriteByte(&net_message, CCREP_REJECT);
    982 		MSG_WriteString(&net_message, "Incompatible version.\n");
    983 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
    984 		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
    985 		SZ_Clear(&net_message);
    986 		return NULL;
    987 	}
    988 
    989 #ifdef BAN_TEST
    990 	// check for a ban
    991 	if (clientaddr.sa_family == AF_INET)
    992 	{
    993 	    qsockaddr2sockaddr_in temp;
    994 	    temp.q = clientaddr;
    995 	    unsigned long testAddr = temp.i.sin_addr.s_addr;
    996 		if ((testAddr & banMask) == banAddr)
    997 		{
    998 			SZ_Clear(&net_message);
    999 			// save space for the header, filled in later
   1000 			MSG_WriteLong(&net_message, 0);
   1001 			MSG_WriteByte(&net_message, CCREP_REJECT);
   1002 			MSG_WriteString(&net_message, "You have been banned.\n");
   1003 			*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
   1004 			dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
   1005 			SZ_Clear(&net_message);
   1006 			return NULL;
   1007 		}
   1008 	}
   1009 #endif
   1010 
   1011 	// see if this guy is already connected
   1012 	for (s = net_activeSockets; s; s = s->next)
   1013 	{
   1014 		if (s->driver != net_driverlevel)
   1015 			continue;
   1016 		ret = dfunc.AddrCompare(&clientaddr, &s->addr);
   1017 		if (ret >= 0)
   1018 		{
   1019 			// is this a duplicate connection reqeust?
   1020 			if (ret == 0 && net_time - s->connecttime < 2.0)
   1021 			{
   1022 				// yes, so send a duplicate reply
   1023 				SZ_Clear(&net_message);
   1024 				// save space for the header, filled in later
   1025 				MSG_WriteLong(&net_message, 0);
   1026 				MSG_WriteByte(&net_message, CCREP_ACCEPT);
   1027 				dfunc.GetSocketAddr(s->socket, &newaddr);
   1028 				MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
   1029 				*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
   1030 				dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
   1031 				SZ_Clear(&net_message);
   1032 				return NULL;
   1033 			}
   1034 			// it's somebody coming back in from a crash/disconnect
   1035 			// so close the old qsocket and let their retry get them back in
   1036 			NET_Close(s);
   1037 			return NULL;
   1038 		}
   1039 	}
   1040 
   1041 	// allocate a QSocket
   1042 	sock = NET_NewQSocket ();
   1043 	if (sock == NULL)
   1044 	{
   1045 		// no room; try to let him know
   1046 		SZ_Clear(&net_message);
   1047 		// save space for the header, filled in later
   1048 		MSG_WriteLong(&net_message, 0);
   1049 		MSG_WriteByte(&net_message, CCREP_REJECT);
   1050 		MSG_WriteString(&net_message, "Server is full.\n");
   1051 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
   1052 		dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
   1053 		SZ_Clear(&net_message);
   1054 		return NULL;
   1055 	}
   1056 
   1057 	// allocate a network socket
   1058 	newsock = dfunc.OpenSocket(0);
   1059 	if (newsock == -1)
   1060 	{
   1061 		NET_FreeQSocket(sock);
   1062 		return NULL;
   1063 	}
   1064 
   1065 	// connect to the client
   1066 	if (dfunc.Connect (newsock, &clientaddr) == -1)
   1067 	{
   1068 		dfunc.CloseSocket(newsock);
   1069 		NET_FreeQSocket(sock);
   1070 		return NULL;
   1071 	}
   1072 
   1073 	// everything is allocated, just fill in the details
   1074 	sock->socket = newsock;
   1075 	sock->landriver = net_landriverlevel;
   1076 	sock->addr = clientaddr;
   1077 	Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr));
   1078 
   1079 	// send him back the info about the server connection he has been allocated
   1080 	SZ_Clear(&net_message);
   1081 	// save space for the header, filled in later
   1082 	MSG_WriteLong(&net_message, 0);
   1083 	MSG_WriteByte(&net_message, CCREP_ACCEPT);
   1084 	dfunc.GetSocketAddr(newsock, &newaddr);
   1085 	MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
   1086 //	MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
   1087 	*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
   1088 	dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
   1089 	SZ_Clear(&net_message);
   1090 
   1091 	return sock;
   1092 }
   1093 
   1094 qsocket_t *Datagram_CheckNewConnections (void)
   1095 {
   1096 	qsocket_t *ret = NULL;
   1097 
   1098 	for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
   1099 		if (net_landrivers[net_landriverlevel].initialized)
   1100 			if ((ret = _Datagram_CheckNewConnections ()) != NULL)
   1101 				break;
   1102 	return ret;
   1103 }
   1104 
   1105 
   1106 static void _Datagram_SearchForHosts (qboolean xmit)
   1107 {
   1108 	int		ret;
   1109 	int		n;
   1110 	int		i;
   1111 	struct qsockaddr readaddr;
   1112 	struct qsockaddr myaddr;
   1113 	int		control;
   1114 
   1115 	dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
   1116 	if (xmit)
   1117 	{
   1118 		SZ_Clear(&net_message);
   1119 		// save space for the header, filled in later
   1120 		MSG_WriteLong(&net_message, 0);
   1121 		MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
   1122 		MSG_WriteString(&net_message, "QUAKE");
   1123 		MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
   1124 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
   1125 		dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
   1126 		SZ_Clear(&net_message);
   1127 	}
   1128 
   1129 	while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
   1130 	{
   1131 		if (ret < (int) sizeof(int))
   1132 			continue;
   1133 		net_message.cursize = ret;
   1134 
   1135 		// don't answer our own query
   1136 		if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
   1137 			continue;
   1138 
   1139 		// is the cache full?
   1140 		if (hostCacheCount == HOSTCACHESIZE)
   1141 			continue;
   1142 
   1143 		MSG_BeginReading ();
   1144 		control = BigLong(*((int *)net_message.data));
   1145 		MSG_ReadLong();
   1146 		if (control == -1)
   1147 			continue;
   1148 		if ((control & (~NETFLAG_LENGTH_MASK)) !=  (int) NETFLAG_CTL)
   1149 			continue;
   1150 		if ((control & NETFLAG_LENGTH_MASK) != ret)
   1151 			continue;
   1152 
   1153 		if (MSG_ReadByte() != CCREP_SERVER_INFO)
   1154 			continue;
   1155 
   1156 		dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
   1157 		// search the cache for this server
   1158 		for (n = 0; n < hostCacheCount; n++)
   1159 			if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
   1160 				break;
   1161 
   1162 		// is it already there?
   1163 		if (n < hostCacheCount)
   1164 			continue;
   1165 
   1166 		// add it
   1167 		hostCacheCount++;
   1168 		Q_strcpy(hostcache[n].name, MSG_ReadString());
   1169 		Q_strcpy(hostcache[n].map, MSG_ReadString());
   1170 		hostcache[n].users = MSG_ReadByte();
   1171 		hostcache[n].maxusers = MSG_ReadByte();
   1172 		if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
   1173 		{
   1174 			Q_strcpy(hostcache[n].cname, hostcache[n].name);
   1175 			hostcache[n].cname[14] = 0;
   1176 			Q_strcpy(hostcache[n].name, "*");
   1177 			Q_strcat(hostcache[n].name, hostcache[n].cname);
   1178 		}
   1179 		Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
   1180 		hostcache[n].driver = net_driverlevel;
   1181 		hostcache[n].ldriver = net_landriverlevel;
   1182 		Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
   1183 
   1184 		// check for a name conflict
   1185 		for (i = 0; i < hostCacheCount; i++)
   1186 		{
   1187 			if (i == n)
   1188 				continue;
   1189 			if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
   1190 			{
   1191 				i = Q_strlen(hostcache[n].name);
   1192 				if (i < 15 && hostcache[n].name[i-1] > '8')
   1193 				{
   1194 					hostcache[n].name[i] = '0';
   1195 					hostcache[n].name[i+1] = 0;
   1196 				}
   1197 				else
   1198 					hostcache[n].name[i-1]++;
   1199 				i = -1;
   1200 			}
   1201 		}
   1202 	}
   1203 }
   1204 
   1205 void Datagram_SearchForHosts (qboolean xmit)
   1206 {
   1207 	for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
   1208 	{
   1209 		if (hostCacheCount == HOSTCACHESIZE)
   1210 			break;
   1211 		if (net_landrivers[net_landriverlevel].initialized)
   1212 			_Datagram_SearchForHosts (xmit);
   1213 	}
   1214 }
   1215 
   1216 
   1217 static qsocket_t *_Datagram_Connect (const char *host)
   1218 {
   1219 	struct qsockaddr sendaddr;
   1220 	struct qsockaddr readaddr;
   1221 	qsocket_t	*sock;
   1222 	int			newsock;
   1223 	int			ret;
   1224 	int			reps;
   1225 	double		start_time;
   1226 	int			control;
   1227 	const char		*reason;
   1228 
   1229 	// see if we can resolve the host name
   1230 	if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
   1231 		return NULL;
   1232 
   1233 	newsock = dfunc.OpenSocket (0);
   1234 	if (newsock == -1)
   1235 		return NULL;
   1236 
   1237 	sock = NET_NewQSocket ();
   1238 	if (sock == NULL)
   1239 		goto ErrorReturn2;
   1240 	sock->socket = newsock;
   1241 	sock->landriver = net_landriverlevel;
   1242 
   1243 	// connect to the host
   1244 	if (dfunc.Connect (newsock, &sendaddr) == -1)
   1245 		goto ErrorReturn;
   1246 
   1247 	// send the connection request
   1248 	Con_Printf("trying...\n"); SCR_UpdateScreen ();
   1249 	start_time = net_time;
   1250 
   1251 	for (reps = 0; reps < 3; reps++)
   1252 	{
   1253 		SZ_Clear(&net_message);
   1254 		// save space for the header, filled in later
   1255 		MSG_WriteLong(&net_message, 0);
   1256 		MSG_WriteByte(&net_message, CCREQ_CONNECT);
   1257 		MSG_WriteString(&net_message, "QUAKE");
   1258 		MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
   1259 		*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
   1260 		dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
   1261 		SZ_Clear(&net_message);
   1262 		do
   1263 		{
   1264 			ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
   1265 			// if we got something, validate it
   1266 			if (ret > 0)
   1267 			{
   1268 				// is it from the right place?
   1269 				if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
   1270 				{
   1271 #ifdef DEBUG
   1272 					Con_Printf("wrong reply address\n");
   1273 					Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
   1274 					Con_Printf("Received: %s\n", StrAddr (&readaddr));
   1275 					SCR_UpdateScreen ();
   1276 #endif
   1277 					ret = 0;
   1278 					continue;
   1279 				}
   1280 
   1281 				if (ret < (int) sizeof(int))
   1282 				{
   1283 					ret = 0;
   1284 					continue;
   1285 				}
   1286 
   1287 				net_message.cursize = ret;
   1288 				MSG_BeginReading ();
   1289 
   1290 				control = BigLong(*((int *)net_message.data));
   1291 				MSG_ReadLong();
   1292 				if (control == -1)
   1293 				{
   1294 					ret = 0;
   1295 					continue;
   1296 				}
   1297 				if ((control & (~NETFLAG_LENGTH_MASK)) !=  (int) NETFLAG_CTL)
   1298 				{
   1299 					ret = 0;
   1300 					continue;
   1301 				}
   1302 				if ((control & NETFLAG_LENGTH_MASK) != ret)
   1303 				{
   1304 					ret = 0;
   1305 					continue;
   1306 				}
   1307 			}
   1308 		}
   1309 		while (ret == 0 && (SetNetTime() - start_time) < 2.5);
   1310 		if (ret)
   1311 			break;
   1312 		Con_Printf("still trying...\n"); SCR_UpdateScreen ();
   1313 		start_time = SetNetTime();
   1314 	}
   1315 
   1316 	if (ret == 0)
   1317 	{
   1318 		reason = "No Response";
   1319 		Con_Printf("%s\n", reason);
   1320 		Q_strcpy(m_return_reason, reason);
   1321 		goto ErrorReturn;
   1322 	}
   1323 
   1324 	if (ret == -1)
   1325 	{
   1326 		reason = "Network Error";
   1327 		Con_Printf("%s\n", reason);
   1328 		Q_strcpy(m_return_reason, reason);
   1329 		goto ErrorReturn;
   1330 	}
   1331 
   1332 	ret = MSG_ReadByte();
   1333 	if (ret == CCREP_REJECT)
   1334 	{
   1335 		reason = MSG_ReadString();
   1336 		Con_Printf(reason);
   1337 		Q_strncpy(m_return_reason, reason, 31);
   1338 		goto ErrorReturn;
   1339 	}
   1340 
   1341 	if (ret == CCREP_ACCEPT)
   1342 	{
   1343 		Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
   1344 		dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
   1345 	}
   1346 	else
   1347 	{
   1348 		reason = "Bad Response";
   1349 		Con_Printf("%s\n", reason);
   1350 		Q_strcpy(m_return_reason, reason);
   1351 		goto ErrorReturn;
   1352 	}
   1353 
   1354 	dfunc.GetNameFromAddr (&sendaddr, sock->address);
   1355 
   1356 	Con_Printf ("Connection accepted\n");
   1357 	sock->lastMessageTime = SetNetTime();
   1358 
   1359 	// switch the connection to the specified address
   1360 	if (dfunc.Connect (newsock, &sock->addr) == -1)
   1361 	{
   1362 		reason = "Connect to Game failed";
   1363 		Con_Printf("%s\n", reason);
   1364 		Q_strcpy(m_return_reason, reason);
   1365 		goto ErrorReturn;
   1366 	}
   1367 
   1368 	m_return_onerror = false;
   1369 	return sock;
   1370 
   1371 ErrorReturn:
   1372 	NET_FreeQSocket(sock);
   1373 ErrorReturn2:
   1374 	dfunc.CloseSocket(newsock);
   1375 	if (m_return_onerror)
   1376 	{
   1377 		key_dest = key_menu;
   1378 		m_state = m_return_state;
   1379 		m_return_onerror = false;
   1380 	}
   1381 	return NULL;
   1382 }
   1383 
   1384 qsocket_t *Datagram_Connect (const char *host)
   1385 {
   1386 	qsocket_t *ret = NULL;
   1387 
   1388 	for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
   1389 		if (net_landrivers[net_landriverlevel].initialized)
   1390 			if ((ret = _Datagram_Connect (host)) != NULL)
   1391 				break;
   1392 	return ret;
   1393 }
   1394