home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / net_dgrm.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  34.6 KB  |  1,399 lines

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