summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/net_main.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-02-11 15:34:30 -0500
committerFranklin Wei <git@fwei.tk>2018-02-11 15:34:30 -0500
commit33bfba86222efb6cc5b271b3e12b6cf3f38836c5 (patch)
tree8a7f11e101af6a094b4b86d3c0b9d72793005ed3 /apps/plugins/sdl/progs/quake/net_main.c
parent8dd00a02d49a99997165a4c38a967738e90ba72f (diff)
downloadrockbox-duke3d.zip
rockbox-duke3d.tar.gz
rockbox-duke3d.tar.bz2
rockbox-duke3d.tar.xz
Quake: attempt 2duke3d
Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
Diffstat (limited to 'apps/plugins/sdl/progs/quake/net_main.c')
-rw-r--r--apps/plugins/sdl/progs/quake/net_main.c997
1 files changed, 997 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/net_main.c b/apps/plugins/sdl/progs/quake/net_main.c
new file mode 100644
index 0000000..5f5d2cf
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/net_main.c
@@ -0,0 +1,997 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// net_main.c
+
+#include "quakedef.h"
+#include "net_vcr.h"
+
+qsocket_t *net_activeSockets = NULL;
+qsocket_t *net_freeSockets = NULL;
+int net_numsockets = 0;
+
+qboolean serialAvailable = false;
+qboolean ipxAvailable = false;
+qboolean tcpipAvailable = false;
+
+int net_hostport;
+int DEFAULTnet_hostport = 26000;
+
+char my_ipx_address[NET_NAMELEN];
+char my_tcpip_address[NET_NAMELEN];
+
+void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem);
+void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem);
+void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
+void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup);
+
+static qboolean listening = false;
+
+qboolean slistInProgress = false;
+qboolean slistSilent = false;
+qboolean slistLocal = true;
+static double slistStartTime;
+static int slistLastShown;
+
+static void Slist_Send(void);
+static void Slist_Poll(void);
+PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send};
+PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll};
+
+
+sizebuf_t net_message;
+int net_activeconnections = 0;
+
+int messagesSent = 0;
+int messagesReceived = 0;
+int unreliableMessagesSent = 0;
+int unreliableMessagesReceived = 0;
+
+cvar_t net_messagetimeout = {"net_messagetimeout","300"};
+cvar_t hostname = {"hostname", "UNNAMED"};
+
+qboolean configRestored = false;
+cvar_t config_com_port = {"_config_com_port", "0x3f8", true};
+cvar_t config_com_irq = {"_config_com_irq", "4", true};
+cvar_t config_com_baud = {"_config_com_baud", "57600", true};
+cvar_t config_com_modem = {"_config_com_modem", "1", true};
+cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true};
+cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true};
+cvar_t config_modem_init = {"_config_modem_init", "", true};
+cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true};
+
+#ifdef IDGODS
+cvar_t idgods = {"idgods", "0"};
+#endif
+
+int vcrFile = -1;
+qboolean recording = false;
+
+// these two macros are to make the code more readable
+#define sfunc net_drivers[sock->driver]
+#define dfunc net_drivers[net_driverlevel]
+
+int net_driverlevel;
+
+
+double net_time;
+
+double SetNetTime(void)
+{
+ net_time = Sys_FloatTime();
+ return net_time;
+}
+
+
+/*
+===================
+NET_NewQSocket
+
+Called by drivers when a new communications endpoint is required
+The sequence and buffer fields will be filled in properly
+===================
+*/
+qsocket_t *NET_NewQSocket (void)
+{
+ qsocket_t *sock;
+
+ if (net_freeSockets == NULL)
+ return NULL;
+
+ if (net_activeconnections >= svs.maxclients)
+ return NULL;
+
+ // get one from free list
+ sock = net_freeSockets;
+ net_freeSockets = sock->next;
+
+ // add it to active list
+ sock->next = net_activeSockets;
+ net_activeSockets = sock;
+
+ sock->disconnected = false;
+ sock->connecttime = net_time;
+ Q_strcpy (sock->address,"UNSET ADDRESS");
+ sock->driver = net_driverlevel;
+ sock->socket = 0;
+ sock->driverdata = NULL;
+ sock->canSend = true;
+ sock->sendNext = false;
+ sock->lastMessageTime = net_time;
+ sock->ackSequence = 0;
+ sock->sendSequence = 0;
+ sock->unreliableSendSequence = 0;
+ sock->sendMessageLength = 0;
+ sock->receiveSequence = 0;
+ sock->unreliableReceiveSequence = 0;
+ sock->receiveMessageLength = 0;
+
+ return sock;
+}
+
+
+void NET_FreeQSocket(qsocket_t *sock)
+{
+ qsocket_t *s;
+
+ // remove it from active list
+ if (sock == net_activeSockets)
+ net_activeSockets = net_activeSockets->next;
+ else
+ {
+ for (s = net_activeSockets; s; s = s->next)
+ if (s->next == sock)
+ {
+ s->next = sock->next;
+ break;
+ }
+ if (!s)
+ Sys_Error ("NET_FreeQSocket: not active\n");
+ }
+
+ // add it to free list
+ sock->next = net_freeSockets;
+ net_freeSockets = sock;
+ sock->disconnected = true;
+}
+
+
+static void NET_Listen_f (void)
+{
+ if (Cmd_Argc () != 2)
+ {
+ Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0);
+ return;
+ }
+
+ listening = Q_atoi(Cmd_Argv(1)) ? true : false;
+
+ for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
+ {
+ if (net_drivers[net_driverlevel].initialized == false)
+ continue;
+ dfunc.Listen (listening);
+ }
+}
+
+
+static void MaxPlayers_f (void)
+{
+ int n;
+
+ if (Cmd_Argc () != 2)
+ {
+ Con_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients);
+ return;
+ }
+
+ if (sv.active)
+ {
+ Con_Printf ("maxplayers can not be changed while a server is running.\n");
+ return;
+ }
+
+ n = Q_atoi(Cmd_Argv(1));
+ if (n < 1)
+ n = 1;
+ if (n > svs.maxclientslimit)
+ {
+ n = svs.maxclientslimit;
+ Con_Printf ("\"maxplayers\" set to \"%u\"\n", n);
+ }
+
+ if ((n == 1) && listening)
+ Cbuf_AddText ("listen 0\n");
+
+ if ((n > 1) && (!listening))
+ Cbuf_AddText ("listen 1\n");
+
+ svs.maxclients = n;
+ if (n == 1)
+ Cvar_Set ("deathmatch", "0");
+ else
+ Cvar_Set ("deathmatch", "1");
+}
+
+
+static void NET_Port_f (void)
+{
+ int n;
+
+ if (Cmd_Argc () != 2)
+ {
+ Con_Printf ("\"port\" is \"%u\"\n", net_hostport);
+ return;
+ }
+
+ n = Q_atoi(Cmd_Argv(1));
+ if (n < 1 || n > 65534)
+ {
+ Con_Printf ("Bad value, must be between 1 and 65534\n");
+ return;
+ }
+
+ DEFAULTnet_hostport = n;
+ net_hostport = n;
+
+ if (listening)
+ {
+ // force a change to the new port
+ Cbuf_AddText ("listen 0\n");
+ Cbuf_AddText ("listen 1\n");
+ }
+}
+
+
+static void PrintSlistHeader(void)
+{
+ Con_Printf("Server Map Users\n");
+ Con_Printf("--------------- --------------- -----\n");
+ slistLastShown = 0;
+}
+
+
+static void PrintSlist(void)
+{
+ int n;
+
+ for (n = slistLastShown; n < hostCacheCount; n++)
+ {
+ if (hostcache[n].maxusers)
+ Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers);
+ else
+ Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map);
+ }
+ slistLastShown = n;
+}
+
+
+static void PrintSlistTrailer(void)
+{
+ if (hostCacheCount)
+ Con_Printf("== end list ==\n\n");
+ else
+ Con_Printf("No Quake servers found.\n\n");
+}
+
+
+void NET_Slist_f (void)
+{
+ if (slistInProgress)
+ return;
+
+ if (! slistSilent)
+ {
+ Con_Printf("Looking for Quake servers...\n");
+ PrintSlistHeader();
+ }
+
+ slistInProgress = true;
+ slistStartTime = Sys_FloatTime();
+
+ SchedulePollProcedure(&slistSendProcedure, 0.0);
+ SchedulePollProcedure(&slistPollProcedure, 0.1);
+
+ hostCacheCount = 0;
+}
+
+
+static void Slist_Send(void)
+{
+ for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
+ {
+ if (!slistLocal && net_driverlevel == 0)
+ continue;
+ if (net_drivers[net_driverlevel].initialized == false)
+ continue;
+ dfunc.SearchForHosts (true);
+ }
+
+ if ((Sys_FloatTime() - slistStartTime) < 0.5)
+ SchedulePollProcedure(&slistSendProcedure, 0.75);
+}
+
+
+static void Slist_Poll(void)
+{
+ for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
+ {
+ if (!slistLocal && net_driverlevel == 0)
+ continue;
+ if (net_drivers[net_driverlevel].initialized == false)
+ continue;
+ dfunc.SearchForHosts (false);
+ }
+
+ if (! slistSilent)
+ PrintSlist();
+
+ if ((Sys_FloatTime() - slistStartTime) < 1.5)
+ {
+ SchedulePollProcedure(&slistPollProcedure, 0.1);
+ return;
+ }
+
+ if (! slistSilent)
+ PrintSlistTrailer();
+ slistInProgress = false;
+ slistSilent = false;
+ slistLocal = true;
+}
+
+
+/*
+===================
+NET_Connect
+===================
+*/
+
+int hostCacheCount = 0;
+hostcache_t hostcache[HOSTCACHESIZE];
+
+qsocket_t *NET_Connect (char *host)
+{
+ qsocket_t *ret;
+ int n;
+ int numdrivers = net_numdrivers;
+
+ SetNetTime();
+
+ if (host && *host == 0)
+ host = NULL;
+
+ if (host)
+ {
+ if (Q_strcasecmp (host, "local") == 0)
+ {
+ numdrivers = 1;
+ goto JustDoIt;
+ }
+
+ if (hostCacheCount)
+ {
+ for (n = 0; n < hostCacheCount; n++)
+ if (Q_strcasecmp (host, hostcache[n].name) == 0)
+ {
+ host = hostcache[n].cname;
+ break;
+ }
+ if (n < hostCacheCount)
+ goto JustDoIt;
+ }
+ }
+
+ slistSilent = host ? true : false;
+ NET_Slist_f ();
+
+ while(slistInProgress)
+ NET_Poll();
+
+ if (host == NULL)
+ {
+ if (hostCacheCount != 1)
+ return NULL;
+ host = hostcache[0].cname;
+ Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
+ }
+
+ if (hostCacheCount)
+ for (n = 0; n < hostCacheCount; n++)
+ if (Q_strcasecmp (host, hostcache[n].name) == 0)
+ {
+ host = hostcache[n].cname;
+ break;
+ }
+
+JustDoIt:
+ for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
+ {
+ if (net_drivers[net_driverlevel].initialized == false)
+ continue;
+ ret = dfunc.Connect (host);
+ if (ret)
+ return ret;
+ }
+
+ if (host)
+ {
+ Con_Printf("\n");
+ PrintSlistHeader();
+ PrintSlist();
+ PrintSlistTrailer();
+ }
+
+ return NULL;
+}
+
+
+/*
+===================
+NET_CheckNewConnections
+===================
+*/
+
+struct
+{
+ double time;
+ int op;
+ long session;
+} vcrConnect;
+
+qsocket_t *NET_CheckNewConnections (void)
+{
+ qsocket_t *ret;
+
+ SetNetTime();
+
+ for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
+ {
+ if (net_drivers[net_driverlevel].initialized == false)
+ continue;
+ if (net_driverlevel && listening == false)
+ continue;
+ ret = dfunc.CheckNewConnections ();
+ if (ret)
+ {
+ if (recording)
+ {
+ vcrConnect.time = host_time;
+ vcrConnect.op = VCR_OP_CONNECT;
+ vcrConnect.session = (long)ret;
+ Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
+ Sys_FileWrite (vcrFile, ret->address, NET_NAMELEN);
+ }
+ return ret;
+ }
+ }
+
+ if (recording)
+ {
+ vcrConnect.time = host_time;
+ vcrConnect.op = VCR_OP_CONNECT;
+ vcrConnect.session = 0;
+ Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect));
+ }
+
+ return NULL;
+}
+
+/*
+===================
+NET_Close
+===================
+*/
+void NET_Close (qsocket_t *sock)
+{
+ if (!sock)
+ return;
+
+ if (sock->disconnected)
+ return;
+
+ SetNetTime();
+
+ // call the driver_Close function
+ sfunc.Close (sock);
+
+ NET_FreeQSocket(sock);
+}
+
+
+/*
+=================
+NET_GetMessage
+
+If there is a complete message, return it in net_message
+
+returns 0 if no data is waiting
+returns 1 if a message was received
+returns -1 if connection is invalid
+=================
+*/
+
+struct
+{
+ double time;
+ int op;
+ long session;
+ int ret;
+ int len;
+} vcrGetMessage;
+
+extern void PrintStats(qsocket_t *s);
+
+int NET_GetMessage (qsocket_t *sock)
+{
+ int ret;
+
+ if (!sock)
+ return -1;
+
+ if (sock->disconnected)
+ {
+ Con_Printf("NET_GetMessage: disconnected socket\n");
+ return -1;
+ }
+
+ SetNetTime();
+
+ ret = sfunc.QGetMessage(sock);
+
+ // see if this connection has timed out
+ if (ret == 0 && sock->driver)
+ {
+ if (net_time - sock->lastMessageTime > net_messagetimeout.value)
+ {
+ NET_Close(sock);
+ return -1;
+ }
+ }
+
+
+ if (ret > 0)
+ {
+ if (sock->driver)
+ {
+ sock->lastMessageTime = net_time;
+ if (ret == 1)
+ messagesReceived++;
+ else if (ret == 2)
+ unreliableMessagesReceived++;
+ }
+
+ if (recording)
+ {
+ vcrGetMessage.time = host_time;
+ vcrGetMessage.op = VCR_OP_GETMESSAGE;
+ vcrGetMessage.session = (long)sock;
+ vcrGetMessage.ret = ret;
+ vcrGetMessage.len = net_message.cursize;
+ Sys_FileWrite (vcrFile, &vcrGetMessage, 24);
+ Sys_FileWrite (vcrFile, net_message.data, net_message.cursize);
+ }
+ }
+ else
+ {
+ if (recording)
+ {
+ vcrGetMessage.time = host_time;
+ vcrGetMessage.op = VCR_OP_GETMESSAGE;
+ vcrGetMessage.session = (long)sock;
+ vcrGetMessage.ret = ret;
+ Sys_FileWrite (vcrFile, &vcrGetMessage, 20);
+ }
+ }
+
+ return ret;
+}
+
+
+/*
+==================
+NET_SendMessage
+
+Try to send a complete length+message unit over the reliable stream.
+returns 0 if the message cannot be delivered reliably, but the connection
+ is still considered valid
+returns 1 if the message was sent properly
+returns -1 if the connection died
+==================
+*/
+struct
+{
+ double time;
+ int op;
+ long session;
+ int r;
+} vcrSendMessage;
+
+int NET_SendMessage (qsocket_t *sock, sizebuf_t *data)
+{
+ int r;
+
+ if (!sock)
+ return -1;
+
+ if (sock->disconnected)
+ {
+ Con_Printf("NET_SendMessage: disconnected socket\n");
+ return -1;
+ }
+
+ SetNetTime();
+ r = sfunc.QSendMessage(sock, data);
+ if (r == 1 && sock->driver)
+ messagesSent++;
+
+ if (recording)
+ {
+ vcrSendMessage.time = host_time;
+ vcrSendMessage.op = VCR_OP_SENDMESSAGE;
+ vcrSendMessage.session = (long)sock;
+ vcrSendMessage.r = r;
+ Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
+ }
+
+ return r;
+}
+
+
+int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data)
+{
+ int r;
+
+ if (!sock)
+ return -1;
+
+ if (sock->disconnected)
+ {
+ Con_Printf("NET_SendMessage: disconnected socket\n");
+ return -1;
+ }
+
+ SetNetTime();
+ r = sfunc.SendUnreliableMessage(sock, data);
+ if (r == 1 && sock->driver)
+ unreliableMessagesSent++;
+
+ if (recording)
+ {
+ vcrSendMessage.time = host_time;
+ vcrSendMessage.op = VCR_OP_SENDMESSAGE;
+ vcrSendMessage.session = (long)sock;
+ vcrSendMessage.r = r;
+ Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
+ }
+
+ return r;
+}
+
+
+/*
+==================
+NET_CanSendMessage
+
+Returns true or false if the given qsocket can currently accept a
+message to be transmitted.
+==================
+*/
+qboolean NET_CanSendMessage (qsocket_t *sock)
+{
+ int r;
+
+ if (!sock)
+ return false;
+
+ if (sock->disconnected)
+ return false;
+
+ SetNetTime();
+
+ r = sfunc.CanSendMessage(sock);
+
+ if (recording)
+ {
+ vcrSendMessage.time = host_time;
+ vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
+ vcrSendMessage.session = (long)sock;
+ vcrSendMessage.r = r;
+ Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
+ }
+
+ return r;
+}
+
+
+int NET_SendToAll(sizebuf_t *data, int blocktime)
+{
+ double start;
+ int i;
+ int count = 0;
+ qboolean state1 [MAX_SCOREBOARD];
+ qboolean state2 [MAX_SCOREBOARD];
+
+ for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
+ {
+ if (!host_client->netconnection)
+ continue;
+ if (host_client->active)
+ {
+ if (host_client->netconnection->driver == 0)
+ {
+ NET_SendMessage(host_client->netconnection, data);
+ state1[i] = true;
+ state2[i] = true;
+ continue;
+ }
+ count++;
+ state1[i] = false;
+ state2[i] = false;
+ }
+ else
+ {
+ state1[i] = true;
+ state2[i] = true;
+ }
+ }
+
+ start = Sys_FloatTime();
+ while (count)
+ {
+ count = 0;
+ for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
+ {
+ if (! state1[i])
+ {
+ if (NET_CanSendMessage (host_client->netconnection))
+ {
+ state1[i] = true;
+ NET_SendMessage(host_client->netconnection, data);
+ }
+ else
+ {
+ NET_GetMessage (host_client->netconnection);
+ }
+ count++;
+ continue;
+ }
+
+ if (! state2[i])
+ {
+ if (NET_CanSendMessage (host_client->netconnection))
+ {
+ state2[i] = true;
+ }
+ else
+ {
+ NET_GetMessage (host_client->netconnection);
+ }
+ count++;
+ continue;
+ }
+ }
+ if ((Sys_FloatTime() - start) > blocktime)
+ break;
+ }
+ return count;
+}
+
+
+//=============================================================================
+
+/*
+====================
+NET_Init
+====================
+*/
+
+void NET_Init (void)
+{
+ int i;
+ int controlSocket;
+ qsocket_t *s;
+
+ if (COM_CheckParm("-playback"))
+ {
+ net_numdrivers = 1;
+ net_drivers[0].Init = VCR_Init;
+ }
+
+ if (COM_CheckParm("-record"))
+ recording = true;
+
+ i = COM_CheckParm ("-port");
+ if (!i)
+ i = COM_CheckParm ("-udpport");
+ if (!i)
+ i = COM_CheckParm ("-ipxport");
+
+ if (i)
+ {
+ if (i < com_argc-1)
+ DEFAULTnet_hostport = Q_atoi (com_argv[i+1]);
+ else
+ Sys_Error ("NET_Init: you must specify a number after -port");
+ }
+ net_hostport = DEFAULTnet_hostport;
+
+ if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
+ listening = true;
+ net_numsockets = svs.maxclientslimit;
+ if (cls.state != ca_dedicated)
+ net_numsockets++;
+
+ SetNetTime();
+
+ for (i = 0; i < net_numsockets; i++)
+ {
+ s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket");
+ s->next = net_freeSockets;
+ net_freeSockets = s;
+ s->disconnected = true;
+ }
+
+ // allocate space for network message buffer
+ SZ_Alloc (&net_message, NET_MAXMESSAGE);
+
+ Cvar_RegisterVariable (&net_messagetimeout);
+ Cvar_RegisterVariable (&hostname);
+ Cvar_RegisterVariable (&config_com_port);
+ Cvar_RegisterVariable (&config_com_irq);
+ Cvar_RegisterVariable (&config_com_baud);
+ Cvar_RegisterVariable (&config_com_modem);
+ Cvar_RegisterVariable (&config_modem_dialtype);
+ Cvar_RegisterVariable (&config_modem_clear);
+ Cvar_RegisterVariable (&config_modem_init);
+ Cvar_RegisterVariable (&config_modem_hangup);
+#ifdef IDGODS
+ Cvar_RegisterVariable (&idgods);
+#endif
+
+ Cmd_AddCommand ("slist", NET_Slist_f);
+ Cmd_AddCommand ("listen", NET_Listen_f);
+ Cmd_AddCommand ("maxplayers", MaxPlayers_f);
+ Cmd_AddCommand ("port", NET_Port_f);
+
+ // initialize all the drivers
+ for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
+ {
+ controlSocket = net_drivers[net_driverlevel].Init();
+ if (controlSocket == -1)
+ continue;
+ net_drivers[net_driverlevel].initialized = true;
+ net_drivers[net_driverlevel].controlSock = controlSocket;
+ if (listening)
+ net_drivers[net_driverlevel].Listen (true);
+ }
+
+ if (*my_ipx_address)
+ Con_DPrintf("IPX address %s\n", my_ipx_address);
+ if (*my_tcpip_address)
+ Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
+}
+
+/*
+====================
+NET_Shutdown
+====================
+*/
+
+void NET_Shutdown (void)
+{
+ qsocket_t *sock;
+
+ SetNetTime();
+
+ for (sock = net_activeSockets; sock; sock = sock->next)
+ NET_Close(sock);
+
+//
+// shutdown the drivers
+//
+ for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++)
+ {
+ if (net_drivers[net_driverlevel].initialized == true)
+ {
+ net_drivers[net_driverlevel].Shutdown ();
+ net_drivers[net_driverlevel].initialized = false;
+ }
+ }
+
+ if (vcrFile != -1)
+ {
+ Con_Printf ("Closing vcrfile.\n");
+ Sys_FileClose(vcrFile);
+ }
+}
+
+
+static PollProcedure *pollProcedureList = NULL;
+
+void NET_Poll(void)
+{
+ PollProcedure *pp;
+ qboolean useModem;
+
+ if (!configRestored)
+ {
+ if (serialAvailable)
+ {
+ if (config_com_modem.value == 1.0)
+ useModem = true;
+ else
+ useModem = false;
+ SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem);
+ SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string);
+ }
+ configRestored = true;
+ }
+
+ SetNetTime();
+
+ for (pp = pollProcedureList; pp; pp = pp->next)
+ {
+ if (pp->nextTime > net_time)
+ break;
+ pollProcedureList = pp->next;
+ pp->procedure(pp->arg);
+ }
+}
+
+
+void SchedulePollProcedure(PollProcedure *proc, double timeOffset)
+{
+ PollProcedure *pp, *prev;
+
+ proc->nextTime = Sys_FloatTime() + timeOffset;
+ for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
+ {
+ if (pp->nextTime >= proc->nextTime)
+ break;
+ prev = pp;
+ }
+
+ if (prev == NULL)
+ {
+ proc->next = pollProcedureList;
+ pollProcedureList = proc;
+ return;
+ }
+
+ proc->next = pp;
+ prev->next = proc;
+}
+
+
+#ifdef IDGODS
+#define IDNET 0xc0f62800
+
+qboolean IsID(struct qsockaddr *addr)
+{
+ if (idgods.value == 0.0)
+ return false;
+
+ if (addr->sa_family != 2)
+ return false;
+
+ if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET)
+ return true;
+ return false;
+}
+#endif