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