]> icculus.org git repositories - divverent/darkplaces.git/blob - net_dgrm.c
fixed 4 warnings in MSVC related to assigning -1000 to unsigned shorts
[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 // these two macros are to make the code more readable
59 #define sfunc   net_landrivers[sock->landriver]
60 #define dfunc   net_landrivers[net_landriverlevel]
61
62 static int net_landriverlevel;
63
64 /* statistic counters */
65 int     packetsSent = 0;
66 int     packetsReSent = 0;
67 int packetsReceived = 0;
68 int receivedDuplicateCount = 0;
69 int shortPacketCount = 0;
70 int droppedDatagrams;
71
72 static int myDriverLevel;
73
74 struct
75 {
76         unsigned int    length;
77         unsigned int    sequence;
78         byte                    data[MAX_DATAGRAM];
79 } packetBuffer;
80
81
82 //#ifdef DEBUG
83 char *StrAddr (struct qsockaddr *addr)
84 {
85         static char buf[34];
86         byte *p = (byte *)addr;
87         int n;
88
89         for (n = 0; n < 16; n++)
90                 sprintf (buf + n * 2, "%02x", *p++);
91         return buf;
92 }
93 //#endif
94
95
96 #ifdef BAN_TEST
97 unsigned long banAddr = 0x00000000;
98 unsigned long banMask = 0xffffffff;
99
100 void NET_Ban_f (void)
101 {
102         char    addrStr [32];
103         char    maskStr [32];
104         void    (*print) (char *fmt, ...);
105
106         if (cmd_source == src_command)
107         {
108                 if (!sv.active)
109                 {
110                         Cmd_ForwardToServer ();
111                         return;
112                 }
113                 print = Con_Printf;
114         }
115         else
116         {
117                 if (pr_global_struct->deathmatch)
118                         return;
119                 print = SV_ClientPrintf;
120         }
121
122         switch (Cmd_Argc ())
123         {
124                 case 1:
125                         if (((struct in_addr *)&banAddr)->s_addr)
126                         {
127                                 strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr));
128                                 strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask));
129                                 print("Banning %s [%s]\n", addrStr, maskStr);
130                         }
131                         else
132                                 print("Banning not active\n");
133                         break;
134
135                 case 2:
136                         if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
137                                 banAddr = 0x00000000;
138                         else
139                                 banAddr = inet_addr(Cmd_Argv(1));
140                         banMask = 0xffffffff;
141                         break;
142
143                 case 3:
144                         banAddr = inet_addr(Cmd_Argv(1));
145                         banMask = inet_addr(Cmd_Argv(2));
146                         break;
147
148                 default:
149                         print("BAN ip_address [mask]\n");
150                         break;
151         }
152 }
153 #endif
154
155
156 int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data)
157 {
158         unsigned int    packetLen;
159         unsigned int    dataLen;
160         unsigned int    eom;
161
162 #ifdef DEBUG
163         if (data->cursize == 0)
164                 Sys_Error("Datagram_SendMessage: zero length message\n");
165
166         if (data->cursize > NET_MAXMESSAGE)
167                 Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize);
168
169         if (sock->canSend == false)
170                 Sys_Error("SendMessage: called with canSend == false\n");
171 #endif
172
173         memcpy(sock->sendMessage, data->data, data->cursize);
174         sock->sendMessageLength = data->cursize;
175
176         if (data->cursize <= MAX_DATAGRAM)
177         {
178                 dataLen = data->cursize;
179                 eom = NETFLAG_EOM;
180         }
181         else
182         {
183                 dataLen = MAX_DATAGRAM;
184                 eom = 0;
185         }
186         packetLen = NET_HEADERSIZE + dataLen;
187
188         packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
189         packetBuffer.sequence = BigLong(sock->sendSequence++);
190         memcpy (packetBuffer.data, sock->sendMessage, dataLen);
191
192         sock->canSend = false;
193
194         if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
195                 return -1;
196
197         sock->lastSendTime = net_time;
198         packetsSent++;
199         return 1;
200 }
201
202
203 int SendMessageNext (qsocket_t *sock)
204 {
205         unsigned int    packetLen;
206         unsigned int    dataLen;
207         unsigned int    eom;
208
209         if (sock->sendMessageLength <= MAX_DATAGRAM)
210         {
211                 dataLen = sock->sendMessageLength;
212                 eom = NETFLAG_EOM;
213         }
214         else
215         {
216                 dataLen = MAX_DATAGRAM;
217                 eom = 0;
218         }
219         packetLen = NET_HEADERSIZE + dataLen;
220
221         packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
222         packetBuffer.sequence = BigLong(sock->sendSequence++);
223         memcpy (packetBuffer.data, sock->sendMessage, dataLen);
224
225         sock->sendNext = false;
226
227         if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
228                 return -1;
229
230         sock->lastSendTime = net_time;
231         packetsSent++;
232         return 1;
233 }
234
235
236 int ReSendMessage (qsocket_t *sock)
237 {
238         unsigned int    packetLen;
239         unsigned int    dataLen;
240         unsigned int    eom;
241
242         if (sock->sendMessageLength <= MAX_DATAGRAM)
243         {
244                 dataLen = sock->sendMessageLength;
245                 eom = NETFLAG_EOM;
246         }
247         else
248         {
249                 dataLen = MAX_DATAGRAM;
250                 eom = 0;
251         }
252         packetLen = NET_HEADERSIZE + dataLen;
253
254         packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom));
255         packetBuffer.sequence = BigLong(sock->sendSequence - 1);
256         memcpy (packetBuffer.data, sock->sendMessage, dataLen);
257
258         sock->sendNext = false;
259
260         if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
261                 return -1;
262
263         sock->lastSendTime = net_time;
264         packetsReSent++;
265         return 1;
266 }
267
268
269 qboolean Datagram_CanSendMessage (qsocket_t *sock)
270 {
271         if (sock->sendNext)
272                 SendMessageNext (sock);
273
274         return sock->canSend;
275 }
276
277
278 qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock)
279 {
280         return true;
281 }
282
283
284 int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
285 {
286         int     packetLen;
287
288 #ifdef DEBUG
289         if (data->cursize == 0)
290                 Sys_Error("Datagram_SendUnreliableMessage: zero length message\n");
291
292         if (data->cursize > MAX_DATAGRAM)
293                 Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
294 #endif
295
296         packetLen = NET_HEADERSIZE + data->cursize;
297
298         packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE);
299         packetBuffer.sequence = BigLong(sock->unreliableSendSequence++);
300         memcpy (packetBuffer.data, data->data, data->cursize);
301
302         if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1)
303                 return -1;
304
305         packetsSent++;
306         return 1;
307 }
308
309
310 int     Datagram_GetMessage (qsocket_t *sock)
311 {
312         unsigned int    length;
313         unsigned int    flags;
314         int                             ret = 0;
315         struct qsockaddr readaddr;
316         unsigned int    sequence;
317         unsigned int    count;
318
319         if (!sock->canSend)
320                 if ((net_time - sock->lastSendTime) > 1.0)
321                         ReSendMessage (sock);
322
323         while(1)
324         {       
325                 length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr);
326
327 //      if ((rand() & 255) > 220)
328 //              continue;
329
330                 if (length == 0)
331                         break;
332
333                 if (length == -1)
334                 {
335                         Con_Printf("Read error\n");
336                         return -1;
337                 }
338
339                 if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
340                 {
341 #ifdef DEBUG
342                         Con_DPrintf("Forged packet received\n");
343                         Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
344                         Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
345 #endif
346                         continue;
347                 }
348
349                 if (length < NET_HEADERSIZE)
350                 {
351                         shortPacketCount++;
352                         continue;
353                 }
354
355                 length = BigLong(packetBuffer.length);
356                 flags = length & (~NETFLAG_LENGTH_MASK);
357                 length &= NETFLAG_LENGTH_MASK;
358
359                 if (flags & NETFLAG_CTL)
360                         continue;
361
362                 sequence = BigLong(packetBuffer.sequence);
363                 packetsReceived++;
364
365                 if (flags & NETFLAG_UNRELIABLE)
366                 {
367                         if (sequence < sock->unreliableReceiveSequence)
368                         {
369                                 Con_DPrintf("Got a stale datagram\n");
370                                 ret = 0;
371                                 break;
372                         }
373                         if (sequence != sock->unreliableReceiveSequence)
374                         {
375                                 count = sequence - sock->unreliableReceiveSequence;
376                                 droppedDatagrams += count;
377                                 Con_DPrintf("Dropped %u datagram(s)\n", count);
378                         }
379                         sock->unreliableReceiveSequence = sequence + 1;
380
381                         length -= NET_HEADERSIZE;
382
383                         SZ_Clear (&net_message);
384                         SZ_Write (&net_message, packetBuffer.data, length);
385
386                         ret = 2;
387                         break;
388                 }
389
390                 if (flags & NETFLAG_ACK)
391                 {
392                         if (sequence != (sock->sendSequence - 1))
393                         {
394                                 Con_DPrintf("Stale ACK received\n");
395                                 continue;
396                         }
397                         if (sequence == sock->ackSequence)
398                         {
399                                 sock->ackSequence++;
400                                 if (sock->ackSequence != sock->sendSequence)
401                                         Con_DPrintf("ack sequencing error\n");
402                         }
403                         else
404                         {
405                                 Con_DPrintf("Duplicate ACK received\n");
406                                 continue;
407                         }
408                         sock->sendMessageLength -= MAX_DATAGRAM;
409                         if (sock->sendMessageLength > 0)
410                         {
411                                 memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
412                                 sock->sendNext = true;
413                         }
414                         else
415                         {
416                                 sock->sendMessageLength = 0;
417                                 sock->canSend = true;
418                         }
419                         continue;
420                 }
421
422                 if (flags & NETFLAG_DATA)
423                 {
424                         packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
425                         packetBuffer.sequence = BigLong(sequence);
426                         sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
427
428                         if (sequence != sock->receiveSequence)
429                         {
430                                 receivedDuplicateCount++;
431                                 continue;
432                         }
433                         sock->receiveSequence++;
434
435                         length -= NET_HEADERSIZE;
436
437                         if (flags & NETFLAG_EOM)
438                         {
439                                 SZ_Clear(&net_message);
440                                 SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
441                                 SZ_Write(&net_message, packetBuffer.data, length);
442                                 sock->receiveMessageLength = 0;
443
444                                 ret = 1;
445                                 break;
446                         }
447
448                         memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
449                         sock->receiveMessageLength += length;
450                         continue;
451                 }
452         }
453
454         if (sock->sendNext)
455                 SendMessageNext (sock);
456
457         return ret;
458 }
459
460
461 void PrintStats(qsocket_t *s)
462 {
463         Con_Printf("canSend = %4u   \n", s->canSend);
464         Con_Printf("sendSeq = %4u   ", s->sendSequence);
465         Con_Printf("recvSeq = %4u   \n", s->receiveSequence);
466         Con_Printf("\n");
467 }
468
469 void NET_Stats_f (void)
470 {
471         qsocket_t       *s;
472
473         if (Cmd_Argc () == 1)
474         {
475                 Con_Printf("unreliable messages sent   = %i\n", unreliableMessagesSent);
476                 Con_Printf("unreliable messages recv   = %i\n", unreliableMessagesReceived);
477                 Con_Printf("reliable messages sent     = %i\n", messagesSent);
478                 Con_Printf("reliable messages received = %i\n", messagesReceived);
479                 Con_Printf("packetsSent                = %i\n", packetsSent);
480                 Con_Printf("packetsReSent              = %i\n", packetsReSent);
481                 Con_Printf("packetsReceived            = %i\n", packetsReceived);
482                 Con_Printf("receivedDuplicateCount     = %i\n", receivedDuplicateCount);
483                 Con_Printf("shortPacketCount           = %i\n", shortPacketCount);
484                 Con_Printf("droppedDatagrams           = %i\n", droppedDatagrams);
485         }
486         else if (strcmp(Cmd_Argv(1), "*") == 0)
487         {
488                 for (s = net_activeSockets; s; s = s->next)
489                         PrintStats(s);
490                 for (s = net_freeSockets; s; s = s->next)
491                         PrintStats(s);
492         }
493         else
494         {
495                 for (s = net_activeSockets; s; s = s->next)
496                         if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
497                                 break;
498                 if (s == NULL)
499                         for (s = net_freeSockets; s; s = s->next)
500                                 if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
501                                         break;
502                 if (s == NULL)
503                         return;
504                 PrintStats(s);
505         }
506 }
507
508
509 static qboolean testInProgress = false;
510 static int              testPollCount;
511 static int              testDriver;
512 static int              testSocket;
513
514 static void Test_Poll(void);
515 PollProcedure   testPollProcedure = {NULL, 0.0, Test_Poll};
516
517 static void Test_Poll(void)
518 {
519         struct qsockaddr clientaddr;
520         int             control;
521         int             len;
522         char    name[32];
523         char    address[64];
524         int             colors;
525         int             frags;
526         int             connectTime;
527         byte    playerNumber;
528
529         net_landriverlevel = testDriver;
530
531         while (1)
532         {
533                 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
534                 if (len < sizeof(int))
535                         break;
536
537                 net_message.cursize = len;
538
539                 MSG_BeginReading ();
540                 control = BigLong(*((int *)net_message.data));
541                 MSG_ReadLong();
542                 if (control == -1)
543                         break;
544                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
545                         break;
546                 if ((control & NETFLAG_LENGTH_MASK) != len)
547                         break;
548
549                 if (MSG_ReadByte() != CCREP_PLAYER_INFO)
550                         Sys_Error("Unexpected repsonse to Player Info request\n");
551
552                 playerNumber = MSG_ReadByte();
553                 strcpy(name, MSG_ReadString());
554                 colors = MSG_ReadLong();
555                 frags = MSG_ReadLong();
556                 connectTime = MSG_ReadLong();
557                 strcpy(address, MSG_ReadString());
558
559                 Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
560         }
561
562         testPollCount--;
563         if (testPollCount)
564         {
565                 SchedulePollProcedure(&testPollProcedure, 0.1);
566         }
567         else
568         {
569                 dfunc.CloseSocket(testSocket);
570                 testInProgress = false;
571         }
572 }
573
574 static void Test_f (void)
575 {
576         char    *host;
577         int             n;
578         int             max = MAX_SCOREBOARD;
579         struct qsockaddr sendaddr;
580
581         if (testInProgress)
582                 return;
583
584         host = Cmd_Argv (1);
585
586         if (host && hostCacheCount)
587         {
588                 for (n = 0; n < hostCacheCount; n++)
589                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
590                         {
591                                 if (hostcache[n].driver != myDriverLevel)
592                                         continue;
593                                 net_landriverlevel = hostcache[n].ldriver;
594                                 max = hostcache[n].maxusers;
595                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
596                                 break;
597                         }
598                 if (n < hostCacheCount)
599                         goto JustDoIt;
600         }
601
602         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
603         {
604                 if (!net_landrivers[net_landriverlevel].initialized)
605                         continue;
606
607                 // see if we can resolve the host name
608                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
609                         break;
610         }
611         if (net_landriverlevel == net_numlandrivers)
612                 return;
613
614 JustDoIt:
615         testSocket = dfunc.OpenSocket(0);
616         if (testSocket == -1)
617                 return;
618
619         testInProgress = true;
620         testPollCount = 20;
621         testDriver = net_landriverlevel;
622
623         for (n = 0; n < max; n++)
624         {
625                 SZ_Clear(&net_message);
626                 // save space for the header, filled in later
627                 MSG_WriteLong(&net_message, 0);
628                 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
629                 MSG_WriteByte(&net_message, n);
630                 *((int *)net_message.data) = BigLong(NETFLAG_CTL |      (net_message.cursize & NETFLAG_LENGTH_MASK));
631                 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
632         }
633         SZ_Clear(&net_message);
634         SchedulePollProcedure(&testPollProcedure, 0.1);
635 }
636
637
638 static qboolean test2InProgress = false;
639 static int              test2Driver;
640 static int              test2Socket;
641
642 static void Test2_Poll(void);
643 PollProcedure   test2PollProcedure = {NULL, 0.0, Test2_Poll};
644
645 static void Test2_Poll(void)
646 {
647         struct qsockaddr clientaddr;
648         int             control;
649         int             len;
650         char    name[256];
651         char    value[256];
652
653         net_landriverlevel = test2Driver;
654         name[0] = 0;
655
656         len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
657         if (len < sizeof(int))
658                 goto Reschedule;
659
660         net_message.cursize = len;
661
662         MSG_BeginReading ();
663         control = BigLong(*((int *)net_message.data));
664         MSG_ReadLong();
665         if (control == -1)
666                 goto Error;
667         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
668                 goto Error;
669         if ((control & NETFLAG_LENGTH_MASK) != len)
670                 goto Error;
671
672         if (MSG_ReadByte() != CCREP_RULE_INFO)
673                 goto Error;
674
675         strcpy(name, MSG_ReadString());
676         if (name[0] == 0)
677                 goto Done;
678         strcpy(value, MSG_ReadString());
679
680         Con_Printf("%-16.16s  %-16.16s\n", name, value);
681
682         SZ_Clear(&net_message);
683         // save space for the header, filled in later
684         MSG_WriteLong(&net_message, 0);
685         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
686         MSG_WriteString(&net_message, name);
687         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
688         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
689         SZ_Clear(&net_message);
690
691 Reschedule:
692         SchedulePollProcedure(&test2PollProcedure, 0.05);
693         return;
694
695 Error:
696         Con_Printf("Unexpected repsonse to Rule Info request\n");
697 Done:
698         dfunc.CloseSocket(test2Socket);
699         test2InProgress = false;
700         return;
701 }
702
703 static void Test2_f (void)
704 {
705         char    *host;
706         int             n;
707         struct qsockaddr sendaddr;
708
709         if (test2InProgress)
710                 return;
711
712         host = Cmd_Argv (1);
713
714         if (host && hostCacheCount)
715         {
716                 for (n = 0; n < hostCacheCount; n++)
717                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
718                         {
719                                 if (hostcache[n].driver != myDriverLevel)
720                                         continue;
721                                 net_landriverlevel = hostcache[n].ldriver;
722                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
723                                 break;
724                         }
725                 if (n < hostCacheCount)
726                         goto JustDoIt;
727         }
728
729         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
730         {
731                 if (!net_landrivers[net_landriverlevel].initialized)
732                         continue;
733
734                 // see if we can resolve the host name
735                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
736                         break;
737         }
738         if (net_landriverlevel == net_numlandrivers)
739                 return;
740
741 JustDoIt:
742         test2Socket = dfunc.OpenSocket(0);
743         if (test2Socket == -1)
744                 return;
745
746         test2InProgress = true;
747         test2Driver = net_landriverlevel;
748
749         SZ_Clear(&net_message);
750         // save space for the header, filled in later
751         MSG_WriteLong(&net_message, 0);
752         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
753         MSG_WriteString(&net_message, "");
754         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
755         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
756         SZ_Clear(&net_message);
757         SchedulePollProcedure(&test2PollProcedure, 0.05);
758 }
759
760
761 int Datagram_Init (void)
762 {
763         int i;
764         int csock;
765
766         myDriverLevel = net_driverlevel;
767         Cmd_AddCommand ("net_stats", NET_Stats_f);
768
769         if (COM_CheckParm("-nolan"))
770                 return -1;
771
772         for (i = 0; i < net_numlandrivers; i++)
773                 {
774                 csock = net_landrivers[i].Init ();
775                 if (csock == -1)
776                         continue;
777                 net_landrivers[i].initialized = true;
778                 net_landrivers[i].controlSock = csock;
779                 }
780
781 #ifdef BAN_TEST
782         Cmd_AddCommand ("ban", NET_Ban_f);
783 #endif
784         Cmd_AddCommand ("test", Test_f);
785         Cmd_AddCommand ("test2", Test2_f);
786
787         return 0;
788 }
789
790
791 void Datagram_Shutdown (void)
792 {
793         int i;
794
795 //
796 // shutdown the lan drivers
797 //
798         for (i = 0; i < net_numlandrivers; i++)
799         {
800                 if (net_landrivers[i].initialized)
801                 {
802                         net_landrivers[i].Shutdown ();
803                         net_landrivers[i].initialized = false;
804                 }
805         }
806 }
807
808
809 void Datagram_Close (qsocket_t *sock)
810 {
811         sfunc.CloseSocket(sock->socket);
812 }
813
814
815 void Datagram_Listen (qboolean state)
816 {
817         int i;
818
819         for (i = 0; i < net_numlandrivers; i++)
820                 if (net_landrivers[i].initialized)
821                         net_landrivers[i].Listen (state);
822 }
823
824
825 static qsocket_t *_Datagram_CheckNewConnections (void)
826 {
827         struct qsockaddr clientaddr;
828         struct qsockaddr newaddr;
829         int                     newsock;
830         int                     acceptsock;
831         qsocket_t       *sock;
832         qsocket_t       *s;
833         int                     len;
834         int                     command;
835         int                     control;
836         int                     ret;
837
838         acceptsock = dfunc.CheckNewConnections();
839         if (acceptsock == -1)
840                 return NULL;
841
842         SZ_Clear(&net_message);
843
844         len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
845         if (len < sizeof(int))
846                 return NULL;
847         net_message.cursize = len;
848
849         MSG_BeginReading ();
850         control = BigLong(*((int *)net_message.data));
851         MSG_ReadLong();
852         if (control == -1)
853                 return NULL;
854         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
855                 return NULL;
856         if ((control & NETFLAG_LENGTH_MASK) != len)
857                 return NULL;
858
859         command = MSG_ReadByte();
860         if (command == CCREQ_SERVER_INFO)
861         {
862                 if (strcmp(MSG_ReadString(), "QUAKE") != 0)
863                         return NULL;
864
865                 SZ_Clear(&net_message);
866                 // save space for the header, filled in later
867                 MSG_WriteLong(&net_message, 0);
868                 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
869                 dfunc.GetSocketAddr(acceptsock, &newaddr);
870                 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
871                 MSG_WriteString(&net_message, hostname.string);
872                 MSG_WriteString(&net_message, sv.name);
873                 MSG_WriteByte(&net_message, net_activeconnections);
874                 MSG_WriteByte(&net_message, svs.maxclients);
875                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
876                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
877                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
878                 SZ_Clear(&net_message);
879                 return NULL;
880         }
881
882         if (command == CCREQ_PLAYER_INFO)
883         {
884                 int                     playerNumber;
885                 int                     activeNumber;
886                 int                     clientNumber;
887                 client_t        *client;
888                 
889                 playerNumber = MSG_ReadByte();
890                 activeNumber = -1;
891                 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
892                 {
893                         if (client->active)
894                         {
895                                 activeNumber++;
896                                 if (activeNumber == playerNumber)
897                                         break;
898                         }
899                 }
900                 if (clientNumber == svs.maxclients)
901                         return NULL;
902
903                 SZ_Clear(&net_message);
904                 // save space for the header, filled in later
905                 MSG_WriteLong(&net_message, 0);
906                 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
907                 MSG_WriteByte(&net_message, playerNumber);
908                 MSG_WriteString(&net_message, client->name);
909                 MSG_WriteLong(&net_message, client->colors);
910                 MSG_WriteLong(&net_message, (int)client->edict->v.frags);
911                 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
912                 MSG_WriteString(&net_message, client->netconnection->address);
913                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
914                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
915                 SZ_Clear(&net_message);
916
917                 return NULL;
918         }
919
920         if (command == CCREQ_RULE_INFO)
921         {
922                 char    *prevCvarName;
923                 cvar_t  *var;
924
925                 // find the search start location
926                 prevCvarName = MSG_ReadString();
927                 if (*prevCvarName)
928                 {
929                         var = Cvar_FindVar (prevCvarName);
930                         if (!var)
931                                 return NULL;
932                         var = var->next;
933                 }
934                 else
935                         var = cvar_vars;
936
937                 // search for the next server cvar
938                 while (var)
939                 {
940                         if (var->flags & CVAR_NOTIFY)
941                                 break;
942                         var = var->next;
943                 }
944
945                 // send the response
946
947                 SZ_Clear(&net_message);
948                 // save space for the header, filled in later
949                 MSG_WriteLong(&net_message, 0);
950                 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
951                 if (var)
952                 {
953                         MSG_WriteString(&net_message, var->name);
954                         MSG_WriteString(&net_message, var->string);
955                 }
956                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
957                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
958                 SZ_Clear(&net_message);
959
960                 return NULL;
961         }
962
963         if (command != CCREQ_CONNECT)
964                 return NULL;
965
966         if (strcmp(MSG_ReadString(), "QUAKE") != 0)
967                 return NULL;
968
969         if (MSG_ReadByte() != 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 //      MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
1079         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1080         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1081         SZ_Clear(&net_message);
1082
1083         return sock;
1084 }
1085
1086 qsocket_t *Datagram_CheckNewConnections (void)
1087 {
1088         qsocket_t *ret = NULL;
1089
1090         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1091                 if (net_landrivers[net_landriverlevel].initialized)
1092                         if ((ret = _Datagram_CheckNewConnections ()) != NULL)
1093                                 break;
1094         return ret;
1095 }
1096
1097
1098 static void _Datagram_SearchForHosts (qboolean xmit)
1099 {
1100         int             ret;
1101         int             n;
1102         int             i;
1103         struct qsockaddr readaddr;
1104         struct qsockaddr myaddr;
1105         int             control;
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                 if (MSG_ReadByte() != CCREP_SERVER_INFO)
1146                         continue;
1147
1148                 dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
1149                 // search the cache for this server
1150                 for (n = 0; n < hostCacheCount; n++)
1151                         if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
1152                                 break;
1153
1154                 // is it already there?
1155                 if (n < hostCacheCount)
1156                         continue;
1157
1158                 // add it
1159                 hostCacheCount++;
1160                 strcpy(hostcache[n].name, MSG_ReadString());
1161                 strcpy(hostcache[n].map, MSG_ReadString());
1162                 hostcache[n].users = MSG_ReadByte();
1163                 hostcache[n].maxusers = MSG_ReadByte();
1164                 if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
1165                 {
1166                         strcpy(hostcache[n].cname, hostcache[n].name);
1167                         hostcache[n].cname[14] = 0;
1168                         strcpy(hostcache[n].name, "*");
1169                         strcat(hostcache[n].name, hostcache[n].cname);
1170                 }
1171                 memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
1172                 hostcache[n].driver = net_driverlevel;
1173                 hostcache[n].ldriver = net_landriverlevel;
1174                 strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
1175
1176                 // check for a name conflict
1177                 for (i = 0; i < hostCacheCount; i++)
1178                 {
1179                         if (i == n)
1180                                 continue;
1181                         if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
1182                         {
1183                                 i = strlen(hostcache[n].name);
1184                                 if (i < 15 && hostcache[n].name[i-1] > '8')
1185                                 {
1186                                         hostcache[n].name[i] = '0';
1187                                         hostcache[n].name[i+1] = 0;
1188                                 }
1189                                 else
1190                                         hostcache[n].name[i-1]++;
1191                                 i = -1;
1192                         }
1193                 }
1194         }
1195 }
1196
1197 void Datagram_SearchForHosts (qboolean xmit)
1198 {
1199         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1200         {
1201                 if (hostCacheCount == HOSTCACHESIZE)
1202                         break;
1203                 if (net_landrivers[net_landriverlevel].initialized)
1204                         _Datagram_SearchForHosts (xmit);
1205         }
1206 }
1207
1208
1209 static qsocket_t *_Datagram_Connect (char *host)
1210 {
1211         struct qsockaddr sendaddr;
1212         struct qsockaddr readaddr;
1213         qsocket_t       *sock;
1214         int                     newsock;
1215         int                     ret;
1216         int                     reps;
1217         double          start_time;
1218         int                     control;
1219         char            *reason;
1220
1221         // see if we can resolve the host name
1222         if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
1223                 return NULL;
1224
1225         newsock = dfunc.OpenSocket (0);
1226         if (newsock == -1)
1227                 return NULL;
1228
1229         sock = NET_NewQSocket ();
1230         if (sock == NULL)
1231                 goto ErrorReturn2;
1232         sock->socket = newsock;
1233         sock->landriver = net_landriverlevel;
1234
1235         // connect to the host
1236         if (dfunc.Connect (newsock, &sendaddr) == -1)
1237                 goto ErrorReturn;
1238
1239         // send the connection request
1240         Con_Printf("trying...\n"); SCR_UpdateScreen ();
1241         start_time = net_time;
1242
1243         for (reps = 0; reps < 3; reps++)
1244         {
1245                 SZ_Clear(&net_message);
1246                 // save space for the header, filled in later
1247                 MSG_WriteLong(&net_message, 0);
1248                 MSG_WriteByte(&net_message, CCREQ_CONNECT);
1249                 MSG_WriteString(&net_message, "QUAKE");
1250                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1251                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1252                 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
1253                 SZ_Clear(&net_message);
1254                 do
1255                 {
1256                         ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
1257                         // if we got something, validate it
1258                         if (ret > 0)
1259                         {
1260                                 // is it from the right place?
1261                                 if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
1262                                 {
1263 //#ifdef DEBUG
1264                                         Con_DPrintf("wrong reply address\n");
1265                                         Con_DPrintf("Expected: %s\n", StrAddr (&sendaddr));
1266                                         Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
1267                                         SCR_UpdateScreen ();
1268 //#endif
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"); SCR_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\n");
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 }