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