mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
Fetch server list from multiple masters to improve redundancy
This commit is contained in:
parent
007c680b45
commit
8aa1ebef5f
6 changed files with 180 additions and 71 deletions
|
@ -25,12 +25,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "cl_gamespy.h"
|
||||
#include "q_gamespy.h"
|
||||
|
||||
const char *ServerListGetHost()
|
||||
{
|
||||
return Com_GetMasterHost();
|
||||
unsigned int ServerListGetNumMasters() {
|
||||
return Com_GetNumMasterEntries();
|
||||
}
|
||||
|
||||
int ServerListGetMsPort()
|
||||
const char *ServerListGetHost(int index)
|
||||
{
|
||||
return Com_GetMasterQueryPort();
|
||||
return Com_GetMasterEntry(index)->host;
|
||||
}
|
||||
|
||||
int ServerListGetMsPort(int index)
|
||||
{
|
||||
return Com_GetMasterEntry(index)->queryport;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,23 @@ Fax(714)549-0757
|
|||
for this SDK. It also has a change history for the SDK.
|
||||
|
||||
******/
|
||||
|
||||
/**
|
||||
* The following modifications were made:
|
||||
*
|
||||
* 1) Non-blocking server list sockets. List requests are asynchronous and will not block the game. The only blocking request could be due to DNS resolution.
|
||||
* 2) Parallel server list requests.
|
||||
* 2.1) A pool of sockets is initially created
|
||||
* 2.2) The server list, initially in the `sl_idle` state, will connect those sockets to available masters.
|
||||
* 2.3) When at least one master replies, the server list transitions to sl_listxfer state.
|
||||
* 2.4) The server list receives from multiple masters
|
||||
* 2.5) When finished fetchign from 1 master, the server list transitions to sl_querying
|
||||
* 2.6) At this point all received servers get queried. Masters that haven't finished sending the list are still being processed
|
||||
* 2.7) When all received servers have been queried, the server list restarts from 2.4 with next masters to query
|
||||
*
|
||||
* NOTE: The idea here is mostly to ensure the redundancy of the server list between multiple masters
|
||||
* even if the results are combined.
|
||||
*/
|
||||
#include "goaceng.h"
|
||||
#include "gserver.h"
|
||||
#if defined(applec) || defined(THINK_C) || defined(__MWERKS__) && !defined(__KATANA__)
|
||||
|
@ -53,11 +70,12 @@ Fax(714)549-0757
|
|||
*
|
||||
* @return const char* The master host
|
||||
*/
|
||||
extern const char *ServerListGetHost();
|
||||
extern int ServerListGetMsPort();
|
||||
extern unsigned int ServerListGetNumMasters();
|
||||
extern const char *ServerListGetHost(int index);
|
||||
extern int ServerListGetMsPort(int index);
|
||||
|
||||
#define MSHOST ServerListGetHost()
|
||||
#define MSPORT ServerListGetMsPort()
|
||||
//#define MSHOST ServerListGetHost(0)
|
||||
//#define MSPORT ServerListGetMsPort(0)
|
||||
#define SERVER_GROWBY 64
|
||||
#define LAN_SEARCH_TIME 3000 //3 sec
|
||||
#define LIST_NUMKEYBUCKETS 500
|
||||
|
@ -80,6 +98,13 @@ typedef struct
|
|||
typedef enum { pi_fieldcount, pi_fields, pi_servers } GParseInfoState;
|
||||
typedef enum { ls_connecting, ls_connected, ls_finished } GListSocketState;
|
||||
|
||||
typedef struct GServerListSocketImplementation
|
||||
{
|
||||
SOCKET s;
|
||||
GListSocketState socketstate;
|
||||
char data[2048];
|
||||
} *GServerListSocket;
|
||||
|
||||
struct GServerListImplementation
|
||||
{
|
||||
GServerListState state;
|
||||
|
@ -96,9 +121,9 @@ struct GServerListImplementation
|
|||
void *instance;
|
||||
char *sortkey;
|
||||
gbool sortascending;
|
||||
GListSocketState socketstate;
|
||||
SOCKET slsocket;
|
||||
//SOCKET slsockets;
|
||||
GServerListSocket slsockets;
|
||||
int numslsockets;
|
||||
int startslindex;
|
||||
unsigned long lanstarttime;
|
||||
GQueryType querytype;
|
||||
HashTable keylist;
|
||||
|
@ -154,6 +179,10 @@ GServerList ServerListNew(const char *gamename, const char *enginename, const ch
|
|||
// Added in OPM
|
||||
list->encryptdata = 1;
|
||||
|
||||
list->slsockets = (GServerListSocket)malloc(sizeof(struct GServerListSocketImplementation));
|
||||
list->numslsockets = 1;
|
||||
list->startslindex = 0;
|
||||
|
||||
SocketStartUp();
|
||||
return list;
|
||||
}
|
||||
|
@ -166,6 +195,7 @@ void ServerListFree(GServerList serverlist)
|
|||
ArrayFree(serverlist->servers);
|
||||
TableFree(serverlist->keylist);
|
||||
free(serverlist->updatelist);
|
||||
free(serverlist->slsockets);
|
||||
|
||||
free(serverlist);
|
||||
SocketShutDown();
|
||||
|
@ -208,53 +238,79 @@ static GError FreeUpdateList(GServerList serverlist)
|
|||
}
|
||||
|
||||
//create and connect a server list socket
|
||||
static GError CreateServerListSocket(GServerList serverlist, gbool async)
|
||||
static GError CreateServerListSocket(GServerList serverlist, GServerListSocket slsocket, gbool async)
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
struct hostent *hent;
|
||||
int lasterr;
|
||||
int i;
|
||||
int port;
|
||||
const char *host;
|
||||
|
||||
if (serverlist->startslindex >= ServerListGetNumMasters()) {
|
||||
return GE_NODNS;
|
||||
}
|
||||
|
||||
port = ServerListGetMsPort(serverlist->startslindex);
|
||||
host = ServerListGetHost(serverlist->startslindex);
|
||||
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(MSPORT);
|
||||
saddr.sin_addr.s_addr = inet_addr(MSHOST);
|
||||
saddr.sin_port = htons(port);
|
||||
saddr.sin_addr.s_addr = inet_addr(host);
|
||||
if (saddr.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
hent = gethostbyname(MSHOST);
|
||||
hent = gethostbyname(host);
|
||||
if (!hent)
|
||||
return GE_NODNS;
|
||||
saddr.sin_addr.s_addr = *(u_long *)hent->h_addr_list[0];
|
||||
}
|
||||
serverlist->slsocket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if (serverlist->slsocket == INVALID_SOCKET)
|
||||
slsocket->s = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if (slsocket->s == INVALID_SOCKET)
|
||||
return GE_NOSOCKET;
|
||||
|
||||
if (async) {
|
||||
SetSockBlocking(serverlist->slsocket, 0);
|
||||
SetSockBlocking(slsocket->s, 0);
|
||||
}
|
||||
|
||||
if (connect ( serverlist->slsocket, (struct sockaddr *) &saddr, sizeof saddr ) != 0
|
||||
&& (lasterr = GOAGetLastError(serverlist->slsocket), lasterr != WSAEWOULDBLOCK && lasterr != WSAEINPROGRESS))
|
||||
if (connect ( slsocket->s, (struct sockaddr *) &saddr, sizeof saddr ) != 0
|
||||
&& (lasterr = GOAGetLastError(slsocket->slsocket), lasterr != WSAEWOULDBLOCK && lasterr != WSAEINPROGRESS))
|
||||
{
|
||||
closesocket(serverlist->slsocket);
|
||||
closesocket(slsocket->s);
|
||||
return GE_NOCONNECT;
|
||||
}
|
||||
|
||||
slsocket->socketstate = ls_connecting;
|
||||
serverlist->startslindex++;
|
||||
|
||||
//else we are connected
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//create and connect a server list sockets
|
||||
static GError CreateServerListSockets(GServerList serverlist, gbool async)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < serverlist->numslsockets; i++) {
|
||||
CreateServerListSocket(serverlist, &serverlist->slsockets[i], async);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//create and connect a server list socket
|
||||
static GError CreateServerListLANSocket(GServerList serverlist)
|
||||
{
|
||||
int optval = 1;
|
||||
GServerListSocket slsocket = &serverlist->slsockets[0];
|
||||
|
||||
serverlist->slsocket = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if (serverlist->slsocket == INVALID_SOCKET)
|
||||
slsocket->s = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if (slsocket->s == INVALID_SOCKET)
|
||||
return GE_NOSOCKET;
|
||||
if (setsockopt(serverlist->slsocket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
if (setsockopt(slsocket->s, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
return GE_NOSOCKET;
|
||||
|
||||
//else we are ready to broadcast
|
||||
|
@ -274,14 +330,14 @@ static void ServerListModeChange(GServerList serverlist, GServerListState newsta
|
|||
|
||||
// validate us to the master and send a list request
|
||||
#define SECURE "\\secure\\"
|
||||
static GError SendListRequest(GServerList serverlist, char *filter)
|
||||
static GError SendListRequest(GServerList serverlist, GServerListSocket slsocket, char *filter)
|
||||
{
|
||||
char data[256], *ptr, result[64];
|
||||
int len;
|
||||
int i;
|
||||
char *modifier;
|
||||
|
||||
len = recv(serverlist->slsocket, data, sizeof(data) - 1, 0);
|
||||
len = recv(slsocket->s, data, sizeof(data) - 1, 0);
|
||||
if (gsiSocketIsError(len)) {
|
||||
return GE_NOCONNECT;
|
||||
}
|
||||
|
@ -312,7 +368,7 @@ static GError SendListRequest(GServerList serverlist, char *filter)
|
|||
serverlist->enginename, ENGINE_VERSION, result); //validate us
|
||||
}
|
||||
|
||||
len = send ( serverlist->slsocket, data, strlen(data), 0 );
|
||||
len = send ( slsocket->s, data, strlen(data), 0 );
|
||||
if (gsiSocketIsError(len) || len == 0)
|
||||
return GE_NOCONNECT;
|
||||
|
||||
|
@ -333,7 +389,7 @@ static GError SendListRequest(GServerList serverlist, char *filter)
|
|||
sprintf(data, "\\list\\%s\\gamename\\%s\\where\\%s\\final\\", modifier, serverlist->gamename, filter);
|
||||
else
|
||||
sprintf(data, "\\list\\%s\\gamename\\%s\\final\\", modifier, serverlist->gamename);
|
||||
len = send ( serverlist->slsocket, data, strlen(data), 0 );
|
||||
len = send ( slsocket->s, data, strlen(data), 0 );
|
||||
if (gsiSocketIsError(len) || len == 0)
|
||||
return GE_NOCONNECT;
|
||||
|
||||
|
@ -352,7 +408,7 @@ static GError SendBroadcastRequest(GServerList serverlist, int startport, int en
|
|||
for (i = startport ; i <= endport ; i += delta)
|
||||
{
|
||||
saddr.sin_port = htons(i);
|
||||
sendto(serverlist->slsocket, "\\status\\",8,0,(struct sockaddr *)&saddr,sizeof(saddr));
|
||||
sendto(serverlist->slsockets[0].s, "\\status\\",8,0,(struct sockaddr *)&saddr,sizeof(saddr));
|
||||
}
|
||||
ServerListModeChange(serverlist, sl_lanlist);
|
||||
serverlist->lanstarttime = current_time();
|
||||
|
@ -385,17 +441,17 @@ GError ServerListUpdate(GServerList serverlist, gbool async)
|
|||
/* ServerListStartQuery
|
||||
-------------------------
|
||||
Start querying a GServerList. */
|
||||
GError ServerListStartQuery(GServerList serverlist, gbool async)
|
||||
GError ServerListStartQuery(GServerList serverlist, GServerListSocket slsocket, gbool async)
|
||||
{
|
||||
GError error;
|
||||
|
||||
if (serverlist->socketstate != ls_connecting) {
|
||||
if (slsocket->socketstate != ls_connecting) {
|
||||
return GE_BUSY;
|
||||
}
|
||||
|
||||
if (serverlist->abortupdate) {
|
||||
closesocket(serverlist->slsocket);
|
||||
serverlist->slsocket = INVALID_SOCKET;
|
||||
closesocket(slsocket->s);
|
||||
slsocket->s = INVALID_SOCKET;
|
||||
ServerListModeChange(serverlist, sl_idle);
|
||||
return GE_NOCONNECT;
|
||||
}
|
||||
|
@ -404,23 +460,23 @@ GError ServerListStartQuery(GServerList serverlist, gbool async)
|
|||
// Abort if the socket is in error
|
||||
int so_error;
|
||||
int len = sizeof(so_error);
|
||||
getsockopt(serverlist->slsocket, SOL_SOCKET, SO_ERROR, &so_error, &len);
|
||||
getsockopt(slsocket->s, SOL_SOCKET, SO_ERROR, &so_error, &len);
|
||||
|
||||
if (so_error) {
|
||||
serverlist->socketstate = ls_connected;
|
||||
slsocket->socketstate = ls_finished;
|
||||
return GE_NOCONNECT;
|
||||
}
|
||||
|
||||
// Check for pending data
|
||||
char buf;
|
||||
if (recv(serverlist->slsocket, &buf, 1, MSG_PEEK) == -1) {
|
||||
if (recv(slsocket->s, &buf, 1, MSG_PEEK) == -1) {
|
||||
return GE_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
serverlist->socketstate = ls_connected;
|
||||
slsocket->socketstate = ls_connected;
|
||||
|
||||
error = SendListRequest(serverlist, serverlist->filter);
|
||||
error = SendListRequest(serverlist, slsocket, serverlist->filter);
|
||||
if (error) return error;
|
||||
if (serverlist->querytype != qt_grouprooms && serverlist->querytype != qt_masterinfo) {
|
||||
error = InitUpdateList(serverlist);
|
||||
|
@ -439,13 +495,14 @@ Start updating a GServerList. */
|
|||
GError ServerListUpdate2(GServerList serverlist, gbool async, char *filter, GQueryType querytype)
|
||||
{
|
||||
GError error;
|
||||
int i;
|
||||
|
||||
if (serverlist->state != sl_idle)
|
||||
return GE_BUSY;
|
||||
|
||||
serverlist->querytype = querytype;
|
||||
error = CreateServerListSocket(serverlist, async);
|
||||
if (error) return error;
|
||||
error = CreateServerListSockets(serverlist, async);
|
||||
//if (error) return error;
|
||||
|
||||
serverlist->nextupdate = 0;
|
||||
serverlist->abortupdate = 0;
|
||||
|
@ -455,13 +512,13 @@ GError ServerListUpdate2(GServerList serverlist, gbool async, char *filter, GQue
|
|||
serverlist->cryptinfo.offset = -1;
|
||||
strncpy(serverlist->filter, filter, sizeof(serverlist->filter));
|
||||
|
||||
serverlist->socketstate = ls_connecting;
|
||||
|
||||
if (async) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ServerListStartQuery(serverlist, async);
|
||||
for(i = 0; i < serverlist->numslsockets; i++) {
|
||||
ServerListStartQuery(serverlist, &serverlist->slsockets[i], async);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -650,7 +707,7 @@ GError ServerListAuxUpdate(GServerList serverlist, const char *ip, int port, gbo
|
|||
return 0;
|
||||
}
|
||||
|
||||
static GError ServerListLANList(GServerList serverlist)
|
||||
static GError ServerListLANList(GServerList serverlist, GServerListSocket slsocket)
|
||||
{
|
||||
struct timeval timeout = {0,0};
|
||||
fd_set set;
|
||||
|
@ -662,11 +719,11 @@ static GError ServerListLANList(GServerList serverlist)
|
|||
while (1) //we break if the select fails
|
||||
{
|
||||
FD_ZERO(&set);
|
||||
FD_SET( serverlist->slsocket, &set);
|
||||
FD_SET( slsocket->s, &set);
|
||||
error = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
|
||||
if (gsiSocketIsError(error) || 0 == error) //no data
|
||||
break;
|
||||
error = recvfrom(serverlist->slsocket, indata, sizeof(indata) - 1, 0, (struct sockaddr *)&saddr, &saddrlen );
|
||||
error = recvfrom(slsocket->s, indata, sizeof(indata) - 1, 0, (struct sockaddr *)&saddr, &saddrlen );
|
||||
if (gsiSocketIsError(error))
|
||||
continue;
|
||||
//we got data, add the server to the list to update
|
||||
|
@ -675,8 +732,8 @@ static GError ServerListLANList(GServerList serverlist)
|
|||
}
|
||||
if (current_time() - serverlist->lanstarttime > LAN_SEARCH_TIME) //done waiting for replies
|
||||
{
|
||||
closesocket(serverlist->slsocket);
|
||||
serverlist->slsocket = INVALID_SOCKET;
|
||||
closesocket(slsocket->s);
|
||||
slsocket->s = INVALID_SOCKET;
|
||||
ServerListModeChange(serverlist, sl_querying);
|
||||
}
|
||||
return 0;
|
||||
|
@ -772,7 +829,7 @@ static int ServerListParseInfoList(GServerList serverlist, char *data, int len)
|
|||
}
|
||||
|
||||
//reads the server list from the socket and parses it
|
||||
static GError ServerListReadList(GServerList serverlist)
|
||||
static GError ServerListReadList(GServerList serverlist, GServerListSocket slsocket)
|
||||
{
|
||||
static char data[2048]; //static input buffer
|
||||
static int oldlen = 0;
|
||||
|
@ -784,7 +841,7 @@ static GError ServerListReadList(GServerList serverlist)
|
|||
unsigned short port;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(serverlist->slsocket, &set);
|
||||
FD_SET(slsocket->s, &set);
|
||||
#ifndef KGTRN_ACCESS
|
||||
i = select( FD_SETSIZE, &set, NULL, NULL, &timeout );
|
||||
if (i <= 0)
|
||||
|
@ -792,11 +849,11 @@ static GError ServerListReadList(GServerList serverlist)
|
|||
#endif
|
||||
|
||||
//append to data
|
||||
len = recv(serverlist->slsocket, data + oldlen, sizeof(data) - oldlen - 1, 0);
|
||||
len = recv(slsocket->s, data + oldlen, sizeof(data) - oldlen - 1, 0);
|
||||
if (gsiSocketIsError(len) || len == 0)
|
||||
{
|
||||
closesocket(serverlist->slsocket);
|
||||
serverlist->slsocket = INVALID_SOCKET;
|
||||
closesocket(slsocket->s);
|
||||
slsocket->s = INVALID_SOCKET;
|
||||
oldlen = 0; //clear data so it can be used again
|
||||
ServerListHalt(serverlist);
|
||||
ServerListModeChange(serverlist, sl_querying);
|
||||
|
@ -835,8 +892,8 @@ static GError ServerListReadList(GServerList serverlist)
|
|||
{
|
||||
if (strncmp(p,"\\final\\",7) == 0 || serverlist->abortupdate)
|
||||
{
|
||||
closesocket(serverlist->slsocket);
|
||||
serverlist->slsocket = INVALID_SOCKET;
|
||||
closesocket(slsocket->s);
|
||||
slsocket->s = INVALID_SOCKET;
|
||||
oldlen = 0; //clear data so it can be used again
|
||||
if (serverlist->querytype == qt_grouprooms || serverlist->querytype == qt_masterinfo) {
|
||||
ServerListModeChange(serverlist, sl_idle);
|
||||
|
@ -971,16 +1028,16 @@ static GError ServerListQueryLoop(GServerList serverlist)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ServerListThink
|
||||
/* ServerListThinkSocket
|
||||
------------------
|
||||
For use with Async Updates. This needs to be called every ~10ms for list processing and
|
||||
updating to occur during async server list updates */
|
||||
GError ServerListThink(GServerList serverlist)
|
||||
GError ServerListThinkSocket(GServerList serverlist, GServerListSocket slsocket)
|
||||
{
|
||||
switch(serverlist->socketstate)
|
||||
switch(slsocket->socketstate)
|
||||
{
|
||||
case ls_connecting:
|
||||
ServerListStartQuery(serverlist, 1);
|
||||
ServerListStartQuery(serverlist, slsocket, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -991,16 +1048,30 @@ GError ServerListThink(GServerList serverlist)
|
|||
case sl_idle: return 0;
|
||||
case sl_listxfer:
|
||||
//read the data
|
||||
return ServerListReadList(serverlist);
|
||||
return ServerListReadList(serverlist, slsocket);
|
||||
break;
|
||||
case sl_lanlist:
|
||||
return ServerListLANList(serverlist);
|
||||
return ServerListLANList(serverlist, slsocket);
|
||||
case sl_querying:
|
||||
//do some queries
|
||||
return ServerListQueryLoop(serverlist);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ServerListThink
|
||||
------------------
|
||||
For use with Async Updates. This needs to be called every ~10ms for list processing and
|
||||
updating to occur during async server list updates */
|
||||
GError ServerListThink(GServerList serverlist)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < serverlist->numslsockets; i++) {
|
||||
ServerListThinkSocket(serverlist, &serverlist->slsockets[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,22 +23,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#pragma once
|
||||
|
||||
#include "q_gamespy.h"
|
||||
#include "q_shared.h"
|
||||
|
||||
master_entry_t entries[16] =
|
||||
{
|
||||
{ "master.333networks.com", 28900, 27900 },
|
||||
{ "master.errorist.eu", 28900, 27900 }
|
||||
};
|
||||
|
||||
int num_entries = 1;
|
||||
|
||||
void Com_InitGameSpy()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int Com_GetNumMasterEntries() {
|
||||
return num_entries;
|
||||
}
|
||||
|
||||
const master_entry_t *Com_GetMasterEntry(int index) {
|
||||
if (index >= num_entries) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &entries[index];
|
||||
}
|
||||
|
||||
const char *Com_GetMasterHost()
|
||||
{
|
||||
return "master.333networks.com";
|
||||
return entries[0].host;
|
||||
}
|
||||
|
||||
int Com_GetMasterQueryPort()
|
||||
{
|
||||
return 28900;
|
||||
return entries[0].queryport;
|
||||
}
|
||||
|
||||
int Com_GetMasterHeartbeatPort()
|
||||
{
|
||||
return 27900;
|
||||
return entries[0].hbport;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
char host[128];
|
||||
int queryport;
|
||||
int hbport;
|
||||
} master_entry_t;
|
||||
|
||||
void Com_InitGameSpy();
|
||||
|
||||
unsigned int Com_GetNumMasterEntries();
|
||||
const master_entry_t *Com_GetMasterEntry(int index);
|
||||
const char *Com_GetMasterHost();
|
||||
int Com_GetMasterQueryPort();
|
||||
int Com_GetMasterHeartbeatPort();
|
||||
|
|
|
@ -503,12 +503,17 @@ void SV_GamespyAuthorize(netadr_t from, const char *response)
|
|||
}
|
||||
}
|
||||
|
||||
const char *qr_get_master_host()
|
||||
unsigned int qr_get_num_masters()
|
||||
{
|
||||
return Com_GetMasterHost();
|
||||
return Com_GetNumMasterEntries();
|
||||
}
|
||||
|
||||
int qr_get_master_port()
|
||||
const char *qr_get_master_host(int index)
|
||||
{
|
||||
return Com_GetMasterHeartbeatPort();
|
||||
return Com_GetMasterEntry(index)->host;
|
||||
}
|
||||
|
||||
int qr_get_master_port(int index)
|
||||
{
|
||||
return Com_GetMasterEntry(index)->hbport;
|
||||
}
|
||||
|
|
|
@ -65,9 +65,9 @@ as the base port. Generally there is no reason to modify this value.
|
|||
/********
|
||||
DEFINES
|
||||
********/
|
||||
#define MASTER_PORT qr_get_master_port()
|
||||
#define MASTER_PORT qr_get_master_port(0)
|
||||
//#define MASTER_ADDR "master." GSI_DOMAIN_NAME
|
||||
#define MASTER_ADDR qr_get_master_host()
|
||||
#define MASTER_ADDR qr_get_master_host(0)
|
||||
#define FIRST_HB_TIME 30000 /* 30 sec */
|
||||
#define HB_TIME 300000 /* 5 minutes */
|
||||
#define MAX_FIRST_COUNT 10 /* 10 tries = 5 minutes */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue