summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/net_dgrm.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/net_dgrm.c')
-rw-r--r--apps/plugins/sdl/progs/quake/net_dgrm.c1390
1 files changed, 1390 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/net_dgrm.c b/apps/plugins/sdl/progs/quake/net_dgrm.c
new file mode 100644
index 0000000000..a293b77b9f
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/net_dgrm.c
@@ -0,0 +1,1390 @@
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#define AF_INET 2 /* internet */
33struct 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 */
43struct sockaddr_in
44{
45 short sin_family;
46 unsigned short sin_port;
47 struct in_addr sin_addr;
48 char sin_zero[8];
49};
50char *inet_ntoa(struct in_addr in);
51unsigned 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
62static int net_landriverlevel;
63
64/* statistic counters */
65int packetsSent = 0;
66int packetsReSent = 0;
67int packetsReceived = 0;
68int receivedDuplicateCount = 0;
69int shortPacketCount = 0;
70int droppedDatagrams;
71
72static int myDriverLevel;
73
74struct
75{
76 unsigned int length;
77 unsigned int sequence;
78 byte data[MAX_DATAGRAM];
79} packetBuffer;
80
81extern int m_return_state;
82extern int m_state;
83extern qboolean m_return_onerror;
84extern char m_return_reason[32];
85
86
87#ifdef DEBUG
88char *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
102unsigned long banAddr = 0x00000000;
103unsigned long banMask = 0xffffffff;
104
105void 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
161int 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
208int 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
241int 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
274qboolean Datagram_CanSendMessage (qsocket_t *sock)
275{
276 if (sock->sendNext)
277 SendMessageNext (sock);
278
279 return sock->canSend;
280}
281
282
283qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
284{
285 return true;
286}
287
288
289int 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
315int 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
466void 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
474void 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
514static qboolean testInProgress = false;
515static int testPollCount;
516static int testDriver;
517static int testSocket;
518
519static void Test_Poll(void);
520PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll};
521
522static 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
579static 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
619JustDoIt:
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
643static qboolean test2InProgress = false;
644static int test2Driver;
645static int test2Socket;
646
647static void Test2_Poll(void);
648PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll};
649
650static 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
696Reschedule:
697 SchedulePollProcedure(&test2PollProcedure, 0.05);
698 return;
699
700Error:
701 Con_Printf("Unexpected repsonse to Rule Info request\n");
702Done:
703 dfunc.CloseSocket(test2Socket);
704 test2InProgress = false;
705 return;
706}
707
708static 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
746JustDoIt:
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
766int 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
796void 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
814void Datagram_Close (qsocket_t *sock)
815{
816 sfunc.CloseSocket(sock->socket);
817}
818
819
820void 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
830static 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
1091qsocket_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
1103static 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
1202void 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
1214static 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
1368ErrorReturn:
1369 NET_FreeQSocket(sock);
1370ErrorReturn2:
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
1381qsocket_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}