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