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