]> icculus.org git repositories - divverent/darkplaces.git/blob - net_dgrm.c
Updated DSP file. Fixed a bunch of warnings with MSVC6
[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                 // LordHavoc: sockets are dynamically allocated now
491                 //for (s = net_freeSockets; s; s = s->next)
492                 //      PrintStats(s);
493         }
494         else
495         {
496                 for (s = net_activeSockets; s; s = s->next)
497                         if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
498                                 break;
499                 // LordHavoc: sockets are dynamically allocated now
500                 //if (s == NULL)
501                 //      for (s = net_freeSockets; s; s = s->next)
502                 //              if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
503                 //                      break;
504                 if (s == NULL)
505                         return;
506                 PrintStats(s);
507         }
508 }
509
510
511 static qboolean testInProgress = false;
512 static int              testPollCount;
513 static int              testDriver;
514 static int              testSocket;
515
516 static void Test_Poll(void);
517 PollProcedure   testPollProcedure = {NULL, 0.0, Test_Poll};
518
519 static void Test_Poll(void)
520 {
521         struct qsockaddr clientaddr;
522         int             control;
523         int             len;
524         char    name[32];
525         char    address[64];
526         int             colors;
527         int             frags;
528         int             connectTime;
529         byte    playerNumber;
530
531         net_landriverlevel = testDriver;
532
533         while (1)
534         {
535                 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
536                 if (len < sizeof(int))
537                         break;
538
539                 net_message.cursize = len;
540
541                 MSG_BeginReading ();
542                 control = BigLong(*((int *)net_message.data));
543                 MSG_ReadLong();
544                 if (control == -1)
545                         break;
546                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
547                         break;
548                 if ((control & NETFLAG_LENGTH_MASK) != len)
549                         break;
550
551                 if (MSG_ReadByte() != CCREP_PLAYER_INFO)
552                         Sys_Error("Unexpected repsonse to Player Info request\n");
553
554                 playerNumber = MSG_ReadByte();
555                 strcpy(name, MSG_ReadString());
556                 colors = MSG_ReadLong();
557                 frags = MSG_ReadLong();
558                 connectTime = MSG_ReadLong();
559                 strcpy(address, MSG_ReadString());
560
561                 Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
562         }
563
564         testPollCount--;
565         if (testPollCount)
566         {
567                 SchedulePollProcedure(&testPollProcedure, 0.1);
568         }
569         else
570         {
571                 dfunc.CloseSocket(testSocket);
572                 testInProgress = false;
573         }
574 }
575
576 static void Test_f (void)
577 {
578         char    *host;
579         int             n;
580         int             max = MAX_SCOREBOARD;
581         struct qsockaddr sendaddr;
582
583         if (testInProgress)
584                 return;
585
586         host = Cmd_Argv (1);
587
588         if (host && hostCacheCount)
589         {
590                 for (n = 0; n < hostCacheCount; n++)
591                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
592                         {
593                                 if (hostcache[n].driver != myDriverLevel)
594                                         continue;
595                                 net_landriverlevel = hostcache[n].ldriver;
596                                 max = hostcache[n].maxusers;
597                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
598                                 break;
599                         }
600                 if (n < hostCacheCount)
601                         goto JustDoIt;
602         }
603
604         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
605         {
606                 if (!net_landrivers[net_landriverlevel].initialized)
607                         continue;
608
609                 // see if we can resolve the host name
610                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
611                         break;
612         }
613         if (net_landriverlevel == net_numlandrivers)
614                 return;
615
616 JustDoIt:
617         testSocket = dfunc.OpenSocket(0);
618         if (testSocket == -1)
619                 return;
620
621         testInProgress = true;
622         testPollCount = 20;
623         testDriver = net_landriverlevel;
624
625         for (n = 0; n < max; n++)
626         {
627                 SZ_Clear(&net_message);
628                 // save space for the header, filled in later
629                 MSG_WriteLong(&net_message, 0);
630                 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
631                 MSG_WriteByte(&net_message, n);
632                 *((int *)net_message.data) = BigLong(NETFLAG_CTL |      (net_message.cursize & NETFLAG_LENGTH_MASK));
633                 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
634         }
635         SZ_Clear(&net_message);
636         SchedulePollProcedure(&testPollProcedure, 0.1);
637 }
638
639
640 static qboolean test2InProgress = false;
641 static int              test2Driver;
642 static int              test2Socket;
643
644 static void Test2_Poll(void);
645 PollProcedure   test2PollProcedure = {NULL, 0.0, Test2_Poll};
646
647 static void Test2_Poll(void)
648 {
649         struct qsockaddr clientaddr;
650         int             control;
651         int             len;
652         char    name[256];
653         char    value[256];
654
655         net_landriverlevel = test2Driver;
656         name[0] = 0;
657
658         len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
659         if (len < sizeof(int))
660                 goto Reschedule;
661
662         net_message.cursize = len;
663
664         MSG_BeginReading ();
665         control = BigLong(*((int *)net_message.data));
666         MSG_ReadLong();
667         if (control == -1)
668                 goto Error;
669         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
670                 goto Error;
671         if ((control & NETFLAG_LENGTH_MASK) != len)
672                 goto Error;
673
674         if (MSG_ReadByte() != CCREP_RULE_INFO)
675                 goto Error;
676
677         strcpy(name, MSG_ReadString());
678         if (name[0] == 0)
679                 goto Done;
680         strcpy(value, MSG_ReadString());
681
682         Con_Printf("%-16.16s  %-16.16s\n", name, value);
683
684         SZ_Clear(&net_message);
685         // save space for the header, filled in later
686         MSG_WriteLong(&net_message, 0);
687         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
688         MSG_WriteString(&net_message, name);
689         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
690         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
691         SZ_Clear(&net_message);
692
693 Reschedule:
694         SchedulePollProcedure(&test2PollProcedure, 0.05);
695         return;
696
697 Error:
698         Con_Printf("Unexpected repsonse to Rule Info request\n");
699 Done:
700         dfunc.CloseSocket(test2Socket);
701         test2InProgress = false;
702         return;
703 }
704
705 static void Test2_f (void)
706 {
707         char    *host;
708         int             n;
709         struct qsockaddr sendaddr;
710
711         if (test2InProgress)
712                 return;
713
714         host = Cmd_Argv (1);
715
716         if (host && hostCacheCount)
717         {
718                 for (n = 0; n < hostCacheCount; n++)
719                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
720                         {
721                                 if (hostcache[n].driver != myDriverLevel)
722                                         continue;
723                                 net_landriverlevel = hostcache[n].ldriver;
724                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
725                                 break;
726                         }
727                 if (n < hostCacheCount)
728                         goto JustDoIt;
729         }
730
731         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
732         {
733                 if (!net_landrivers[net_landriverlevel].initialized)
734                         continue;
735
736                 // see if we can resolve the host name
737                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
738                         break;
739         }
740         if (net_landriverlevel == net_numlandrivers)
741                 return;
742
743 JustDoIt:
744         test2Socket = dfunc.OpenSocket(0);
745         if (test2Socket == -1)
746                 return;
747
748         test2InProgress = true;
749         test2Driver = net_landriverlevel;
750
751         SZ_Clear(&net_message);
752         // save space for the header, filled in later
753         MSG_WriteLong(&net_message, 0);
754         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
755         MSG_WriteString(&net_message, "");
756         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
757         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
758         SZ_Clear(&net_message);
759         SchedulePollProcedure(&test2PollProcedure, 0.05);
760 }
761
762
763 int Datagram_Init (void)
764 {
765         int i;
766         int csock;
767
768         myDriverLevel = net_driverlevel;
769         Cmd_AddCommand ("net_stats", NET_Stats_f);
770
771         if (COM_CheckParm("-nolan"))
772                 return -1;
773
774         for (i = 0; i < net_numlandrivers; i++)
775                 {
776                 csock = net_landrivers[i].Init ();
777                 if (csock == -1)
778                         continue;
779                 net_landrivers[i].initialized = true;
780                 net_landrivers[i].controlSock = csock;
781                 }
782
783 #ifdef BAN_TEST
784         Cmd_AddCommand ("ban", NET_Ban_f);
785 #endif
786         Cmd_AddCommand ("test", Test_f);
787         Cmd_AddCommand ("test2", Test2_f);
788
789         return 0;
790 }
791
792
793 void Datagram_Shutdown (void)
794 {
795         int i;
796
797 //
798 // shutdown the lan drivers
799 //
800         for (i = 0; i < net_numlandrivers; i++)
801         {
802                 if (net_landrivers[i].initialized)
803                 {
804                         net_landrivers[i].Shutdown ();
805                         net_landrivers[i].initialized = false;
806                 }
807         }
808 }
809
810
811 void Datagram_Close (qsocket_t *sock)
812 {
813         sfunc.CloseSocket(sock->socket);
814 }
815
816
817 void Datagram_Listen (qboolean state)
818 {
819         int i;
820
821         for (i = 0; i < net_numlandrivers; i++)
822                 if (net_landrivers[i].initialized)
823                         net_landrivers[i].Listen (state);
824 }
825
826
827 static qsocket_t *_Datagram_CheckNewConnections (void)
828 {
829         struct qsockaddr clientaddr;
830         struct qsockaddr newaddr;
831         int                     newsock;
832         int                     acceptsock;
833         qsocket_t       *sock;
834         qsocket_t       *s;
835         int                     len;
836         int                     command;
837         int                     control;
838         int                     ret;
839
840         acceptsock = dfunc.CheckNewConnections();
841         if (acceptsock == -1)
842                 return NULL;
843
844         SZ_Clear(&net_message);
845
846         len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
847         if (len < sizeof(int))
848                 return NULL;
849         net_message.cursize = len;
850
851         MSG_BeginReading ();
852         control = BigLong(*((int *)net_message.data));
853         MSG_ReadLong();
854         if (control == -1)
855                 return NULL;
856         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
857                 return NULL;
858         if ((control & NETFLAG_LENGTH_MASK) != len)
859                 return NULL;
860
861         command = MSG_ReadByte();
862         if (command == CCREQ_SERVER_INFO)
863         {
864                 if (strcmp(MSG_ReadString(), "QUAKE") != 0)
865                         return NULL;
866
867                 SZ_Clear(&net_message);
868                 // save space for the header, filled in later
869                 MSG_WriteLong(&net_message, 0);
870                 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
871                 dfunc.GetSocketAddr(acceptsock, &newaddr);
872                 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
873                 MSG_WriteString(&net_message, hostname.string);
874                 MSG_WriteString(&net_message, sv.name);
875                 MSG_WriteByte(&net_message, net_activeconnections);
876                 MSG_WriteByte(&net_message, svs.maxclients);
877                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
878                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
879                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
880                 SZ_Clear(&net_message);
881                 return NULL;
882         }
883
884         if (command == CCREQ_PLAYER_INFO)
885         {
886                 int                     playerNumber;
887                 int                     activeNumber;
888                 int                     clientNumber;
889                 client_t        *client;
890                 
891                 playerNumber = MSG_ReadByte();
892                 activeNumber = -1;
893                 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
894                 {
895                         if (client->active)
896                         {
897                                 activeNumber++;
898                                 if (activeNumber == playerNumber)
899                                         break;
900                         }
901                 }
902                 if (clientNumber == svs.maxclients)
903                         return NULL;
904
905                 SZ_Clear(&net_message);
906                 // save space for the header, filled in later
907                 MSG_WriteLong(&net_message, 0);
908                 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
909                 MSG_WriteByte(&net_message, playerNumber);
910                 MSG_WriteString(&net_message, client->name);
911                 MSG_WriteLong(&net_message, client->colors);
912                 MSG_WriteLong(&net_message, (int)client->edict->v.frags);
913                 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
914                 MSG_WriteString(&net_message, client->netconnection->address);
915                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
916                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
917                 SZ_Clear(&net_message);
918
919                 return NULL;
920         }
921
922         if (command == CCREQ_RULE_INFO)
923         {
924                 char    *prevCvarName;
925                 cvar_t  *var;
926
927                 // find the search start location
928                 prevCvarName = MSG_ReadString();
929                 if (*prevCvarName)
930                 {
931                         var = Cvar_FindVar (prevCvarName);
932                         if (!var)
933                                 return NULL;
934                         var = var->next;
935                 }
936                 else
937                         var = cvar_vars;
938
939                 // search for the next server cvar
940                 while (var)
941                 {
942                         if (var->flags & CVAR_NOTIFY)
943                                 break;
944                         var = var->next;
945                 }
946
947                 // send the response
948
949                 SZ_Clear(&net_message);
950                 // save space for the header, filled in later
951                 MSG_WriteLong(&net_message, 0);
952                 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
953                 if (var)
954                 {
955                         MSG_WriteString(&net_message, var->name);
956                         MSG_WriteString(&net_message, var->string);
957                 }
958                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
959                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
960                 SZ_Clear(&net_message);
961
962                 return NULL;
963         }
964
965         if (command != CCREQ_CONNECT)
966                 return NULL;
967
968         if (strcmp(MSG_ReadString(), "QUAKE") != 0)
969                 return NULL;
970
971         if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
972         {
973                 SZ_Clear(&net_message);
974                 // save space for the header, filled in later
975                 MSG_WriteLong(&net_message, 0);
976                 MSG_WriteByte(&net_message, CCREP_REJECT);
977                 MSG_WriteString(&net_message, "Incompatible version.\n");
978                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
979                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
980                 SZ_Clear(&net_message);
981                 return NULL;
982         }
983
984 #ifdef BAN_TEST
985         // check for a ban
986         if (clientaddr.sa_family == AF_INET)
987         {
988                 unsigned long testAddr;
989                 testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
990                 if ((testAddr & banMask) == banAddr)
991                 {
992                         SZ_Clear(&net_message);
993                         // save space for the header, filled in later
994                         MSG_WriteLong(&net_message, 0);
995                         MSG_WriteByte(&net_message, CCREP_REJECT);
996                         MSG_WriteString(&net_message, "You have been banned.\n");
997                         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
998                         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
999                         SZ_Clear(&net_message);
1000                         return NULL;
1001                 }
1002         }
1003 #endif
1004
1005         // see if this guy is already connected
1006         for (s = net_activeSockets; s; s = s->next)
1007         {
1008                 if (s->driver != net_driverlevel)
1009                         continue;
1010                 ret = dfunc.AddrCompare(&clientaddr, &s->addr);
1011                 if (ret >= 0)
1012                 {
1013                         // is this a duplicate connection reqeust?
1014                         if (ret == 0 && net_time - s->connecttime < 2.0)
1015                         {
1016                                 // yes, so send a duplicate reply
1017                                 SZ_Clear(&net_message);
1018                                 // save space for the header, filled in later
1019                                 MSG_WriteLong(&net_message, 0);
1020                                 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1021                                 dfunc.GetSocketAddr(s->socket, &newaddr);
1022                                 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1023                                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1024                                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1025                                 SZ_Clear(&net_message);
1026                                 return NULL;
1027                         }
1028                         // it's somebody coming back in from a crash/disconnect
1029                         // so close the old qsocket and let their retry get them back in
1030                         NET_Close(s);
1031                         return NULL;
1032                 }
1033         }
1034
1035         // allocate a QSocket
1036         sock = NET_NewQSocket ();
1037         if (sock == NULL)
1038         {
1039                 // no room; try to let him know
1040                 SZ_Clear(&net_message);
1041                 // save space for the header, filled in later
1042                 MSG_WriteLong(&net_message, 0);
1043                 MSG_WriteByte(&net_message, CCREP_REJECT);
1044                 MSG_WriteString(&net_message, "Server is full.\n");
1045                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1046                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1047                 SZ_Clear(&net_message);
1048                 return NULL;
1049         }
1050
1051         // allocate a network socket
1052         newsock = dfunc.OpenSocket(0);
1053         if (newsock == -1)
1054         {
1055                 NET_FreeQSocket(sock);
1056                 return NULL;
1057         }
1058
1059         // connect to the client
1060         if (dfunc.Connect (newsock, &clientaddr) == -1)
1061         {
1062                 dfunc.CloseSocket(newsock);
1063                 NET_FreeQSocket(sock);
1064                 return NULL;
1065         }
1066
1067         // everything is allocated, just fill in the details    
1068         sock->socket = newsock;
1069         sock->landriver = net_landriverlevel;
1070         sock->addr = clientaddr;
1071         strcpy(sock->address, dfunc.AddrToString(&clientaddr));
1072
1073         // send him back the info about the server connection he has been allocated
1074         SZ_Clear(&net_message);
1075         // save space for the header, filled in later
1076         MSG_WriteLong(&net_message, 0);
1077         MSG_WriteByte(&net_message, CCREP_ACCEPT);
1078         dfunc.GetSocketAddr(newsock, &newaddr);
1079         MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1080 //      MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
1081         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1082         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1083         SZ_Clear(&net_message);
1084
1085         return sock;
1086 }
1087
1088 qsocket_t *Datagram_CheckNewConnections (void)
1089 {
1090         qsocket_t *ret = NULL;
1091
1092         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1093                 if (net_landrivers[net_landriverlevel].initialized)
1094                         if ((ret = _Datagram_CheckNewConnections ()) != NULL)
1095                                 break;
1096         return ret;
1097 }
1098
1099
1100 static void _Datagram_SearchForHosts (qboolean xmit)
1101 {
1102         int             ret;
1103         int             n;
1104         int             i;
1105         struct qsockaddr readaddr;
1106         struct qsockaddr myaddr;
1107         int             control;
1108
1109         dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
1110         if (xmit)
1111         {
1112                 SZ_Clear(&net_message);
1113                 // save space for the header, filled in later
1114                 MSG_WriteLong(&net_message, 0);
1115                 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
1116                 MSG_WriteString(&net_message, "QUAKE");
1117                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1118                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1119                 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
1120                 SZ_Clear(&net_message);
1121         }
1122
1123         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1124         {
1125                 if (ret < sizeof(int))
1126                         continue;
1127                 net_message.cursize = ret;
1128
1129                 // don't answer our own query
1130                 if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
1131                         continue;
1132
1133                 // is the cache full?
1134                 if (hostCacheCount == HOSTCACHESIZE)
1135                         continue;
1136
1137                 MSG_BeginReading ();
1138                 control = BigLong(*((int *)net_message.data));
1139                 MSG_ReadLong();
1140                 if (control == -1)
1141                         continue;
1142                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
1143                         continue;
1144                 if ((control & NETFLAG_LENGTH_MASK) != ret)
1145                         continue;
1146
1147                 if (MSG_ReadByte() != CCREP_SERVER_INFO)
1148                         continue;
1149
1150                 dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
1151                 // search the cache for this server
1152                 for (n = 0; n < hostCacheCount; n++)
1153                         if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
1154                                 break;
1155
1156                 // is it already there?
1157                 if (n < hostCacheCount)
1158                         continue;
1159
1160                 // add it
1161                 hostCacheCount++;
1162                 strcpy(hostcache[n].name, MSG_ReadString());
1163                 strcpy(hostcache[n].map, MSG_ReadString());
1164                 hostcache[n].users = MSG_ReadByte();
1165                 hostcache[n].maxusers = MSG_ReadByte();
1166                 if (MSG_ReadByte() != 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 (0);
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 ();
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 //#ifdef DEBUG
1266                                         Con_DPrintf("wrong reply address\n");
1267                                         Con_DPrintf("Expected: %s\n", StrAddr (&sendaddr));
1268                                         Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
1269                                         CL_UpdateScreen ();
1270 //#endif
1271                                         ret = 0;
1272                                         continue;
1273                                 }
1274
1275                                 if (ret < sizeof(int))
1276                                 {
1277                                         ret = 0;
1278                                         continue;
1279                                 }
1280
1281                                 net_message.cursize = ret;
1282                                 MSG_BeginReading ();
1283
1284                                 control = BigLong(*((int *)net_message.data));
1285                                 MSG_ReadLong();
1286                                 if (control == -1)
1287                                 {
1288                                         ret = 0;
1289                                         continue;
1290                                 }
1291                                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
1292                                 {
1293                                         ret = 0;
1294                                         continue;
1295                                 }
1296                                 if ((control & NETFLAG_LENGTH_MASK) != ret)
1297                                 {
1298                                         ret = 0;
1299                                         continue;
1300                                 }
1301                         }
1302                 }
1303                 while (ret == 0 && (SetNetTime() - start_time) < 2.5);
1304                 if (ret)
1305                         break;
1306                 Con_Printf("still trying...\n"); CL_UpdateScreen ();
1307                 start_time = SetNetTime();
1308         }
1309
1310         if (ret == 0)
1311         {
1312                 reason = "No Response";
1313                 Con_Printf("%s\n", reason);
1314                 strcpy(m_return_reason, reason);
1315                 goto ErrorReturn;
1316         }
1317
1318         if (ret == -1)
1319         {
1320                 reason = "Network Error";
1321                 Con_Printf("%s\n", reason);
1322                 strcpy(m_return_reason, reason);
1323                 goto ErrorReturn;
1324         }
1325
1326         ret = MSG_ReadByte();
1327         if (ret == CCREP_REJECT)
1328         {
1329                 reason = MSG_ReadString();
1330                 Con_Printf("%s", reason);
1331                 strncpy(m_return_reason, reason, 31);
1332                 goto ErrorReturn;
1333         }
1334
1335         if (ret == CCREP_ACCEPT)
1336         {
1337                 memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
1338                 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
1339         }
1340         else
1341         {
1342                 reason = "Bad Response";
1343                 Con_Printf("%s\n", reason);
1344                 strcpy(m_return_reason, reason);
1345                 goto ErrorReturn;
1346         }
1347
1348         dfunc.GetNameFromAddr (&sendaddr, sock->address);
1349
1350         Con_Printf ("Connection accepted\n");
1351         sock->lastMessageTime = SetNetTime();
1352
1353         // switch the connection to the specified address
1354         if (dfunc.Connect (newsock, &sock->addr) == -1)
1355         {
1356                 reason = "Connect to Game failed";
1357                 Con_Printf("%s\n", reason);
1358                 strcpy(m_return_reason, reason);
1359                 goto ErrorReturn;
1360         }
1361
1362         m_return_onerror = false;
1363         return sock;
1364
1365 ErrorReturn:
1366         NET_FreeQSocket(sock);
1367 ErrorReturn2:
1368         dfunc.CloseSocket(newsock);
1369         if (m_return_onerror)
1370         {
1371                 key_dest = key_menu;
1372                 m_state = m_return_state;
1373                 m_return_onerror = false;
1374         }
1375         return NULL;
1376 }
1377
1378 qsocket_t *Datagram_Connect (char *host)
1379 {
1380         qsocket_t *ret = NULL;
1381
1382         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1383                 if (net_landrivers[net_landriverlevel].initialized)
1384                         if ((ret = _Datagram_Connect (host)) != NULL)
1385                                 break;
1386         return ret;
1387 }