//========= 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 bool IsType ( void ) const { return false; } template T *Get ( void ) { return NULL; } template const T *Get ( void ) const { return NULL; } template T &AsType ( void ) { static T dummy; return dummy; } template 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 ( void ) const { return (m_AddrType == P2P_STEAMID); } template <> inline CSteamID * CPeerToPeerAddress::Get ( void ) { return IsType ( ) ? &m_steamID : NULL; } template <> inline const CSteamID * CPeerToPeerAddress::Get ( void ) const { return IsType ( ) ? &m_steamID : NULL; } template <> inline CSteamID &CPeerToPeerAddress::AsType ( void ) { Assert ( IsType ( ) ); return m_steamID; } template <> inline const CSteamID &CPeerToPeerAddress::AsType ( void ) const { Assert ( IsType ( ) ); 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 bool IsType ( void ) const { //defer to subtype switch ( m_AddrType ) { case NSAT_P2P: return m_steamID.IsType ( ); }; return false; } template T *Get ( void ) { //defer to subtype switch ( m_AddrType ) { case NSAT_P2P: return m_steamID.Get ( ); }; return NULL; } template const T *Get ( void ) const { //defer to subtype switch ( m_AddrType ) { case NSAT_P2P: return m_steamID.Get ( ); }; return NULL; } template T &AsType ( void ) { //defer to subtype switch ( m_AddrType ) { case NSAT_P2P: return m_steamID.AsType ( ); }; Assert ( false ); static T dummy; return dummy; } template const T &AsType ( void ) const { //defer to subtype switch ( m_AddrType ) { case NSAT_P2P: return m_steamID.AsType ( ); }; 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 ( void ) const { return (m_AddrType == NSAT_NETADR); } template <> inline bool ns_address::IsType ( void ) const { return (m_AddrType == NSAT_P2P); } template <> inline netadr_t *ns_address::Get ( void ) { return IsType ( ) ? &m_adr : NULL; } template <> inline const netadr_t *ns_address::Get ( void ) const { return IsType ( ) ? &m_adr : NULL; } template <> inline CPeerToPeerAddress *ns_address::Get ( void ) { return IsType ( ) ? &m_steamID : NULL; } template <> inline const CPeerToPeerAddress *ns_address::Get ( void ) const { return IsType ( ) ? &m_steamID : NULL; } template <> inline netadr_t &ns_address::AsType ( void ) { Assert ( IsType ( ) ); return m_adr; } template <> inline const netadr_t &ns_address::AsType ( void ) const { Assert ( IsType ( ) ); return m_adr; } template <> inline CPeerToPeerAddress &ns_address::AsType ( void ) { Assert ( IsType ( ) ); return m_steamID; } template <> inline const CPeerToPeerAddress &ns_address::AsType ( void ) const { Assert ( IsType ( ) ); 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