MSG_WriteByte (&client->message, 0);
}
- NET_Heartbeat ();
+ NET_Heartbeat (1);
}
/*
// stop all client sounds immediately
CL_Disconnect ();
- NET_Heartbeat ();
- NET_Heartbeat ();
+ NET_Heartbeat (2);
+ NET_Heartbeat (2);
// flush any pending messages - like the score!!!
start = Sys_DoubleTime();
// send all messages to the clients
SV_SendClientMessages ();
+
+// send an heartbeat if enough time has passed since the last one
+ NET_Heartbeat (0);
}
int (*Init) (void);
void (*Listen) (qboolean state);
void (*SearchForHosts) (qboolean xmit);
- qboolean (*SearchForInetHosts) (char *master);
- qsocket_t *(*Connect) (char *host);
+ qboolean (*SearchForInetHosts) (const char *master);
+ qsocket_t *(*Connect) (const char *host);
qsocket_t *(*CheckNewConnections) (void);
int (*QGetMessage) (qsocket_t *sock);
int (*QSendMessage) (qsocket_t *sock, sizebuf_t *data);
qboolean (*CanSendUnreliableMessage) (qsocket_t *sock);
void (*Close) (qsocket_t *sock);
void (*Shutdown) (void);
- void (*Heartbeat) (char *host);
+ void (*Heartbeat) (const char *host);
int controlSock;
} net_driver_t;
struct qsocket_s *NET_Connect (char *host);
// called by client to connect to a host. Returns -1 if not able to
-void NET_Heartbeat (void);
-// Send an heartbeat to the master server(s)
+void NET_Heartbeat (int priority);
+// Send an heartbeat to the master server(s). priority: 0 = lowest, 1 = state change, 2 = force
qboolean NET_CanSendMessage (qsocket_t *sock);
// Returns true or false if the given qsocket can currently accept a
}
-static qboolean _Datagram_SearchForInetHosts (char *master)
+static qboolean _Datagram_SearchForInetHosts (const char *master)
{
qboolean result = false;
struct qsockaddr masteraddr;
}
-qboolean Datagram_SearchForInetHosts (char *master)
+qboolean Datagram_SearchForInetHosts (const char *master)
{
qboolean result = false;
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
}
-static qsocket_t *_Datagram_Connect (char *host)
+static qsocket_t *_Datagram_Connect (const char *host)
{
struct qsockaddr sendaddr;
struct qsockaddr readaddr;
return NULL;
}
-qsocket_t *Datagram_Connect (char *host)
+qsocket_t *Datagram_Connect (const char *host)
{
qsocket_t *ret = NULL;
return ret;
}
-static void _Datagram_Heartbeat (char *master)
+static void _Datagram_Heartbeat (const char *master)
{
struct qsockaddr masteraddr;
int portnum;
dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
}
-void Datagram_Heartbeat (char *master)
+void Datagram_Heartbeat (const char *master)
{
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++)
if (net_landrivers[net_landriverlevel].initialized)
int Datagram_Init (void);
void Datagram_Listen (qboolean state);
void Datagram_SearchForHosts (qboolean xmit);
-qboolean Datagram_SearchForInetHosts (char *master);
-qsocket_t *Datagram_Connect (char *host);
+qboolean Datagram_SearchForInetHosts (const char *master);
+qsocket_t *Datagram_Connect (const char *host);
qsocket_t *Datagram_CheckNewConnections (void);
int Datagram_GetMessage (qsocket_t *sock);
int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock);
void Datagram_Close (qsocket_t *sock);
void Datagram_Shutdown (void);
-void Datagram_Heartbeat (char *master);
+void Datagram_Heartbeat (const char *master);
#endif
}
-void Loop_Heartbeat (char *master)
+void Loop_Heartbeat (const char *master)
{
}
}
-qboolean Loop_SearchForInetHosts (char *master)
+qboolean Loop_SearchForInetHosts (const char *master)
{
return false;
}
-qsocket_t *Loop_Connect (char *host)
+qsocket_t *Loop_Connect (const char *host)
{
if (strcmp(host,"local") != 0)
return NULL;
int Loop_Init (void);
void Loop_Listen (qboolean state);
void Loop_SearchForHosts (qboolean xmit);
-qboolean Loop_SearchForInetHosts (char *master);
-qsocket_t *Loop_Connect (char *host);
+qboolean Loop_SearchForInetHosts (const char *master);
+qsocket_t *Loop_Connect (const char *host);
qsocket_t *Loop_CheckNewConnections (void);
int Loop_GetMessage (qsocket_t *sock);
int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data);
qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock);
void Loop_Close (qsocket_t *sock);
void Loop_Shutdown (void);
-void Loop_Heartbeat (char *master);
+void Loop_Heartbeat (const char *master);
#endif
static void NET_Heartbeat_f (void)
{
- NET_Heartbeat ();
+ NET_Heartbeat (2);
}
static void InetSlist_Send(void)
{
- char* host;
+ const char* host;
if (!slistInProgress)
return;
Send an heartbeat to the master server(s)
====================
*/
-void NET_Heartbeat (void)
+void NET_Heartbeat (int priority)
{
- char* host;
+ const char* host;
+
+ if (! Master_AllowHeartbeat (priority))
+ return;
+
while ((host = Master_BuildHeartbeat ()) != NULL)
{
for (net_driverlevel=0 ; net_driverlevel<net_numdrivers; net_driverlevel++)
#include "quakedef.h"
+
cvar_t sv_masters [] =
{
{CVAR_SAVE, "sv_master1", ""},
{CVAR_SAVE, "sv_master4", ""}
};
+static qboolean masteravailable = false;
+static double nextheartbeattime = 0;
+static unsigned int nbtries = 6;
+
+
+/*
+====================
+Master_AllowHeartbeat
+
+Allow (or not) NET_Heartbeat to proceed depending on various factors
+====================
+*/
+qboolean Master_AllowHeartbeat (int priority)
+{
+ // We try "nbtries" times to contact a master server before giving up
+ if (! masteravailable)
+ {
+ if (!nbtries || realtime < nextheartbeattime)
+ return false;
+
+ nbtries--;
+ }
+ else
+ {
+ // if it's a state change, it can wait a little bit (30 sec max for now)
+ if (priority == 1 && nextheartbeattime - realtime > 30.0)
+ {
+ nextheartbeattime = realtime + 30.0;
+ return false;
+ }
+
+ if (priority <= 1 && realtime < nextheartbeattime)
+ return false;
+ }
+
+ // send an heartbeat every 3 minutes by default (every 5 sec if we haven't yet found a master server)
+ // TODO: some cvars would be better than hardcoded values
+ nextheartbeattime = realtime + (masteravailable ? (3.0 * 60.0) : 5.0);
+ return true;
+}
+
/*
====================
Build a getservers request for a master server
====================
*/
-char* Master_BuildGetServers (void)
+const char* Master_BuildGetServers (void)
{
static int nextmaster = 0;
cvar_t* sv_master;
Build an heartbeat for a master server
====================
*/
-char* Master_BuildHeartbeat (void)
+const char* Master_BuildHeartbeat (void)
{
static int nextmaster = 0;
cvar_t* sv_master;
char response [512];
size_t length;
+ masteravailable = true;
+
length = snprintf (response, sizeof (response), "infoResponse\x0A"
"\\gamename\\%s\\modname\\%s\\sv_maxclients\\%d"
"\\clients\\%d\\mapname\\%s\\hostname\\%s\\protocol\\%d",
#define MASTER_PORT 27950
-char* Master_BuildGetServers (void);
-char* Master_BuildHeartbeat (void);
-int Master_HandleMessage (void);
-void Master_Init (void);
-void Master_ParseServerList (net_landriver_t* dfunc);
+qboolean Master_AllowHeartbeat (int priority);
+const char* Master_BuildGetServers (void);
+const char* Master_BuildHeartbeat (void);
+int Master_HandleMessage (void);
+void Master_Init (void);
+void Master_ParseServerList (net_landriver_t* dfunc);
#endif
Loop_CanSendMessage,
Loop_CanSendUnreliableMessage,
Loop_Close,
- Loop_Shutdown
+ Loop_Shutdown,
+ Loop_Heartbeat
}
,
{
Datagram_CanSendMessage,
Datagram_CanSendUnreliableMessage,
Datagram_Close,
- Datagram_Shutdown
+ Datagram_Shutdown,
+ Datagram_Heartbeat
}
};
SV_ConnectClient (i);
net_activeconnections++;
- NET_Heartbeat ();
+ NET_Heartbeat (1);
}
}
SV_SendServerinfo (host_client);
Con_DPrintf ("Server spawned.\n");
- NET_Heartbeat ();
+ NET_Heartbeat (2);
}