mirror of
https://github.com/nillerusr/source-engine.git
synced 2025-04-20 18:07:26 +00:00

The domain form does not work properly on the dedicated server's Windows build. If you need to fix it, you can execute UseDefault() again after the program is fully loaded or use the console command "addmaster". Everything works fine on Linux.
724 lines
18 KiB
C++
724 lines
18 KiB
C++
//======177== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ========
|
|
//
|
|
// The copyright to the contents herein is the property of Valve, L.L.C.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $Workfile: $
|
|
// $Date: $
|
|
// $NoKeywords: $
|
|
//=============================================================================
|
|
#include "quakedef.h"
|
|
#include "server.h"
|
|
#include "master.h"
|
|
#include "proto_oob.h"
|
|
#include "host.h"
|
|
#include "eiface.h"
|
|
#include "server.h"
|
|
#include "utlmap.h"
|
|
|
|
extern ConVar sv_tags;
|
|
extern ConVar sv_lan;
|
|
|
|
#define S2A_EXTRA_DATA_HAS_GAMETAG_DATA 0x01 // Next bytes are the game tag string
|
|
#define RETRY_INFO_REQUEST_TIME 0.4 // seconds
|
|
#define MASTER_RESPONSE_TIMEOUT 1.5 // seconds
|
|
#define INFO_REQUEST_TIMEOUT 5.0 // seconds
|
|
|
|
static char g_MasterServers[][64] =
|
|
{
|
|
"185.192.97.130:27010",
|
|
"168.138.92.21:27016",
|
|
"157.173.106.37:27010",
|
|
"oreo922.cn:27010"
|
|
};
|
|
|
|
#ifdef DEDICATED
|
|
#define IsLan() false
|
|
#else
|
|
#define IsLan() sv_lan.GetInt()
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: List of master servers and some state info about them
|
|
//-----------------------------------------------------------------------------
|
|
typedef struct adrlist_s
|
|
{
|
|
// Next master in chain
|
|
struct adrlist_s *next;
|
|
// Challenge request sent to master
|
|
qboolean heartbeatwaiting;
|
|
// Challenge request send time
|
|
float heartbeatwaitingtime;
|
|
// Last one is Main master
|
|
int heartbeatchallenge;
|
|
// Time we sent last heartbeat
|
|
double last_heartbeat;
|
|
// Master server address
|
|
netadr_t adr;
|
|
} adrlist_t;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Implements the master server interface
|
|
//-----------------------------------------------------------------------------
|
|
class CMaster : public IMaster, public IServersInfo
|
|
{
|
|
public:
|
|
CMaster( void );
|
|
virtual ~CMaster( void );
|
|
|
|
// Heartbeat functions.
|
|
void Init( void );
|
|
void Shutdown( void );
|
|
// Sets up master address
|
|
void ShutdownConnection(void);
|
|
void SendHeartbeat( struct adrlist_s *p );
|
|
void AddServer( struct netadr_s *adr );
|
|
void UseDefault ( void );
|
|
void CheckHeartbeat (void);
|
|
void RespondToHeartbeatChallenge( netadr_t &from, bf_read &msg );
|
|
void PingServer( netadr_t &svadr );
|
|
|
|
void ProcessConnectionlessPacket( netpacket_t *packet );
|
|
|
|
void AddMaster_f( const CCommand &args );
|
|
void Heartbeat_f( void );
|
|
|
|
void RunFrame();
|
|
void RetryServersInfoRequest();
|
|
|
|
void ReplyInfo( const netadr_t &adr, uint sequence );
|
|
newgameserver_t &ProcessInfo( bf_read &buf );
|
|
|
|
// SeversInfo
|
|
void RequestInternetServerList( const char *gamedir, IServerListResponse *response );
|
|
void RequestLANServerList( const char *gamedir, IServerListResponse *response );
|
|
void AddServerAddresses( netadr_t **adr, int count );
|
|
void RequestServerInfo( const netadr_t &adr );
|
|
void StopRefresh();
|
|
|
|
private:
|
|
// List of known master servers
|
|
adrlist_t *m_pMasterAddresses;
|
|
|
|
bool m_bInitialized;
|
|
bool m_bRefreshing;
|
|
|
|
int m_iServersResponded;
|
|
|
|
double m_flStartRequestTime;
|
|
double m_flRetryRequestTime;
|
|
double m_flMasterRequestTime;
|
|
|
|
uint m_iInfoSequence;
|
|
char m_szGameDir[256];
|
|
|
|
// If nomaster is true, the server will not send heartbeats to the master server
|
|
bool m_bNoMasters;
|
|
|
|
CUtlMap<netadr_t, bool> m_serverAddresses;
|
|
CUtlMap<uint, double> m_serversRequestTime;
|
|
|
|
IServerListResponse *m_serverListResponse;
|
|
};
|
|
|
|
static CMaster s_MasterServer;
|
|
IMaster *master = (IMaster *)&s_MasterServer;
|
|
|
|
IServersInfo *g_pServersInfo = (IServersInfo*)&s_MasterServer;
|
|
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CMaster, IServersInfo, SERVERLIST_INTERFACE_VERSION, s_MasterServer );
|
|
|
|
#define HEARTBEAT_SECONDS 140.0
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CMaster::CMaster( void )
|
|
{
|
|
m_pMasterAddresses = NULL;
|
|
m_bNoMasters = false;
|
|
m_bInitialized = false;
|
|
m_iServersResponded = 0;
|
|
|
|
m_serverListResponse = NULL;
|
|
SetDefLessFunc( m_serverAddresses );
|
|
SetDefLessFunc( m_serversRequestTime );
|
|
m_bRefreshing = false;
|
|
m_iInfoSequence = 1;
|
|
|
|
Init();
|
|
}
|
|
|
|
CMaster::~CMaster( void )
|
|
{
|
|
}
|
|
|
|
void CMaster::RunFrame()
|
|
{
|
|
CheckHeartbeat();
|
|
|
|
if( !m_bRefreshing )
|
|
return;
|
|
|
|
if( m_serverListResponse &&
|
|
m_flStartRequestTime < Plat_FloatTime()-INFO_REQUEST_TIMEOUT )
|
|
{
|
|
StopRefresh();
|
|
m_serverListResponse->RefreshComplete( NServerResponse::nServerFailedToRespond );
|
|
return;
|
|
}
|
|
|
|
if( m_iServersResponded > 0 &&
|
|
m_iServersResponded >= m_serverAddresses.Count() &&
|
|
m_flMasterRequestTime < Plat_FloatTime() - MASTER_RESPONSE_TIMEOUT )
|
|
{
|
|
StopRefresh();
|
|
m_serverListResponse->RefreshComplete( NServerResponse::nServerResponded );
|
|
return;
|
|
}
|
|
|
|
if( m_flRetryRequestTime < Plat_FloatTime() - RETRY_INFO_REQUEST_TIME )
|
|
{
|
|
m_flRetryRequestTime = Plat_FloatTime();
|
|
|
|
if( m_serverAddresses.Count() == 0 ) // Retry masterserver request
|
|
{
|
|
g_pServersInfo->RequestInternetServerList(m_szGameDir, NULL);
|
|
return;
|
|
}
|
|
|
|
if( m_iServersResponded < m_serverAddresses.Count() )
|
|
RetryServersInfoRequest();
|
|
}
|
|
}
|
|
|
|
void CMaster::StopRefresh()
|
|
{
|
|
if( !m_bRefreshing )
|
|
return;
|
|
|
|
m_iServersResponded = 0;
|
|
m_bRefreshing = false;
|
|
m_serverAddresses.RemoveAll();
|
|
m_serversRequestTime.RemoveAll();
|
|
}
|
|
|
|
void CMaster::ReplyInfo( const netadr_t &adr, uint sequence )
|
|
{
|
|
static char gamedir[MAX_OSPATH];
|
|
Q_FileBase( com_gamedir, gamedir, sizeof( gamedir ) );
|
|
|
|
CUtlBuffer buf;
|
|
buf.EnsureCapacity( 2048 );
|
|
|
|
buf.PutUnsignedInt( LittleDWord( CONNECTIONLESS_HEADER ) );
|
|
buf.PutUnsignedChar( S2C_INFOREPLY );
|
|
|
|
buf.PutUnsignedInt(sequence);
|
|
buf.PutUnsignedChar( PROTOCOL_VERSION ); // Hardcoded protocol version number
|
|
buf.PutString( sv.GetName() );
|
|
buf.PutString( sv.GetMapName() );
|
|
buf.PutString( gamedir );
|
|
buf.PutString( serverGameDLL->GetGameDescription() );
|
|
|
|
// player info
|
|
buf.PutUnsignedChar( sv.GetNumClients() );
|
|
buf.PutUnsignedChar( sv.GetMaxClients() );
|
|
buf.PutUnsignedChar( sv.GetNumFakeClients() );
|
|
|
|
// Password?
|
|
buf.PutUnsignedChar( sv.GetPassword() != NULL ? 1 : 0 );
|
|
|
|
// Write a byte with some flags that describe what is to follow.
|
|
const char *pchTags = sv_tags.GetString();
|
|
int nFlags = 0;
|
|
|
|
if ( pchTags && pchTags[0] != '\0' )
|
|
nFlags |= S2A_EXTRA_DATA_HAS_GAMETAG_DATA;
|
|
|
|
buf.PutUnsignedInt( nFlags );
|
|
|
|
if ( nFlags & S2A_EXTRA_DATA_HAS_GAMETAG_DATA )
|
|
buf.PutString( pchTags );
|
|
|
|
NET_SendPacket( NULL, NS_SERVER, adr, (unsigned char *)buf.Base(), buf.TellPut() );
|
|
}
|
|
|
|
newgameserver_t &CMaster::ProcessInfo(bf_read &buf)
|
|
{
|
|
static newgameserver_t s;
|
|
memset( &s, 0, sizeof(s) );
|
|
|
|
s.m_nProtocolVersion = buf.ReadByte();
|
|
|
|
buf.ReadString( s.m_szServerName, sizeof(s.m_szServerName) );
|
|
buf.ReadString( s.m_szMap, sizeof(s.m_szMap) );
|
|
buf.ReadString( s.m_szGameDir, sizeof(s.m_szGameDir) );
|
|
|
|
buf.ReadString( s.m_szGameDescription, sizeof(s.m_szGameDescription) );
|
|
|
|
// player info
|
|
s.m_nPlayers = buf.ReadByte();
|
|
s.m_nMaxPlayers = buf.ReadByte();
|
|
s.m_nBotPlayers = buf.ReadByte();
|
|
|
|
// Password?
|
|
s.m_bPassword = buf.ReadByte();
|
|
s.m_iFlags = buf.ReadLong();
|
|
|
|
if( s.m_iFlags & S2A_EXTRA_DATA_HAS_GAMETAG_DATA )
|
|
{
|
|
buf.ReadString( s.m_szGameTags, sizeof(s.m_szGameTags) );
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
void CMaster::ProcessConnectionlessPacket( netpacket_t *packet )
|
|
{
|
|
static ALIGN4 char string[2048] ALIGN4_POST; // Buffer for sending heartbeat
|
|
|
|
uint ip; uint16 port;
|
|
|
|
bf_read msg = packet->message;
|
|
char c = msg.ReadChar();
|
|
|
|
if ( c == 0 )
|
|
return;
|
|
|
|
switch( c )
|
|
{
|
|
case M2S_CHALLENGE:
|
|
{
|
|
RespondToHeartbeatChallenge( packet->from, msg );
|
|
break;
|
|
}
|
|
case M2C_QUERY:
|
|
{
|
|
if( !m_bRefreshing )
|
|
break;
|
|
|
|
ip = msg.ReadLong();
|
|
port = msg.ReadShort();
|
|
|
|
while( ip != 0 && port != 0 )
|
|
{
|
|
netadr_t adr(ip, port);
|
|
|
|
unsigned short index = m_serverAddresses.Find(adr);
|
|
if( index != m_serverAddresses.InvalidIndex() )
|
|
{
|
|
ip = msg.ReadLong();
|
|
port = msg.ReadShort();
|
|
continue;
|
|
}
|
|
|
|
m_serverAddresses.Insert(adr, false);
|
|
RequestServerInfo(adr);
|
|
|
|
ip = msg.ReadLong();
|
|
port = msg.ReadShort();
|
|
}
|
|
break;
|
|
}
|
|
case C2S_INFOREQUEST:
|
|
{
|
|
ReplyInfo(packet->from, msg.ReadLong());
|
|
break;
|
|
}
|
|
case S2C_INFOREPLY:
|
|
{
|
|
if( !m_bRefreshing )
|
|
break;
|
|
|
|
uint sequence = msg.ReadLong();
|
|
newgameserver_t &s = ProcessInfo( msg );
|
|
|
|
unsigned short index = m_serverAddresses.Find(packet->from);
|
|
unsigned short rindex = m_serversRequestTime.Find(sequence);
|
|
|
|
if( index == m_serverAddresses.InvalidIndex() ||
|
|
rindex == m_serversRequestTime.InvalidIndex() )
|
|
break;
|
|
|
|
double requestTime = m_serversRequestTime[rindex];
|
|
|
|
if( m_serverAddresses[index] ) // shit happens
|
|
return;
|
|
|
|
m_serverAddresses[index] = true;
|
|
s.m_nPing = (Plat_FloatTime()-requestTime)*1000.0;
|
|
s.m_NetAdr = packet->from;
|
|
m_serverListResponse->ServerResponded( s );
|
|
|
|
m_iServersResponded++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMaster::RequestServerInfo( const netadr_t &adr )
|
|
{
|
|
static ALIGN4 char string[256] ALIGN4_POST; // Buffer for sending heartbeat
|
|
bf_write msg( string, sizeof(string) );
|
|
|
|
msg.WriteLong( CONNECTIONLESS_HEADER );
|
|
msg.WriteByte( C2S_INFOREQUEST );
|
|
msg.WriteLong( m_iInfoSequence );
|
|
m_serversRequestTime.Insert(m_iInfoSequence, Plat_FloatTime());
|
|
|
|
m_iInfoSequence++;
|
|
NET_SendPacket( NULL, NS_CLIENT, adr, msg.GetData(), msg.GetNumBytesWritten() );
|
|
}
|
|
|
|
void CMaster::RetryServersInfoRequest()
|
|
{
|
|
FOR_EACH_MAP_FAST( m_serverAddresses, i )
|
|
{
|
|
bool bResponded = m_serverAddresses.Element(i);
|
|
if( bResponded )
|
|
continue;
|
|
|
|
const netadr_t adr = m_serverAddresses.Key(i);
|
|
RequestServerInfo( adr );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Sends a heartbeat to the master server
|
|
// Input : *p - x00\x00\x00\x00\x00\x00
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::SendHeartbeat ( adrlist_t *p )
|
|
{
|
|
static ALIGN4 char string[256] ALIGN4_POST; // Buffer for sending heartbeat
|
|
char szGD[ MAX_OSPATH ];
|
|
|
|
if ( !p )
|
|
return;
|
|
|
|
// Still waiting on challenge response?
|
|
if ( p->heartbeatwaiting )
|
|
return;
|
|
|
|
// Waited too long
|
|
if ( (realtime - p->heartbeatwaitingtime ) >= HB_TIMEOUT )
|
|
return;
|
|
|
|
// Send to master
|
|
Q_FileBase( com_gamedir, szGD, sizeof( szGD ) );
|
|
|
|
bf_write buf( string, sizeof(string) );
|
|
buf.WriteByte( S2M_HEARTBEAT );
|
|
buf.WriteLong( p->heartbeatchallenge );
|
|
buf.WriteShort( PROTOCOL_VERSION );
|
|
buf.WriteString( szGD );
|
|
|
|
NET_SendPacket( NULL, NS_SERVER, p->adr, buf.GetData(), buf.GetNumBytesWritten() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Requests a challenge so we can then send a heartbeat
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::CheckHeartbeat (void)
|
|
{
|
|
adrlist_t *p;
|
|
ALIGN4 char buf[256] ALIGN4_POST;
|
|
|
|
if ( m_bNoMasters || // We are ignoring heartbeats
|
|
IsLan() || // Lan servers don't heartbeat
|
|
(sv.GetMaxClients() <= 1) || // not a multiplayer server.
|
|
!sv.IsActive() ) // only heartbeat if a server is running.
|
|
return;
|
|
|
|
p = m_pMasterAddresses;
|
|
while ( p )
|
|
{
|
|
// Time for another try?
|
|
if ( ( realtime - p->last_heartbeat) < HEARTBEAT_SECONDS) // not time to send yet
|
|
{
|
|
p = p->next;
|
|
continue;
|
|
}
|
|
|
|
// Should we resend challenge request?
|
|
if ( p->heartbeatwaiting &&
|
|
( ( realtime - p->heartbeatwaitingtime ) < HB_TIMEOUT ) )
|
|
{
|
|
p = p->next;
|
|
continue;
|
|
}
|
|
|
|
int32 challenge = RandomInt( 0, INT_MAX );
|
|
|
|
p->heartbeatwaiting = true;
|
|
p->heartbeatwaitingtime = realtime;
|
|
|
|
p->last_heartbeat = realtime; // Flag at start so we don't just keep trying for hb's when
|
|
p->heartbeatchallenge = challenge;
|
|
|
|
bf_write msg("Master Join", buf, sizeof(buf));
|
|
|
|
msg.WriteByte( S2M_GETCHALLENGE );
|
|
msg.WriteLong( challenge );
|
|
|
|
// Send to master asking for a challenge #
|
|
NET_SendPacket( NULL, NS_SERVER, p->adr, msg.GetData(), msg.GetNumBytesWritten() );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Server is shutting down, unload master servers list, tell masters that we are closing the server
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::ShutdownConnection( void )
|
|
{
|
|
adrlist_t *p;
|
|
|
|
if ( !host_initialized )
|
|
return;
|
|
|
|
if ( m_bNoMasters || // We are ignoring heartbeats
|
|
IsLan() || // Lan servers don't heartbeat
|
|
(sv.GetMaxClients() <= 1) ) // not a multiplayer server.
|
|
return;
|
|
|
|
const char packet = S2M_SHUTDOWN;
|
|
|
|
p = m_pMasterAddresses;
|
|
while ( p )
|
|
{
|
|
NET_SendPacket( NULL, NS_SERVER, p->adr, (unsigned char*)&packet, 1);
|
|
p->last_heartbeat = -99999.0;
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Add server to the master list
|
|
// Input : *adr -
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::AddServer( netadr_t *adr )
|
|
{
|
|
adrlist_t *n;
|
|
|
|
// See if it's there
|
|
n = m_pMasterAddresses;
|
|
while ( n )
|
|
{
|
|
if ( n->adr.CompareAdr( *adr ) )
|
|
break;
|
|
n = n->next;
|
|
}
|
|
|
|
// Found it in the list.
|
|
if ( n )
|
|
return;
|
|
|
|
n = ( adrlist_t * ) malloc ( sizeof( adrlist_t ) );
|
|
if ( !n )
|
|
Sys_Error( "Error allocating %zd bytes for master address.", sizeof( adrlist_t ) );
|
|
|
|
memset( n, 0, sizeof( adrlist_t ) );
|
|
|
|
n->adr = *adr;
|
|
|
|
// Queue up a full heartbeat to all master servers.
|
|
n->last_heartbeat = -99999.0;
|
|
|
|
// Link it in.
|
|
n->next = m_pMasterAddresses;
|
|
m_pMasterAddresses = n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Add built-in default master if woncomm.lst doesn't parse
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::UseDefault ( void )
|
|
{
|
|
netadr_t adr;
|
|
|
|
for( int i = 0; i < ARRAYSIZE(g_MasterServers);i++ )
|
|
{
|
|
// Convert to netadr_t
|
|
if ( NET_StringToAdr ( g_MasterServers[i], &adr ) )
|
|
{
|
|
// Add to master list
|
|
AddServer( &adr );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::RespondToHeartbeatChallenge( netadr_t &from, bf_read &msg )
|
|
{
|
|
adrlist_t *p;
|
|
uint challenge, challenge2;
|
|
|
|
// No masters, just ignore.
|
|
if ( !m_pMasterAddresses )
|
|
return;
|
|
|
|
p = m_pMasterAddresses;
|
|
while ( p )
|
|
{
|
|
if ( from.CompareAdr( p->adr ) )
|
|
break;
|
|
|
|
p = p->next;
|
|
}
|
|
|
|
// Not a known master server.
|
|
if ( !p )
|
|
return;
|
|
|
|
challenge = msg.ReadLong();
|
|
challenge2 = msg.ReadLong();
|
|
|
|
if( p->heartbeatchallenge != challenge2 )
|
|
{
|
|
Warning("unexpected master server info query packet (wrong challenge!)\n");
|
|
return;
|
|
}
|
|
|
|
// Kill timer
|
|
p->heartbeatwaiting = false;
|
|
p->heartbeatchallenge = challenge;
|
|
|
|
// Send the actual heartbeat request to this master server.
|
|
SendHeartbeat( p );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Add/remove master servers
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::AddMaster_f ( const CCommand &args )
|
|
{
|
|
CUtlString cmd( ( args.ArgC() > 1 ) ? args[ 1 ] : "" );
|
|
|
|
netadr_t adr;
|
|
|
|
if( !NET_StringToAdr(cmd.String(), &adr) )
|
|
{
|
|
Warning("Invalid address\n");
|
|
return;
|
|
}
|
|
|
|
this->AddServer(&adr);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Send a new heartbeat to the master
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::Heartbeat_f (void)
|
|
{
|
|
adrlist_t *p;
|
|
|
|
p = m_pMasterAddresses;
|
|
while ( p )
|
|
{
|
|
// Queue up a full hearbeat
|
|
p->last_heartbeat = -9999.0;
|
|
p->heartbeatwaitingtime = -9999.0;
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void AddMaster_f( const CCommand &args )
|
|
{
|
|
master->AddMaster_f( args );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void Heartbeat1_f( void )
|
|
{
|
|
master->Heartbeat_f();
|
|
}
|
|
|
|
static ConCommand setmaster("addmaster", AddMaster_f );
|
|
static ConCommand heartbeat("heartbeat", Heartbeat1_f, "Force heartbeat of master servers" );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Adds master server console commands
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::Init( void )
|
|
{
|
|
// Already able to initialize at least once?
|
|
if ( m_bInitialized )
|
|
return;
|
|
|
|
// So we don't do this a send time.sv_mas
|
|
m_bInitialized = true;
|
|
|
|
UseDefault();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CMaster::Shutdown(void)
|
|
{
|
|
adrlist_t *p, *n;
|
|
|
|
// Free the master list now.
|
|
p = m_pMasterAddresses;
|
|
while ( p )
|
|
{
|
|
n = p->next;
|
|
free( p );
|
|
p = n;
|
|
}
|
|
|
|
m_pMasterAddresses = NULL;
|
|
}
|
|
|
|
// ServersInfo
|
|
void CMaster::RequestInternetServerList(const char *gamedir, IServerListResponse *response)
|
|
{
|
|
if( m_bNoMasters ) return;
|
|
strncpy( m_szGameDir, gamedir, sizeof(m_szGameDir) );
|
|
|
|
if( response )
|
|
{
|
|
StopRefresh();
|
|
m_bRefreshing = true;
|
|
m_serverListResponse = response;
|
|
m_flRetryRequestTime = m_flStartRequestTime = m_flMasterRequestTime = Plat_FloatTime();
|
|
}
|
|
|
|
ALIGN4 char buf[256] ALIGN4_POST;
|
|
bf_write msg(buf, sizeof(buf));
|
|
|
|
msg.WriteByte( C2M_CLIENTQUERY );
|
|
msg.WriteString(gamedir);
|
|
|
|
adrlist_t *p;
|
|
|
|
p = m_pMasterAddresses;
|
|
while ( p )
|
|
{
|
|
NET_SendPacket(NULL, NS_CLIENT, p->adr, msg.GetData(), msg.GetNumBytesWritten() );
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
void CMaster::RequestLANServerList(const char *gamedir, IServerListResponse *response)
|
|
{
|
|
|
|
}
|
|
|
|
void CMaster::AddServerAddresses( netadr_t **adr, int count )
|
|
{
|
|
|
|
}
|