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_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.