297 lines
7.0 KiB
C++
297 lines
7.0 KiB
C++
//====== Copyright © 1996-2009, Valve Corporation, All rights reserved. =======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "net_support.h"
|
|
|
|
#ifndef DEDICATED
|
|
#include "client.h"
|
|
#endif
|
|
|
|
#include "server.h"
|
|
#include "host_cmd.h"
|
|
#include "net.h"
|
|
#include "proto_oob.h"
|
|
#include "steamdatagram/isteamdatagramclient.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
CNetSupportImpl::CNetSupportImpl()
|
|
{
|
|
;
|
|
}
|
|
|
|
CNetSupportImpl::~CNetSupportImpl()
|
|
{
|
|
;
|
|
}
|
|
|
|
static CNetSupportImpl g_NetSupport;
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CNetSupportImpl, INetSupport,
|
|
INETSUPPORT_VERSION_STRING, g_NetSupport );
|
|
|
|
//
|
|
// IAppSystem implementation
|
|
//
|
|
|
|
static CreateInterfaceFn s_pfnDelegateFactory;
|
|
static void * InternalFactory( const char *pName, int *pReturnCode )
|
|
{
|
|
if ( pReturnCode )
|
|
{
|
|
*pReturnCode = IFACE_OK;
|
|
}
|
|
|
|
// Try to get interface via delegate
|
|
if ( void *pInterface = s_pfnDelegateFactory ? s_pfnDelegateFactory( pName, pReturnCode ) : NULL )
|
|
{
|
|
return pInterface;
|
|
}
|
|
|
|
// Try to get internal interface
|
|
if ( void *pInterface = Sys_GetFactoryThis()( pName, pReturnCode ) )
|
|
{
|
|
return pInterface;
|
|
}
|
|
|
|
// Failed
|
|
if ( pReturnCode )
|
|
{
|
|
*pReturnCode = IFACE_FAILED;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool CNetSupportImpl::Connect( CreateInterfaceFn factory )
|
|
{
|
|
Assert( !s_pfnDelegateFactory );
|
|
|
|
s_pfnDelegateFactory = factory;
|
|
|
|
CreateInterfaceFn ourFactory = InternalFactory;
|
|
ConnectTier1Libraries( &ourFactory, 1 );
|
|
ConnectTier2Libraries( &ourFactory, 1 );
|
|
|
|
s_pfnDelegateFactory = NULL;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CNetSupportImpl::Disconnect()
|
|
{
|
|
DisconnectTier2Libraries();
|
|
DisconnectTier1Libraries();
|
|
}
|
|
|
|
void * CNetSupportImpl::QueryInterface( const char *pInterfaceName )
|
|
{
|
|
if ( !Q_stricmp( pInterfaceName, INETSUPPORT_VERSION_STRING ) )
|
|
return static_cast< INetSupport * >( this );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
InitReturnVal_t CNetSupportImpl::Init()
|
|
{
|
|
return INIT_OK;
|
|
}
|
|
|
|
void CNetSupportImpl::Shutdown()
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Net support implementation
|
|
//
|
|
|
|
int CNetSupportImpl::GetEngineBuildNumber()
|
|
{
|
|
return GetHostVersion();
|
|
}
|
|
|
|
void CNetSupportImpl::GetServerInfo( ServerInfo_t *pServerInfo )
|
|
{
|
|
if ( !pServerInfo )
|
|
return;
|
|
memset( pServerInfo, 0, sizeof( *pServerInfo ) );
|
|
|
|
extern netadr_t net_local_adr;
|
|
extern ConVar sv_steamgroup_exclusive;
|
|
|
|
pServerInfo->m_netAdr = net_local_adr;
|
|
static bool s_bHideHostIP = !!CommandLine()->FindParm( "-hidehostip" );
|
|
if ( !NET_GetPublicAdr( pServerInfo->m_netAdrOnline ) )
|
|
{
|
|
if ( s_bHideHostIP )
|
|
{
|
|
static netadr_t s_netAdrLocalhost( "127.0.0.1" );
|
|
pServerInfo->m_netAdr.SetIP( s_netAdrLocalhost.GetIPHostByteOrder() );
|
|
}
|
|
pServerInfo->m_netAdrOnline = pServerInfo->m_netAdr;
|
|
}
|
|
else if ( s_bHideHostIP )
|
|
{
|
|
pServerInfo->m_netAdr = pServerInfo->m_netAdrOnline;
|
|
}
|
|
pServerInfo->m_nPort = sv.GetUDPPort();
|
|
|
|
pServerInfo->m_netAdr.SetPort( pServerInfo->m_nPort );
|
|
pServerInfo->m_netAdrOnline.SetPort( pServerInfo->m_nPort );
|
|
|
|
pServerInfo->m_bActive = sv.IsActive() || sv.IsLoading();
|
|
pServerInfo->m_bDedicated = sv.IsDedicated();
|
|
pServerInfo->m_bLobbyExclusive = sv.IsExclusiveToLobbyConnections();
|
|
pServerInfo->m_bGroupExclusive = sv_steamgroup_exclusive.GetBool() || sv.GetPassword();
|
|
pServerInfo->m_bInMainMenuBkgnd = sv.IsLevelMainMenuBackground();
|
|
|
|
pServerInfo->m_szServerName = sv.GetName();
|
|
pServerInfo->m_szMapName = sv.GetMapName();
|
|
pServerInfo->m_szMapGroupName = sv.GetMapGroupName();
|
|
|
|
pServerInfo->m_numMaxHumanPlayers = sv.GetMaxHumanPlayers();
|
|
pServerInfo->m_numHumanPlayers = sv.GetNumHumanPlayers();
|
|
}
|
|
|
|
void CNetSupportImpl::GetClientInfo( ClientInfo_t *pClientInfo )
|
|
{
|
|
#ifndef DEDICATED
|
|
if ( !pClientInfo )
|
|
return;
|
|
memset( pClientInfo, 0, sizeof( *pClientInfo ) );
|
|
|
|
#ifndef DEDICATED
|
|
CClientState &rcs = GetBaseLocalClient();
|
|
|
|
pClientInfo->m_nSignonState = rcs.m_nSignonState;
|
|
pClientInfo->m_nSocket = rcs.m_Socket;
|
|
pClientInfo->m_pNetChannel = rcs.m_NetChannel;
|
|
#endif
|
|
|
|
// Compute number of human players on the server
|
|
pClientInfo->m_numHumanPlayers = 0;
|
|
if ( rcs.IsConnected() && rcs.m_pUserInfoTable )
|
|
{
|
|
for ( int i = 0; i < rcs.m_nMaxClients; i++ )
|
|
{
|
|
extern IVEngineClient *engineClient;
|
|
player_info_t pi;
|
|
|
|
if ( engineClient->GetPlayerInfo( i + 1, &pi ) &&
|
|
!pi.fakeplayer &&
|
|
!pi.ishltv )
|
|
{
|
|
++ pClientInfo->m_numHumanPlayers; // This is an actual human player
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CNetSupportImpl::UpdateClientReservation( uint64 uiReservation, uint64 uiMachineIdHost )
|
|
{
|
|
#ifndef DEDICATED
|
|
GetBaseLocalClient().SetServerReservationCookie( uiReservation );
|
|
GetBaseLocalClient().m_ListenServerSteamID = uiMachineIdHost;
|
|
#endif
|
|
}
|
|
|
|
void CNetSupportImpl::UpdateServerReservation( uint64 uiReservation )
|
|
{
|
|
sv.SetReservationCookie( uiReservation, "netsupport" );
|
|
}
|
|
|
|
|
|
|
|
void CNetSupportImpl::ReserveServer(
|
|
const ns_address &netAdrPublic, const ns_address &netAdrPrivate, uint64 nServerReservationCookie,
|
|
KeyValues *pKVGameSettings,
|
|
IMatchAsyncOperationCallback *pCallback, IMatchAsyncOperation **ppAsyncOperation )
|
|
{
|
|
#ifndef DEDICATED
|
|
GetBaseLocalClient().ReserveServer( netAdrPublic, netAdrPrivate,
|
|
nServerReservationCookie, pKVGameSettings,
|
|
pCallback, ppAsyncOperation );
|
|
#else
|
|
Assert( 0 );
|
|
#endif
|
|
}
|
|
|
|
bool CNetSupportImpl::CheckServerReservation(
|
|
const ns_address &netAdrPublic, uint64 nServerReservationCookie, uint32 uiReservationStage,
|
|
IMatchAsyncOperationCallback *pCallback, IMatchAsyncOperation **ppAsyncOperation )
|
|
{
|
|
#ifndef DEDICATED
|
|
return GetBaseLocalClient().CheckServerReservation( netAdrPublic,
|
|
nServerReservationCookie, uiReservationStage, pCallback, ppAsyncOperation );
|
|
#else
|
|
Assert( 0 );
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
bool CNetSupportImpl::ServerPing( const ns_address &netAdrPublic,
|
|
IMatchAsyncOperationCallback *pCallback, IMatchAsyncOperation **ppAsyncOperation )
|
|
{
|
|
#ifndef DEDICATED
|
|
return GetBaseLocalClient().ServerPing( netAdrPublic, pCallback, ppAsyncOperation );
|
|
#else
|
|
Assert( 0 );
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
// When client event is fired
|
|
void CNetSupportImpl::OnMatchEvent( KeyValues *pEvent )
|
|
{
|
|
#ifndef DEDICATED
|
|
GetBaseLocalClient().OnEvent( pEvent );
|
|
#endif
|
|
}
|
|
|
|
void CNetSupportImpl::ProcessSocket( int sock, IConnectionlessPacketHandler * pHandler )
|
|
{
|
|
NET_ProcessSocket( sock, pHandler );
|
|
}
|
|
|
|
// Send a network packet
|
|
int CNetSupportImpl::SendPacket (
|
|
INetChannel *chan, int sock, const netadr_t &to,
|
|
const void *data, int length,
|
|
bf_write *pVoicePayload /*= NULL*/,
|
|
bool bUseCompression /*= false*/ )
|
|
{
|
|
netadr_t inetAddr( to );
|
|
if ( !inetAddr.GetPort() && inetAddr.GetType() == NA_BROADCAST )
|
|
{
|
|
inetAddr.SetPort(
|
|
#ifdef _X360
|
|
NET_GetUDPPort( NS_X360_SYSTEMLINK )
|
|
#else
|
|
PORT_SERVER
|
|
#endif
|
|
);
|
|
}
|
|
|
|
return NET_SendPacket( chan, sock, inetAddr, ( const unsigned char * ) data, length, pVoicePayload, bUseCompression );
|
|
}
|
|
|
|
ISteamNetworkingUtils *CNetSupportImpl::GetSteamNetworkingUtils()
|
|
{
|
|
#ifdef DEDICATED
|
|
Assert( false ); // why are we asking?
|
|
return nullptr;
|
|
#else
|
|
return ::SteamNetworkingUtils();
|
|
#endif
|
|
}
|