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