]> icculus.org git repositories - divverent/darkplaces.git/blob - net_dgrm.c
got rid of my attempts to delay sending the ServerInfo packet until the first message...
[divverent/darkplaces.git] / net_dgrm.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // net_dgrm.c
21
22 // This is enables a simple IP banning mechanism
23 #define BAN_TEST
24
25 #ifdef BAN_TEST
26 #if defined(_WIN32)
27 #include <windows.h>
28 #elif defined (NeXT)
29 #include <sys/socket.h>
30 #include <arpa/inet.h>
31 #else
32 #define AF_INET                 2       /* internet */
33 struct in_addr
34 {
35         union
36         {
37                 struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
38                 struct { unsigned short s_w1,s_w2; } S_un_w;
39                 unsigned long S_addr;
40         } S_un;
41 };
42 #define s_addr  S_un.S_addr     /* can be used for most tcp & ip code */
43 struct sockaddr_in
44 {
45     short                       sin_family;
46     unsigned short      sin_port;
47         struct in_addr  sin_addr;
48     char                        sin_zero[8];
49 };
50 char *inet_ntoa(struct in_addr in);
51 unsigned long inet_addr(const char *cp);
52 #endif
53 #endif  // BAN_TEST
54
55 #include "quakedef.h"
56 #include "net_dgrm.h"
57 #include "net_master.h"
58
59 cvar_t cl_port = {CVAR_SAVE, "cl_port", "0"};
60
61 // these two macros are to make the code more readable
62 #define sfunc   net_landrivers[sock->landriver]
63 #define dfunc   net_landrivers[net_landriverlevel]
64
65 static int net_landriverlevel;
66
67 /* statistic counters */
68 int     packetsSent = 0;
69 int     packetsReSent = 0;
70 int packetsReceived = 0;
71 int receivedDuplicateCount = 0;
72 int shortPacketCount = 0;
73 int droppedDatagrams;
74
75 static int myDriverLevel;
76
77 struct
78 {
79         unsigned int    length;
80         unsigned int    sequence;
81         qbyte                   data[MAX_DATAGRAM];
82 } packetBuffer;
83
84
85 //#ifdef DEBUG
86 char *StrAddr (struct qsockaddr *addr)
87 {
88         static char buf[34];
89         qbyte *p = (qbyte *)addr;
90         int n;
91
92         for (n = 0; n < 16; n++)
93                 sprintf (buf + n * 2, "%02x", *p++);
94         return buf;
95 }
96 //#endif
97
98
99 #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;
1109         char cname[256];
1110
1111         if (net_message.cursize < (int)sizeof(int))
1112                 return false;
1113
1114         // don't answer our own query
1115         //dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
1116         //if (dfunc.AddrCompare(readaddr, &myaddr) >= 0)
1117         //      return false;
1118
1119         // is the cache full?
1120         if (hostCacheCount == HOSTCACHESIZE)
1121                 return false;
1122
1123         MSG_BeginReading ();
1124         control = BigLong(*((int *)net_message.data));
1125         MSG_ReadLong();
1126         if (control == -1)
1127                 return false;
1128         if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
1129                 return false;
1130         if ((control & NETFLAG_LENGTH_MASK) != net_message.cursize)
1131                 return false;
1132
1133         c = MSG_ReadByte();
1134         if (c != CCREP_SERVER_INFO)
1135                 return false;
1136
1137         // LordHavoc: because the UDP driver reports 0.0.0.0:26000 as the address
1138         // string we just ignore it and keep the real address
1139         MSG_ReadString();
1140         // hostcache only uses text addresses
1141         strcpy(cname, dfunc.AddrToString(readaddr));
1142         // search the cache for this server
1143         for (n = 0; n < hostCacheCount; n++)
1144                 //if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0)
1145                 if (!strcmp(cname, hostcache[n].cname))
1146                         return false;
1147
1148         // add it
1149         hostCacheCount++;
1150         strcpy(hostcache[n].name, MSG_ReadString());
1151         strcpy(hostcache[n].map, MSG_ReadString());
1152         hostcache[n].users = MSG_ReadByte();
1153         hostcache[n].maxusers = MSG_ReadByte();
1154         c = MSG_ReadByte();
1155         if (c != NET_PROTOCOL_VERSION)
1156         {
1157                 strncpy(hostcache[n].cname, hostcache[n].name, sizeof(hostcache[n].cname) - 1);
1158                 hostcache[n].cname[sizeof(hostcache[n].cname) - 1] = 0;
1159                 strcpy(hostcache[n].name, "*");
1160                 strncat(hostcache[n].name, hostcache[n].cname, sizeof(hostcache[n].name) - 1);
1161                 hostcache[n].name[sizeof(hostcache[n].name) - 1] = 0;
1162         }
1163         strcpy(hostcache[n].cname, cname);
1164         //memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr));
1165         //hostcache[n].driver = net_driverlevel;
1166         //hostcache[n].ldriver = net_landriverlevel;
1167
1168         /*
1169         // check for a name conflict
1170         for (i = 0; i < hostCacheCount; i++)
1171         {
1172                 if (i == n)
1173                         continue;
1174                 if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
1175                 {
1176                         i = strlen(hostcache[n].name);
1177                         if (i < 15 && hostcache[n].name[i-1] > '8')
1178                         {
1179                                 hostcache[n].name[i] = '0';
1180                                 hostcache[n].name[i+1] = 0;
1181                         }
1182                         else
1183                                 hostcache[n].name[i-1]++;
1184                         i = -1;
1185                 }
1186         }
1187         */
1188
1189         return true;
1190 }
1191
1192
1193 static void _Datagram_SearchForHosts (qboolean xmit)
1194 {
1195         int             ret;
1196         struct qsockaddr readaddr;
1197
1198         if (xmit)
1199         {
1200                 SZ_Clear(&net_message);
1201                 // save space for the header, filled in later
1202                 MSG_WriteLong(&net_message, 0);
1203                 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
1204                 MSG_WriteString(&net_message, "QUAKE");
1205                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1206                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1207                 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
1208                 SZ_Clear(&net_message);
1209         }
1210
1211         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1212         {
1213                 net_message.cursize = ret;
1214                 Datagram_HandleServerInfo (&readaddr);
1215         }
1216 }
1217
1218 void Datagram_SearchForHosts (qboolean xmit)
1219 {
1220         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1221         {
1222                 if (hostCacheCount == HOSTCACHESIZE)
1223                         break;
1224                 if (net_landrivers[net_landriverlevel].initialized)
1225                         _Datagram_SearchForHosts (xmit);
1226         }
1227 }
1228
1229
1230 static qboolean _Datagram_SearchForInetHosts (const char *master)
1231 {
1232         qboolean result = false;
1233         struct qsockaddr masteraddr;
1234         struct qsockaddr readaddr;
1235         int ret;
1236
1237         if (master)
1238         {
1239                 if (dfunc.GetAddrFromName(master, &masteraddr) != -1)
1240                 {
1241                         int portnum = 0;
1242                         const char* port = strrchr (master, ':');
1243                         if (port)
1244                                 portnum = atoi (port + 1);
1245                         if (!portnum)
1246                                 portnum = MASTER_PORT;
1247                         Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s port %i\n", net_message.cursize, master, portnum);
1248                         dfunc.SetSocketPort (&masteraddr, portnum);
1249                         dfunc.Write (dfunc.controlSock, net_message.data, net_message.cursize, &masteraddr);
1250                 }
1251         }
1252
1253         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
1254         {
1255                 net_message.cursize = ret;
1256                 Con_DPrintf("Datagram_SearchForInetHosts: Read received %d byte message\n", net_message.cursize);
1257                 if (Datagram_HandleServerInfo (&readaddr))
1258                         result = true;
1259                 else
1260                         Master_ParseServerList (&dfunc);
1261         }
1262
1263         return result;
1264 }
1265
1266
1267 qboolean Datagram_SearchForInetHosts (const char *master)
1268 {
1269         qboolean result = false;
1270         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1271         {
1272                 if (hostCacheCount == HOSTCACHESIZE)
1273                         break;
1274                 if (net_landrivers[net_landriverlevel].initialized)
1275                         if (_Datagram_SearchForInetHosts (master))
1276                                 result = true;
1277         }
1278
1279         return result;
1280 }
1281
1282
1283 static qsocket_t *_Datagram_Connect (const char *host)
1284 {
1285         struct qsockaddr sendaddr;
1286         struct qsockaddr readaddr;
1287         struct qsockaddr testaddr;
1288         qsocket_t       *sock;
1289         int                     newsock;
1290         int                     ret;
1291         int                     reps;
1292         double          start_time;
1293         int                     control;
1294         char            *reason;
1295
1296         // see if we can resolve the host name
1297         if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
1298                 return NULL;
1299
1300         newsock = dfunc.OpenSocket (cl_port.integer);
1301         if (newsock == -1)
1302                 return NULL;
1303
1304         sock = NET_NewQSocket ();
1305         if (sock == NULL)
1306                 goto ErrorReturn2;
1307         sock->socket = newsock;
1308         sock->landriver = net_landriverlevel;
1309
1310         // connect to the host
1311         if (dfunc.Connect (newsock, &sendaddr) == -1)
1312                 goto ErrorReturn;
1313
1314         // send the connection request
1315         Con_Printf("trying...\n");CL_UpdateScreen();CL_UpdateScreen();
1316         start_time = net_time;
1317
1318         for (reps = 0; reps < 3; reps++)
1319         {
1320                 SZ_Clear(&net_message);
1321                 // save space for the header, filled in later
1322                 MSG_WriteLong(&net_message, 0);
1323                 MSG_WriteByte(&net_message, CCREQ_CONNECT);
1324                 MSG_WriteString(&net_message, "QUAKE");
1325                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
1326                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
1327                 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
1328                 SZ_Clear(&net_message);
1329                 do
1330                 {
1331                         ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
1332                         // if we got something, validate it
1333                         if (ret > 0)
1334                         {
1335                                 // is it from the right place?
1336                                 // we don't care if the port matches (this adds support for
1337                                 // the NAT fix in the server inspired by faded)
1338                                 memcpy(&testaddr, &sendaddr, sizeof(struct qsockaddr));
1339                                 dfunc.SetSocketPort (&testaddr, dfunc.GetSocketPort(&readaddr));
1340                                 if (sfunc.AddrCompare(&readaddr, &testaddr) != 0)
1341                                 {
1342                                         Con_Printf("wrong reply address\n");
1343                                         Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
1344                                         Con_Printf("Received: %s\n", StrAddr (&readaddr));
1345                                         CL_UpdateScreen ();
1346                                         CL_UpdateScreen ();
1347                                         ret = 0;
1348                                         continue;
1349                                 }
1350
1351                                 if (ret < (int)sizeof(int))
1352                                 {
1353                                         ret = 0;
1354                                         continue;
1355                                 }
1356
1357                                 net_message.cursize = ret;
1358                                 MSG_BeginReading ();
1359
1360                                 control = BigLong(*((int *)net_message.data));
1361                                 MSG_ReadLong();
1362                                 if (control == -1)
1363                                 {
1364                                         ret = 0;
1365                                         continue;
1366                                 }
1367                                 if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
1368                                 {
1369                                         ret = 0;
1370                                         continue;
1371                                 }
1372                                 if ((control & NETFLAG_LENGTH_MASK) != ret)
1373                                 {
1374                                         ret = 0;
1375                                         continue;
1376                                 }
1377                         }
1378                 }
1379                 while (ret == 0 && (SetNetTime() - start_time) < 2.5);
1380                 if (ret)
1381                         break;
1382                 Con_Printf("still trying...\n");CL_UpdateScreen();CL_UpdateScreen();
1383                 start_time = SetNetTime();
1384         }
1385
1386         if (ret == 0)
1387         {
1388                 reason = "No Response";
1389                 Con_Printf("%s\n", reason);
1390                 strcpy(m_return_reason, reason);
1391                 goto ErrorReturn;
1392         }
1393
1394         if (ret == -1)
1395         {
1396                 reason = "Network Error";
1397                 Con_Printf("%s\n", reason);
1398                 strcpy(m_return_reason, reason);
1399                 goto ErrorReturn;
1400         }
1401
1402         ret = MSG_ReadByte();
1403         if (ret == CCREP_REJECT)
1404         {
1405                 reason = MSG_ReadString();
1406                 Con_Printf("%s", reason);
1407                 strncpy(m_return_reason, reason, 31);
1408                 goto ErrorReturn;
1409         }
1410
1411         if (ret == CCREP_ACCEPT)
1412         {
1413                 memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
1414                 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
1415         }
1416         else
1417         {
1418                 reason = "Bad Response";
1419                 Con_Printf("%s\n", reason);
1420                 strcpy(m_return_reason, reason);
1421                 goto ErrorReturn;
1422         }
1423
1424         dfunc.GetNameFromAddr (&sendaddr, sock->address);
1425
1426         Con_Printf ("Connection accepted to %s\n", sock->address);
1427         sock->lastMessageTime = SetNetTime();
1428
1429         // switch the connection to the specified address
1430         if (dfunc.Connect (newsock, &sock->addr) == -1)
1431         {
1432                 reason = "Connect to Game failed";
1433                 Con_Printf("%s\n", reason);
1434                 strcpy(m_return_reason, reason);
1435                 goto ErrorReturn;
1436         }
1437
1438         m_return_onerror = false;
1439         return sock;
1440
1441 ErrorReturn:
1442         NET_FreeQSocket(sock);
1443 ErrorReturn2:
1444         dfunc.CloseSocket(newsock);
1445         if (m_return_onerror)
1446         {
1447                 key_dest = key_menu;
1448                 m_state = m_return_state;
1449                 m_return_onerror = false;
1450         }
1451         return NULL;
1452 }
1453
1454 qsocket_t *Datagram_Connect (const char *host)
1455 {
1456         qsocket_t *ret = NULL;
1457
1458         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1459                 if (net_landrivers[net_landriverlevel].initialized)
1460                         if ((ret = _Datagram_Connect (host)) != NULL)
1461                                 break;
1462         return ret;
1463 }
1464
1465 static void _Datagram_Heartbeat (const char *master)
1466 {
1467         struct qsockaddr masteraddr;
1468         int portnum;
1469         const char* port;
1470
1471         if (dfunc.GetAddrFromName(master, &masteraddr) == -1)
1472                 return;
1473
1474         portnum = 0;
1475         port = strrchr (master, ':');
1476         if (port)
1477                 portnum = atoi (port + 1);
1478         if (!portnum)
1479                 portnum = MASTER_PORT;
1480         dfunc.SetSocketPort (&masteraddr, portnum);
1481
1482         // FIXME: this is the only use of UDP_Send in the entire engine, add a dfunc.acceptSock to get rid of this function!
1483         dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
1484 }
1485
1486 void Datagram_Heartbeat (const char *master)
1487 {
1488         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
1489                 if (net_landrivers[net_landriverlevel].initialized)
1490                         _Datagram_Heartbeat (master);
1491 }