• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
StrAddr(struct qsockaddr * addr)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 
NET_Ban_f(void)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 
Datagram_SendMessage(qsocket_t * sock,sizebuf_t * data)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 
SendMessageNext(qsocket_t * sock)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 
ReSendMessage(qsocket_t * sock)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 
Datagram_CanSendMessage(qsocket_t * sock)276 qboolean Datagram_CanSendMessage (qsocket_t *sock)
277 {
278 	if (sock->sendNext)
279 		SendMessageNext (sock);
280 
281 	return sock->canSend;
282 }
283 
284 
Datagram_CanSendUnreliableMessage(qsocket_t * sock)285 qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
286 {
287 	return true;
288 }
289 
290 
Datagram_SendUnreliableMessage(qsocket_t * sock,sizebuf_t * data)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 
Datagram_GetMessage(qsocket_t * sock)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 
PrintStats(qsocket_t * s)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 
NET_Stats_f(void)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 
Test_Poll(void *)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 
Test_f(void)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 
Test2_Poll(void *)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 
Test2_f(void)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 
Datagram_Init(void)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 
Datagram_Shutdown(void)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 
Datagram_Close(qsocket_t * sock)816 void Datagram_Close (qsocket_t *sock)
817 {
818 	sfunc.CloseSocket(sock->socket);
819 }
820 
821 
Datagram_Listen(qboolean state)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 
_Datagram_CheckNewConnections(void)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 
Datagram_CheckNewConnections(void)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 
_Datagram_SearchForHosts(qboolean xmit)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 
Datagram_SearchForHosts(qboolean xmit)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 
_Datagram_Connect(const char * host)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 
Datagram_Connect(const char * host)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