home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / net_main.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  21KB  |  1,003 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_main.c
  21.  
  22. #include "quakedef.h"
  23. #include "net_vcr.h"
  24.  
  25. qsocket_t *net_activeSockets = NULL;
  26. qsocket_t *net_freeSockets = NULL;
  27. int     net_numsockets = 0;
  28.  
  29. qboolean  serialAvailable = false;
  30. qboolean  ipxAvailable = false;
  31. qboolean  tcpipAvailable = false;
  32.  
  33. int     net_hostport;
  34. int     DEFAULTnet_hostport = 26000;
  35.  
  36. char    my_ipx_address[NET_NAMELEN];
  37. char    my_tcpip_address[NET_NAMELEN];
  38.  
  39. void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
  40. void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
  41. void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
  42. void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
  43.  
  44. static qboolean listening = false;
  45.  
  46. qboolean  slistInProgress = false;
  47. qboolean  slistSilent = false;
  48. qboolean  slistLocal = true;
  49. static double slistStartTime;
  50. static int    slistLastShown;
  51.  
  52. static void Slist_Send(void);
  53. static void Slist_Poll(void);
  54. #ifdef __STORM__
  55. PollProcedure slistSendProcedure = {NULL, 0.0, (void *)Slist_Send};
  56. PollProcedure slistPollProcedure = {NULL, 0.0, (void *)Slist_Poll};
  57. #else
  58. PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send};
  59. PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll};
  60. #endif
  61.  
  62.  
  63. sizebuf_t   net_message;
  64. int       net_activeconnections = 0;
  65.  
  66. int messagesSent = 0;
  67. int messagesReceived = 0;
  68. int unreliableMessagesSent = 0;
  69. int unreliableMessagesReceived = 0;
  70.  
  71. cvar_t  net_messagetimeout = {"net_messagetimeout","300"};
  72. cvar_t  hostname = {"hostname", "UNNAMED"};
  73.  
  74. qboolean  configRestored = false;
  75. cvar_t  config_com_port = {"_config_com_port", "0x3f8", true};
  76. cvar_t  config_com_irq = {"_config_com_irq", "4", true};
  77. cvar_t  config_com_baud = {"_config_com_baud", "57600", true};
  78. cvar_t  config_com_modem = {"_config_com_modem", "1", true};
  79. cvar_t  config_modem_dialtype = {"_config_modem_dialtype", "T", true};
  80. cvar_t  config_modem_clear = {"_config_modem_clear", "ATZ", true};
  81. cvar_t  config_modem_init = {"_config_modem_init", "", true};
  82. cvar_t  config_modem_hangup = {"_config_modem_hangup", "AT H", true};
  83.  
  84. #ifdef IDGODS
  85. cvar_t  idgods = {"idgods", "0"};
  86. #endif
  87.  
  88. int vcrFile = -1;
  89. qboolean recording = false;
  90.  
  91. // these two macros are to make the code more readable
  92. #define sfunc net_drivers[sock->driver]
  93. #define dfunc net_drivers[net_driverlevel]
  94.  
  95. int net_driverlevel;
  96.  
  97.  
  98. double      net_time;
  99.  
  100. double SetNetTime(void)
  101. {
  102.   net_time = Sys_FloatTime();
  103.   return net_time;
  104. }
  105.  
  106.  
  107. /*
  108. ===================
  109. NET_NewQSocket
  110.  
  111. Called by drivers when a new communications endpoint is required
  112. The sequence and buffer fields will be filled in properly
  113. ===================
  114. */
  115. qsocket_t *NET_NewQSocket (void)
  116. {
  117.   qsocket_t *sock;
  118.  
  119.   if (net_freeSockets == NULL)
  120.     return NULL;
  121.  
  122.   if (net_activeconnections >= svs.maxclients)
  123.     return NULL;
  124.  
  125.   // get one from free list
  126.   sock = net_freeSockets;
  127.   net_freeSockets = sock->next;
  128.  
  129.   // add it to active list
  130.   sock->next = net_activeSockets;
  131.   net_activeSockets = sock;
  132.  
  133.   sock->disconnected = false;
  134.   sock->connecttime = net_time;
  135.   Q_strcpy (sock->address,"UNSET ADDRESS");
  136.   sock->driver = net_driverlevel;
  137.   sock->socket = 0;
  138.   sock->driverdata = NULL;
  139.   sock->canSend = true;
  140.   sock->sendNext = false;
  141.   sock->lastMessageTime = net_time;
  142.   sock->ackSequence = 0;
  143.   sock->sendSequence = 0;
  144.   sock->unreliableSendSequence = 0;
  145.   sock->sendMessageLength = 0;
  146.   sock->receiveSequence = 0;
  147.   sock->unreliableReceiveSequence = 0;
  148.   sock->receiveMessageLength = 0;
  149.  
  150.   return sock;
  151. }
  152.  
  153.  
  154. void NET_FreeQSocket(qsocket_t *sock)
  155. {
  156.   qsocket_t *s;
  157.  
  158.   // remove it from active list
  159.   if (sock == net_activeSockets)
  160.     net_activeSockets = net_activeSockets->next;
  161.   else
  162.   {
  163.     for (s = net_activeSockets; s; s = s->next)
  164.       if (s->next == sock)
  165.       {
  166.         s->next = sock->next;
  167.         break;
  168.       }
  169.     if (!s)
  170.       Sys_Error ("NET_FreeQSocket: not active\n");
  171.   }
  172.  
  173.   // add it to free list
  174.   sock->next = net_freeSockets;
  175.   net_freeSockets = sock;
  176.   sock->disconnected = true;
  177. }
  178.  
  179.  
  180. static void NET_Listen_f (void)
  181. {
  182.   if (Cmd_Argc () != 2)
  183.   {
  184.     Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0);
  185.     return;
  186.   }
  187.  
  188.   listening = Q_atoi(Cmd_Argv(1)) ? true : false;
  189.  
  190.   for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
  191.   {
  192.     if (net_drivers[net_driverlevel].initialized == false)
  193.       continue;
  194.     dfunc.Listen (listening);
  195.   }
  196. }
  197.  
  198.  
  199. static void MaxPlayers_f (void)
  200. {
  201.   int   n;
  202.  
  203.   if (Cmd_Argc () != 2)
  204.   {
  205.     Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
  206.     return;
  207.   }
  208.  
  209.   if (sv.active)
  210.   {
  211.     Con_Printf ("maxplayers can not be changed while a server is running.\n");
  212.     return;
  213.   }
  214.  
  215.   n = Q_atoi(Cmd_Argv(1));
  216.   if (n < 1)
  217.     n = 1;
  218.   if (n > svs.maxclientslimit)
  219.   {
  220.     n = svs.maxclientslimit;
  221.     Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
  222.   }
  223.  
  224.   if ((n == 1) && listening)
  225.     Cbuf_AddText ("listen 0\n");
  226.  
  227.   if ((n > 1) && (!listening))
  228.     Cbuf_AddText ("listen 1\n");
  229.  
  230.   svs.maxclients = n;
  231.   if (n == 1)
  232.     Cvar_Set ("deathmatch", "0");
  233.   else
  234.     Cvar_Set ("deathmatch", "1");
  235. }
  236.  
  237.  
  238. static void NET_Port_f (void)
  239. {
  240.   int   n;
  241.  
  242.   if (Cmd_Argc () != 2)
  243.   {
  244.     Con_Printf ("\"port\" is \"%u\"\n", net_hostport);
  245.     return;
  246.   }
  247.  
  248.   n = Q_atoi(Cmd_Argv(1));
  249.   if (n < 1 || n > 65534)
  250.   {
  251.     Con_Printf ("Bad value, must be between 1 and 65534\n");
  252.     return;
  253.   }
  254.  
  255.   DEFAULTnet_hostport = n;
  256.   net_hostport = n;
  257.  
  258.   if (listening)
  259.   {
  260.     // force a change to the new port
  261.     Cbuf_AddText ("listen 0\n");
  262.     Cbuf_AddText ("listen 1\n");
  263.   }
  264. }
  265.  
  266.  
  267. static void PrintSlistHeader(void)
  268. {
  269.   Con_Printf("Server          Map             Users\n");
  270.   Con_Printf("--------------- --------------- -----\n");
  271.   slistLastShown = 0;
  272. }
  273.  
  274.  
  275. static void PrintSlist(void)
  276. {
  277.   int n;
  278.  
  279.   for (n = slistLastShown; n < hostCacheCount; n++)
  280.   {
  281.     if (hostcache[n].maxusers)
  282.       Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
  283.     else
  284.       Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
  285.   }
  286.   slistLastShown = n;
  287. }
  288.  
  289.  
  290. static void PrintSlistTrailer(void)
  291. {
  292.   if (hostCacheCount)
  293.     Con_Printf("== end list ==\n\n");
  294.   else
  295.     Con_Printf("No Quake servers found.\n\n");
  296. }
  297.  
  298.  
  299. void NET_Slist_f (void)
  300. {
  301.   if (slistInProgress)
  302.     return;
  303.  
  304.   if (! slistSilent)
  305.   {
  306.     Con_Printf("Looking for Quake servers...\n");
  307.     PrintSlistHeader();
  308.   }
  309.  
  310.   slistInProgress = true;
  311.   slistStartTime = Sys_FloatTime();
  312.  
  313.   SchedulePollProcedure(&slistSendProcedure, 0.0);
  314.   SchedulePollProcedure(&slistPollProcedure, 0.1);
  315.  
  316.   hostCacheCount = 0;
  317. }
  318.  
  319.  
  320. static void Slist_Send(void)
  321. {
  322.   for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
  323.   {
  324.     if (!slistLocal && net_driverlevel == 0)
  325.       continue;
  326.     if (net_drivers[net_driverlevel].initialized == false)
  327.       continue;
  328.     dfunc.SearchForHosts (true);
  329.   }
  330.  
  331.   if ((Sys_FloatTime() - slistStartTime) < 0.5)
  332.     SchedulePollProcedure(&slistSendProcedure, 0.75);
  333. }
  334.  
  335.  
  336. static void Slist_Poll(void)
  337. {
  338.   for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
  339.   {
  340.     if (!slistLocal && net_driverlevel == 0)
  341.       continue;
  342.     if (net_drivers[net_driverlevel].initialized == false)
  343.       continue;
  344.     dfunc.SearchForHosts (false);
  345.   }
  346.  
  347.   if (! slistSilent)
  348.     PrintSlist();
  349.  
  350.   if ((Sys_FloatTime() - slistStartTime) < 1.5)
  351.   {
  352.     SchedulePollProcedure(&slistPollProcedure, 0.1);
  353.     return;
  354.   }
  355.  
  356.   if (! slistSilent)
  357.     PrintSlistTrailer();
  358.   slistInProgress = false;
  359.   slistSilent = false;
  360.   slistLocal = true;
  361. }
  362.  
  363.  
  364. /*
  365. ===================
  366. NET_Connect
  367. ===================
  368. */
  369.  
  370. int hostCacheCount = 0;
  371. hostcache_t hostcache[HOSTCACHESIZE];
  372.  
  373. qsocket_t *NET_Connect (char *host)
  374. {
  375.   qsocket_t   *ret;
  376.   int       n;
  377.   int       numdrivers = net_numdrivers;
  378.  
  379.   SetNetTime();
  380.  
  381.   if (host && *host == 0)
  382.     host = NULL;
  383.  
  384.   if (host)
  385.   {
  386.     if (Q_strcasecmp (host, "local") == 0)
  387.     {
  388.       numdrivers = 1;
  389.       goto JustDoIt;
  390.     }
  391.  
  392.     if (hostCacheCount)
  393.     {
  394.       for (n = 0; n < hostCacheCount; n++)
  395.         if (Q_strcasecmp (host, hostcache[n].name) == 0)
  396.         {
  397.           host = hostcache[n].cname;
  398.           break;
  399.         }
  400.       if (n < hostCacheCount)
  401.         goto JustDoIt;
  402.     }
  403.   }
  404.  
  405.   slistSilent = host ? true : false;
  406.   NET_Slist_f ();
  407.  
  408.   while(slistInProgress)
  409.     NET_Poll();
  410.  
  411.   if (host == NULL)
  412.   {
  413.     if (hostCacheCount != 1)
  414.       return NULL;
  415.     host = hostcache[0].cname;
  416.     Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
  417.   }
  418.  
  419.   if (hostCacheCount)
  420.     for (n = 0; n < hostCacheCount; n++)
  421.       if (Q_strcasecmp (host, hostcache[n].name) == 0)
  422.       {
  423.         host = hostcache[n].cname;
  424.         break;
  425.       }
  426.  
  427. JustDoIt:
  428.   for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
  429.   {
  430.     if (net_drivers[net_driverlevel].initialized == false)
  431.       continue;
  432.     ret = dfunc.Connect (host);
  433.     if (ret)
  434.       return ret;
  435.   }
  436.  
  437.   if (host)
  438.   {
  439.     Con_Printf("\n");
  440.     PrintSlistHeader();
  441.     PrintSlist();
  442.     PrintSlistTrailer();
  443.   }
  444.   
  445.   return NULL;
  446. }
  447.  
  448.  
  449. /*
  450. ===================
  451. NET_CheckNewConnections
  452. ===================
  453. */
  454.  
  455. struct
  456. {
  457.   double  time;
  458.   int   op;
  459.   long  session;
  460. } vcrConnect;
  461.  
  462. qsocket_t *NET_CheckNewConnections (void)
  463. {
  464.   qsocket_t *ret;
  465.  
  466.   SetNetTime();
  467.  
  468.   for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
  469.   {
  470.     if (net_drivers[net_driverlevel].initialized == false)
  471.       continue;
  472.     if (net_driverlevel && listening == false)
  473.       continue;
  474.     ret = dfunc.CheckNewConnections ();
  475.     if (ret)
  476.     {
  477.       if (recording)
  478.       {
  479.         vcrConnect.time = host_time;
  480.         vcrConnect.op = VCR_OP_CONNECT;
  481.         vcrConnect.session = (long)ret;
  482.         Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
  483.         Sys_FileWrite (vcrFile, ret->address, NET_NAMELEN);
  484.       }
  485.       return ret;
  486.     }
  487.   }
  488.   
  489.   if (recording)
  490.   {
  491.     vcrConnect.time = host_time;
  492.     vcrConnect.op = VCR_OP_CONNECT;
  493.     vcrConnect.session = 0;
  494.     Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
  495.   }
  496.  
  497.   return NULL;
  498. }
  499.  
  500. /*
  501. ===================
  502. NET_Close
  503. ===================
  504. */
  505. void NET_Close (qsocket_t *sock)
  506. {
  507.   if (!sock)
  508.     return;
  509.  
  510.   if (sock->disconnected)
  511.     return;
  512.  
  513.   SetNetTime();
  514.  
  515.   // call the driver_Close function
  516.   sfunc.Close (sock);
  517.  
  518.   NET_FreeQSocket(sock);
  519. }
  520.  
  521.  
  522. /*
  523. =================
  524. NET_GetMessage
  525.  
  526. If there is a complete message, return it in net_message
  527.  
  528. returns 0 if no data is waiting
  529. returns 1 if a message was received
  530. returns -1 if connection is invalid
  531. =================
  532. */
  533.  
  534. struct
  535. {
  536.   double  time;
  537.   int   op;
  538.   long  session;
  539.   int   ret;
  540.   int   len;
  541. } vcrGetMessage;
  542.  
  543. extern void PrintStats(qsocket_t *s);
  544.  
  545. int NET_GetMessage (qsocket_t *sock)
  546. {
  547.   int ret;
  548.  
  549.   if (!sock)
  550.     return -1;
  551.  
  552.   if (sock->disconnected)
  553.   {
  554.     Con_Printf("NET_GetMessage: disconnected socket\n");
  555.     return -1;
  556.   }
  557.  
  558.   SetNetTime();
  559.  
  560.   ret = sfunc.QGetMessage(sock);
  561.  
  562.   // see if this connection has timed out
  563.   if (ret == 0 && sock->driver)
  564.   {
  565.     if (net_time - sock->lastMessageTime > net_messagetimeout.value)
  566.     {
  567.       NET_Close(sock);
  568.       return -1;
  569.     }
  570.   }
  571.  
  572.  
  573.   if (ret > 0)
  574.   {
  575.     if (sock->driver)
  576.     {
  577.       sock->lastMessageTime = net_time;
  578.       if (ret == 1)
  579.         messagesReceived++;
  580.       else if (ret == 2)
  581.         unreliableMessagesReceived++;
  582.     }
  583.  
  584.     if (recording)
  585.     {
  586.       vcrGetMessage.time = host_time;
  587.       vcrGetMessage.op = VCR_OP_GETMESSAGE;
  588.       vcrGetMessage.session = (long)sock;
  589.       vcrGetMessage.ret = ret;
  590.       vcrGetMessage.len = net_message.cursize;
  591.       Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
  592.       Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
  593.     }
  594.   }
  595.   else
  596.   {
  597.     if (recording)
  598.     {
  599.       vcrGetMessage.time = host_time;
  600.       vcrGetMessage.op = VCR_OP_GETMESSAGE;
  601.       vcrGetMessage.session = (long)sock;
  602.       vcrGetMessage.ret = ret;
  603.       Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
  604.     }
  605.   }
  606.  
  607.   return ret;
  608. }
  609.  
  610.  
  611. /*
  612. ==================
  613. NET_SendMessage
  614.  
  615. Try to send a complete length+message unit over the reliable stream.
  616. returns 0 if the message cannot be delivered reliably, but the connection
  617.     is still considered valid
  618. returns 1 if the message was sent properly
  619. returns -1 if the connection died
  620. ==================
  621. */
  622. struct
  623. {
  624.   double  time;
  625.   int   op;
  626.   long  session;
  627.   int   r;
  628. } vcrSendMessage;
  629.  
  630. int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
  631. {
  632.   int   r;
  633.   
  634.   if (!sock)
  635.     return -1;
  636.  
  637.   if (sock->disconnected)
  638.   {
  639.     Con_Printf("NET_SendMessage: disconnected socket\n");
  640.     return -1;
  641.   }
  642.  
  643.   SetNetTime();
  644.   r = sfunc.QSendMessage(sock, data);
  645.   if (r == 1 && sock->driver)
  646.     messagesSent++;
  647.  
  648.   if (recording)
  649.   {
  650.     vcrSendMessage.time = host_time;
  651.     vcrSendMessage.op = VCR_OP_SENDMESSAGE;
  652.     vcrSendMessage.session = (long)sock;
  653.     vcrSendMessage.r = r;
  654.     Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  655.   }
  656.   
  657.   return r;
  658. }
  659.  
  660.  
  661. int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
  662. {
  663.   int   r;
  664.   
  665.   if (!sock)
  666.     return -1;
  667.  
  668.   if (sock->disconnected)
  669.   {
  670.     Con_Printf("NET_SendMessage: disconnected socket\n");
  671.     return -1;
  672.   }
  673.  
  674.   SetNetTime();
  675.   r = sfunc.SendUnreliableMessage(sock, data);
  676.   if (r == 1 && sock->driver)
  677.     unreliableMessagesSent++;
  678.  
  679.   if (recording)
  680.   {
  681.     vcrSendMessage.time = host_time;
  682.     vcrSendMessage.op = VCR_OP_SENDMESSAGE;
  683.     vcrSendMessage.session = (long)sock;
  684.     vcrSendMessage.r = r;
  685.     Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  686.   }
  687.   
  688.   return r;
  689. }
  690.  
  691.  
  692. /*
  693. ==================
  694. NET_CanSendMessage
  695.  
  696. Returns true or false if the given qsocket can currently accept a
  697. message to be transmitted.
  698. ==================
  699. */
  700. qboolean NET_CanSendMessage (qsocket_t *sock)
  701. {
  702.   int   r;
  703.   
  704.   if (!sock)
  705.     return false;
  706.  
  707.   if (sock->disconnected)
  708.     return false;
  709.  
  710.   SetNetTime();
  711.  
  712.   r = sfunc.CanSendMessage(sock);
  713.   
  714.   if (recording)
  715.   {
  716.     vcrSendMessage.time = host_time;
  717.     vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
  718.     vcrSendMessage.session = (long)sock;
  719.     vcrSendMessage.r = r;
  720.     Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
  721.   }
  722.   
  723.   return r;
  724. }
  725.  
  726.  
  727. int NET_SendToAll(sizebuf_t *data, int blocktime)
  728. {
  729.   double    start;
  730.   int     i;
  731.   int     count = 0;
  732.   qboolean  state1 [MAX_SCOREBOARD];
  733.   qboolean  state2 [MAX_SCOREBOARD];
  734.  
  735.   for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  736.   {
  737.     if (!host_client->netconnection)
  738.       continue;
  739.     if (host_client->active)
  740.     {
  741.       if (host_client->netconnection->driver == 0)
  742.       {
  743.         NET_SendMessage(host_client->netconnection, data);
  744.         state1[i] = true;
  745.         state2[i] = true;
  746.         continue;
  747.       }
  748.       count++;
  749.       state1[i] = false;
  750.       state2[i] = false;
  751.     }
  752.     else
  753.     {
  754.       state1[i] = true;
  755.       state2[i] = true;
  756.     }
  757.   }
  758.  
  759.   start = Sys_FloatTime();
  760.   while (count)
  761.   {
  762.     count = 0;
  763.     for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
  764.     {
  765.       if (! state1[i])
  766.       {
  767.         if (NET_CanSendMessage (host_client->netconnection))
  768.         {
  769.           state1[i] = true;
  770.           NET_SendMessage(host_client->netconnection, data);
  771.         }
  772.         else
  773.         {
  774.           NET_GetMessage (host_client->netconnection);
  775.         }
  776.         count++;
  777.         continue;
  778.       }
  779.  
  780.       if (! state2[i])
  781.       {
  782.         if (NET_CanSendMessage (host_client->netconnection))
  783.         {
  784.           state2[i] = true;
  785.         }
  786.         else
  787.         {
  788.           NET_GetMessage (host_client->netconnection);
  789.         }
  790.         count++;
  791.         continue;
  792.       }
  793.     }
  794.     if ((Sys_FloatTime() - start) > blocktime)
  795.       break;
  796.   }
  797.   return count;
  798. }
  799.  
  800.  
  801. //=============================================================================
  802.  
  803. /*
  804. ====================
  805. NET_Init
  806. ====================
  807. */
  808.  
  809. void NET_Init (void)
  810. {
  811.   int     i;
  812.   int     controlSocket;
  813.   qsocket_t *s;
  814.  
  815.   if (COM_CheckParm("-playback"))
  816.   {
  817.     net_numdrivers = 1;
  818.     net_drivers[0].Init = VCR_Init;
  819.   }
  820.  
  821.   if (COM_CheckParm("-record"))
  822.     recording = true;
  823.  
  824.   i = COM_CheckParm ("-port");
  825.   if (!i)
  826.     i = COM_CheckParm ("-udpport");
  827.   if (!i)
  828.     i = COM_CheckParm ("-ipxport");
  829.  
  830.   if (i)
  831.   {
  832.     if (i < com_argc-1)
  833.       DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
  834.     else
  835.       Sys_Error ("NET_Init: you must specify a number after -port");
  836.   }
  837.   net_hostport = DEFAULTnet_hostport;
  838.  
  839.   if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
  840.     listening = true;
  841.   net_numsockets = svs.maxclientslimit;
  842.   if (cls.state != ca_dedicated)
  843.     net_numsockets++;
  844.  
  845.   SetNetTime();
  846.  
  847.   for (i = 0; i < net_numsockets; i++)
  848.   {
  849.     s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
  850.     s->next = net_freeSockets;
  851.     net_freeSockets = s;
  852.     s->disconnected = true;
  853.   }
  854.  
  855.   // allocate space for network message buffer
  856.   SZ_Alloc (&net_message, NET_MAXMESSAGE);
  857.  
  858.   Cvar_RegisterVariable (&net_messagetimeout);
  859.   Cvar_RegisterVariable (&hostname);
  860.   Cvar_RegisterVariable (&config_com_port);
  861.   Cvar_RegisterVariable (&config_com_irq);
  862.   Cvar_RegisterVariable (&config_com_baud);
  863.   Cvar_RegisterVariable (&config_com_modem);
  864.   Cvar_RegisterVariable (&config_modem_dialtype);
  865.   Cvar_RegisterVariable (&config_modem_clear);
  866.   Cvar_RegisterVariable (&config_modem_init);
  867.   Cvar_RegisterVariable (&config_modem_hangup);
  868. #ifdef IDGODS
  869.   Cvar_RegisterVariable (&idgods);
  870. #endif
  871.  
  872.   Cmd_AddCommand ("slist", NET_Slist_f);
  873.   Cmd_AddCommand ("listen", NET_Listen_f);
  874.   Cmd_AddCommand ("maxplayers", MaxPlayers_f);
  875.   Cmd_AddCommand ("port", NET_Port_f);
  876.  
  877.   // initialize all the drivers
  878.   for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
  879.     {
  880.     controlSocket = net_drivers[net_driverlevel].Init();
  881.     if (controlSocket == -1)
  882.       continue;
  883.     net_drivers[net_driverlevel].initialized = true;
  884.     net_drivers[net_driverlevel].controlSock = controlSocket;
  885.     if (listening)
  886.       net_drivers[net_driverlevel].Listen (true);
  887.     }
  888.  
  889.   if (*my_ipx_address)
  890.     Con_DPrintf("IPX address %s\n", my_ipx_address);
  891.   if (*my_tcpip_address)
  892.     Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
  893. }
  894.  
  895. /*
  896. ====================
  897. NET_Shutdown
  898. ====================
  899. */
  900.  
  901. void    NET_Shutdown (void)
  902. {
  903.   qsocket_t *sock;
  904.  
  905.   SetNetTime();
  906.  
  907.   for (sock = net_activeSockets; sock; sock = sock->next)
  908.     NET_Close(sock);
  909.  
  910. //
  911. // shutdown the drivers
  912. //
  913.   for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
  914.   {
  915.     if (net_drivers[net_driverlevel].initialized == true)
  916.     {
  917.       net_drivers[net_driverlevel].Shutdown ();
  918.       net_drivers[net_driverlevel].initialized = false;
  919.     }
  920.   }
  921.  
  922.   if (vcrFile != -1)
  923.   {
  924.     Con_Printf ("Closing vcrfile.\n");
  925.     Sys_FileClose(vcrFile);
  926.   }
  927. }
  928.  
  929.  
  930. static PollProcedure *pollProcedureList = NULL;
  931.  
  932. void NET_Poll(void)
  933. {
  934.   PollProcedure *pp;
  935.   qboolean  useModem;
  936.  
  937.   if (!configRestored)
  938.   {
  939.     if (serialAvailable)
  940.     {
  941.       if (config_com_modem.value == 1.0)
  942.         useModem = true;
  943.       else
  944.         useModem = false;
  945.       SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
  946.       SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
  947.     }
  948.     configRestored = true;
  949.   }
  950.  
  951.   SetNetTime();
  952.  
  953.   for (pp = pollProcedureList; pp; pp = pp->next)
  954.   {
  955.     if (pp->nextTime > net_time)
  956.       break;
  957.     pollProcedureList = pp->next;
  958.     pp->procedure(pp->arg);
  959.   }
  960. }
  961.  
  962.  
  963. void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
  964. {
  965.   PollProcedure *pp, *prev;
  966.  
  967.   proc->nextTime = Sys_FloatTime() + timeOffset;
  968.   for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
  969.   {
  970.     if (pp->nextTime >= proc->nextTime)
  971.       break;
  972.     prev = pp;
  973.   }
  974.  
  975.   if (prev == NULL)
  976.   {
  977.     proc->next = pollProcedureList;
  978.     pollProcedureList = proc;
  979.     return;
  980.   }
  981.  
  982.   proc->next = pp;
  983.   prev->next = proc;
  984. }
  985.  
  986.  
  987. #ifdef IDGODS
  988. #define IDNET 0xc0f62800
  989.  
  990. qboolean IsID(struct qsockaddr *addr)
  991. {
  992.   if (idgods.value == 0.0)
  993.     return false;
  994.  
  995.   if (addr->sa_family != 2)
  996.     return false;
  997.  
  998.   if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
  999.     return true;
  1000.   return false;
  1001. }
  1002. #endif
  1003.