Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 (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. PollProcedure   testPollProcedure = {NULL, 0.0, Test_Poll};
  521.  
  522. static void Test_Poll(void)
  523. {
  524.         struct qsockaddr clientaddr;
  525.         int             control;
  526.         int             len;
  527.         char    name[32];
  528.         char    address[64];
  529.         int             colors;
  530.         int             frags;
  531.         int             connectTime;
  532.         byte    playerNumber;
  533.  
  534.         net_landriverlevel = testDriver;
  535.  
  536.         while (1)
  537.         {
  538.                 len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
  539.                 if (len < sizeof(int))
  540.                         break;
  541.  
  542.                 net_message.cursize = len;
  543.  
  544.                 MSG_BeginReading ();
  545.                 control = BigLong(*((int *)net_message.data));
  546.                 MSG_ReadLong();
  547.                 if (control == -1)
  548.                         break;
  549.                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
  550.                         break;
  551.                 if ((control & NETFLAG_LENGTH_MASK) != len)
  552.                         break;
  553.  
  554.                 if (MSG_ReadByte() != CCREP_PLAYER_INFO)
  555.                         Sys_Error("Unexpected repsonse to Player Info request\n");
  556.  
  557.                 playerNumber = MSG_ReadByte();
  558.                 Q_strcpy(name, MSG_ReadString());
  559.                 colors = MSG_ReadLong();
  560.                 frags = MSG_ReadLong();
  561.                 connectTime = MSG_ReadLong();
  562.                 Q_strcpy(address, MSG_ReadString());
  563.  
  564.                 Con_Printf("%s\n  frags:%3i  colors:%u %u  time:%u\n  %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address);
  565.         }
  566.  
  567.         testPollCount--;
  568.         if (testPollCount)
  569.         {
  570.                 SchedulePollProcedure(&testPollProcedure, 0.1);
  571.         }
  572.         else
  573.         {
  574.                 dfunc.CloseSocket(testSocket);
  575.                 testInProgress = false;
  576.         }
  577. }
  578.  
  579. static void Test_f (void)
  580. {
  581.         char    *host;
  582.         int             n;
  583.         int             max = MAX_SCOREBOARD;
  584.         struct qsockaddr sendaddr;
  585.  
  586.         if (testInProgress)
  587.                 return;
  588.  
  589.         host = Cmd_Argv (1);
  590.  
  591.         if (host && hostCacheCount)
  592.         {
  593.                 for (n = 0; n < hostCacheCount; n++)
  594.                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
  595.                         {
  596.                                 if (hostcache[n].driver != myDriverLevel)
  597.                                         continue;
  598.                                 net_landriverlevel = hostcache[n].ldriver;
  599.                                 max = hostcache[n].maxusers;
  600.                                 Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
  601.                                 break;
  602.                         }
  603.                 if (n < hostCacheCount)
  604.                         goto JustDoIt;
  605.         }
  606.  
  607.         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
  608.         {
  609.                 if (!net_landrivers[net_landriverlevel].initialized)
  610.                         continue;
  611.  
  612.                 // see if we can resolve the host name
  613.                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
  614.                         break;
  615.         }
  616.         if (net_landriverlevel == net_numlandrivers)
  617.                 return;
  618.  
  619. JustDoIt:
  620.         testSocket = dfunc.OpenSocket(0);
  621.         if (testSocket == -1)
  622.                 return;
  623.  
  624.         testInProgress = true;
  625.         testPollCount = 20;
  626.         testDriver = net_landriverlevel;
  627.  
  628.         for (n = 0; n < max; n++)
  629.         {
  630.                 SZ_Clear(&net_message);
  631.                 // save space for the header, filled in later
  632.                 MSG_WriteLong(&net_message, 0);
  633.                 MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
  634.                 MSG_WriteByte(&net_message, n);
  635.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL |      (net_message.cursize & NETFLAG_LENGTH_MASK));
  636.                 dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr);
  637.         }
  638.         SZ_Clear(&net_message);
  639.         SchedulePollProcedure(&testPollProcedure, 0.1);
  640. }
  641.  
  642.  
  643. static qboolean test2InProgress = false;
  644. static int              test2Driver;
  645. static int              test2Socket;
  646.  
  647. static void Test2_Poll(void);
  648. PollProcedure   test2PollProcedure = {NULL, 0.0, Test2_Poll};
  649.  
  650. static void Test2_Poll(void)
  651. {
  652.         struct qsockaddr clientaddr;
  653.         int             control;
  654.         int             len;
  655.         char    name[256];
  656.         char    value[256];
  657.  
  658.         net_landriverlevel = test2Driver;
  659.         name[0] = 0;
  660.  
  661.         len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
  662.         if (len < sizeof(int))
  663.                 goto Reschedule;
  664.  
  665.         net_message.cursize = len;
  666.  
  667.         MSG_BeginReading ();
  668.         control = BigLong(*((int *)net_message.data));
  669.         MSG_ReadLong();
  670.         if (control == -1)
  671.                 goto Error;
  672.         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
  673.                 goto Error;
  674.         if ((control & NETFLAG_LENGTH_MASK) != len)
  675.                 goto Error;
  676.  
  677.         if (MSG_ReadByte() != CCREP_RULE_INFO)
  678.                 goto Error;
  679.  
  680.         Q_strcpy(name, MSG_ReadString());
  681.         if (name[0] == 0)
  682.                 goto Done;
  683.         Q_strcpy(value, MSG_ReadString());
  684.  
  685.         Con_Printf("%-16.16s  %-16.16s\n", name, value);
  686.  
  687.         SZ_Clear(&net_message);
  688.         // save space for the header, filled in later
  689.         MSG_WriteLong(&net_message, 0);
  690.         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
  691.         MSG_WriteString(&net_message, name);
  692.         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  693.         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr);
  694.         SZ_Clear(&net_message);
  695.  
  696. Reschedule:
  697.         SchedulePollProcedure(&test2PollProcedure, 0.05);
  698.         return;
  699.  
  700. Error:
  701.         Con_Printf("Unexpected repsonse to Rule Info request\n");
  702. Done:
  703.         dfunc.CloseSocket(test2Socket);
  704.         test2InProgress = false;
  705.         return;
  706. }
  707.  
  708. static void Test2_f (void)
  709. {
  710.         char    *host;
  711.         int             n;
  712.         struct qsockaddr sendaddr;
  713.  
  714.         if (test2InProgress)
  715.                 return;
  716.  
  717.         host = Cmd_Argv (1);
  718.  
  719.         if (host && hostCacheCount)
  720.         {
  721.                 for (n = 0; n < hostCacheCount; n++)
  722.                         if (Q_strcasecmp (host, hostcache[n].name) == 0)
  723.                         {
  724.                                 if (hostcache[n].driver != myDriverLevel)
  725.                                         continue;
  726.                                 net_landriverlevel = hostcache[n].ldriver;
  727.                                 Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
  728.                                 break;
  729.                         }
  730.                 if (n < hostCacheCount)
  731.                         goto JustDoIt;
  732.         }
  733.  
  734.         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
  735.         {
  736.                 if (!net_landrivers[net_landriverlevel].initialized)
  737.                         continue;
  738.  
  739.                 // see if we can resolve the host name
  740.                 if (dfunc.GetAddrFromName(host, &sendaddr) != -1)
  741.                         break;
  742.         }
  743.         if (net_landriverlevel == net_numlandrivers)
  744.                 return;
  745.  
  746. JustDoIt:
  747.         test2Socket = dfunc.OpenSocket(0);
  748.         if (test2Socket == -1)
  749.                 return;
  750.  
  751.         test2InProgress = true;
  752.         test2Driver = net_landriverlevel;
  753.  
  754.         SZ_Clear(&net_message);
  755.         // save space for the header, filled in later
  756.         MSG_WriteLong(&net_message, 0);
  757.         MSG_WriteByte(&net_message, CCREQ_RULE_INFO);
  758.         MSG_WriteString(&net_message, "");
  759.         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  760.         dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr);
  761.         SZ_Clear(&net_message);
  762.         SchedulePollProcedure(&test2PollProcedure, 0.05);
  763. }
  764.  
  765.  
  766. int Datagram_Init (void)
  767. {
  768.         int i;
  769.         int csock;
  770.  
  771.         myDriverLevel = net_driverlevel;
  772.         Cmd_AddCommand ("net_stats", NET_Stats_f);
  773.  
  774.         if (COM_CheckParm("-nolan"))
  775.                 return -1;
  776.  
  777.         for (i = 0; i < net_numlandrivers; i++)
  778.                 {
  779.                 csock = net_landrivers[i].Init ();
  780.                 if (csock == -1)
  781.                         continue;
  782.                 net_landrivers[i].initialized = true;
  783.                 net_landrivers[i].controlSock = csock;
  784.                 }
  785.  
  786. #ifdef BAN_TEST
  787.         Cmd_AddCommand ("ban", NET_Ban_f);
  788. #endif
  789.         Cmd_AddCommand ("test", Test_f);
  790.         Cmd_AddCommand ("test2", Test2_f);
  791.  
  792.         return 0;
  793. }
  794.  
  795.  
  796. void Datagram_Shutdown (void)
  797. {
  798.         int i;
  799.  
  800. //
  801. // shutdown the lan drivers
  802. //
  803.         for (i = 0; i < net_numlandrivers; i++)
  804.         {
  805.                 if (net_landrivers[i].initialized)
  806.                 {
  807.                         net_landrivers[i].Shutdown ();
  808.                         net_landrivers[i].initialized = false;
  809.                 }
  810.         }
  811. }
  812.  
  813.  
  814. void Datagram_Close (qsocket_t *sock)
  815. {
  816.         sfunc.CloseSocket(sock->socket);
  817. }
  818.  
  819.  
  820. void Datagram_Listen (qboolean state)
  821. {
  822.         int i;
  823.  
  824.         for (i = 0; i < net_numlandrivers; i++)
  825.                 if (net_landrivers[i].initialized)
  826.                         net_landrivers[i].Listen (state);
  827. }
  828.  
  829.  
  830. static qsocket_t *_Datagram_CheckNewConnections (void)
  831. {
  832.         struct qsockaddr clientaddr;
  833.         struct qsockaddr newaddr;
  834.         int                     newsock;
  835.         int                     acceptsock;
  836.         qsocket_t       *sock;
  837.         qsocket_t       *s;
  838.         int                     len;
  839.         int                     command;
  840.         int                     control;
  841.         int                     ret;
  842.  
  843.         acceptsock = dfunc.CheckNewConnections();
  844.         if (acceptsock == -1)
  845.                 return NULL;
  846.  
  847.         SZ_Clear(&net_message);
  848.  
  849.         len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
  850.         if (len < sizeof(int))
  851.                 return NULL;
  852.         net_message.cursize = len;
  853.  
  854.         MSG_BeginReading ();
  855.         control = BigLong(*((int *)net_message.data));
  856.         MSG_ReadLong();
  857.         if (control == -1)
  858.                 return NULL;
  859.         if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
  860.                 return NULL;
  861.         if ((control & NETFLAG_LENGTH_MASK) != len)
  862.                 return NULL;
  863.  
  864.         command = MSG_ReadByte();
  865.         if (command == CCREQ_SERVER_INFO)
  866.         {
  867.                 if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
  868.                         return NULL;
  869.  
  870.                 SZ_Clear(&net_message);
  871.                 // save space for the header, filled in later
  872.                 MSG_WriteLong(&net_message, 0);
  873.                 MSG_WriteByte(&net_message, CCREP_SERVER_INFO);
  874.                 dfunc.GetSocketAddr(acceptsock, &newaddr);
  875.                 MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
  876.                 MSG_WriteString(&net_message, hostname.string);
  877.                 MSG_WriteString(&net_message, sv.name);
  878.                 MSG_WriteByte(&net_message, net_activeconnections);
  879.                 MSG_WriteByte(&net_message, svs.maxclients);
  880.                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
  881.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  882.                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  883.                 SZ_Clear(&net_message);
  884.                 return NULL;
  885.         }
  886.  
  887.         if (command == CCREQ_PLAYER_INFO)
  888.         {
  889.                 int                     playerNumber;
  890.                 int                     activeNumber;
  891.                 int                     clientNumber;
  892.                 client_t        *client;
  893.                
  894.                 playerNumber = MSG_ReadByte();
  895.                 activeNumber = -1;
  896.                 for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++)
  897.                 {
  898.                         if (client->active)
  899.                         {
  900.                                 activeNumber++;
  901.                                 if (activeNumber == playerNumber)
  902.                                         break;
  903.                         }
  904.                 }
  905.                 if (clientNumber == svs.maxclients)
  906.                         return NULL;
  907.  
  908.                 SZ_Clear(&net_message);
  909.                 // save space for the header, filled in later
  910.                 MSG_WriteLong(&net_message, 0);
  911.                 MSG_WriteByte(&net_message, CCREP_PLAYER_INFO);
  912.                 MSG_WriteByte(&net_message, playerNumber);
  913.                 MSG_WriteString(&net_message, client->name);
  914.                 MSG_WriteLong(&net_message, client->colors);
  915.                 MSG_WriteLong(&net_message, (int)client->edict->v.frags);
  916.                 MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime));
  917.                 MSG_WriteString(&net_message, client->netconnection->address);
  918.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  919.                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  920.                 SZ_Clear(&net_message);
  921.  
  922.                 return NULL;
  923.         }
  924.  
  925.         if (command == CCREQ_RULE_INFO)
  926.         {
  927.                 char    *prevCvarName;
  928.                 cvar_t  *var;
  929.  
  930.                 // find the search start location
  931.                 prevCvarName = MSG_ReadString();
  932.                 if (*prevCvarName)
  933.                 {
  934.                         var = Cvar_FindVar (prevCvarName);
  935.                         if (!var)
  936.                                 return NULL;
  937.                         var = var->next;
  938.                 }
  939.                 else
  940.                         var = cvar_vars;
  941.  
  942.                 // search for the next server cvar
  943.                 while (var)
  944.                 {
  945.                         if (var->server)
  946.                                 break;
  947.                         var = var->next;
  948.                 }
  949.  
  950.                 // send the response
  951.  
  952.                 SZ_Clear(&net_message);
  953.                 // save space for the header, filled in later
  954.                 MSG_WriteLong(&net_message, 0);
  955.                 MSG_WriteByte(&net_message, CCREP_RULE_INFO);
  956.                 if (var)
  957.                 {
  958.                         MSG_WriteString(&net_message, var->name);
  959.                         MSG_WriteString(&net_message, var->string);
  960.                 }
  961.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  962.                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  963.                 SZ_Clear(&net_message);
  964.  
  965.                 return NULL;
  966.         }
  967.  
  968.         if (command != CCREQ_CONNECT)
  969.                 return NULL;
  970.  
  971.         if (Q_strcmp(MSG_ReadString(), "QUAKE") != 0)
  972.                 return NULL;
  973.  
  974.         if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
  975.         {
  976.                 SZ_Clear(&net_message);
  977.                 // save space for the header, filled in later
  978.                 MSG_WriteLong(&net_message, 0);
  979.                 MSG_WriteByte(&net_message, CCREP_REJECT);
  980.                 MSG_WriteString(&net_message, "Incompatible version.\n");
  981.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  982.                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  983.                 SZ_Clear(&net_message);
  984.                 return NULL;
  985.         }
  986.  
  987. #ifdef BAN_TEST
  988.         // check for a ban
  989.         if (clientaddr.sa_family == AF_INET)
  990.         {
  991.                 unsigned long testAddr;
  992.                 testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr;
  993.                 if ((testAddr & banMask) == banAddr)
  994.                 {
  995.                         SZ_Clear(&net_message);
  996.                         // save space for the header, filled in later
  997.                         MSG_WriteLong(&net_message, 0);
  998.                         MSG_WriteByte(&net_message, CCREP_REJECT);
  999.                         MSG_WriteString(&net_message, "You have been banned.\n");
  1000.                         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  1001.                         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  1002.                         SZ_Clear(&net_message);
  1003.                         return NULL;
  1004.                 }
  1005.         }
  1006. #endif
  1007.  
  1008.         // see if this guy is already connected
  1009.         for (s = net_activeSockets; s; s = s->next)
  1010.         {
  1011.                 if (s->driver != net_driverlevel)
  1012.                         continue;
  1013.                 ret = dfunc.AddrCompare(&clientaddr, &s->addr);
  1014.                 if (ret >= 0)
  1015.                 {
  1016.                         // is this a duplicate connection reqeust?
  1017.                         if (ret == 0 && net_time - s->connecttime < 2.0)
  1018.                         {
  1019.                                 // yes, so send a duplicate reply
  1020.                                 SZ_Clear(&net_message);
  1021.                                 // save space for the header, filled in later
  1022.                                 MSG_WriteLong(&net_message, 0);
  1023.                                 MSG_WriteByte(&net_message, CCREP_ACCEPT);
  1024.                                 dfunc.GetSocketAddr(s->socket, &newaddr);
  1025.                                 MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
  1026.                                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  1027.                                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  1028.                                 SZ_Clear(&net_message);
  1029.                                 return NULL;
  1030.                         }
  1031.                         // it's somebody coming back in from a crash/disconnect
  1032.                         // so close the old qsocket and let their retry get them back in
  1033.                         NET_Close(s);
  1034.                         return NULL;
  1035.                 }
  1036.         }
  1037.  
  1038.         // allocate a QSocket
  1039.         sock = NET_NewQSocket ();
  1040.         if (sock == NULL)
  1041.         {
  1042.                 // no room; try to let him know
  1043.                 SZ_Clear(&net_message);
  1044.                 // save space for the header, filled in later
  1045.                 MSG_WriteLong(&net_message, 0);
  1046.                 MSG_WriteByte(&net_message, CCREP_REJECT);
  1047.                 MSG_WriteString(&net_message, "Server is full.\n");
  1048.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  1049.                 dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  1050.                 SZ_Clear(&net_message);
  1051.                 return NULL;
  1052.         }
  1053.  
  1054.         // allocate a network socket
  1055.         newsock = dfunc.OpenSocket(0);
  1056.         if (newsock == -1)
  1057.         {
  1058.                 NET_FreeQSocket(sock);
  1059.                 return NULL;
  1060.         }
  1061.  
  1062.         // connect to the client
  1063.         if (dfunc.Connect (newsock, &clientaddr) == -1)
  1064.         {
  1065.                 dfunc.CloseSocket(newsock);
  1066.                 NET_FreeQSocket(sock);
  1067.                 return NULL;
  1068.         }
  1069.  
  1070.         // everything is allocated, just fill in the details   
  1071.         sock->socket = newsock;
  1072.         sock->landriver = net_landriverlevel;
  1073.         sock->addr = clientaddr;
  1074.         Q_strcpy(sock->address, dfunc.AddrToString(&clientaddr));
  1075.  
  1076.         // send him back the info about the server connection he has been allocated
  1077.         SZ_Clear(&net_message);
  1078.         // save space for the header, filled in later
  1079.         MSG_WriteLong(&net_message, 0);
  1080.         MSG_WriteByte(&net_message, CCREP_ACCEPT);
  1081.         dfunc.GetSocketAddr(newsock, &newaddr);
  1082.         MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
  1083. //      MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr));
  1084.         *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  1085.         dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
  1086.         SZ_Clear(&net_message);
  1087.  
  1088.         return sock;
  1089. }
  1090.  
  1091. qsocket_t *Datagram_CheckNewConnections (void)
  1092. {
  1093.         qsocket_t *ret = NULL;
  1094.  
  1095.         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
  1096.                 if (net_landrivers[net_landriverlevel].initialized)
  1097.                         if ((ret = _Datagram_CheckNewConnections ()) != NULL)
  1098.                                 break;
  1099.         return ret;
  1100. }
  1101.  
  1102.  
  1103. static void _Datagram_SearchForHosts (qboolean xmit)
  1104. {
  1105.         int             ret;
  1106.         int             n;
  1107.         int             i;
  1108.         struct qsockaddr readaddr;
  1109.         struct qsockaddr myaddr;
  1110.         int             control;
  1111.  
  1112.         dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
  1113.         if (xmit)
  1114.         {
  1115.                 SZ_Clear(&net_message);
  1116.                 // save space for the header, filled in later
  1117.                 MSG_WriteLong(&net_message, 0);
  1118.                 MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
  1119.                 MSG_WriteString(&net_message, "QUAKE");
  1120.                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
  1121.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  1122.                 dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
  1123.                 SZ_Clear(&net_message);
  1124.         }
  1125.  
  1126.         while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
  1127.         {
  1128.                 if (ret < sizeof(int))
  1129.                         continue;
  1130.                 net_message.cursize = ret;
  1131.  
  1132.                 // don't answer our own query
  1133.                 if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0)
  1134.                         continue;
  1135.  
  1136.                 // is the cache full?
  1137.                 if (hostCacheCount == HOSTCACHESIZE)
  1138.                         continue;
  1139.  
  1140.                 MSG_BeginReading ();
  1141.                 control = BigLong(*((int *)net_message.data));
  1142.                 MSG_ReadLong();
  1143.                 if (control == -1)
  1144.                         continue;
  1145.                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
  1146.                         continue;
  1147.                 if ((control & NETFLAG_LENGTH_MASK) != ret)
  1148.                         continue;
  1149.  
  1150.                 if (MSG_ReadByte() != CCREP_SERVER_INFO)
  1151.                         continue;
  1152.  
  1153.                 dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
  1154.                 // search the cache for this server
  1155.                 for (n = 0; n < hostCacheCount; n++)
  1156.                         if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0)
  1157.                                 break;
  1158.  
  1159.                 // is it already there?
  1160.                 if (n < hostCacheCount)
  1161.                         continue;
  1162.  
  1163.                 // add it
  1164.                 hostCacheCount++;
  1165.                 Q_strcpy(hostcache[n].name, MSG_ReadString());
  1166.                 Q_strcpy(hostcache[n].map, MSG_ReadString());
  1167.                 hostcache[n].users = MSG_ReadByte();
  1168.                 hostcache[n].maxusers = MSG_ReadByte();
  1169.                 if (MSG_ReadByte() != NET_PROTOCOL_VERSION)
  1170.                 {
  1171.                         Q_strcpy(hostcache[n].cname, hostcache[n].name);
  1172.                         hostcache[n].cname[14] = 0;
  1173.                         Q_strcpy(hostcache[n].name, "*");
  1174.                         Q_strcat(hostcache[n].name, hostcache[n].cname);
  1175.                 }
  1176.                 Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
  1177.                 hostcache[n].driver = net_driverlevel;
  1178.                 hostcache[n].ldriver = net_landriverlevel;
  1179.                 Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));
  1180.  
  1181.                 // check for a name conflict
  1182.                 for (i = 0; i < hostCacheCount; i++)
  1183.                 {
  1184.                         if (i == n)
  1185.                                 continue;
  1186.                         if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
  1187.                         {
  1188.                                 i = Q_strlen(hostcache[n].name);
  1189.                                 if (i < 15 && hostcache[n].name[i-1] > '8')
  1190.                                 {
  1191.                                         hostcache[n].name[i] = '0';
  1192.                                         hostcache[n].name[i+1] = 0;
  1193.                                 }
  1194.                                 else
  1195.                                         hostcache[n].name[i-1]++;
  1196.                                 i = -1;
  1197.                         }
  1198.                 }
  1199.         }
  1200. }
  1201.  
  1202. void Datagram_SearchForHosts (qboolean xmit)
  1203. {
  1204.         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
  1205.         {
  1206.                 if (hostCacheCount == HOSTCACHESIZE)
  1207.                         break;
  1208.                 if (net_landrivers[net_landriverlevel].initialized)
  1209.                         _Datagram_SearchForHosts (xmit);
  1210.         }
  1211. }
  1212.  
  1213.  
  1214. static qsocket_t *_Datagram_Connect (char *host)
  1215. {
  1216.         struct qsockaddr sendaddr;
  1217.         struct qsockaddr readaddr;
  1218.         qsocket_t       *sock;
  1219.         int                     newsock;
  1220.         int                     ret;
  1221.         int                     reps;
  1222.         double          start_time;
  1223.         int                     control;
  1224.         char            *reason;
  1225.  
  1226.         // see if we can resolve the host name
  1227.         if (dfunc.GetAddrFromName(host, &sendaddr) == -1)
  1228.                 return NULL;
  1229.  
  1230.         newsock = dfunc.OpenSocket (0);
  1231.         if (newsock == -1)
  1232.                 return NULL;
  1233.  
  1234.         sock = NET_NewQSocket ();
  1235.         if (sock == NULL)
  1236.                 goto ErrorReturn2;
  1237.         sock->socket = newsock;
  1238.         sock->landriver = net_landriverlevel;
  1239.  
  1240.         // connect to the host
  1241.         if (dfunc.Connect (newsock, &sendaddr) == -1)
  1242.                 goto ErrorReturn;
  1243.  
  1244.         // send the connection request
  1245.         Con_Printf("trying...\n"); SCR_UpdateScreen ();
  1246.         start_time = net_time;
  1247.  
  1248.         for (reps = 0; reps < 3; reps++)
  1249.         {
  1250.                 SZ_Clear(&net_message);
  1251.                 // save space for the header, filled in later
  1252.                 MSG_WriteLong(&net_message, 0);
  1253.                 MSG_WriteByte(&net_message, CCREQ_CONNECT);
  1254.                 MSG_WriteString(&net_message, "QUAKE");
  1255.                 MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
  1256.                 *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
  1257.                 dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr);
  1258.                 SZ_Clear(&net_message);
  1259.                 do
  1260.                 {
  1261.                         ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr);
  1262.                         // if we got something, validate it
  1263.                         if (ret > 0)
  1264.                         {
  1265.                                 // is it from the right place?
  1266.                                 if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
  1267.                                 {
  1268. #ifdef DEBUG
  1269.                                         Con_Printf("wrong reply address\n");
  1270.                                         Con_Printf("Expected: %s\n", StrAddr (&sendaddr));
  1271.                                         Con_Printf("Received: %s\n", StrAddr (&readaddr));
  1272.                                         SCR_UpdateScreen ();
  1273. #endif
  1274.                                         ret = 0;
  1275.                                         continue;
  1276.                                 }
  1277.  
  1278.                                 if (ret < sizeof(int))
  1279.                                 {
  1280.                                         ret = 0;
  1281.                                         continue;
  1282.                                 }
  1283.  
  1284.                                 net_message.cursize = ret;
  1285.                                 MSG_BeginReading ();
  1286.  
  1287.                                 control = BigLong(*((int *)net_message.data));
  1288.                                 MSG_ReadLong();
  1289.                                 if (control == -1)
  1290.                                 {
  1291.                                         ret = 0;
  1292.                                         continue;
  1293.                                 }
  1294.                                 if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
  1295.                                 {
  1296.                                         ret = 0;
  1297.                                         continue;
  1298.                                 }
  1299.                                 if ((control & NETFLAG_LENGTH_MASK) != ret)
  1300.                                 {
  1301.                                         ret = 0;
  1302.                                         continue;
  1303.                                 }
  1304.                         }
  1305.                 }
  1306.                 while (ret == 0 && (SetNetTime() - start_time) < 2.5);
  1307.                 if (ret)
  1308.                         break;
  1309.                 Con_Printf("still trying...\n"); SCR_UpdateScreen ();
  1310.                 start_time = SetNetTime();
  1311.         }
  1312.  
  1313.         if (ret == 0)
  1314.         {
  1315.                 reason = "No Response";
  1316.                 Con_Printf("%s\n", reason);
  1317.                 Q_strcpy(m_return_reason, reason);
  1318.                 goto ErrorReturn;
  1319.         }
  1320.  
  1321.         if (ret == -1)
  1322.         {
  1323.                 reason = "Network Error";
  1324.                 Con_Printf("%s\n", reason);
  1325.                 Q_strcpy(m_return_reason, reason);
  1326.                 goto ErrorReturn;
  1327.         }
  1328.  
  1329.         ret = MSG_ReadByte();
  1330.         if (ret == CCREP_REJECT)
  1331.         {
  1332.                 reason = MSG_ReadString();
  1333.                 Con_Printf(reason);
  1334.                 Q_strncpy(m_return_reason, reason, 31);
  1335.                 goto ErrorReturn;
  1336.         }
  1337.  
  1338.         if (ret == CCREP_ACCEPT)
  1339.         {
  1340.                 Q_memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr));
  1341.                 dfunc.SetSocketPort (&sock->addr, MSG_ReadLong());
  1342.         }
  1343.         else
  1344.         {
  1345.                 reason = "Bad Response";
  1346.                 Con_Printf("%s\n", reason);
  1347.                 Q_strcpy(m_return_reason, reason);
  1348.                 goto ErrorReturn;
  1349.         }
  1350.  
  1351.         dfunc.GetNameFromAddr (&sendaddr, sock->address);
  1352.  
  1353.         Con_Printf ("Connection accepted\n");
  1354.         sock->lastMessageTime = SetNetTime();
  1355.  
  1356.         // switch the connection to the specified address
  1357.         if (dfunc.Connect (newsock, &sock->addr) == -1)
  1358.         {
  1359.                 reason = "Connect to Game failed";
  1360.                 Con_Printf("%s\n", reason);
  1361.                 Q_strcpy(m_return_reason, reason);
  1362.                 goto ErrorReturn;
  1363.         }
  1364.  
  1365.         m_return_onerror = false;
  1366.         return sock;
  1367.  
  1368. ErrorReturn:
  1369.         NET_FreeQSocket(sock);
  1370. ErrorReturn2:
  1371.         dfunc.CloseSocket(newsock);
  1372.         if (m_return_onerror)
  1373.         {
  1374.                 key_dest = key_menu;
  1375.                 m_state = m_return_state;
  1376.                 m_return_onerror = false;
  1377.         }
  1378.         return NULL;
  1379. }
  1380.  
  1381. qsocket_t *Datagram_Connect (char *host)
  1382. {
  1383.         qsocket_t *ret = NULL;
  1384.  
  1385.         for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
  1386.                 if (net_landrivers[net_landriverlevel].initialized)
  1387.                         if ((ret = _Datagram_Connect (host)) != NULL)
  1388.                                 break;
  1389.         return ret;
  1390. }
  1391.