]> icculus.org git repositories - divverent/darkplaces.git/blob - net_dgrm.c
Fixed video modes menu on Win32
[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 (length == 0)
330                         break;
331
332                 if (length == -1)
333                 {
334                         Con_Printf("Read error\n");
335                         return -1;
336                 }
337
338                 if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
339                 {
340 #ifdef DEBUG
341                         Con_DPrintf("Forged packet received\n");
342                         Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
343                         Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
344 #endif
345                         continue;
346                 }
347
348                 if (length < NET_HEADERSIZE)
349                 {
350                         shortPacketCount++;
351                         continue;
352                 }
353
354                 length = BigLong(packetBuffer.length);
355                 flags = length & (~NETFLAG_LENGTH_MASK);
356                 length &= NETFLAG_LENGTH_MASK;
357
358                 if (flags & NETFLAG_CTL)
359                         continue;
360
361                 sequence = BigLong(packetBuffer.sequence);
362                 packetsReceived++;
363
364                 if (flags & NETFLAG_UNRELIABLE)
365                 {
366                         if (sequence < sock->unreliableReceiveSequence)
367                         {
368                                 Con_DPrintf("Got a stale datagram\n");
369                                 ret = 0;
370                                 break;
371                         }
372                         if (sequence != sock->unreliableReceiveSequence)
373                         {
374                                 count = sequence - sock->unreliableReceiveSequence;
375                                 droppedDatagrams += count;
376                                 Con_DPrintf("Dropped %u datagram(s)\n", count);
377                         }
378                         sock->unreliableReceiveSequence = sequence + 1;
379
380                         length -= NET_HEADERSIZE;
381
382                         SZ_Clear (&net_message);
383                         SZ_Write (&net_message, packetBuffer.data, length);
384
385                         ret = 2;
386                         break;
387                 }
388
389                 if (flags & NETFLAG_ACK)
390                 {
391                         if (sequence != (sock->sendSequence - 1))
392                         {
393                                 Con_DPrintf("Stale ACK received\n");
394                                 continue;
395                         }
396                         if (sequence == sock->ackSequence)
397                         {
398                                 sock->ackSequence++;
399                                 if (sock->ackSequence != sock->sendSequence)
400                                         Con_DPrintf("ack sequencing error\n");
401                         }
402                         else
403                         {
404                                 Con_DPrintf("Duplicate ACK received\n");
405                                 continue;
406                         }
407                         sock->sendMessageLength -= MAX_DATAGRAM;
408                         if (sock->sendMessageLength > 0)
409                         {
410                                 memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
411                                 sock->sendNext = true;
412                         }
413                         else
414                         {
415                                 sock->sendMessageLength = 0;
416                                 sock->canSend = true;
417                         }
418                         continue;
419                 }
420
421                 if (flags & NETFLAG_DATA)
422                 {
423                         packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
424                         packetBuffer.sequence = BigLong(sequence);
425                         sfunc.Write (sock->socket, (qbyte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
426
427                         if (sequence != sock->receiveSequence)
428                         {
429                                 receivedDuplicateCount++;
430                                 continue;
431                         }
432                         sock->receiveSequence++;
433
434                         length -= NET_HEADERSIZE;
435
436                         if (flags & NETFLAG_EOM)
437                         {
438                                 SZ_Clear(&net_message);
439                                 SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
440                                 SZ_Write(&net_message, packetBuffer.data, length);
441                                 sock->receiveMessageLength = 0;
442
443                                 ret = 1;
444                                 break;
445                         }
446
447                         memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
448                         sock->receiveMessageLength += length;
449                         continue;
450                 }
451         }
452
453         if (sock->sendNext)
454                 SendMessageNext (sock);
455
456         return ret;
457 }
458
459
460 void PrintStats(qsocket_t *s)
461 {
462         Con_Printf("canSend = %4u   \n", s->canSend);
463         Con_Printf("sendSeq = %4u   ", s->sendSequence);
464         Con_Printf("recvSeq = %4u   \n", s->receiveSequence);
465         Con_Printf("\n");
466 }
467
468 void NET_Stats_f (void)
469 {
470         qsocket_t       *s;
471
472         if (Cmd_Argc () == 1)
473         {
474                 Con_Printf("unreliable messages sent   = %i\n", unreliableMessagesSent);
475                 Con_Printf("unreliable messages recv   = %i\n", unreliableMessagesReceived);
476                 Con_Printf("reliable messages sent     = %i\n", messagesSent);
477                 Con_Printf("reliable messages received = %i\n", messagesReceived);
478                 Con_Printf("packetsSent                = %i\n", packetsSent);
479                 Con_Printf("packetsReSent              = %i\n", packetsReSent);
480                 Con_Printf("packetsReceived            = %i\n", packetsReceived);
481                 Con_Printf("receivedDuplicateCount     = %i\n", receivedDuplicateCount);
482                 Con_Printf("shortPacketCount           = %i\n", shortPacketCount);
483                 Con_Printf("droppedDatagrams           = %i\n", droppedDatagrams);
484         }
485         else if (strcmp(Cmd_Argv(1), "*") == 0)
486         {
487                 for (s = net_activeSockets; s; s = s->next)
488                         PrintStats(s);
489         }
490         else
491         {
492                 for (s = net_activeSockets; s; s = s->next)
493                         if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
494                                 break;
495                 if (s == NULL)
496                         return;
497                 PrintStats(s);
498         }
499 }
500
501
502 static qboolean testInProgress = false;
503 static int              testPollCount;
504 static int              testDriver;
505 static int              testSocket;
506
507 static void Test_Poll(void);
508 PollProcedure   testPollProcedure = {NULL, 0.0, Test_Poll};
509
510 static void Test_Poll(void)
511 {
512         struct qsockaddr clientaddr;
513         int             control;
514         int             len;
515         char    name[32];
516         char    address[64];
517         int             colors;
518         int             frags;
519         int             connectTime;
520         qbyte   playerNumber;
521         int             c;
522
523         net_landriverlevel = testDriver;
524
525         while (1)
526         {
527                 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
528                 if (len < sizeof(int))
529                         break;
530
531                 net_message.cursize = len;
532
533                 MSG_BeginReading ();
534                 control = BigLong(*((int *)net_message.data));
535                 MSG_ReadLong();
536                 if (control == -1)
537                         break;
538                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
539                         break;
540                 if ((control & NETFLAG_LENGTH_MASK) != len)
541                         break;
542
543                 c = MSG_ReadByte();
544                 if (c != CCREP_PLAYER_INFO)
545                         Sys_Error("Unexpected repsonse to Player Info request\n");
546
547                 playerNumber = MSG_ReadByte();
548                 strcpy(name, MSG_ReadString());
549                 colors = MSG_ReadLong();
550                 frags = MSG_ReadLong();
551                 connectTime = MSG_ReadLong();
552                 strcpy(address, MSG_ReadString());
553
554                 Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
555         }
556
557         testPollCount--;
558         if (testPollCount)
559         {
560                 SchedulePollProcedure(&testPollProcedure, 0.1);
561         }
562         else
563         {
564                 dfunc.CloseSocket(testSocket);
565                 testInProgress = false;
566         }
567 }
568
569 static void Test_f (void)
570 {
571         char    *host;
572         int             n;
573         int             max = MAX_SCOREBOARD;
574         struct qsockaddr sendaddr;
575
576         if (testInProgress)
577                 return;
578
579         host = Cmd_Argv (1);
580
581         if (host && hostCacheCount)
582         {
583                 for (n = 0; n < hostCacheCount; n++)
584                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
585                         {
586                                 if (hostcache[n].driver != myDriverLevel)
587                                         continue;
588                                 net_landriverlevel = hostcache[n].ldriver;
589                                 max = hostcache[n].maxusers;
590                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
591                                 break;
592                         }
593                 if (n < hostCacheCount)
594                         goto JustDoIt;
595         }
596
597         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
598         {
599                 if (!net_landrivers[net_landriverlevel].initialized)
600                         continue;
601
602                 // see if we can resolve the host name
603                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
604                         break;
605         }
606         if (net_landriverlevel == net_numlandrivers)
607                 return;
608
609 JustDoIt:
610         testSocket = dfunc.OpenSocket(0);
611         if (testSocket == -1)
612                 return;
613
614         testInProgress = true;
615         testPollCount = 20;
616         testDriver = net_landriverlevel;
617
618         for (n = 0; n < max; n++)
619         {
620                 SZ_Clear(&net_message);
621                 // save space for the header, filled in later
622                 MSG_WriteLong(&net_message, 0);
623                 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
624                 MSG_WriteByte(&net_message, n);
625                 *((int *)net_message.data) = BigLong(NETFLAG_CTL |      (net_message.cursize & NETFLAG_LENGTH_MASK));
626                 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
627         }
628         SZ_Clear(&net_message);
629         SchedulePollProcedure(&testPollProcedure, 0.1);
630 }
631
632
633 static qboolean test2InProgress = false;
634 static int              test2Driver;
635 static int              test2Socket;
636
637 static void Test2_Poll(void);
638 PollProcedure   test2PollProcedure = {NULL, 0.0, Test2_Poll};
639
640 static void Test2_Poll(void)
641 {
642         struct qsockaddr clientaddr;
643         int             control;
644         int             len;
645         int             c;
646         char    name[256];
647         char    value[256];
648
649         net_landriverlevel = test2Driver;
650         name[0] = 0;
651
652         len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
653         if (len < sizeof(int))
654                 goto Reschedule;
655
656         net_message.cursize = len;
657
658         MSG_BeginReading ();
659         control = BigLong(*((int *)net_message.data));
660         MSG_ReadLong();
661         if (control == -1)
662                 goto Error;
663         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
664                 goto Error;
665         if ((control & NETFLAG_LENGTH_MASK) != len)
666                 goto Error;
667
668         c = MSG_ReadByte();
669         if (c != CCREP_RULE_INFO)
670                 goto Error;
671
672         strcpy(name, MSG_ReadString());
673         if (name[0] == 0)
674                 goto Done;
675         strcpy(value, MSG_ReadString());
676
677         Con_Printf("%-16.16s  %-16.16s\n", name, value);
678
679         SZ_Clear(&net_message);
680         // save space for the header, filled in later
681         MSG_WriteLong(&net_message, 0);
682         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
683         MSG_WriteString(&net_message, name);
684         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
685         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
686         SZ_Clear(&net_message);
687
688 Reschedule:
689         SchedulePollProcedure(&test2PollProcedure, 0.05);
690         return;
691
692 Error:
693         Con_Printf("Unexpected repsonse to Rule Info request\n");
694 Done:
695         dfunc.CloseSocket(test2Socket);
696         test2InProgress = false;
697         return;
698 }
699
700 static void Test2_f (void)
701 {
702         char    *host;
703         int             n;
704         struct qsockaddr sendaddr;
705
706         if (test2InProgress)
707                 return;
708
709         host = Cmd_Argv (1);
710
711         if (host && hostCacheCount)
712         {
713                 for (n = 0; n < hostCacheCount; n++)
714                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
715                         {
716                                 if (hostcache[n].driver != myDriverLevel)
717                                         continue;
718                                 net_landriverlevel = hostcache[n].ldriver;
719                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
720                                 break;
721                         }
722                 if (n < hostCacheCount)
723                         goto JustDoIt;
724         }
725
726         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
727         {
728                 if (!net_landrivers[net_landriverlevel].initialized)
729                         continue;
730
731                 // see if we can resolve the host name
732                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
733                         break;
734         }
735         if (net_landriverlevel == net_numlandrivers)
736                 return;
737
738 JustDoIt:
739         test2Socket = dfunc.OpenSocket(0);
740         if (test2Socket == -1)
741                 return;
742
743         test2InProgress = true;
744         test2Driver = net_landriverlevel;
745
746         SZ_Clear(&net_message);
747         // save space for the header, filled in later
748         MSG_WriteLong(&net_message, 0);
749         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
750         MSG_WriteString(&net_message, "");
751         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
752         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
753         SZ_Clear(&net_message);
754         SchedulePollProcedure(&test2PollProcedure, 0.05);
755 }
756
757
758 int Datagram_Init (void)
759 {
760         int i;
761         int csock;
762
763         myDriverLevel = net_driverlevel;
764         Cmd_AddCommand ("net_stats", NET_Stats_f);
765         Cvar_RegisterVariable (&cl_port);
766
767         if (COM_CheckParm("-nolan"))
768                 return -1;
769
770         for (i = 0; i < net_numlandrivers; i++)
771                 {
772                 csock = net_landrivers[i].Init ();
773                 if (csock == -1)
774                         continue;
775                 net_landrivers[i].initialized = true;
776                 net_landrivers[i].controlSock = csock;
777                 }
778
779 #ifdef BAN_TEST
780         Cmd_AddCommand ("ban", NET_Ban_f);
781 #endif
782         Cmd_AddCommand ("test", Test_f);
783         Cmd_AddCommand ("test2", Test2_f);
784
785         return 0;
786 }
787
788
789 void Datagram_Shutdown (void)
790 {
791         int i;
792
793 //
794 // shutdown the lan drivers
795 //
796         for (i = 0; i < net_numlandrivers; i++)
797         {
798                 if (net_landrivers[i].initialized)
799                 {
800                         net_landrivers[i].Shutdown ();
801                         net_landrivers[i].initialized = false;
802                 }
803         }
804 }
805
806
807 void Datagram_Close (qsocket_t *sock)
808 {
809         sfunc.CloseSocket(sock->socket);
810 }
811
812
813 void Datagram_Listen (qboolean state)
814 {
815         int i;
816
817         for (i = 0; i < net_numlandrivers; i++)
818                 if (net_landrivers[i].initialized)
819                         net_landrivers[i].Listen (state);
820 }
821
822
823 static qsocket_t *_Datagram_CheckNewConnections (void)
824 {
825         struct qsockaddr clientaddr;
826         struct qsockaddr newaddr;
827         int                     newsock;
828         int                     acceptsock;
829         qsocket_t       *sock;
830         qsocket_t       *s;
831         int                     len;
832         int                     command;
833         int                     control;
834         int                     ret;
835         int                     c;
836
837         acceptsock = dfunc.CheckNewConnections();
838         if (acceptsock == -1)
839                 return NULL;
840
841         SZ_Clear(&net_message);
842
843         len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
844         if (len < sizeof(int))
845                 return NULL;
846         net_message.cursize = len;
847
848         MSG_BeginReading ();
849         control = BigLong(*((int *)net_message.data));
850         MSG_ReadLong();
851         if (control == -1)
852                 return NULL;
853         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
854                 return NULL;
855         if ((control & NETFLAG_LENGTH_MASK) != len)
856                 return NULL;
857
858         command = MSG_ReadByte();
859         if (command == CCREQ_SERVER_INFO)
860         {
861                 if (strcmp(MSG_ReadString(), "QUAKE") != 0)
862                         return NULL;
863
864                 SZ_Clear(&net_message);
865                 // save space for the header, filled in later
866                 MSG_WriteLong(&net_message, 0);
867                 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
868                 dfunc.GetSocketAddr(acceptsock, &newaddr);
869                 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
870                 MSG_WriteString(&net_message, hostname.string);
871                 MSG_WriteString(&net_message, sv.name);
872                 MSG_WriteByte(&net_message, net_activeconnections);
873                 MSG_WriteByte(&net_message, svs.maxclients);
874                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
875                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
876                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
877                 SZ_Clear(&net_message);
878                 return NULL;
879         }
880
881         if (command == CCREQ_PLAYER_INFO)
882         {
883                 int                     playerNumber;
884                 int                     activeNumber;
885                 int                     clientNumber;
886                 client_t        *client;
887
888                 playerNumber = MSG_ReadByte();
889                 activeNumber = -1;
890                 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
891                 {
892                         if (client->active)
893                         {
894                                 activeNumber++;
895                                 if (activeNumber == playerNumber)
896                                         break;
897                         }
898                 }
899                 if (clientNumber == svs.maxclients)
900                         return NULL;
901
902                 SZ_Clear(&net_message);
903                 // save space for the header, filled in later
904                 MSG_WriteLong(&net_message, 0);
905                 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
906                 MSG_WriteByte(&net_message, playerNumber);
907                 MSG_WriteString(&net_message, client->name);
908                 MSG_WriteLong(&net_message, client->colors);
909                 MSG_WriteLong(&net_message, (int)client->edict->v.frags);
910                 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
911                 MSG_WriteString(&net_message, client->netconnection->address);
912                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
913                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
914                 SZ_Clear(&net_message);
915
916                 return NULL;
917         }
918
919         if (command == CCREQ_RULE_INFO)
920         {
921                 char    *prevCvarName;
922                 cvar_t  *var;
923
924                 // find the search start location
925                 prevCvarName = MSG_ReadString();
926                 if (*prevCvarName)
927                 {
928                         var = Cvar_FindVar (prevCvarName);
929                         if (!var)
930                                 return NULL;
931                         var = var->next;
932                 }
933                 else
934                         var = cvar_vars;
935
936                 // search for the next server cvar
937                 while (var)
938                 {
939                         if (var->flags & CVAR_NOTIFY)
940                                 break;
941                         var = var->next;
942                 }
943
944                 // send the response
945
946                 SZ_Clear(&net_message);
947                 // save space for the header, filled in later
948                 MSG_WriteLong(&net_message, 0);
949                 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
950                 if (var)
951                 {
952                         MSG_WriteString(&net_message, var->name);
953                         MSG_WriteString(&net_message, var->string);
954                 }
955                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
956                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
957                 SZ_Clear(&net_message);
958
959                 return NULL;
960         }
961
962         if (command != CCREQ_CONNECT)
963                 return NULL;
964
965         if (strcmp(MSG_ReadString(), "QUAKE") != 0)
966                 return NULL;
967
968         c = MSG_ReadByte();
969         if (c != NET_PROTOCOL_VERSION)
970         {
971                 SZ_Clear(&net_message);
972                 // save space for the header, filled in later
973                 MSG_WriteLong(&net_message, 0);
974                 MSG_WriteByte(&net_message, CCREP_REJECT);
975                 MSG_WriteString(&net_message, "Incompatible version.\n");
976                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
977                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
978                 SZ_Clear(&net_message);
979                 return NULL;
980         }
981
982 #ifdef BAN_TEST
983         // check for a ban
984         if (clientaddr.sa_family == AF_INET)
985         {
986                 unsigned long testAddr;
987                 testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
988                 if ((testAddr & banMask) == banAddr)
989                 {
990                         SZ_Clear(&net_message);
991                         // save space for the header, filled in later
992                         MSG_WriteLong(&net_message, 0);
993                         MSG_WriteByte(&net_message, CCREP_REJECT);
994                         MSG_WriteString(&net_message, "You have been banned.\n");
995                         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
996                         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
997                         SZ_Clear(&net_message);
998                         return NULL;
999                 }
1000         }
1001 #endif
1002
1003         // see if this guy is already connected
1004         for (s = net_activeSockets; s; s = s->next)
1005         {
1006                 if (s->driver != net_driverlevel)
1007                         continue;
1008                 ret = dfunc.AddrCompare(&clientaddr, &s->addr);
1009                 if (ret >= 0)
1010                 {
1011                         // is this a duplicate connection reqeust?
1012                         if (ret == 0 && net_time - s->connecttime < 2.0)
1013                         {
1014                                 // yes, so send a duplicate reply
1015                                 SZ_Clear(&net_message);
1016                                 // save space for the header, filled in later
1017                                 MSG_WriteLong(&net_message, 0);
1018                                 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1019                                 dfunc.GetSocketAddr(s->socket, &newaddr);
1020                                 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1021                                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1022                                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1023                                 SZ_Clear(&net_message);
1024                                 return NULL;
1025                         }
1026                         // it's somebody coming back in from a crash/disconnect
1027                         // so close the old qsocket and let their retry get them back in
1028                         NET_Close(s);
1029                         return NULL;
1030                 }
1031         }
1032
1033         // allocate a QSocket
1034         sock = NET_NewQSocket ();
1035         if (sock == NULL)
1036         {
1037                 // no room; try to let him know
1038                 SZ_Clear(&net_message);
1039                 // save space for the header, filled in later
1040                 MSG_WriteLong(&net_message, 0);
1041                 MSG_WriteByte(&net_message, CCREP_REJECT);
1042                 MSG_WriteString(&net_message, "Server is full.\n");
1043                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1044                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1045                 SZ_Clear(&net_message);
1046                 return NULL;
1047         }
1048
1049         // allocate a network socket
1050         newsock = dfunc.OpenSocket(0);
1051         if (newsock == -1)
1052         {
1053                 NET_FreeQSocket(sock);
1054                 return NULL;
1055         }
1056
1057         // connect to the client
1058         if (dfunc.Connect (newsock, &clientaddr) == -1)
1059         {
1060                 dfunc.CloseSocket(newsock);
1061                 NET_FreeQSocket(sock);
1062                 return NULL;
1063         }
1064
1065         // everything is allocated, just fill in the details
1066         sock->socket = newsock;
1067         sock->landriver = net_landriverlevel;
1068         sock->addr = clientaddr;
1069         strcpy(sock->address, dfunc.AddrToString(&clientaddr));
1070
1071         // send him back the info about the server connection he has been allocated
1072         SZ_Clear(&net_message);
1073         // save space for the header, filled in later
1074         MSG_WriteLong(&net_message, 0);
1075         MSG_WriteByte(&net_message, CCREP_ACCEPT);
1076         dfunc.GetSocketAddr(newsock, &newaddr);
1077         MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1078         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1079         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1080         SZ_Clear(&net_message);
1081
1082         return sock;
1083 }
1084
1085 qsocket_t *Datagram_CheckNewConnections (void)
1086 {
1087         qsocket_t *ret = NULL;
1088
1089         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1090                 if (net_landrivers[net_landriverlevel].initialized)
1091                         if ((ret = _Datagram_CheckNewConnections ()) != NULL)
1092                                 break;
1093         return ret;
1094 }
1095
1096
1097 static void _Datagram_SearchForHosts (qboolean xmit)
1098 {
1099         int             ret;
1100         int             n;
1101         int             i;
1102         struct qsockaddr readaddr;
1103         struct qsockaddr myaddr;
1104         int             control;
1105         int             c;
1106
1107         dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
1108         if (xmit)
1109         {
1110                 SZ_Clear(&net_message);
1111                 // save space for the header, filled in later
1112                 MSG_WriteLong(&net_message, 0);
1113                 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
1114                 MSG_WriteString(&net_message, "QUAKE");
1115                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1116                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1117                 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
1118                 SZ_Clear(&net_message);
1119         }
1120
1121         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1122         {
1123                 if (ret < sizeof(int))
1124                         continue;
1125                 net_message.cursize = ret;
1126
1127                 // don't answer our own query
1128                 if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
1129                         continue;
1130
1131                 // is the cache full?
1132                 if (hostCacheCount == HOSTCACHESIZE)
1133                         continue;
1134
1135                 MSG_BeginReading ();
1136                 control = BigLong(*((int *)net_message.data));
1137                 MSG_ReadLong();
1138                 if (control == -1)
1139                         continue;
1140                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
1141                         continue;
1142                 if ((control & NETFLAG_LENGTH_MASK) != ret)
1143                         continue;
1144
1145                 c = MSG_ReadByte();
1146                 if (c != CCREP_SERVER_INFO)
1147                         continue;
1148
1149                 dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
1150                 // search the cache for this server
1151                 for (n = 0; n < hostCacheCount; n++)
1152                         if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
1153                                 break;
1154
1155                 // is it already there?
1156                 if (n < hostCacheCount)
1157                         continue;
1158
1159                 // add it
1160                 hostCacheCount++;
1161                 strcpy(hostcache[n].name, MSG_ReadString());
1162                 strcpy(hostcache[n].map, MSG_ReadString());
1163                 hostcache[n].users = MSG_ReadByte();
1164                 hostcache[n].maxusers = MSG_ReadByte();
1165                 c = MSG_ReadByte();
1166                 if (c != NET_PROTOCOL_VERSION)
1167                 {
1168                         strcpy(hostcache[n].cname, hostcache[n].name);
1169                         hostcache[n].cname[14] = 0;
1170                         strcpy(hostcache[n].name, "*");
1171                         strcat(hostcache[n].name, hostcache[n].cname);
1172                 }
1173                 memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
1174                 hostcache[n].driver = net_driverlevel;
1175                 hostcache[n].ldriver = net_landriverlevel;
1176                 strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
1177
1178                 // check for a name conflict
1179                 for (i = 0; i < hostCacheCount; i++)
1180                 {
1181                         if (i == n)
1182                                 continue;
1183                         if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
1184                         {
1185                                 i = strlen(hostcache[n].name);
1186                                 if (i < 15 && hostcache[n].name[i-1] > '8')
1187                                 {
1188                                         hostcache[n].name[i] = '0';
1189                                         hostcache[n].name[i+1] = 0;
1190                                 }
1191                                 else
1192                                         hostcache[n].name[i-1]++;
1193                                 i = -1;
1194                         }
1195                 }
1196         }
1197 }
1198
1199 void Datagram_SearchForHosts (qboolean xmit)
1200 {
1201         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1202         {
1203                 if (hostCacheCount == HOSTCACHESIZE)
1204                         break;
1205                 if (net_landrivers[net_landriverlevel].initialized)
1206                         _Datagram_SearchForHosts (xmit);
1207         }
1208 }
1209
1210
1211 static qsocket_t *_Datagram_Connect (char *host)
1212 {
1213         struct qsockaddr sendaddr;
1214         struct qsockaddr readaddr;
1215         qsocket_t       *sock;
1216         int                     newsock;
1217         int                     ret;
1218         int                     reps;
1219         double          start_time;
1220         int                     control;
1221         char            *reason;
1222
1223         // see if we can resolve the host name
1224         if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
1225                 return NULL;
1226
1227         newsock = dfunc.OpenSocket (cl_port.integer);
1228         if (newsock == -1)
1229                 return NULL;
1230
1231         sock = NET_NewQSocket ();
1232         if (sock == NULL)
1233                 goto ErrorReturn2;
1234         sock->socket = newsock;
1235         sock->landriver = net_landriverlevel;
1236
1237         // connect to the host
1238         if (dfunc.Connect (newsock, &sendaddr) == -1)
1239                 goto ErrorReturn;
1240
1241         // send the connection request
1242         Con_Printf("trying...\n");CL_UpdateScreen();CL_UpdateScreen();
1243         start_time = net_time;
1244
1245         for (reps = 0; reps < 3; reps++)
1246         {
1247                 SZ_Clear(&net_message);
1248                 // save space for the header, filled in later
1249                 MSG_WriteLong(&net_message, 0);
1250                 MSG_WriteByte(&net_message, CCREQ_CONNECT);
1251                 MSG_WriteString(&net_message, "QUAKE");
1252                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1253                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1254                 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
1255                 SZ_Clear(&net_message);
1256                 do
1257                 {
1258                         ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
1259                         // if we got something, validate it
1260                         if (ret > 0)
1261                         {
1262                                 // is it from the right place?
1263                                 if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
1264                                 {
1265                                         Con_DPrintf("wrong reply address\n");
1266                                         Con_DPrintf("Expected: %s\n", StrAddr (&sendaddr));
1267                                         Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
1268                                         CL_UpdateScreen ();
1269                                         ret = 0;
1270                                         continue;
1271                                 }
1272
1273                                 if (ret < sizeof(int))
1274                                 {
1275                                         ret = 0;
1276                                         continue;
1277                                 }
1278
1279                                 net_message.cursize = ret;
1280                                 MSG_BeginReading ();
1281
1282                                 control = BigLong(*((int *)net_message.data));
1283                                 MSG_ReadLong();
1284                                 if (control == -1)
1285                                 {
1286                                         ret = 0;
1287                                         continue;
1288                                 }
1289                                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
1290                                 {
1291                                         ret = 0;
1292                                         continue;
1293                                 }
1294                                 if ((control & NETFLAG_LENGTH_MASK) != ret)
1295                                 {
1296                                         ret = 0;
1297                                         continue;
1298                                 }
1299                         }
1300                 }
1301                 while (ret == 0 && (SetNetTime() - start_time) < 2.5);
1302                 if (ret)
1303                         break;
1304                 Con_Printf("still trying...\n");CL_UpdateScreen();CL_UpdateScreen();
1305                 start_time = SetNetTime();
1306         }
1307
1308         if (ret == 0)
1309         {
1310                 reason = "No Response";
1311                 Con_Printf("%s\n", reason);
1312                 strcpy(m_return_reason, reason);
1313                 goto ErrorReturn;
1314         }
1315
1316         if (ret == -1)
1317         {
1318                 reason = "Network Error";
1319                 Con_Printf("%s\n", reason);
1320                 strcpy(m_return_reason, reason);
1321                 goto ErrorReturn;
1322         }
1323
1324         ret = MSG_ReadByte();
1325         if (ret == CCREP_REJECT)
1326         {
1327                 reason = MSG_ReadString();
1328                 Con_Printf("%s", reason);
1329                 strncpy(m_return_reason, reason, 31);
1330                 goto ErrorReturn;
1331         }
1332
1333         if (ret == CCREP_ACCEPT)
1334         {
1335                 memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
1336                 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
1337         }
1338         else
1339         {
1340                 reason = "Bad Response";
1341                 Con_Printf("%s\n", reason);
1342                 strcpy(m_return_reason, reason);
1343                 goto ErrorReturn;
1344         }
1345
1346         dfunc.GetNameFromAddr (&sendaddr, sock->address);
1347
1348         Con_Printf ("Connection accepted to %s\n", sock->address);
1349         sock->lastMessageTime = SetNetTime();
1350
1351         // switch the connection to the specified address
1352         if (dfunc.Connect (newsock, &sock->addr) == -1)
1353         {
1354                 reason = "Connect to Game failed";
1355                 Con_Printf("%s\n", reason);
1356                 strcpy(m_return_reason, reason);
1357                 goto ErrorReturn;
1358         }
1359
1360         m_return_onerror = false;
1361         return sock;
1362
1363 ErrorReturn:
1364         NET_FreeQSocket(sock);
1365 ErrorReturn2:
1366         dfunc.CloseSocket(newsock);
1367         if (m_return_onerror)
1368         {
1369                 key_dest = key_menu;
1370                 m_state = m_return_state;
1371                 m_return_onerror = false;
1372         }
1373         return NULL;
1374 }
1375
1376 qsocket_t *Datagram_Connect (char *host)
1377 {
1378         qsocket_t *ret = NULL;
1379
1380         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1381                 if (net_landrivers[net_landriverlevel].initialized)
1382                         if ((ret = _Datagram_Connect (host)) != NULL)
1383                                 break;
1384         return ret;
1385 }
1386