1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
47static int net_landriverlevel;
48
49/* statistic counters */
50int	packetsSent = 0;
51int	packetsReSent = 0;
52int packetsReceived = 0;
53int receivedDuplicateCount = 0;
54int shortPacketCount = 0;
55int droppedDatagrams;
56
57static int myDriverLevel;
58
59struct packetBuffer_t
60{
61	unsigned int	length;
62	unsigned int	sequence;
63	byte			data[MAX_DATAGRAM];
64} packetBuffer;
65
66extern int m_return_state;
67extern int m_state;
68extern qboolean m_return_onerror;
69extern char m_return_reason[32];
70
71
72#ifdef DEBUG
73char *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
87typedef union {
88    unsigned long ul;
89    struct in_addr addr;
90} ulongaddr;
91
92typedef union {
93    qsockaddr q;
94    sockaddr_in i;
95} qsockaddr2sockaddr_in;
96
97unsigned long banAddr = 0x00000000;
98unsigned long banMask = 0xffffffff;
99
100void 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
163int 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
210int 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
243int 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
276qboolean Datagram_CanSendMessage (qsocket_t *sock)
277{
278	if (sock->sendNext)
279		SendMessageNext (sock);
280
281	return sock->canSend;
282}
283
284
285qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
286{
287	return true;
288}
289
290
291int 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
317int	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
468void 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
476void 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
516static qboolean testInProgress = false;
517static int		testPollCount;
518static int		testDriver;
519static int		testSocket;
520
521static void Test_Poll(void* arg);
522PollProcedure	testPollProcedure = {NULL, 0.0, Test_Poll, NULL};
523
524static 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
581static 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
621JustDoIt:
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
645static qboolean test2InProgress = false;
646static int		test2Driver;
647static int		test2Socket;
648
649static void Test2_Poll(void*);
650PollProcedure	test2PollProcedure = {NULL, 0.0, Test2_Poll, NULL};
651
652static 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
698Reschedule:
699	SchedulePollProcedure(&test2PollProcedure, 0.05);
700	return;
701
702Error:
703	Con_Printf("Unexpected repsonse to Rule Info request\n");
704Done:
705	dfunc.CloseSocket(test2Socket);
706	test2InProgress = false;
707	return;
708}
709
710static 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
748JustDoIt:
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
768int 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
798void 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
816void Datagram_Close (qsocket_t *sock)
817{
818	sfunc.CloseSocket(sock->socket);
819}
820
821
822void 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
832static 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
1094qsocket_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
1106static 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
1205void 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
1217static 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
1371ErrorReturn:
1372	NET_FreeQSocket(sock);
1373ErrorReturn2:
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
1384qsocket_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