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