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.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
// net_main.c
#include "quakedef.h"
-#include "net_vcr.h"
+#include "net_master.h"
-qsocket_t *net_activeSockets = NULL;
-qsocket_t *net_freeSockets = NULL;
-int net_numsockets = 0;
+qsocket_t *net_activeSockets = NULL;
+mempool_t *net_mempool;
-qboolean serialAvailable = false;
qboolean ipxAvailable = false;
qboolean tcpipAvailable = false;
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;
PollProcedure slistSendProcedure = {NULL, 0.0, Slist_Send};
PollProcedure slistPollProcedure = {NULL, 0.0, Slist_Poll};
+static void InetSlist_Send(void);
+static void InetSlist_Poll(void);
+PollProcedure inetSlistSendProcedure = {NULL, 0.0, InetSlist_Send};
+PollProcedure inetSlistPollProcedure = {NULL, 0.0, InetSlist_Poll};
+
sizebuf_t net_message;
int net_activeconnections = 0;
int unreliableMessagesSent = 0;
int unreliableMessagesReceived = 0;
-cvar_t net_messagetimeout = {"net_messagetimeout","300"};
-cvar_t hostname = {"hostname", "UNNAMED"};
+cvar_t net_messagetimeout = {0, "net_messagetimeout","300"};
+cvar_t hostname = {CVAR_SAVE, "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]
int net_driverlevel;
+/*
+#define SLSERVERS 1024
+#define SLNAME 40
+#define SLMAPNAME 16
+#define SLMODNAME 16
+typedef struct slserver_s
+{
+ unsigned int ipaddr;
+ unsigned short port;
+ unsigned short ping;
+ char name[SLNAME];
+ char mapname[SLMAPNAME];
+ char modname[SLMODNAME];
+}
+slserver_t;
+
+slserver_t sl_server[SLSERVERS];
+int sl_numservers = 0;
+
+void SL_ClearServers(void)
+{
+ sl_numservers = 0;
+}
+
+slserver_t *SL_FindServer(unsigned int ipaddr, unsigned short port)
+{
+ int i;
+ slserver_t *sl;
+ for (i = 0, sl = sl_server;i < sl_numservers;i++, sl++)
+ if (sl->ipaddr == ipaddr && sl->port == port)
+ return;
+}
+
+void SL_AddServer(unsigned int ipaddr, unsigned short port)
+{
+ if (SL_FindServer(ipaddr, port))
+ return;
+ memset(sl_server + sl_numservers, 0, sizeof(slserver_t));
+ sl_server[sl_numservers].ipaddr = ipaddr;
+ sl_server[sl_numservers].port = port;
+ sl_server[sl_numservers].ping = 0xFFFF;
+ sl_numservers++;
+}
+
+void SL_UpdateServerName(unsigned int ipaddr, unsigned short port, const char *name);
+{
+ int namelen;
+ slserver_t *sl;
+ sl = SL_FindServer(ipaddr, port);
+ if (sl == NULL)
+ return;
+ memset(sl->name, 0, sizeof(sl->name));
+ namelen = strlen(name);
+ if (namelen > sizeof(sl->name) - 1)
+ namelen = sizeof(sl->name) - 1;
+ if (namelen)
+ memcpy(sl->name, name, namelen);
+}
+
+void SL_UpdateServerModName(unsigned int ipaddr, unsigned short port, const char *name);
+{
+ int namelen;
+ slserver_t *sl;
+ sl = SL_FindServer(ipaddr, port);
+ if (sl == NULL)
+ return;
+ memset(sl->modname, 0, sizeof(sl->modname));
+ namelen = strlen(name);
+ if (namelen > sizeof(sl->modname) - 1)
+ namelen = sizeof(sl->modname) - 1;
+ if (namelen)
+ memcpy(sl->modname, name, namelen);
+}
+
+void SL_UpdateServerMapName(unsigned int ipaddr, unsigned short port, const char *name);
+{
+ int namelen;
+ slserver_t *sl;
+ sl = SL_FindServer(ipaddr, port);
+ if (sl == NULL)
+ return;
+ memset(sl->mapname, 0, sizeof(sl->mapname));
+ namelen = strlen(name);
+ if (namelen > sizeof(sl->mapname) - 1)
+ namelen = sizeof(sl->mapname) - 1;
+ if (namelen)
+ memcpy(sl->mapname, name, namelen);
+}
+
+void SL_UpdateServerPing(unsigned int ipaddr, unsigned short port, float ping);
+{
+ int i;
+ slserver_t *sl;
+ sl = SL_FindServer(ipaddr, port);
+ if (sl == NULL)
+ return;
+ i = ping * 1000.0;
+ sl->ping = bound(0, i, 9999);
+}
+*/
+
double net_time;
double SetNetTime(void)
{
- net_time = Sys_FloatTime();
+ net_time = Sys_DoubleTime();
return net_time;
}
{
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;
+ sock = Mem_Alloc(net_mempool, sizeof(qsocket_t));
// add it to active list
sock->next = net_activeSockets;
Sys_Error ("NET_FreeQSocket: not active\n");
}
- // add it to free list
- sock->next = net_freeSockets;
- net_freeSockets = sock;
- sock->disconnected = true;
+ Mem_Free(sock);
}
static void MaxPlayers_f (void)
{
- int n;
+ int n;
if (Cmd_Argc () != 2)
{
}
n = atoi(Cmd_Argv(1));
- if (n < 1)
- n = 1;
- if (n > svs.maxclientslimit)
- {
- n = svs.maxclientslimit;
+ n = bound(1, n, MAX_SCOREBOARD);
+ if (svs.maxclients != n)
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;
- // LordHavoc: resetting deathmatch and coop was silly
- /*
- if (n == 1)
- Cvar_Set ("deathmatch", "0");
- else
- Cvar_Set ("deathmatch", "1");
- */
+ SV_SetMaxClients(n);
}
}
+static void NET_Heartbeat_f (void)
+{
+ NET_Heartbeat (2);
+}
+
+
static void PrintSlistHeader(void)
{
Con_Printf("Server Map Users\n");
if (hostCacheCount)
Con_Printf("== end list ==\n\n");
else
- Con_Printf("No Quake servers found.\n\n");
+ {
+ if (gamemode == GAME_TRANSFUSION)
+ Con_Printf("No Transfusion servers found.\n\n");
+ else
+ Con_Printf("No Quake servers found.\n\n");
+ }
}
-void NET_Slist_f (void)
+void NET_SlistCommon (PollProcedure *sendProcedure, PollProcedure *pollProcedure)
{
if (slistInProgress)
return;
if (! slistSilent)
{
- Con_Printf("Looking for Quake servers...\n");
+ if (gamemode == GAME_TRANSFUSION)
+ Con_Printf("Looking for Transfusion servers...\n");
+ else
+ Con_Printf("Looking for Quake servers...\n");
PrintSlistHeader();
}
slistInProgress = true;
- slistStartTime = Sys_FloatTime();
+ slistStartTime = Sys_DoubleTime();
- SchedulePollProcedure(&slistSendProcedure, 0.0);
- SchedulePollProcedure(&slistPollProcedure, 0.1);
+ SchedulePollProcedure(sendProcedure, 0.0);
+ SchedulePollProcedure(pollProcedure, 0.1);
hostCacheCount = 0;
}
+void NET_Slist_f (void)
+{
+ NET_SlistCommon (&slistSendProcedure, &slistPollProcedure);
+}
+
+
+void NET_InetSlist_f (void)
+{
+ NET_SlistCommon (&inetSlistSendProcedure, &inetSlistPollProcedure);
+}
+
+
static void Slist_Send(void)
{
for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++)
dfunc.SearchForHosts (true);
}
- if ((Sys_FloatTime() - slistStartTime) < 0.5)
+ if ((Sys_DoubleTime() - slistStartTime) < 0.5)
SchedulePollProcedure(&slistSendProcedure, 0.75);
}
if (! slistSilent)
PrintSlist();
- if ((Sys_FloatTime() - slistStartTime) < 1.5)
+ if ((Sys_DoubleTime() - slistStartTime) < 1.5)
{
SchedulePollProcedure(&slistPollProcedure, 0.1);
return;
}
+static void InetSlist_Send(void)
+{
+ const char* host;
+
+ if (!slistInProgress)
+ return;
+
+ while ((host = Master_BuildGetServers ()) != NULL)
+ {
+ 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.SearchForInetHosts (host);
+ }
+ }
+
+ if ((Sys_DoubleTime() - slistStartTime) < 3.5)
+ SchedulePollProcedure(&inetSlistSendProcedure, 1.0);
+}
+
+
+static void InetSlist_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;
+ // We stop as soon as we have one answer (FIXME: bad...)
+ if (dfunc.SearchForInetHosts (NULL))
+ slistInProgress = false;
+ }
+
+ if (! slistSilent)
+ PrintSlist();
+
+ if (slistInProgress && (Sys_DoubleTime() - slistStartTime) < 4.0)
+ {
+ SchedulePollProcedure(&inetSlistPollProcedure, 0.1);
+ return;
+ }
+
+ if (! slistSilent)
+ PrintSlistTrailer();
+ slistInProgress = false;
+ slistSilent = false;
+ slistLocal = true;
+}
+
+
/*
===================
NET_Connect
{
qsocket_t *ret;
int n;
- int numdrivers = net_numdrivers;
SetNetTime();
{
if (Q_strcasecmp (host, "local") == 0)
{
- numdrivers = 1;
- goto JustDoIt;
+ net_driverlevel = 0;
+ return dfunc.Connect (host);
}
if (hostCacheCount)
}
JustDoIt:
- for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
+ for (net_driverlevel = 0;net_driverlevel < net_numdrivers;net_driverlevel++)
{
if (net_drivers[net_driverlevel].initialized == false)
continue;
PrintSlist();
PrintSlistTrailer();
}
-
+
return NULL;
}
===================
*/
-struct
-{
- double time;
- int op;
- long session;
-} vcrConnect;
-
qsocket_t *NET_CheckNewConnections (void)
{
qsocket_t *ret;
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;
=================
*/
-struct
-{
- double time;
- int op;
- long session;
- int ret;
- int len;
-} vcrGetMessage;
-
extern void PrintStats(qsocket_t *s);
int NET_GetMessage (qsocket_t *sock)
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;
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 (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;
}
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;
}
r = sfunc.CanSendMessage(sock);
- if (recording)
+ return r;
+}
+
+
+/*
+====================
+NET_Heartbeat
+
+Send an heartbeat to the master server(s)
+====================
+*/
+void NET_Heartbeat (int priority)
+{
+ const char* host;
+
+ if (! Master_AllowHeartbeat (priority))
+ return;
+
+ while ((host = Master_BuildHeartbeat ()) != NULL)
{
- vcrSendMessage.time = host_time;
- vcrSendMessage.op = VCR_OP_CANSENDMESSAGE;
- vcrSendMessage.session = (long)sock;
- vcrSendMessage.r = r;
- Sys_FileWrite (vcrFile, &vcrSendMessage, 20);
+ for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
+ {
+ if (net_drivers[net_driverlevel].initialized == false)
+ continue;
+ if (net_driverlevel && listening == false)
+ continue;
+ dfunc.Heartbeat (host);
+ }
}
-
- return r;
}
}
}
- start = Sys_FloatTime();
+ start = Sys_DoubleTime();
while (count)
{
count = 0;
continue;
}
}
- if ((Sys_FloatTime() - start) > blocktime)
+ if ((Sys_DoubleTime() - start) > blocktime)
break;
}
return count;
{
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)
}
net_hostport = DEFAULTnet_hostport;
- if (COM_CheckParm("-listen") || cls.state == ca_dedicated)
+ if (COM_CheckParm("-listen") || cls.state == ca_dedicated || gamemode == GAME_TRANSFUSION)
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;
- }
+ net_mempool = Mem_AllocPool("qsocket");
// allocate space for network message buffer
- SZ_Alloc (&net_message, NET_MAXMESSAGE);
+ SZ_Alloc (&net_message, NET_MAXMESSAGE, "net_message");
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 ("net_slist", NET_Slist_f);
+ Cmd_AddCommand ("net_inetslist", NET_InetSlist_f);
Cmd_AddCommand ("listen", NET_Listen_f);
Cmd_AddCommand ("maxplayers", MaxPlayers_f);
Cmd_AddCommand ("port", NET_Port_f);
+ Cmd_AddCommand ("heartbeat", NET_Heartbeat_f);
// initialize all the drivers
for (net_driverlevel=0 ; net_driverlevel<net_numdrivers ; net_driverlevel++)
Con_DPrintf("IPX address %s\n", my_ipx_address);
if (*my_tcpip_address)
Con_DPrintf("TCP/IP address %s\n", my_tcpip_address);
+
+ Master_Init ();
}
/*
====================
*/
-void NET_Shutdown (void)
+void NET_Shutdown (void)
{
- qsocket_t *sock;
-
SetNetTime();
- for (sock = net_activeSockets; sock; sock = sock->next)
- NET_Close(sock);
+ while (net_activeSockets)
+ NET_Close(net_activeSockets);
//
// shutdown the drivers
}
}
- if (vcrFile != -1)
- {
- Con_Printf ("Closing vcrfile.\n");
- Sys_FileClose(vcrFile);
- }
+ Mem_FreePool(&net_mempool);
}
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();
{
PollProcedure *pp, *prev;
- proc->nextTime = Sys_FloatTime() + timeOffset;
+ proc->nextTime = Sys_DoubleTime() + timeOffset;
for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next)
{
if (pp->nextTime >= proc->nextTime)
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