You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
564 lines
11 KiB
564 lines
11 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
// netadr.h
|
|
#ifndef NS_ADDRESS_H
|
|
#define NS_ADDRESS_H
|
|
#pragma once
|
|
|
|
#include "tier0/platform.h"
|
|
#include "tier0/dbg.h"
|
|
#include "tier1/netadr.h"
|
|
#include "steam/steamclientpublic.h" // for CSteamID
|
|
#include "tier1/strtools.h" // V_memset
|
|
|
|
#if defined( NO_STEAM )
|
|
typedef CSteamID uint64;
|
|
#endif
|
|
|
|
enum PeerToPeerAddressType_t
|
|
{
|
|
P2P_STEAMID,
|
|
};
|
|
|
|
// Build int subchannel types
|
|
// FIXME - these really are game specific. I wish we could standardize!
|
|
enum SteamPeerToPeerChannel_t
|
|
{
|
|
STEAM_P2P_GAME_CLIENT = 0,
|
|
STEAM_P2P_GAME_SERVER = 1,
|
|
STEAM_P2P_LOBBY = 2,
|
|
STEAM_P2P_HLTV = 3,
|
|
STEAM_P2P_HLTV1 = 4,
|
|
};
|
|
|
|
class CPeerToPeerAddress
|
|
{
|
|
public:
|
|
CPeerToPeerAddress ( void )
|
|
: m_AddrType( P2P_STEAMID )
|
|
, m_steamChannel( STEAM_P2P_GAME_CLIENT )
|
|
{}
|
|
|
|
void Clear ( void )
|
|
{
|
|
m_AddrType = P2P_STEAMID;
|
|
m_steamID.Clear();
|
|
m_steamChannel = STEAM_P2P_GAME_CLIENT;
|
|
}
|
|
|
|
void SetSteamChannel( int nChannel )
|
|
{
|
|
m_steamChannel = nChannel;
|
|
}
|
|
|
|
int GetSteamChannel() const
|
|
{
|
|
return m_steamChannel;
|
|
}
|
|
|
|
const CSteamID &GetSteamID() const
|
|
{
|
|
return m_steamID;
|
|
}
|
|
|
|
CPeerToPeerAddress ( const CSteamID &steamID, int nSteamChannel )
|
|
: m_AddrType ( P2P_STEAMID )
|
|
, m_steamID ( steamID )
|
|
, m_steamChannel( nSteamChannel )
|
|
{
|
|
}
|
|
|
|
private:
|
|
// disallow since we can't deal with steamchannel
|
|
CPeerToPeerAddress &operator=(const CSteamID &steamID);
|
|
public:
|
|
|
|
// Like operator =
|
|
CPeerToPeerAddress &SetFromSteamID( const CSteamID &steamID, int nSteamChannel )
|
|
{
|
|
m_AddrType = P2P_STEAMID;
|
|
m_steamID = steamID;
|
|
m_steamChannel = nSteamChannel;
|
|
return *this;
|
|
}
|
|
|
|
bool IsValid ( void ) const
|
|
{
|
|
switch ( m_AddrType )
|
|
{
|
|
case P2P_STEAMID:
|
|
return m_steamID.IsValid ( );
|
|
};
|
|
|
|
return false;
|
|
}
|
|
|
|
const char *ToString ( void ) const
|
|
{
|
|
switch ( m_AddrType )
|
|
{
|
|
case P2P_STEAMID:
|
|
return m_steamID.Render ( );
|
|
};
|
|
|
|
return "";
|
|
}
|
|
|
|
bool CompareAdr ( const CPeerToPeerAddress &other, bool onlyBase = false ) const
|
|
{
|
|
if ( m_AddrType != -other.m_AddrType )
|
|
return false;
|
|
|
|
switch ( m_AddrType )
|
|
{
|
|
case P2P_STEAMID:
|
|
return ((m_steamID == other.m_steamID) && (m_steamChannel == other.m_steamChannel));
|
|
};
|
|
|
|
return false;
|
|
}
|
|
|
|
bool operator==(const CPeerToPeerAddress &rhs) const
|
|
{
|
|
return CompareAdr( rhs, false );
|
|
}
|
|
|
|
PeerToPeerAddressType_t GetAddressType ( void ) const
|
|
{
|
|
return m_AddrType;
|
|
}
|
|
|
|
|
|
template <typename T> bool IsType ( void ) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <typename T> T *Get ( void ) { return NULL; }
|
|
template <typename T> const T *Get ( void ) const { return NULL; }
|
|
|
|
template <typename T> T &AsType ( void ) { static T dummy; return dummy; }
|
|
template <typename T> const T &AsType ( void ) const { static T dummy; return dummy; }
|
|
|
|
private:
|
|
CSteamID m_steamID;
|
|
int m_steamChannel; // SteamID channel (like a port number to disambiguate multiple connections)
|
|
|
|
PeerToPeerAddressType_t m_AddrType;
|
|
};
|
|
|
|
template <>
|
|
inline bool CPeerToPeerAddress::IsType<CSteamID> ( void ) const
|
|
{
|
|
return (m_AddrType == P2P_STEAMID);
|
|
}
|
|
|
|
template <>
|
|
inline CSteamID * CPeerToPeerAddress::Get<CSteamID> ( void )
|
|
{
|
|
return IsType<CSteamID> ( ) ? &m_steamID : NULL;
|
|
}
|
|
|
|
template <>
|
|
inline const CSteamID * CPeerToPeerAddress::Get<CSteamID> ( void ) const
|
|
{
|
|
return IsType<CSteamID> ( ) ? &m_steamID : NULL;
|
|
}
|
|
|
|
template <>
|
|
inline CSteamID &CPeerToPeerAddress::AsType<CSteamID> ( void )
|
|
{
|
|
Assert ( IsType<CSteamID> ( ) );
|
|
return m_steamID;
|
|
}
|
|
|
|
template <>
|
|
inline const CSteamID &CPeerToPeerAddress::AsType<CSteamID> ( void ) const
|
|
{
|
|
Assert ( IsType<CSteamID> ( ) );
|
|
return m_steamID;
|
|
}
|
|
|
|
enum NetworkSystemAddressType_t
|
|
{
|
|
NSAT_NETADR,
|
|
NSAT_P2P,
|
|
NSAT_PROXIED_GAMESERVER, // Client proxied through Steam Datagram Transport
|
|
NSAT_PROXIED_CLIENT, // Client proxied through Steam Datagram Transport
|
|
};
|
|
|
|
// Used to represent a remote address which can be a network address or SteamID
|
|
// Basically if m_steamID.IsValid() then we send to that otherwise we use the m_adr
|
|
struct ns_address
|
|
{
|
|
netadr_t m_adr; // ip:port and network type (NULL/IP/BROADCAST/etc).
|
|
CPeerToPeerAddress m_steamID; // SteamID destination
|
|
NetworkSystemAddressType_t m_AddrType;
|
|
|
|
ns_address() : m_AddrType( NSAT_NETADR ){}
|
|
|
|
~ns_address()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void Clear ( )
|
|
{
|
|
m_AddrType = NSAT_NETADR;
|
|
m_adr.Clear ( );
|
|
m_steamID.Clear ( );
|
|
}
|
|
|
|
ns_address ( const netadr_t &other )
|
|
: m_AddrType ( NSAT_NETADR )
|
|
, m_adr ( other )
|
|
{
|
|
m_steamID.Clear();
|
|
}
|
|
|
|
ns_address& operator=(const netadr_t &other)
|
|
{
|
|
Clear ( );
|
|
m_AddrType = NSAT_NETADR;
|
|
m_adr = other;
|
|
return *this;
|
|
}
|
|
|
|
|
|
ns_address ( const CPeerToPeerAddress &steamID )
|
|
: m_AddrType ( NSAT_P2P )
|
|
, m_steamID ( steamID )
|
|
{
|
|
m_adr.Clear ( );
|
|
}
|
|
|
|
ns_address& operator=(const CPeerToPeerAddress &steamID)
|
|
{
|
|
Clear ( );
|
|
m_AddrType = NSAT_P2P;
|
|
m_steamID = steamID;
|
|
return *this;
|
|
}
|
|
|
|
ns_address &SetFromSteamID ( const CSteamID &steamID, int nSteamChannel )
|
|
{
|
|
Clear ( );
|
|
m_AddrType = NSAT_P2P;
|
|
m_steamID.SetFromSteamID( steamID, nSteamChannel );
|
|
return *this;
|
|
}
|
|
|
|
|
|
bool IsLoopback ( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR) && m_adr.IsLoopback ( );
|
|
}
|
|
|
|
bool IsLocalhost ( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR) && m_adr.IsLocalhost ( );
|
|
}
|
|
|
|
bool IsBroadcast( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR) && m_adr.GetType() == NA_BROADCAST;
|
|
}
|
|
|
|
bool IsReservedAdr( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR) && m_adr.IsReservedAdr();
|
|
}
|
|
|
|
bool IsNull ( void ) const
|
|
{
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_NETADR:
|
|
return m_adr.GetType ( ) == NA_NULL;
|
|
case NSAT_P2P:
|
|
case NSAT_PROXIED_GAMESERVER:
|
|
case NSAT_PROXIED_CLIENT:
|
|
return !m_steamID.IsValid ( );
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IsValid ( ) const
|
|
{
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_NETADR:
|
|
return m_adr.IsValid ( );
|
|
case NSAT_P2P:
|
|
case NSAT_PROXIED_GAMESERVER:
|
|
case NSAT_PROXIED_CLIENT:
|
|
return m_steamID.IsValid ( );
|
|
};
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CompareAdr ( const ns_address &other, bool onlyBase = false ) const
|
|
{
|
|
if ( m_AddrType != other.m_AddrType )
|
|
return false;
|
|
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_NETADR:
|
|
return m_adr.CompareAdr ( other.m_adr, onlyBase );
|
|
|
|
case NSAT_P2P:
|
|
case NSAT_PROXIED_GAMESERVER:
|
|
case NSAT_PROXIED_CLIENT:
|
|
return m_steamID.CompareAdr( other.m_steamID, onlyBase );
|
|
};
|
|
|
|
return false;
|
|
}
|
|
|
|
bool operator==( const ns_address &rhs ) const
|
|
{
|
|
return CompareAdr( rhs, false );
|
|
}
|
|
|
|
bool operator!=( const ns_address &rhs ) const
|
|
{
|
|
return !CompareAdr( rhs, false );
|
|
}
|
|
|
|
NetworkSystemAddressType_t GetAddressType ( void ) const
|
|
{
|
|
return m_AddrType;
|
|
}
|
|
|
|
void SetAddrType( NetworkSystemAddressType_t type )
|
|
{
|
|
Clear();
|
|
m_AddrType = type;
|
|
}
|
|
|
|
bool SetFromSockadr ( const struct sockaddr * s )
|
|
{
|
|
m_AddrType = NSAT_NETADR;
|
|
m_steamID.Clear ( );
|
|
return m_adr.SetFromSockadr ( s );
|
|
}
|
|
|
|
unsigned int GetIP ( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR) ? m_adr.GetIPHostByteOrder( ) : 0;
|
|
}
|
|
|
|
unsigned short GetPort ( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR) ? m_adr.GetPort ( ) : 0;
|
|
}
|
|
|
|
template <typename T> bool IsType ( void ) const
|
|
{
|
|
//defer to subtype
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_P2P:
|
|
return m_steamID.IsType<T> ( );
|
|
};
|
|
return false;
|
|
}
|
|
|
|
template <typename T> T *Get ( void )
|
|
{
|
|
//defer to subtype
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_P2P:
|
|
return m_steamID.Get<T> ( );
|
|
};
|
|
return NULL;
|
|
}
|
|
|
|
template <typename T> const T *Get ( void ) const
|
|
{
|
|
//defer to subtype
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_P2P:
|
|
return m_steamID.Get<T> ( );
|
|
};
|
|
return NULL;
|
|
}
|
|
|
|
template <typename T> T &AsType ( void )
|
|
{
|
|
//defer to subtype
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_P2P:
|
|
return m_steamID.AsType<T> ( );
|
|
};
|
|
Assert ( false );
|
|
static T dummy;
|
|
return dummy;
|
|
}
|
|
|
|
template <typename T> const T &AsType ( void ) const
|
|
{
|
|
//defer to subtype
|
|
switch ( m_AddrType )
|
|
{
|
|
case NSAT_P2P:
|
|
return m_steamID.AsType<T> ( );
|
|
};
|
|
Assert ( false );
|
|
static T dummy;
|
|
return dummy;
|
|
}
|
|
|
|
bool SetFromString( const char *s )
|
|
{
|
|
Clear();
|
|
if ( !s )
|
|
return false;
|
|
bool bProxied = false;
|
|
if ( *s == '=' )
|
|
{
|
|
++s;
|
|
bProxied = true;
|
|
}
|
|
if ( *s == '[' )
|
|
{
|
|
CSteamID tempSteamID( s );
|
|
if ( !tempSteamID.IsValid() )
|
|
return false;
|
|
|
|
if ( bProxied && tempSteamID.BGameServerAccount() )
|
|
{
|
|
m_AddrType = NSAT_PROXIED_GAMESERVER;
|
|
m_steamID.SetFromSteamID( tempSteamID, STEAM_P2P_GAME_SERVER );
|
|
}
|
|
else
|
|
{
|
|
m_AddrType = bProxied ? NSAT_PROXIED_CLIENT : NSAT_P2P;
|
|
m_steamID.SetFromSteamID( tempSteamID, STEAM_P2P_GAME_CLIENT );
|
|
}
|
|
s = strchr( s, ']' );
|
|
int nChannel = -1;
|
|
if ( s && s[1] == ':' && sscanf( s+2, "%d", &nChannel ) == 1 && nChannel >= 0 )
|
|
{
|
|
m_steamID.SetSteamChannel( nChannel );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( !bProxied && m_adr.SetFromString( s, true ) )
|
|
{
|
|
m_AddrType = NSAT_NETADR;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
template <>
|
|
inline bool ns_address::IsType<netadr_t> ( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_NETADR);
|
|
}
|
|
|
|
template <>
|
|
inline bool ns_address::IsType<CPeerToPeerAddress> ( void ) const
|
|
{
|
|
return (m_AddrType == NSAT_P2P);
|
|
}
|
|
|
|
template <>
|
|
inline netadr_t *ns_address::Get<netadr_t> ( void )
|
|
{
|
|
return IsType<netadr_t> ( ) ? &m_adr : NULL;
|
|
}
|
|
|
|
template <>
|
|
inline const netadr_t *ns_address::Get<netadr_t> ( void ) const
|
|
{
|
|
return IsType<netadr_t> ( ) ? &m_adr : NULL;
|
|
}
|
|
|
|
template <>
|
|
inline CPeerToPeerAddress *ns_address::Get<CPeerToPeerAddress> ( void )
|
|
{
|
|
return IsType<CPeerToPeerAddress> ( ) ? &m_steamID : NULL;
|
|
}
|
|
|
|
template <>
|
|
inline const CPeerToPeerAddress *ns_address::Get<CPeerToPeerAddress> ( void ) const
|
|
{
|
|
return IsType<CPeerToPeerAddress> ( ) ? &m_steamID : NULL;
|
|
}
|
|
|
|
template <>
|
|
inline netadr_t &ns_address::AsType<netadr_t> ( void )
|
|
{
|
|
Assert ( IsType<netadr_t> ( ) );
|
|
return m_adr;
|
|
}
|
|
|
|
template <>
|
|
inline const netadr_t &ns_address::AsType<netadr_t> ( void ) const
|
|
{
|
|
Assert ( IsType<netadr_t> ( ) );
|
|
return m_adr;
|
|
}
|
|
|
|
template <>
|
|
inline CPeerToPeerAddress &ns_address::AsType<CPeerToPeerAddress> ( void )
|
|
{
|
|
Assert ( IsType<CPeerToPeerAddress> ( ) );
|
|
return m_steamID;
|
|
}
|
|
|
|
template <>
|
|
inline const CPeerToPeerAddress &ns_address::AsType<CPeerToPeerAddress> ( void ) const
|
|
{
|
|
Assert ( IsType<CPeerToPeerAddress> ( ) );
|
|
return m_steamID;
|
|
}
|
|
|
|
/// Utility class used to render an address
|
|
class ns_address_render
|
|
{
|
|
char m_buf[64];
|
|
public:
|
|
ns_address_render( const ns_address &a )
|
|
{
|
|
switch ( a.m_AddrType )
|
|
{
|
|
case NSAT_NETADR:
|
|
a.m_adr.ToString( m_buf, sizeof( m_buf ) );
|
|
break;
|
|
|
|
case NSAT_P2P:
|
|
V_sprintf_safe( m_buf, "%s:%d", a.m_steamID.ToString(), a.m_steamID.GetSteamChannel() );
|
|
break;
|
|
|
|
case NSAT_PROXIED_CLIENT:
|
|
case NSAT_PROXIED_GAMESERVER:
|
|
V_sprintf_safe( m_buf, "=%s:%d", a.m_steamID.ToString(), a.m_steamID.GetSteamChannel() );
|
|
break;
|
|
|
|
default:
|
|
m_buf[0] = '\0';
|
|
};
|
|
}
|
|
const char *String() const { return m_buf; }
|
|
};
|
|
|
|
#endif // NS_ADDRESS_H
|