From 6501dea7a3f6bcd48844844924d0f658e3128b26 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 19 Sep 2013 12:06:03 -0700 Subject: [PATCH] IPEndpoint parsing and tidying --- beast/net/IPEndpoint.h | 358 +++++----------------------------- beast/net/impl/IPEndpoint.cpp | 353 ++++++++++++++++++++++++++++++++- 2 files changed, 397 insertions(+), 314 deletions(-) diff --git a/beast/net/IPEndpoint.h b/beast/net/IPEndpoint.h index 9a5200418..dd292de91 100644 --- a/beast/net/IPEndpoint.h +++ b/beast/net/IPEndpoint.h @@ -54,104 +54,49 @@ public: struct V4 { /** Construct the "any" address. */ - V4 () - : value (0) - { - } + V4 (); /** Construct from a 32-bit unsigned. @note Octets are formed in order from the MSB to the LSB. */ - explicit V4 (uint32 value_) - : value (value_) - { - } + explicit V4 (uint32 value_); /** Construct from four individual octets.. @note The resulting address is a.b.c.d */ - V4 (uint8 a, uint8 b, uint8 c, uint8 d) - : value ((a<<24)|(b<<16)|(c<<8)|d) - { - } + V4 (uint8 a, uint8 b, uint8 c, uint8 d); /** Construct a copy of another address. */ - V4 (V4 const& other) - : value (other.value) - { - } + V4 (V4 const& other); /** Assign a copy of another address. */ - V4& operator= (V4 const& other) - { - value = other.value; - return *this; - } + V4& operator= (V4 const& other); /** Returns a V4 address representing the local broadcast address. */ - static V4 localBroadcastAddress () - { - return V4 (0xffffffff); - } + static V4 localBroadcastAddress (); /** Returns the directed broadcast address for the network implied by this address. */ - V4 broadcastAddress () const - { - switch (getClass()) - { - case 'A': return V4 ((value&0xff000000)|0x00ffffff); - case 'B': return V4 ((value&0xffff0000)|0x0000ffff); - case 'C': return V4 ((value&0xffffff00)|0x000000ff); - default: - case 'D': - bassertfalse; - break; - } - return V4(); - } + V4 broadcastAddress () const; /** Returns the IPv4 address class as 'A', 'B', 'C', or 'D'. @note Class 'D' represents multicast addresses (224.*.*.*). */ - char getClass () const - { - static char const* table = "AAAABBCD"; - return table[(value&0xE0000000)>>29]; - } + char getClass () const; /** Returns `true` if this is a public routable address. */ - bool isPublic () const - { - return !isPrivate() && !isBroadcast() && !isMulticast(); - } + bool isPublic () const; /** Returns `true` if this is a private, non-routable address. */ - bool isPrivate () const - { - return - ((value&0xff000000)==0x0a000000) || // Prefix /8, 10.##.#.# - ((value&0xfff00000)==0xac100000) || // Prefix /12 172.16.#.# - 172.31.#.# - ((value&0xffff0000)==0xc0a80000) || // Prefix /16 192.168.#.# - isLoopback(); - } + bool isPrivate () const; /** Returns `true` if this is a broadcast address. */ - bool isBroadcast () const - { - return (value == broadcastAddress().value); - } + bool isBroadcast () const; /** Returns `true` if this is a multicast address. */ - bool isMulticast () const - { - return getClass() == 'D'; - } + bool isMulticast () const; /** Returns `true` if this refers to any loopback adapter address. */ - bool isLoopback () const - { - return (value&0xff000000)==0x7f000000; - } + bool isLoopback () const; /** Supports access via operator[]. */ template @@ -189,50 +134,16 @@ public: }; /** Provides read access to individual octets of the IPv4 address. */ - Proxy operator[] (std::size_t index) const - { - switch (index) - { - default: - bassertfalse; - case 0: return Proxy (24, &value); - case 1: return Proxy (16, &value); - case 2: return Proxy ( 8, &value); - case 3: return Proxy ( 0, &value); - }; - }; + Proxy operator[] (std::size_t index) const; /** Provides read/write access to individual octets of the IPv4 address. */ - Proxy operator[] (std::size_t index) - { - switch (index) - { - default: - bassertfalse; - case 0: return Proxy (24, &value); - case 1: return Proxy (16, &value); - case 2: return Proxy ( 8, &value); - case 3: return Proxy ( 0, &value); - }; - }; + Proxy operator[] (std::size_t index); /** Convert the address to a human readable string. */ /** @{ */ - std::string to_string () const - { - std::string s; - s.reserve (15); - s.append (numberToString ((int)((*this)[0]))); s.push_back ('.'); - s.append (numberToString ((int)((*this)[1]))); s.push_back ('.'); - s.append (numberToString ((int)((*this)[2]))); s.push_back ('.'); - s.append (numberToString ((int)((*this)[3]))); - return s; - } - - operator std::string () const - { - return to_string(); - } + std::string to_string () const; + operator std::string () const; + /** @} */ /** The value as a 32 bit unsigned. */ uint32 value; @@ -290,262 +201,85 @@ public: //-------------------------------------------------------------------------- /** Create an empty address. */ - IPEndpoint () - : m_type (none) - { - } + IPEndpoint (); /** Create an IPv4 address with optional port. */ - IPEndpoint (V4 const& v4, uint16 port = 0) - : m_type (ipv4) - , m_port (port) - , m_v4 (v4) - { - } + IPEndpoint (V4 const& v4, uint16 port = 0); /** Create an IPv6 address with optional port. */ - IPEndpoint (V6 const& v6, uint16 port = 0) - : m_type (ipv6) - , m_port (port) - , m_v6 (v6) - { - } + IPEndpoint (V6 const& v6, uint16 port = 0); /** Create a copy of another IPEndpoint. */ - IPEndpoint (IPEndpoint const& other) - : m_type (other.m_type) - , m_port (other.m_port) - { - switch (m_type) - { - case ipv4: m_v4 = other.m_v4; break; - case ipv6: m_v6 = other.m_v6; break; - default: - case none: - break; - }; - } + IPEndpoint (IPEndpoint const& other); /** Copy assign another IPEndpoint. */ - IPEndpoint& operator= (IPEndpoint const& other) - { - m_type = other.m_type; - m_port = other.m_port; - switch (m_type) - { - case ipv4: m_v4 = other.m_v4; break; - case ipv6: m_v6 = other.m_v6; break; - default: - case none: - break; - }; - return *this; - } + IPEndpoint& operator= (IPEndpoint const& other); /** Copy assign an IPv4 address. The port is set to zero. */ - IPEndpoint& operator= (V4 const& address) - { - m_type = ipv4; - m_port = 0; - m_v4 = address; - return *this; - } + IPEndpoint& operator= (V4 const& address); /** Copy assign an IPv6 address. The port is set to zero. */ - IPEndpoint& operator= (V6 const& address) - { - m_type = ipv6; - m_port = 0; - m_v6 = address; - return *this; - } + IPEndpoint& operator= (V6 const& address); /** Returns a new IPEndpoint with this address, and the given port. */ - IPEndpoint withPort (uint16 port) const - { - switch (m_type) - { - case ipv4: return IPEndpoint (m_v4, port); - case ipv6: return IPEndpoint (m_v6, port); - default: - case none: - bassertfalse; - break; - }; - return IPEndpoint(); - } + IPEndpoint withPort (uint16 port) const; /** Returns `true` if this IPEndpoint refers to nothing. */ - bool empty () const - { - return m_type == none; - } + bool empty () const; /** Returns `true` if this IPEndpoint refers to nothing. */ - bool isNull () const - { - return empty (); - } + bool isNull () const; /** Returns `true` if this IPEndpoint refers to something. */ - bool isNotNull () const - { - return ! empty (); - } + bool isNotNull () const; /** Returns the type of this IPEndpoint. */ - Type type () const - { - return m_type; - } + Type type () const; /** Returns `true` if this IPEndpoint represents an IPv4 address. */ - bool isV4 () const - { - return m_type == ipv4; - } + bool isV4 () const; /** Returns `true` if this IPEndpoint represents an IPv6 address. */ - bool isV6 () const - { - return m_type == ipv6; - } + bool isV6 () const; /** Returns the IPv4 address. Undefined behavior results if type() != ipv4. */ - V4 const& v4 () const - { - return m_v4; - } + V4 const& v4 () const; /** Returns the IPv6 address. Undefined behavior results if type() != ipv4. */ - V6 const& v6 () const - { - return m_v6; - } + V6 const& v6 () const; /** Returns the port number. Undefined if type() == none. */ - uint16 port () const - { - return m_port; - } + uint16 port () const; /** Returns `true` if this is a public routable address. */ - bool isPublic () const - { - switch (m_type) - { - case ipv4: return m_v4.isPublic(); - case ipv6: return m_v6.isPublic(); - default: - bassertfalse; - case none: - break; - }; - return false; - } + bool isPublic () const; /** Returns `true` if this is a private, non-routable address. */ - bool isPrivate () const - { - switch (m_type) - { - case ipv4: return m_v4.isPrivate(); - case ipv6: return m_v6.isPrivate(); - default: - bassertfalse; - case none: - break; - }; - return false; - } + bool isPrivate () const; /** Returns `true` if this is a broadcast address. */ - bool isBroadcast () const - { - switch (m_type) - { - case ipv4: return m_v4.isBroadcast(); - case ipv6: return m_v6.isBroadcast(); - default: - bassertfalse; - case none: - break; - }; - return false; - } + bool isBroadcast () const; /** Returns `true` if this is a multicast address. */ - bool isMulticast () const - { - switch (m_type) - { - case ipv4: return m_v4.isMulticast(); - case ipv6: return m_v6.isMulticast(); - default: - bassertfalse; - case none: - break; - }; - return false; - } + bool isMulticast () const; /** Returns `true` if this refers to any loopback adapter address. */ - bool isLoopback () const - { - switch (m_type) - { - case ipv4: return m_v4.isLoopback(); - case ipv6: return m_v6.isLoopback(); - default: - bassertfalse; - case none: - break; - }; - return false; - } + bool isLoopback () const; /** Convert the address to a human readable string. */ /** @{ */ - std::string to_string () const - { - switch (m_type) - { - case ipv4: - { - std::string s (m_v4.to_string()); - if (m_port != 0) - { - s.append (":"); - s.append (numberToString (m_port)); - } - return s; - } - - case ipv6: - return m_v6.to_string(); - - default: - case none: - bassertfalse; - break; - }; - return std::string(); - } - - operator std::string () const - { - return to_string(); - } + std::string to_string () const; + operator std::string () const; /** @} */ private: @@ -613,11 +347,9 @@ inline std::ostream& operator<< (std::ostream &os, IPEndpoint const& ep) /** Input stream conversions. */ /** @{ */ -inline std::istream& operator>> (std::istream &is, IPEndpoint::V6&) -{ - //is >> addr.to_string(); - return is; -} +std::istream& operator>> (std::istream &is, IPEndpoint::V4& addr); +std::istream& operator>> (std::istream &is, IPEndpoint& ep); +//std::istream& operator>> (std::istream &is, IPEndpoint::V6&); /** @} */ } diff --git a/beast/net/impl/IPEndpoint.cpp b/beast/net/impl/IPEndpoint.cpp index 555c06b44..cdd1c3639 100644 --- a/beast/net/impl/IPEndpoint.cpp +++ b/beast/net/impl/IPEndpoint.cpp @@ -22,6 +22,357 @@ namespace beast { +IPEndpoint::V4::V4 () + : value (0) +{ +} + +IPEndpoint::V4::V4 (uint32 value_) + : value (value_) +{ +} + +IPEndpoint::V4::V4 (uint8 a, uint8 b, uint8 c, uint8 d) + : value ((a<<24)|(b<<16)|(c<<8)|d) +{ +} + +IPEndpoint::V4::V4 (V4 const& other) + : value (other.value) +{ +} + +IPEndpoint::V4& IPEndpoint::V4::operator= (V4 const& other) +{ + value = other.value; + return *this; +} + +IPEndpoint::V4 IPEndpoint::V4::localBroadcastAddress () +{ + return V4 (0xffffffff); +} + +IPEndpoint::V4 IPEndpoint::V4::broadcastAddress () const +{ + switch (getClass()) + { + case 'A': return V4 ((value&0xff000000)|0x00ffffff); + case 'B': return V4 ((value&0xffff0000)|0x0000ffff); + case 'C': return V4 ((value&0xffffff00)|0x000000ff); + default: + case 'D': + bassertfalse; + break; + } + return V4(); +} + +char IPEndpoint::V4::getClass () const +{ + static char const* table = "AAAABBCD"; + return table[(value&0xE0000000)>>29]; +} + +bool IPEndpoint::V4::isPublic () const +{ + return !isPrivate() && !isBroadcast() && !isMulticast(); +} + +bool IPEndpoint::V4::isPrivate () const +{ + return + ((value&0xff000000)==0x0a000000) || // Prefix /8, 10.##.#.# + ((value&0xfff00000)==0xac100000) || // Prefix /12 172.16.#.# - 172.31.#.# + ((value&0xffff0000)==0xc0a80000) || // Prefix /16 192.168.#.# + isLoopback(); +} + +bool IPEndpoint::V4::isBroadcast () const +{ + return (value == broadcastAddress().value); +} + +bool IPEndpoint::V4::isMulticast () const +{ + return getClass() == 'D'; +} + +bool IPEndpoint::V4::isLoopback () const +{ + return (value&0xff000000)==0x7f000000; +} + +IPEndpoint::V4::Proxy IPEndpoint::V4::operator[] (std::size_t index) const +{ + switch (index) + { + default: + bassertfalse; + case 0: return Proxy (24, &value); + case 1: return Proxy (16, &value); + case 2: return Proxy ( 8, &value); + case 3: return Proxy ( 0, &value); + }; +}; + +IPEndpoint::V4::Proxy IPEndpoint::V4::operator[] (std::size_t index) +{ + switch (index) + { + default: + bassertfalse; + case 0: return Proxy (24, &value); + case 1: return Proxy (16, &value); + case 2: return Proxy ( 8, &value); + case 3: return Proxy ( 0, &value); + }; +}; + +std::string IPEndpoint::V4::to_string () const +{ + std::string s; + s.reserve (15); + s.append (numberToString ((int)((*this)[0]))); s.push_back ('.'); + s.append (numberToString ((int)((*this)[1]))); s.push_back ('.'); + s.append (numberToString ((int)((*this)[2]))); s.push_back ('.'); + s.append (numberToString ((int)((*this)[3]))); + return s; +} + +IPEndpoint::V4::operator std::string () const +{ + return to_string(); +} + +//------------------------------------------------------------------------------ + +IPEndpoint::IPEndpoint () + : m_type (none) +{ +} + +IPEndpoint::IPEndpoint (V4 const& v4, uint16 port) + : m_type (ipv4) + , m_port (port) + , m_v4 (v4) +{ +} + +IPEndpoint::IPEndpoint (V6 const& v6, uint16 port) + : m_type (ipv6) + , m_port (port) + , m_v6 (v6) +{ +} + +IPEndpoint::IPEndpoint (IPEndpoint const& other) + : m_type (other.m_type) + , m_port (other.m_port) +{ + switch (m_type) + { + case ipv4: m_v4 = other.m_v4; break; + case ipv6: m_v6 = other.m_v6; break; + default: + case none: + break; + }; +} + +IPEndpoint& IPEndpoint::operator= (IPEndpoint const& other) +{ + m_type = other.m_type; + m_port = other.m_port; + switch (m_type) + { + case ipv4: m_v4 = other.m_v4; break; + case ipv6: m_v6 = other.m_v6; break; + default: + case none: + break; + }; + return *this; +} + +IPEndpoint& IPEndpoint::operator= (V4 const& address) +{ + m_type = ipv4; + m_port = 0; + m_v4 = address; + return *this; +} + +IPEndpoint& IPEndpoint::operator= (V6 const& address) +{ + m_type = ipv6; + m_port = 0; + m_v6 = address; + return *this; +} + +IPEndpoint IPEndpoint::withPort (uint16 port) const +{ + switch (m_type) + { + case ipv4: return IPEndpoint (m_v4, port); + case ipv6: return IPEndpoint (m_v6, port); + default: + case none: + bassertfalse; + break; + }; + return IPEndpoint(); +} + +bool IPEndpoint::empty () const +{ + return m_type == none; +} + +bool IPEndpoint::isNull () const +{ + return empty (); +} + +bool IPEndpoint::isNotNull () const +{ + return ! empty (); +} + +IPEndpoint::Type IPEndpoint::type () const +{ + return m_type; +} + +bool IPEndpoint::isV4 () const +{ + return m_type == ipv4; +} + +bool IPEndpoint::isV6 () const +{ + return m_type == ipv6; +} + +IPEndpoint::V4 const& IPEndpoint::v4 () const +{ + return m_v4; +} + +IPEndpoint::V6 const& IPEndpoint::v6 () const +{ + return m_v6; +} + +uint16 IPEndpoint::port () const +{ + return m_port; +} + +bool IPEndpoint::isPublic () const +{ + switch (m_type) + { + case ipv4: return m_v4.isPublic(); + case ipv6: return m_v6.isPublic(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isPrivate () const +{ + switch (m_type) + { + case ipv4: return m_v4.isPrivate(); + case ipv6: return m_v6.isPrivate(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isBroadcast () const +{ + switch (m_type) + { + case ipv4: return m_v4.isBroadcast(); + case ipv6: return m_v6.isBroadcast(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isMulticast () const +{ + switch (m_type) + { + case ipv4: return m_v4.isMulticast(); + case ipv6: return m_v6.isMulticast(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isLoopback () const +{ + switch (m_type) + { + case ipv4: return m_v4.isLoopback(); + case ipv6: return m_v6.isLoopback(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +std::string IPEndpoint::to_string () const +{ + switch (m_type) + { + case ipv4: + { + std::string s (m_v4.to_string()); + if (m_port != 0) + { + s.append (":"); + s.append (numberToString (m_port)); + } + return s; + } + + case ipv6: + return m_v6.to_string(); + + default: + case none: + bassertfalse; + break; + }; + return std::string(); +} + +IPEndpoint::operator std::string () const +{ + return to_string(); +} + +//------------------------------------------------------------------------------ + namespace parse { @@ -104,7 +455,7 @@ std::istream& operator>> (std::istream &is, IPEndpoint::V4& addr) /** Parse an IPEndpoint. @note Currently only IPv4 addresses are supported. */ -inline std::istream& operator>> (std::istream &is, IPEndpoint& ep) +std::istream& operator>> (std::istream &is, IPEndpoint& ep) { IPEndpoint::V4 v4; is >> v4;