]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - net_dgrm.c
add support for NAT fix in the client (by no longer checking the port a connection...
[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                         Con_DPrintf("Forged packet received\n");
342                         Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
343                         Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
344                         continue;
345                 }
346
347                 if (length < NET_HEADERSIZE)
348                 {
349                         shortPacketCount++;
350                         continue;
351                 }
352
353                 length = BigLong(packetBuffer.length);
354                 flags = length & (~NETFLAG_LENGTH_MASK);
355                 length &= NETFLAG_LENGTH_MASK;
356
357                 if (flags & NETFLAG_CTL)
358                         continue;
359
360                 sequence = BigLong(packetBuffer.sequence);
361                 packetsReceived++;
362
363                 if (flags & NETFLAG_UNRELIABLE)
364                 {
365                         if (sequence < sock->unreliableReceiveSequence)
366                         {
367                                 Con_DPrintf("Got a stale datagram\n");
368                                 ret = 0;
369                                 break;
370                         }
371                         if (sequence != sock->unreliableReceiveSequence)
372                         {
373                                 count = sequence - sock->unreliableReceiveSequence;
374                                 droppedDatagrams += count;
375                                 Con_DPrintf("Dropped %u datagram(s)\n", count);
376                         }
377                         sock->unreliableReceiveSequence = sequence + 1;
378
379                         length -= NET_HEADERSIZE;
380
381                         SZ_Clear (&net_message);
382                         SZ_Write (&net_message, packetBuffer.data, length);
383
384                         ret = 2;
385                         break;
386                 }
387
388                 if (flags & NETFLAG_ACK)
389                 {
390                         if (sequence != (sock->sendSequence - 1))
391                         {
392                                 Con_DPrintf("Stale ACK received\n");
393                                 continue;
394                         }
395                         if (sequence == sock->ackSequence)
396                         {
397                                 sock->ackSequence++;
398                                 if (sock->ackSequence != sock->sendSequence)
399                                         Con_DPrintf("ack sequencing error\n");
400                         }
401                         else
402                         {
403                                 Con_DPrintf("Duplicate ACK received\n");
404                                 continue;
405                         }
406                         sock->sendMessageLength -= MAX_DATAGRAM;
407                         if (sock->sendMessageLength > 0)
408                         {
409                                 memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength);
410                                 sock->sendNext = true;
411                         }
412                         else
413                         {
414                                 sock->sendMessageLength = 0;
415                                 sock->canSend = true;
416                         }
417                         continue;
418                 }
419
420                 if (flags & NETFLAG_DATA)
421                 {
422                         packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK);
423                         packetBuffer.sequence = BigLong(sequence);
424                         sfunc.Write (sock->socket, (qbyte *)&packetBuffer, NET_HEADERSIZE, &readaddr);
425
426                         if (sequence != sock->receiveSequence)
427                         {
428                                 receivedDuplicateCount++;
429                                 continue;
430                         }
431                         sock->receiveSequence++;
432
433                         length -= NET_HEADERSIZE;
434
435                         if (flags & NETFLAG_EOM)
436                         {
437                                 SZ_Clear(&net_message);
438                                 SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength);
439                                 SZ_Write(&net_message, packetBuffer.data, length);
440                                 sock->receiveMessageLength = 0;
441
442                                 ret = 1;
443                                 break;
444                         }
445
446                         memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length);
447                         sock->receiveMessageLength += length;
448                         continue;
449                 }
450         }
451
452         if (sock->sendNext)
453                 SendMessageNext (sock);
454
455         return ret;
456 }
457
458
459 void PrintStats(qsocket_t *s)
460 {
461         Con_Printf("canSend = %4u   \n", s->canSend);
462         Con_Printf("sendSeq = %4u   ", s->sendSequence);
463         Con_Printf("recvSeq = %4u   \n", s->receiveSequence);
464         Con_Printf("\n");
465 }
466
467 void NET_Stats_f (void)
468 {
469         qsocket_t       *s;
470
471         if (Cmd_Argc () == 1)
472         {
473                 Con_Printf("unreliable messages sent   = %i\n", unreliableMessagesSent);
474                 Con_Printf("unreliable messages recv   = %i\n", unreliableMessagesReceived);
475                 Con_Printf("reliable messages sent     = %i\n", messagesSent);
476                 Con_Printf("reliable messages received = %i\n", messagesReceived);
477                 Con_Printf("packetsSent                = %i\n", packetsSent);
478                 Con_Printf("packetsReSent              = %i\n", packetsReSent);
479                 Con_Printf("packetsReceived            = %i\n", packetsReceived);
480                 Con_Printf("receivedDuplicateCount     = %i\n", receivedDuplicateCount);
481                 Con_Printf("shortPacketCount           = %i\n", shortPacketCount);
482                 Con_Printf("droppedDatagrams           = %i\n", droppedDatagrams);
483         }
484         else if (strcmp(Cmd_Argv(1), "*") == 0)
485         {
486                 for (s = net_activeSockets; s; s = s->next)
487                         PrintStats(s);
488         }
489         else
490         {
491                 for (s = net_activeSockets; s; s = s->next)
492                         if (strcasecmp(Cmd_Argv(1), s->address) == 0)
493                                 break;
494                 if (s == NULL)
495                         return;
496                 PrintStats(s);
497         }
498 }
499
500
501 static qboolean testInProgress = false;
502 static int              testPollCount;
503 static int              testDriver;
504 static int              testSocket;
505
506 static void Test_Poll(void);
507 PollProcedure   testPollProcedure = {NULL, 0.0, Test_Poll};
508
509 static void Test_Poll(void)
510 {
511         struct qsockaddr clientaddr;
512         int             control;
513         int             len;
514         char    name[32];
515         char    address[64];
516         int             colors;
517         int             frags;
518         int             connectTime;
519         qbyte   playerNumber;
520         int             c;
521
522         net_landriverlevel = testDriver;
523
524         while (1)
525         {
526                 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
527                 if (len < (int)sizeof(int))
528                         break;
529
530                 net_message.cursize = len;
531
532                 MSG_BeginReading ();
533                 control = BigLong(*((int *)net_message.data));
534                 MSG_ReadLong();
535                 if (control == -1)
536                         break;
537                 if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
538                         break;
539                 if ((control & NETFLAG_LENGTH_MASK) != len)
540                         break;
541
542                 c = MSG_ReadByte();
543                 if (c != CCREP_PLAYER_INFO)
544                         Sys_Error("Unexpected repsonse to Player Info request\n");
545
546                 playerNumber = MSG_ReadByte();
547                 strcpy(name, MSG_ReadString());
548                 colors = MSG_ReadLong();
549                 frags = MSG_ReadLong();
550                 connectTime = MSG_ReadLong();
551                 strcpy(address, MSG_ReadString());
552
553                 Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
554         }
555
556         testPollCount--;
557         if (testPollCount)
558         {
559                 SchedulePollProcedure(&testPollProcedure, 0.1);
560         }
561         else
562         {
563                 dfunc.CloseSocket(testSocket);
564                 testInProgress = false;
565         }
566 }
567
568 static void Test_f (void)
569 {
570         const char *host;
571         int n, max = MAX_SCOREBOARD;
572         struct qsockaddr sendaddr;
573
574         if (testInProgress)
575                 return;
576
577         host = Cmd_Argv (1);
578
579         if (host && hostCacheCount)
580         {
581                 for (n = 0; n < hostCacheCount; n++)
582                         if (strcasecmp (host, hostcache[n].name) == 0)
583                         {
584                                 if (hostcache[n].driver != myDriverLevel)
585                                         continue;
586                                 net_landriverlevel = hostcache[n].ldriver;
587                                 max = hostcache[n].maxusers;
588                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
589                                 break;
590                         }
591                 if (n < hostCacheCount)
592                         goto JustDoIt;
593         }
594
595         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
596         {
597                 if (!net_landrivers[net_landriverlevel].initialized)
598                         continue;
599
600                 // see if we can resolve the host name
601                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
602                         break;
603         }
604         if (net_landriverlevel == net_numlandrivers)
605                 return;
606
607 JustDoIt:
608         testSocket = dfunc.OpenSocket(0);
609         if (testSocket == -1)
610                 return;
611
612         testInProgress = true;
613         testPollCount = 20;
614         testDriver = net_landriverlevel;
615
616         for (n = 0; n < max; n++)
617         {
618                 SZ_Clear(&net_message);
619                 // save space for the header, filled in later
620                 MSG_WriteLong(&net_message, 0);
621                 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
622                 MSG_WriteByte(&net_message, n);
623                 *((int *)net_message.data) = BigLong(NETFLAG_CTL |      (net_message.cursize & NETFLAG_LENGTH_MASK));
624                 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
625         }
626         SZ_Clear(&net_message);
627         SchedulePollProcedure(&testPollProcedure, 0.1);
628 }
629
630
631 static qboolean test2InProgress = false;
632 static int              test2Driver;
633 static int              test2Socket;
634
635 static void Test2_Poll(void);
636 PollProcedure   test2PollProcedure = {NULL, 0.0, Test2_Poll};
637
638 static void Test2_Poll(void)
639 {
640         struct qsockaddr clientaddr;
641         int             control;
642         int             len;
643         int             c;
644         char    name[256];
645         char    value[256];
646
647         net_landriverlevel = test2Driver;
648         name[0] = 0;
649
650         len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
651         if (len < (int)sizeof(int))
652                 goto Reschedule;
653
654         net_message.cursize = len;
655
656         MSG_BeginReading ();
657         control = BigLong(*((int *)net_message.data));
658         MSG_ReadLong();
659         if (control == -1)
660                 goto Error;
661         if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
662                 goto Error;
663         if ((control & NETFLAG_LENGTH_MASK) != len)
664                 goto Error;
665
666         c = MSG_ReadByte();
667         if (c != CCREP_RULE_INFO)
668                 goto Error;
669
670         strcpy(name, MSG_ReadString());
671         if (name[0] == 0)
672                 goto Done;
673         strcpy(value, MSG_ReadString());
674
675         Con_Printf("%-16.16s  %-16.16s\n", name, value);
676
677         SZ_Clear(&net_message);
678         // save space for the header, filled in later
679         MSG_WriteLong(&net_message, 0);
680         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
681         MSG_WriteString(&net_message, name);
682         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
683         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
684         SZ_Clear(&net_message);
685
686 Reschedule:
687         SchedulePollProcedure(&test2PollProcedure, 0.05);
688         return;
689
690 Error:
691         Con_Printf("Unexpected repsonse to Rule Info request\n");
692 Done:
693         dfunc.CloseSocket(test2Socket);
694         test2InProgress = false;
695         return;
696 }
697
698 static void Test2_f (void)
699 {
700         const char *host;
701         int n;
702         struct qsockaddr sendaddr;
703
704         if (test2InProgress)
705                 return;
706
707         host = Cmd_Argv (1);
708
709         if (host && hostCacheCount)
710         {
711                 for (n = 0; n < hostCacheCount; n++)
712                         if (strcasecmp (host, hostcache[n].name) == 0)
713                         {
714                                 if (hostcache[n].driver != myDriverLevel)
715                                         continue;
716                                 net_landriverlevel = hostcache[n].ldriver;
717                                 memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
718                                 break;
719                         }
720                 if (n < hostCacheCount)
721                         goto JustDoIt;
722         }
723
724         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
725         {
726                 if (!net_landrivers[net_landriverlevel].initialized)
727                         continue;
728
729                 // see if we can resolve the host name
730                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
731                         break;
732         }
733         if (net_landriverlevel == net_numlandrivers)
734                 return;
735
736 JustDoIt:
737         test2Socket = dfunc.OpenSocket(0);
738         if (test2Socket == -1)
739                 return;
740
741         test2InProgress = true;
742         test2Driver = net_landriverlevel;
743
744         SZ_Clear(&net_message);
745         // save space for the header, filled in later
746         MSG_WriteLong(&net_message, 0);
747         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
748         MSG_WriteString(&net_message, "");
749         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
750         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
751         SZ_Clear(&net_message);
752         SchedulePollProcedure(&test2PollProcedure, 0.05);
753 }
754
755
756 int Datagram_Init (void)
757 {
758         int i;
759         int csock;
760
761         myDriverLevel = net_driverlevel;
762         Cmd_AddCommand ("net_stats", NET_Stats_f);
763         Cvar_RegisterVariable (&cl_port);
764
765         if (COM_CheckParm("-nolan"))
766                 return -1;
767
768         for (i = 0; i < net_numlandrivers; i++)
769                 {
770                 csock = net_landrivers[i].Init ();
771                 if (csock == -1)
772                         continue;
773                 net_landrivers[i].initialized = true;
774                 net_landrivers[i].controlSock = csock;
775                 }
776
777 #ifdef BAN_TEST
778         Cmd_AddCommand ("ban", NET_Ban_f);
779 #endif
780         Cmd_AddCommand ("test", Test_f);
781         Cmd_AddCommand ("test2", Test2_f);
782
783         return 0;
784 }
785
786
787 void Datagram_Shutdown (void)
788 {
789         int i;
790
791 //
792 // shutdown the lan drivers
793 //
794         for (i = 0; i < net_numlandrivers; i++)
795         {
796                 if (net_landrivers[i].initialized)
797                 {
798                         net_landrivers[i].Shutdown ();
799                         net_landrivers[i].initialized = false;
800                 }
801         }
802 }
803
804
805 void Datagram_Close (qsocket_t *sock)
806 {
807         sfunc.CloseSocket(sock->socket);
808 }
809
810
811 void Datagram_Listen (qboolean state)
812 {
813         int i;
814
815         for (i = 0; i < net_numlandrivers; i++)
816                 if (net_landrivers[i].initialized)
817                         net_landrivers[i].Listen (state);
818 }
819
820
821 static qsocket_t *_Datagram_CheckNewConnections (void)
822 {
823         struct qsockaddr clientaddr;
824         struct qsockaddr newaddr;
825         int                     newsock;
826         int                     acceptsock;
827         qsocket_t       *sock;
828         qsocket_t       *s;
829         int                     len;
830         int                     command;
831         int                     control;
832         int                     ret;
833         int                     c;
834
835         acceptsock = dfunc.CheckNewConnections();
836         if (acceptsock == -1)
837                 return NULL;
838
839         SZ_Clear(&net_message);
840
841         len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
842         if (len < (int)sizeof(int))
843                 return NULL;
844         net_message.cursize = len;
845
846         MSG_BeginReading ();
847         control = BigLong(*((int *)net_message.data));
848         MSG_ReadLong();
849
850         // Messages starting by 0xFFFFFFFF are master server messages
851         if ((unsigned int)control == 0xFFFFFFFF)
852         {
853                 int responsesize = Master_HandleMessage();
854                 if (responsesize > 0)
855                 {
856                         dfunc.Write(acceptsock, net_message.data, responsesize, &clientaddr);
857                         SZ_Clear(&net_message);
858                 }
859                 return NULL;
860         }
861         if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
862                 return NULL;
863         if ((control & NETFLAG_LENGTH_MASK) != len)
864                 return NULL;
865
866         command = MSG_ReadByte();
867         if (command == CCREQ_SERVER_INFO)
868         {
869                 if (strcmp(MSG_ReadString(), "QUAKE") != 0)
870                         return NULL;
871
872                 Con_DPrintf("Datagram_CheckNewConnections: received CCREQ_SERVERINFO, replying.\n");
873
874                 SZ_Clear(&net_message);
875                 // save space for the header, filled in later
876                 MSG_WriteLong(&net_message, 0);
877                 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
878                 dfunc.GetSocketAddr(acceptsock, &newaddr);
879                 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
880                 MSG_WriteString(&net_message, hostname.string);
881                 MSG_WriteString(&net_message, sv.name);
882                 MSG_WriteByte(&net_message, net_activeconnections);
883                 MSG_WriteByte(&net_message, svs.maxclients);
884                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
885                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
886                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
887                 SZ_Clear(&net_message);
888                 return NULL;
889         }
890
891         if (command == CCREQ_PLAYER_INFO)
892         {
893                 int                     playerNumber;
894                 int                     activeNumber;
895                 int                     clientNumber;
896                 client_t        *client;
897
898                 playerNumber = MSG_ReadByte();
899                 activeNumber = -1;
900                 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
901                 {
902                         if (client->active)
903                         {
904                                 activeNumber++;
905                                 if (activeNumber == playerNumber)
906                                         break;
907                         }
908                 }
909                 if (clientNumber == svs.maxclients)
910                         return NULL;
911
912                 SZ_Clear(&net_message);
913                 // save space for the header, filled in later
914                 MSG_WriteLong(&net_message, 0);
915                 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
916                 MSG_WriteByte(&net_message, playerNumber);
917                 MSG_WriteString(&net_message, client->name);
918                 MSG_WriteLong(&net_message, client->colors);
919                 MSG_WriteLong(&net_message, (int)client->edict->v->frags);
920                 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
921                 MSG_WriteString(&net_message, client->netconnection->address);
922                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
923                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
924                 SZ_Clear(&net_message);
925
926                 return NULL;
927         }
928
929         if (command == CCREQ_RULE_INFO)
930         {
931                 char    *prevCvarName;
932                 cvar_t  *var;
933
934                 // find the search start location
935                 prevCvarName = MSG_ReadString();
936                 var = Cvar_FindVarAfter(prevCvarName, CVAR_NOTIFY);
937
938                 // send the response
939
940                 SZ_Clear(&net_message);
941                 // save space for the header, filled in later
942                 MSG_WriteLong(&net_message, 0);
943                 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
944                 if (var)
945                 {
946                         MSG_WriteString(&net_message, var->name);
947                         MSG_WriteString(&net_message, var->string);
948                 }
949                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
950                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
951                 SZ_Clear(&net_message);
952
953                 return NULL;
954         }
955
956         if (command != CCREQ_CONNECT)
957                 return NULL;
958
959         if (strcmp(MSG_ReadString(), "QUAKE") != 0)
960                 return NULL;
961
962         c = MSG_ReadByte();
963         if (c != NET_PROTOCOL_VERSION)
964         {
965                 SZ_Clear(&net_message);
966                 // save space for the header, filled in later
967                 MSG_WriteLong(&net_message, 0);
968                 MSG_WriteByte(&net_message, CCREP_REJECT);
969                 MSG_WriteString(&net_message, "Incompatible version.\n");
970                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
971                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
972                 SZ_Clear(&net_message);
973                 return NULL;
974         }
975
976 #ifdef BAN_TEST
977         // check for a ban
978         if (clientaddr.sa_family == AF_INET)
979         {
980                 unsigned long testAddr;
981                 testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
982                 if ((testAddr & banMask) == banAddr)
983                 {
984                         SZ_Clear(&net_message);
985                         // save space for the header, filled in later
986                         MSG_WriteLong(&net_message, 0);
987                         MSG_WriteByte(&net_message, CCREP_REJECT);
988                         MSG_WriteString(&net_message, "You have been banned.\n");
989                         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
990                         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
991                         SZ_Clear(&net_message);
992                         return NULL;
993                 }
994         }
995 #endif
996
997         // see if this guy is already connected
998         for (s = net_activeSockets; s; s = s->next)
999         {
1000                 if (s->driver != net_driverlevel)
1001                         continue;
1002                 ret = dfunc.AddrCompare(&clientaddr, &s->addr);
1003                 if (ret >= 0)
1004                 {
1005                         // is this a duplicate connection request?
1006                         if (ret == 0 && net_time - s->connecttime < 2.0)
1007                         {
1008                                 // yes, so send a duplicate reply
1009                                 SZ_Clear(&net_message);
1010                                 // save space for the header, filled in later
1011                                 MSG_WriteLong(&net_message, 0);
1012                                 MSG_WriteByte(&net_message, CCREP_ACCEPT);
1013                                 dfunc.GetSocketAddr(s->socket, &newaddr);
1014                                 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
1015                                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1016                                 // LordHavoc: send from s->socket instead of acceptsock, this
1017                                 // way routers usually identify the connection correctly
1018                                 // (thanks to faded for provoking me to recite a lengthy
1019                                 // explanation of NAT nightmares, and realize this easy
1020                                 // workaround for quake)
1021                                 dfunc.Write (s->socket, net_message.data, net_message.cursize, &clientaddr);
1022                                 // LordHavoc: also send from acceptsock, for good measure
1023                                 dfunc.Write (acceptsock, 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         // LordHavoc: also send from acceptsock, for good measure
1086         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
1087         SZ_Clear(&net_message);
1088
1089         return sock;
1090 }
1091
1092 qsocket_t *Datagram_CheckNewConnections (void)
1093 {
1094         qsocket_t *ret = NULL;
1095
1096         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1097                 if (net_landrivers[net_landriverlevel].initialized)
1098                         if ((ret = _Datagram_CheckNewConnections ()) != NULL)
1099                                 break;
1100         return ret;
1101 }
1102
1103
1104 static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
1105 {
1106         //struct qsockaddr myaddr;
1107         int control;
1108         int c, n, i;
1109
1110         if (net_message.cursize < (int)sizeof(int))
1111                 return false;
1112
1113         // don't answer our own query
1114         //dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
1115         //if (dfunc.AddrCompare(readaddr, &myaddr) >= 0)
1116         //      return false;
1117
1118         // is the cache full?
1119         if (hostCacheCount == HOSTCACHESIZE)
1120                 return false;
1121
1122         MSG_BeginReading ();
1123         control = BigLong(*((int *)net_message.data));
1124         MSG_ReadLong();
1125         if (control == -1)
1126                 return false;
1127         if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
1128                 return false;
1129         if ((control & NETFLAG_LENGTH_MASK) != net_message.cursize)
1130                 return false;
1131
1132         c = MSG_ReadByte();
1133         if (c != CCREP_SERVER_INFO)
1134                 return false;
1135
1136         dfunc.GetAddrFromName(MSG_ReadString(), readaddr);
1137         // search the cache for this server
1138         for (n = 0; n < hostCacheCount; n++)
1139                 if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0)
1140                         break;
1141
1142         // is it already there?
1143         if (n < hostCacheCount)
1144                 return false;;
1145
1146         // add it
1147         hostCacheCount++;
1148         strcpy(hostcache[n].name, MSG_ReadString());
1149         strcpy(hostcache[n].map, MSG_ReadString());
1150         hostcache[n].users = MSG_ReadByte();
1151         hostcache[n].maxusers = MSG_ReadByte();
1152         c = MSG_ReadByte();
1153         if (c != NET_PROTOCOL_VERSION)
1154         {
1155                 strcpy(hostcache[n].cname, hostcache[n].name);
1156                 hostcache[n].cname[14] = 0;
1157                 strcpy(hostcache[n].name, "*");
1158                 strcat(hostcache[n].name, hostcache[n].cname);
1159         }
1160         memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr));
1161         hostcache[n].driver = net_driverlevel;
1162         hostcache[n].ldriver = net_landriverlevel;
1163         strcpy(hostcache[n].cname, dfunc.AddrToString(readaddr));
1164
1165         // check for a name conflict
1166         for (i = 0; i < hostCacheCount; i++)
1167         {
1168                 if (i == n)
1169                         continue;
1170                 if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
1171                 {
1172                         i = strlen(hostcache[n].name);
1173                         if (i < 15 && hostcache[n].name[i-1] > '8')
1174                         {
1175                                 hostcache[n].name[i] = '0';
1176                                 hostcache[n].name[i+1] = 0;
1177                         }
1178                         else
1179                                 hostcache[n].name[i-1]++;
1180                         i = -1;
1181                 }
1182         }
1183
1184         return true;
1185 }
1186
1187
1188 static void _Datagram_SearchForHosts (qboolean xmit)
1189 {
1190         int             ret;
1191         struct qsockaddr readaddr;
1192
1193         if (xmit)
1194         {
1195                 SZ_Clear(&net_message);
1196                 // save space for the header, filled in later
1197                 MSG_WriteLong(&net_message, 0);
1198                 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
1199                 MSG_WriteString(&net_message, "QUAKE");
1200                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1201                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1202                 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
1203                 SZ_Clear(&net_message);
1204         }
1205
1206         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1207         {
1208                 net_message.cursize = ret;
1209                 Datagram_HandleServerInfo (&readaddr);
1210         }
1211 }
1212
1213 void Datagram_SearchForHosts (qboolean xmit)
1214 {
1215         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1216         {
1217                 if (hostCacheCount == HOSTCACHESIZE)
1218                         break;
1219                 if (net_landrivers[net_landriverlevel].initialized)
1220                         _Datagram_SearchForHosts (xmit);
1221         }
1222 }
1223
1224
1225 static qboolean _Datagram_SearchForInetHosts (const char *master)
1226 {
1227         qboolean result = false;
1228         struct qsockaddr masteraddr;
1229         struct qsockaddr readaddr;
1230         int ret;
1231
1232         if (master)
1233         {
1234                 if (dfunc.GetAddrFromName(master, &masteraddr) != -1)
1235                 {
1236                         int portnum = 0;
1237                         const char* port = strrchr (master, ':');
1238                         if (port)
1239                                 portnum = atoi (port + 1);
1240                         if (!portnum)
1241                                 portnum = MASTER_PORT;
1242                         Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s port %i\n", net_message.cursize, master, portnum);
1243                         dfunc.SetSocketPort (&masteraddr, portnum);
1244                         dfunc.Write (dfunc.controlSock, net_message.data, net_message.cursize, &masteraddr);
1245                 }
1246         }
1247
1248         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1249         {
1250                 net_message.cursize = ret;
1251                 Con_DPrintf("Datagram_SearchForInetHosts: Read received %d byte message\n", net_message.cursize);
1252                 if (Datagram_HandleServerInfo (&readaddr))
1253                         result = true;
1254                 else
1255                         Master_ParseServerList (&dfunc);
1256         }
1257
1258         return result;
1259 }
1260
1261
1262 qboolean Datagram_SearchForInetHosts (const char *master)
1263 {
1264         qboolean result = false;
1265         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1266         {
1267                 if (hostCacheCount == HOSTCACHESIZE)
1268                         break;
1269                 if (net_landrivers[net_landriverlevel].initialized)
1270                         if (_Datagram_SearchForInetHosts (master))
1271                                 result = true;
1272         }
1273
1274         return result;
1275 }
1276
1277
1278 static qsocket_t *_Datagram_Connect (const char *host)
1279 {
1280         struct qsockaddr sendaddr;
1281         struct qsockaddr readaddr;
1282         struct qsockaddr testaddr;
1283         qsocket_t       *sock;
1284         int                     newsock;
1285         int                     ret;
1286         int                     reps;
1287         double          start_time;
1288         int                     control;
1289         char            *reason;
1290
1291         // see if we can resolve the host name
1292         if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
1293                 return NULL;
1294
1295         newsock = dfunc.OpenSocket (cl_port.integer);
1296         if (newsock == -1)
1297                 return NULL;
1298
1299         sock = NET_NewQSocket ();
1300         if (sock == NULL)
1301                 goto ErrorReturn2;
1302         sock->socket = newsock;
1303         sock->landriver = net_landriverlevel;
1304
1305         // connect to the host
1306         if (dfunc.Connect (newsock, &sendaddr) == -1)
1307                 goto ErrorReturn;
1308
1309         // send the connection request
1310         Con_Printf("trying...\n");CL_UpdateScreen();CL_UpdateScreen();
1311         start_time = net_time;
1312
1313         for (reps = 0; reps < 3; reps++)
1314         {
1315                 SZ_Clear(&net_message);
1316                 // save space for the header, filled in later
1317                 MSG_WriteLong(&net_message, 0);
1318                 MSG_WriteByte(&net_message, CCREQ_CONNECT);
1319                 MSG_WriteString(&net_message, "QUAKE");
1320                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1321                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1322                 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
1323                 SZ_Clear(&net_message);
1324                 do
1325                 {
1326                         ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
1327                         // if we got something, validate it
1328                         if (ret > 0)
1329                         {
1330                                 // is it from the right place?
1331                                 // we don't care if the port matches (this adds support for
1332                                 // the NAT fix in the server inspired by faded)
1333                                 memcpy(&testaddr, &sendaddr, sizeof(struct qsockaddr));
1334                                 dfunc.SetSocketPort (&testaddr, dfunc.GetSocketPort(&readaddr));
1335                                 if (sfunc.AddrCompare(&readaddr, &testaddr) != 0)
1336                                 {
1337                                         Con_Printf("wrong reply address\n");
1338                                         Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
1339                                         Con_Printf("Received: %s\n", StrAddr (&readaddr));
1340                                         CL_UpdateScreen ();
1341                                         CL_UpdateScreen ();
1342                                         ret = 0;
1343                                         continue;
1344                                 }
1345
1346                                 if (ret < (int)sizeof(int))
1347                                 {
1348                                         ret = 0;
1349                                         continue;
1350                                 }
1351
1352                                 net_message.cursize = ret;
1353                                 MSG_BeginReading ();
1354
1355                                 control = BigLong(*((int *)net_message.data));
1356                                 MSG_ReadLong();
1357                                 if (control == -1)
1358                                 {
1359                                         ret = 0;
1360                                         continue;
1361                                 }
1362                                 if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
1363                                 {
1364                                         ret = 0;
1365                                         continue;
1366                                 }
1367                                 if ((control & NETFLAG_LENGTH_MASK) != ret)
1368                                 {
1369                                         ret = 0;
1370                                         continue;
1371                                 }
1372                         }
1373                 }
1374                 while (ret == 0 && (SetNetTime() - start_time) < 2.5);
1375                 if (ret)
1376                         break;
1377                 Con_Printf("still trying...\n");CL_UpdateScreen();CL_UpdateScreen();
1378                 start_time = SetNetTime();
1379         }
1380
1381         if (ret == 0)
1382         {
1383                 reason = "No Response";
1384                 Con_Printf("%s\n", reason);
1385                 strcpy(m_return_reason, reason);
1386                 goto ErrorReturn;
1387         }
1388
1389         if (ret == -1)
1390         {
1391                 reason = "Network Error";
1392                 Con_Printf("%s\n", reason);
1393                 strcpy(m_return_reason, reason);
1394                 goto ErrorReturn;
1395         }
1396
1397         ret = MSG_ReadByte();
1398         if (ret == CCREP_REJECT)
1399         {
1400                 reason = MSG_ReadString();
1401                 Con_Printf("%s", reason);
1402                 strncpy(m_return_reason, reason, 31);
1403                 goto ErrorReturn;
1404         }
1405
1406         if (ret == CCREP_ACCEPT)
1407         {
1408                 memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
1409                 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
1410         }
1411         else
1412         {
1413                 reason = "Bad Response";
1414                 Con_Printf("%s\n", reason);
1415                 strcpy(m_return_reason, reason);
1416                 goto ErrorReturn;
1417         }
1418
1419         dfunc.GetNameFromAddr (&sendaddr, sock->address);
1420
1421         Con_Printf ("Connection accepted to %s\n", sock->address);
1422         sock->lastMessageTime = SetNetTime();
1423
1424         // switch the connection to the specified address
1425         if (dfunc.Connect (newsock, &sock->addr) == -1)
1426         {
1427                 reason = "Connect to Game failed";
1428                 Con_Printf("%s\n", reason);
1429                 strcpy(m_return_reason, reason);
1430                 goto ErrorReturn;
1431         }
1432
1433         m_return_onerror = false;
1434         return sock;
1435
1436 ErrorReturn:
1437         NET_FreeQSocket(sock);
1438 ErrorReturn2:
1439         dfunc.CloseSocket(newsock);
1440         if (m_return_onerror)
1441         {
1442                 key_dest = key_menu;
1443                 m_state = m_return_state;
1444                 m_return_onerror = false;
1445         }
1446         return NULL;
1447 }
1448
1449 qsocket_t *Datagram_Connect (const char *host)
1450 {
1451         qsocket_t *ret = NULL;
1452
1453         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1454                 if (net_landrivers[net_landriverlevel].initialized)
1455                         if ((ret = _Datagram_Connect (host)) != NULL)
1456                                 break;
1457         return ret;
1458 }
1459
1460 static void _Datagram_Heartbeat (const char *master)
1461 {
1462         struct qsockaddr masteraddr;
1463         int portnum;
1464         const char* port;
1465
1466         if (dfunc.GetAddrFromName(master, &masteraddr) == -1)
1467                 return;
1468
1469         portnum = 0;
1470         port = strrchr (master, ':');
1471         if (port)
1472                 portnum = atoi (port + 1);
1473         if (!portnum)
1474                 portnum = MASTER_PORT;
1475         dfunc.SetSocketPort (&masteraddr, portnum);
1476
1477         // FIXME: this is the only use of UDP_Send in the entire engine, add a dfunc.acceptSock to get rid of this function!
1478         dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
1479 }
1480
1481 void Datagram_Heartbeat (const char *master)
1482 {
1483         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1484                 if (net_landrivers[net_landriverlevel].initialized)
1485                         _Datagram_Heartbeat (master);
1486 }