diff --git a/src/beast/Builds/VisualStudio2013/beast.vcxproj b/src/beast/Builds/VisualStudio2013/beast.vcxproj
index f4b93cdcb6..f883a8a237 100644
--- a/src/beast/Builds/VisualStudio2013/beast.vcxproj
+++ b/src/beast/Builds/VisualStudio2013/beast.vcxproj
@@ -157,8 +157,12 @@
+
+
+
+
@@ -577,6 +581,24 @@
true
true
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
true
diff --git a/src/beast/Builds/VisualStudio2013/beast.vcxproj.filters b/src/beast/Builds/VisualStudio2013/beast.vcxproj.filters
index 9a1c036675..36c5a3064a 100644
--- a/src/beast/Builds/VisualStudio2013/beast.vcxproj.filters
+++ b/src/beast/Builds/VisualStudio2013/beast.vcxproj.filters
@@ -294,6 +294,9 @@
{44489531-f44a-439a-a6ea-d32c252b1e8b}
+
+ {43cc0f2a-9905-4081-8104-48d2c4be9e7e}
+
@@ -1143,9 +1146,6 @@
beast\utility
-
- beast\net
-
beast
@@ -1254,6 +1254,21 @@
beast\insight
+
+ beast\net\detail
+
+
+ beast\net
+
+
+ beast\net
+
+
+ beast\net
+
+
+ beast\net
+
@@ -1769,9 +1784,6 @@
beast\utility\impl
-
- beast\net\impl
-
beast\asio
@@ -1820,6 +1832,18 @@
beast\insight\impl
+
+ beast\net\impl
+
+
+ beast\net\impl
+
+
+ beast\net\impl
+
+
+ beast\net\impl
+
diff --git a/src/beast/beast/Net.h b/src/beast/beast/Net.h
index 79515845ad..4ad0b89a66 100644
--- a/src/beast/beast/Net.h
+++ b/src/beast/beast/Net.h
@@ -24,5 +24,13 @@
#include "net/DynamicBuffer.h"
#include "net/IPAddress.h"
+#include "net/IPAddressV4.h"
+#include "net/IPAddressV6.h"
+#include "net/IPEndpoint.h"
+
+// VFALCO DEPRECATED, REMOVE ASAP!
+namespace beast {
+typedef IP::Endpoint IPAddress;
+}
#endif
diff --git a/src/beast/beast/asio/IPAddressConversion.h b/src/beast/beast/asio/IPAddressConversion.h
index 9624c6a8dc..182691c043 100644
--- a/src/beast/beast/asio/IPAddressConversion.h
+++ b/src/beast/beast/asio/IPAddressConversion.h
@@ -20,41 +20,47 @@
#ifndef BEAST_ASIO_IPADDRESSCONVERSION_H_INCLUDED
#define BEAST_ASIO_IPADDRESSCONVERSION_H_INCLUDED
-#include "../net/IPAddress.h"
+#include "../net/IPEndpoint.h"
#include
#include
namespace beast {
+namespace IP {
+/** Convert to Endpoint.
+ The port is set to zero.
+*/
+Endpoint from_asio (boost::asio::ip::address const& address);
+
+/** Convert to Endpoint. */
+Endpoint from_asio (boost::asio::ip::tcp::endpoint const& endpoint);
+
+/** Convert to asio::ip::address.
+ The port is ignored.
+*/
+boost::asio::ip::address to_asio_address (Endpoint const& endpoint);
+
+/** Convert to asio::ip::tcp::endpoint. */
+boost::asio::ip::tcp::endpoint to_asio_endpoint (Endpoint const& endpoint);
+
+}
+}
+
+namespace beast {
+
+// DEPRECATED
struct IPAddressConversion
{
- /** Convert to IPAddress.
- The port is set to zero.
- */
- static IPAddress from_asio (boost::asio::ip::address const& address);
-
- /** Convert to IPAddress, including port. */
- static IPAddress from_asio (boost::asio::ip::tcp::endpoint const& endpoint);
-
- /** Convert to asio::ip::address.
- The port is ignored.
- */
- static boost::asio::ip::address to_asio_address (IPAddress const& address);
-
- /** Convert to asio::ip::tcp::endpoint. */
- static boost::asio::ip::tcp::endpoint to_asio_endpoint (IPAddress const& address);
-
- /** Conversions to string. */
- /** @{ */
- static std::string to_string (boost::asio::ip::tcp::endpoint const& endpoint)
- {
- std::stringstream ss;
- ss << endpoint;
- return ss.str();
- }
- /** @} */
+ static IP::Endpoint from_asio (boost::asio::ip::address const& address)
+ { return IP::from_asio (address); }
+ static IP::Endpoint from_asio (boost::asio::ip::tcp::endpoint const& endpoint)
+ { return IP::from_asio (endpoint); }
+ static boost::asio::ip::address to_asio_address (IP::Endpoint const& address)
+ { return IP::to_asio_address (address); }
+ static boost::asio::ip::tcp::endpoint to_asio_endpoint (IP::Endpoint const& address)
+ { return IP::to_asio_endpoint (address); }
};
}
diff --git a/src/beast/beast/asio/impl/IPAddressConversion.cpp b/src/beast/beast/asio/impl/IPAddressConversion.cpp
index 32c8cba860..62511b6f64 100644
--- a/src/beast/beast/asio/impl/IPAddressConversion.cpp
+++ b/src/beast/beast/asio/impl/IPAddressConversion.cpp
@@ -20,34 +20,35 @@
#include "../IPAddressConversion.h"
namespace beast {
+namespace IP {
-IPAddress IPAddressConversion::from_asio (boost::asio::ip::address const& address)
+Endpoint from_asio (boost::asio::ip::address const& address)
{
if (address.is_v4 ())
{
boost::asio::ip::address_v4::bytes_type const bytes (
address.to_v4().to_bytes());
- return IPAddress (IPAddress::V4 (
+ return Endpoint (AddressV4 (
bytes [0], bytes [1], bytes [2], bytes [3]));
}
// VFALCO TODO IPv6 support
bassertfalse;
- return IPAddress();
+ return Endpoint();
}
-IPAddress IPAddressConversion::from_asio (boost::asio::ip::tcp::endpoint const& endpoint)
+Endpoint from_asio (boost::asio::ip::tcp::endpoint const& endpoint)
{
- return from_asio (endpoint.address()).withPort (endpoint.port());
+ return from_asio (endpoint.address()).at_port (endpoint.port());
}
-boost::asio::ip::address IPAddressConversion::to_asio_address (IPAddress const& address)
+boost::asio::ip::address to_asio_address (Endpoint const& endpoint)
{
- if (address.isV4 ())
+ if (endpoint.address().is_v4())
{
return boost::asio::ip::address (
boost::asio::ip::address_v4 (
- address.v4().value));
+ endpoint.address().to_v4().value));
}
// VFALCO TODO IPv6 support
@@ -56,10 +57,11 @@ boost::asio::ip::address IPAddressConversion::to_asio_address (IPAddress const&
boost::asio::ip::address_v6 ());
}
-boost::asio::ip::tcp::endpoint IPAddressConversion::to_asio_endpoint (IPAddress const& address)
+boost::asio::ip::tcp::endpoint to_asio_endpoint (Endpoint const& endpoint)
{
return boost::asio::ip::tcp::endpoint (
- to_asio_address (address), address.port());
+ to_asio_address (endpoint), endpoint.port());
}
}
+}
diff --git a/src/beast/beast/insight/impl/StatsDCollector.cpp b/src/beast/beast/insight/impl/StatsDCollector.cpp
index 744b3b2704..02e25bf9ff 100644
--- a/src/beast/beast/insight/impl/StatsDCollector.cpp
+++ b/src/beast/beast/insight/impl/StatsDCollector.cpp
@@ -215,11 +215,11 @@ private:
static boost::asio::ip::udp::endpoint to_endpoint (
IPAddress const &address)
{
- if (address.isV4 ())
+ if (address.is_v4 ())
{
return boost::asio::ip::udp::endpoint (
boost::asio::ip::address_v4 (
- address.v4().value), address.port ());
+ address.to_v4().value), address.port ());
}
// VFALCO TODO IPv6 support
diff --git a/src/beast/beast/net/IPAddress.h b/src/beast/beast/net/IPAddress.h
index c67a31179c..0211677afd 100644
--- a/src/beast/beast/net/IPAddress.h
+++ b/src/beast/beast/net/IPAddress.h
@@ -23,388 +23,140 @@
#include
#include
#include
-
+
#include "../CStdInt.h"
+#include "IPAddressV4.h"
+#include "IPAddressV6.h"
//------------------------------------------------------------------------------
namespace beast {
+namespace IP {
-/** Represents an IP address (v4 or v6) and port combination. */
-class IPAddress
+/** A version-independent IP address.
+ This object can represent either an IPv4 or IPv6 address.
+*/
+class Address
{
public:
+ /** Create an unspecified IPv4 address. */
+ Address ();
+
+ /** Create an IPv4 address. */
+ Address (AddressV4 const& addr);
+
+ /** Create an IPv6 address. */
+ Address (AddressV6 const& addr);
+
+ /** Assign a copy from another address in any format. */
+ /** @{ */
+ Address& operator= (AddressV4 const& addr);
+ Address& operator= (AddressV6 const& addr);
+ /** @} */
+
+ /** Create an Address from a string.
+ @return A pair with the address, and bool set to `true` on success.
+ */
+ static std::pair from_string (std::string const& s);
+
+ /** Returns a string representing the address. */
+ std::string to_string () const;
+
+ /** Returns `true` if this address represents an IPv4 address. */
+ bool is_v4 () const
+ { return m_type == ipv4; }
+
+ /** Returns `true` if this address represents an IPv6 address. */
+ bool is_v6 () const
+ { return m_type == ipv6; }
+
+ /** Returns the IPv4 address.
+ Precondition:
+ is_v4() returns true
+ */
+ AddressV4 const& to_v4 () const;
+
+ /** Returns the IPv6 address.
+ Precondition:
+ is_v6() returns true
+ */
+ AddressV6 const& to_v6 () const;
+
+ /** Arithmetic comparison. */
+ /** @{ */
+ friend bool operator== (Address const& lhs, Address const& rhs);
+ friend bool operator< (Address const& lhs, Address const& rhs);
+
+ friend bool operator!= (Address const& lhs, Address const& rhs)
+ { return ! (lhs == rhs); }
+ friend bool operator> (Address const& lhs, Address const& rhs)
+ { return rhs < lhs; }
+ friend bool operator<= (Address const& lhs, Address const& rhs)
+ { return ! (lhs > rhs); }
+ friend bool operator>= (Address const& lhs, Address const& rhs)
+ { return ! (rhs > lhs); }
+ /** @} */
+
+private:
enum Type
{
- none,
ipv4,
ipv6
};
- template
- static std::string numberToString (Number n)
- {
- std::ostringstream os;
- os << std::dec << n;
- return std::string (os.str());
- }
-
- //--------------------------------------------------------------------------
-
- /** Used for IPv4 formats. */
- struct V4
- {
- /** Construct the "any" address. */
- V4 ();
-
- /** Construct from a 32-bit unsigned.
- @note Octets are formed in order from the MSB to the LSB.
- */
- 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);
-
- /** Construct a copy of another address. */
- V4 (V4 const& other);
-
- /** Assign a copy of another address. */
- V4& operator= (V4 const& other);
-
- /** Returns a V4 address representing the local broadcast address. */
- static V4 localBroadcastAddress ();
-
- /** Returns the directed broadcast address for the network implied by this address. */
- V4 broadcastAddress () const;
-
- /** Returns the IPv4 address class as 'A', 'B', 'C', or 'D'.
- @note Class 'D' represents multicast addresses (224.*.*.*).
- */
- char getClass () const;
-
- /** Returns `true` if this is a public routable address. */
- bool isPublic () const;
-
- /** Returns `true` if this is a private, non-routable address. */
- bool isPrivate () const;
-
- /** Returns `true` if this is a broadcast address. */
- bool isBroadcast () const;
-
- /** Returns `true` if this is a multicast address. */
- bool isMulticast () const;
-
- /** Returns `true` if this refers to any loopback adapter address. */
- bool isLoopback () const;
-
- /** Supports access via operator[]. */
- template
- class Proxy
- {
- public:
- typedef typename std::conditional <
- IsConst, uint32 const*, uint32*>::type Pointer;
-
- Proxy (int shift, Pointer value)
- : m_shift (shift)
- , m_value (value)
- {
- }
-
- operator uint8() const
- {
- return ((*m_value)>>m_shift) & 0xff;
- }
-
- template
- Proxy& operator= (IntegralType v)
- {
- (*m_value) =
- ( (*m_value) & (~((0xff)< operator[] (std::size_t index) const;
-
- /** Provides read/write access to individual octets of the IPv4 address. */
- Proxy operator[] (std::size_t index);
-
- /** Convert the address to a human readable string. */
- /** @{ */
- std::string to_string () const;
- operator std::string () const;
- /** @} */
-
- struct hasher
- {
- std::size_t operator() (V4 const& v) const
- {
- return v.value;
- }
- };
-
- /** The value as a 32 bit unsigned. */
- uint32 value;
- };
-
- //--------------------------------------------------------------------------
-
- /** Used for IPv6 formats. */
- struct V6
- {
- /** Returns `true` if this is a public routable address. */
- bool isPublic () const
- {
- return false;
- }
-
- /** Returns `true` if this is a private, non-routable address. */
- bool isPrivate () const
- {
- return false;
- }
-
- /** Returns `true` if this is a broadcast address. */
- bool isBroadcast () const
- {
- return false;
- }
-
- /** Returns `true` if this is a multicast address. */
- bool isMulticast () const
- {
- return false;
- }
-
- /** Returns `true` if this refers to any loopback adapter address. */
- bool isLoopback () const
- {
- return false;
- }
-
- /** Convert the address to a human readable string. */
- /** @{ */
- std::string to_string () const
- {
- return std::string();
- }
-
- operator std::string () const
- {
- return to_string();
- }
- /** @} */
-
- struct hasher
- {
- std::size_t operator() (V6 const&) const
- {
- return 0;
- }
- };
- };
-
- //--------------------------------------------------------------------------
-
- /** Create an empty address. */
- IPAddress ();
-
- /** Create an IPv4 address with optional port. */
- IPAddress (V4 const& v4, uint16 port = 0);
-
- /** Create an IPv6 address with optional port. */
- IPAddress (V6 const& v6, uint16 port = 0);
-
- /** Create a copy of another IPAddress. */
- IPAddress (IPAddress const& other);
-
- /** Copy assign another IPAddress. */
- IPAddress& operator= (IPAddress const& other);
-
- /** Create an IPAddress from a string.
- If a parsing error occurs, the endpoint will be empty.
- */
- static IPAddress from_string (std::string const& s);
-
- /** Create an IPAddress from a string.
- If a parsing error occurs, the endpoint will be empty.
- This recognizes an alternate form of the text. Instead of a colon
- separating the optional port specification, any amount of whitespace
- is allowed.
- */
- static IPAddress from_string_altform (std::string const& s);
-
- /** Copy assign an IPv4 address.
- The port is set to zero.
- */
- IPAddress& operator= (V4 const& address);
-
- /** Copy assign an IPv6 address.
- The port is set to zero.
- */
- IPAddress& operator= (V6 const& address);
-
- /** Returns a new IPAddress with this address, and the given port. */
- IPAddress withPort (uint16 port) const;
-
- /** Returns `true` if this IPAddress refers to nothing. */
- bool empty () const;
-
- /** Returns `true` if this IPAddress refers to nothing. */
- bool isNull () const;
-
- /** Returns `true` if this IPAddress refers to something. */
- bool isNotNull () const;
-
- /** Returns the type of this IPAddress. */
- Type type () const;
-
- /** Returns `true` if this IPAddress represents an IPv4 address. */
- bool isV4 () const;
-
- /** Returns `true` if this IPAddress represents an IPv6 address. */
- bool isV6 () const;
-
- /** Returns the IPv4 address.
- Undefined behavior results if type() != ipv4.
- */
- V4 const& v4 () const;
-
- /** Returns the IPv6 address.
- Undefined behavior results if type() != ipv4.
- */
- V6 const& v6 () const;
-
- /** Returns the port number.
- Undefined if type() == none.
- */
- uint16 port () const;
-
- /** Returns `true` if this is a public routable address. */
- bool isPublic () const;
-
- /** Returns `true` if this is a private, non-routable address. */
- bool isPrivate () const;
-
- /** Returns `true` if this is a broadcast address. */
- bool isBroadcast () const;
-
- /** Returns `true` if this is a multicast address. */
- bool isMulticast () const;
-
- /** Returns `true` if this refers to any loopback adapter address. */
- bool isLoopback () const;
-
- /** Convert the address to a human readable string. */
- /** @{ */
- std::string to_string () const;
- operator std::string () const;
- /** @} */
-
- typedef std::hash hasher;
-
- struct key_equal;
-
- /** LessThanComparable functor that ignores the port. */
- struct LessWithoutPort
- {
- bool operator() (IPAddress const& lhs, IPAddress const& rhs) const;
- };
-
- /** EqualityComparable functor that ignores the port. */
- struct EqualWithoutPort
- {
- bool operator() (IPAddress const& lhs, IPAddress const& rhs) const;
- };
-
-private:
Type m_type;
- uint16 m_port;
- V4 m_v4;
- V6 m_v6;
+ AddressV4 m_v4;
+ AddressV6 m_v6;
};
-/** Comparison. */
-/** @{ */
-bool operator== (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs);
-bool operator!= (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs);
-bool operator< (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs);
-bool operator<= (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs);
-bool operator> (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs);
-bool operator>= (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs);
+//------------------------------------------------------------------------------
-bool operator== (IPAddress const& lhs, IPAddress const& rhs);
-bool operator!= (IPAddress const& lhs, IPAddress const& rhs);
-bool operator< (IPAddress const& lhs, IPAddress const& rhs);
-bool operator<= (IPAddress const& lhs, IPAddress const& rhs);
-bool operator> (IPAddress const& lhs, IPAddress const& rhs);
-bool operator>= (IPAddress const& lhs, IPAddress const& rhs);
+// Properties
-/** Output stream conversions. */
-/** @{ */
-std::ostream& operator<< (std::ostream& os, IPAddress::V4 const& addr);
-std::ostream& operator<< (std::ostream& os, IPAddress::V6 const& addr);
-std::ostream& operator<< (std::ostream& os, IPAddress const& ep);
-/** @} */
+/** Returns `true` if this is a loopback address. */
+bool is_loopback (Address const& addr);
-/** Input stream conversions. */
-/** @{ */
-std::istream& operator>> (std::istream& is, IPAddress::V4& addr);
-std::istream& operator>> (std::istream& is, IPAddress& ep);
-//std::istream& operator>> (std::istream &is, IPAddress::V6&);
-/** @} */
+/** Returns `true` if the address is unspecified. */
+bool is_unspecified (Address const& addr);
-struct IPAddress::key_equal
-{
- bool operator() (IPAddress const& lhs, IPAddress const& rhs) const
- {
- return lhs == rhs;
- }
-};
+/** Returns `true` if the address is a multicast address. */
+bool is_multicast (Address const& addr);
+
+/** Returns `true` if the address is a private unroutable address. */
+bool is_private (Address const& addr);
+
+/** Returns `true` if the address is a public routable address. */
+bool is_public (Address const& addr);
+
+//------------------------------------------------------------------------------
+
+/** boost::hash support. */
+std::size_t hash_value (Address const& addr);
+
+/** Returns the address represented as a string. */
+inline std::string to_string (Address const& addr)
+ { return addr.to_string (); }
+
+/** Output stream conversion. */
+template
+OutputStream& operator<< (OutputStream& os, Address const& addr)
+ { return os << to_string (addr); }
+
+/** Input stream conversion. */
+std::istream& operator>> (std::istream& is, Address& addr);
-inline bool IPAddress::LessWithoutPort::operator() (
- IPAddress const& lhs, IPAddress const& rhs) const
-{
- return lhs.withPort (0) < rhs.withPort (0);
}
-
-inline bool IPAddress::EqualWithoutPort::operator() (
- IPAddress const& lhs, IPAddress const& rhs) const
-{
- return lhs.withPort (0) == rhs.withPort (0);
-}
-
}
//------------------------------------------------------------------------------
namespace std {
-
template <>
-struct hash
+struct hash
{
- std::size_t operator() (beast::IPAddress const& value) const
- {
- std::size_t hash (0);
- if (value.isV4())
- hash = beast::IPAddress::V4::hasher() (value.v4());
- else if (value.isV6())
- hash = beast::IPAddress::V6::hasher() (value.v6());
- hash += value.port();
- return hash;
- }
+ std::size_t operator() (beast::IP::Address const& addr) const
+ { return hash_value (addr); }
};
-
}
#endif
diff --git a/src/beast/beast/net/IPAddressV4.h b/src/beast/beast/net/IPAddressV4.h
new file mode 100644
index 0000000000..58090734e3
--- /dev/null
+++ b/src/beast/beast/net/IPAddressV4.h
@@ -0,0 +1,197 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_NET_IPADDRESSV4_H_INCLUDED
+#define BEAST_NET_IPADDRESSV4_H_INCLUDED
+
+#include
+#include
+#include
+
+#include "../CStdInt.h"
+
+namespace beast {
+namespace IP {
+
+/** Represents a version 4 IP address. */
+struct AddressV4
+{
+ /** Default constructor represents the 'any' address. */
+ AddressV4 ();
+
+ /** Construct from a 32-bit unsigned.
+ @note Octets are formed in order from the MSB to the LSB.
+ */
+ explicit AddressV4 (uint32 value_);
+
+ /** Construct from four individual octets..
+ @note The resulting address is a.b.c.d
+ */
+ AddressV4 (uint8 a, uint8 b, uint8 c, uint8 d);
+
+ /** Create an address from an IPv4 address string in dotted decimal form.
+ @return A pair with the address, and bool set to `true` on success.
+ */
+ static std::pair from_string (std::string const& s);
+
+ /** Returns an address that represents 'any' address. */
+ static AddressV4 any ()
+ { return AddressV4(); }
+
+ /** Returns an address that represents the loopback address. */
+ static AddressV4 loopback ()
+ { return AddressV4 (0x7f000001); }
+
+ /** Returns an address that represents the broadcast address. */
+ static AddressV4 broadcast ()
+ { return AddressV4 (0xffffffff); }
+
+ /** Returns the broadcast address for the specified address. */
+ static AddressV4 broadcast (AddressV4 const& address);
+
+ /** Returns the broadcast address corresponding to the address and mask. */
+ static AddressV4 broadcast (
+ AddressV4 const& address, AddressV4 const& mask);
+
+ /** Returns `true` if this is a broadcast address. */
+ bool is_broadcast () const
+ { return *this == broadcast (*this); }
+
+ /** Returns the address class for the given address.
+ @note Class 'D' represents multicast addresses (224.*.*.*).
+ */
+ static char get_class (AddressV4 const& address);
+
+ /** Returns the netmask for the address class or address. */
+ /** @{ */
+ static AddressV4 netmask (char address_class);
+ static AddressV4 netmask (AddressV4 const& v);
+ /** @} */
+
+ /** Arithmetic comparison. */
+ /** @{ */
+ friend bool operator== (AddressV4 const& lhs, AddressV4 const& rhs)
+ { return lhs.value == rhs.value; }
+ friend bool operator< (AddressV4 const& lhs, AddressV4 const& rhs)
+ { return lhs.value < rhs.value; }
+
+ friend bool operator!= (AddressV4 const& lhs, AddressV4 const& rhs)
+ { return ! (lhs == rhs); }
+ friend bool operator> (AddressV4 const& lhs, AddressV4 const& rhs)
+ { return rhs < lhs; }
+ friend bool operator<= (AddressV4 const& lhs, AddressV4 const& rhs)
+ { return ! (lhs > rhs); }
+ friend bool operator>= (AddressV4 const& lhs, AddressV4 const& rhs)
+ { return ! (rhs > lhs); }
+ /** @} */
+
+ /** Array indexing for reading and writing indiviual octets. */
+ /** @{ */
+ template
+ class Proxy
+ {
+ public:
+ typedef typename std::conditional <
+ IsConst, uint32 const*, uint32*>::type Pointer;
+
+ Proxy (int shift, Pointer value)
+ : m_shift (shift)
+ , m_value (value)
+ {
+ }
+
+ operator uint8() const
+ {
+ return ((*m_value)>>m_shift) & 0xff;
+ }
+
+ template
+ Proxy& operator= (IntegralType v)
+ {
+ (*m_value) =
+ ( (*m_value) & (~((0xff)< operator[] (std::size_t index) const;
+ Proxy operator[] (std::size_t index);
+ /** @{ */
+
+ /** The value as a 32 bit unsigned. */
+ uint32 value;
+};
+
+//------------------------------------------------------------------------------
+
+/** Returns `true` if this is a loopback address. */
+bool is_loopback (AddressV4 const& addr);
+
+/** Returns `true` if the address is unspecified. */
+bool is_unspecified (AddressV4 const& addr);
+
+/** Returns `true` if the address is a multicast address. */
+bool is_multicast (AddressV4 const& addr);
+
+/** Returns `true` if the address is a private unroutable address. */
+bool is_private (AddressV4 const& addr);
+
+/** Returns `true` if the address is a public routable address. */
+bool is_public (AddressV4 const& addr);
+
+//------------------------------------------------------------------------------
+
+/** boost::hash support. */
+inline std::size_t hash_value (AddressV4 const& addr)
+ { return addr.value; }
+
+/** Returns the address represented as a string. */
+std::string to_string (AddressV4 const& addr);
+
+/** Output stream conversion. */
+template
+OutputStream& operator<< (OutputStream& os, AddressV4 const& addr)
+ { return os << to_string (addr); }
+
+/** Input stream conversion. */
+std::istream& operator>> (std::istream& is, AddressV4& addr);
+
+}
+}
+
+//------------------------------------------------------------------------------
+
+namespace std {
+template struct hash;
+/** std::hash support. */
+template <>
+struct hash
+{
+ std::size_t operator() (beast::IP::AddressV4 const& addr) const
+ { return hash_value (addr); }
+};
+}
+
+#endif
diff --git a/src/beast/beast/net/IPAddressV6.h b/src/beast/beast/net/IPAddressV6.h
new file mode 100644
index 0000000000..12ed877fc0
--- /dev/null
+++ b/src/beast/beast/net/IPAddressV6.h
@@ -0,0 +1,105 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_NET_IPADDRESSV6_H_INCLUDED
+#define BEAST_NET_IPADDRESSV6_H_INCLUDED
+
+#include
+#include
+#include
+
+#include "../CStdInt.h"
+
+namespace beast {
+namespace IP {
+
+/** Represents a version 4 IP address. */
+struct AddressV6
+{
+ // VFALCO TODO
+
+ /** Arithmetic comparison. */
+ /** @{ */
+ friend bool operator== (AddressV6 const&, AddressV6 const&)
+ { bassertfalse; return false; }
+ friend bool operator< (AddressV6 const&, AddressV6 const&)
+ { bassertfalse; return false; }
+
+ friend bool operator!= (AddressV6 const& lhs, AddressV6 const& rhs)
+ { return ! (lhs == rhs); }
+ friend bool operator> (AddressV6 const& lhs, AddressV6 const& rhs)
+ { return rhs < lhs; }
+ friend bool operator<= (AddressV6 const& lhs, AddressV6 const& rhs)
+ { return ! (lhs > rhs); }
+ friend bool operator>= (AddressV6 const& lhs, AddressV6 const& rhs)
+ { return ! (rhs > lhs); }
+ /** @} */
+};
+
+//------------------------------------------------------------------------------
+
+/** Returns `true` if this is a loopback address. */
+bool is_loopback (AddressV6 const& addr);
+
+/** Returns `true` if the address is unspecified. */
+bool is_unspecified (AddressV6 const& addr);
+
+/** Returns `true` if the address is a multicast address. */
+bool is_multicast (AddressV6 const& addr);
+
+/** Returns `true` if the address is a private unroutable address. */
+bool is_private (AddressV6 const& addr);
+
+/** Returns `true` if the address is a public routable address. */
+bool is_public (AddressV6 const& addr);
+
+//------------------------------------------------------------------------------
+
+/** boost::hash support. */
+inline std::size_t hash_value (AddressV6 const&)
+ { bassertfalse; return 0; }
+
+/** Returns the address represented as a string. */
+std::string to_string (AddressV6 const& addr);
+
+/** Output stream conversion. */
+template
+OutputStream& operator<< (OutputStream& os, AddressV6 const& addr)
+ { return os << to_string (addr); }
+
+/** Input stream conversion. */
+std::istream& operator>> (std::istream& is, AddressV6& addr);
+
+}
+}
+
+//------------------------------------------------------------------------------
+
+namespace std {
+template struct hash;
+/** std::hash support. */
+template <>
+struct hash
+{
+ std::size_t operator() (beast::IP::AddressV6 const& addr) const
+ { return hash_value (addr); }
+};
+}
+
+#endif
diff --git a/src/beast/beast/net/IPEndpoint.h b/src/beast/beast/net/IPEndpoint.h
new file mode 100644
index 0000000000..033f98c131
--- /dev/null
+++ b/src/beast/beast/net/IPEndpoint.h
@@ -0,0 +1,159 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_NET_IPENDPOINT_H_INCLUDED
+#define BEAST_NET_IPENDPOINT_H_INCLUDED
+
+#include
+#include
+
+#include "../CStdInt.h"
+#include "IPAddress.h"
+
+namespace beast {
+namespace IP {
+
+typedef uint16 Port;
+
+/** A version-independent IP address and port combination. */
+class Endpoint
+{
+public:
+ /** Create an unspecified endpoint. */
+ Endpoint ();
+
+ /** Create an endpoint from the address and optional port. */
+ explicit Endpoint (Address const& addr, Port port = 0);
+
+ /** Create an Endpoint from a string.
+ If the port is omitted, the endpoint will have a zero port.
+ @return A pair with the endpoint, and bool set to `true` on success.
+ */
+ static std::pair from_string_checked (std::string const& s);
+ static Endpoint from_string (std::string const& s);
+ static Endpoint from_string_altform (std::string const& s);
+
+ /** Returns a string representing the endpoint. */
+ std::string to_string () const;
+
+ /** Returns the port number on the endpoint. */
+ Port port () const
+ { return m_port; }
+
+ /** Returns a new Endpoint with a different port. */
+ Endpoint at_port (Port port) const
+ { return Endpoint (m_addr, port); }
+
+ /** Returns the address portion of this endpoint. */
+ Address const& address () const
+ { return m_addr; }
+
+ /** Convenience accessors for the address part. */
+ /** @{ */
+ bool is_v4 () const
+ { return m_addr.is_v4(); }
+ bool is_v6 () const
+ { return m_addr.is_v6(); }
+ AddressV4 const& to_v4 () const
+ { return m_addr.to_v4 (); }
+ AddressV6 const& to_v6 () const
+ { return m_addr.to_v6 (); }
+ /** @} */
+
+ /** Arithmetic comparison. */
+ /** @{ */
+ friend bool operator== (Endpoint const& lhs, Endpoint const& rhs);
+ friend bool operator< (Endpoint const& lhs, Endpoint const& rhs);
+
+ friend bool operator!= (Endpoint const& lhs, Endpoint const& rhs)
+ { return ! (lhs == rhs); }
+ friend bool operator> (Endpoint const& lhs, Endpoint const& rhs)
+ { return rhs < lhs; }
+ friend bool operator<= (Endpoint const& lhs, Endpoint const& rhs)
+ { return ! (lhs > rhs); }
+ friend bool operator>= (Endpoint const& lhs, Endpoint const& rhs)
+ { return ! (rhs > lhs); }
+ /** @} */
+
+private:
+ Address m_addr;
+ Port m_port;
+};
+
+//------------------------------------------------------------------------------
+
+// Properties
+
+/** Returns `true` if the endpoint is a loopback address. */
+inline bool is_loopback (Endpoint const& endpoint)
+ { return is_loopback (endpoint.address ()); }
+
+/** Returns `true` if the endpoint is unspecified. */
+inline bool is_unspecified (Endpoint const& endpoint)
+ { return is_unspecified (endpoint.address ()); }
+
+/** Returns `true` if the endpoint is a multicast address. */
+inline bool is_multicast (Endpoint const& endpoint)
+ { return is_multicast (endpoint.address ()); }
+
+/** Returns `true` if the endpoint is a private unroutable address. */
+inline bool is_private (Endpoint const& endpoint)
+ { return is_private (endpoint.address ()); }
+
+/** Returns `true` if the endpoint is a public routable address. */
+inline bool is_public (Endpoint const& endpoint)
+ { return is_public (endpoint.address ()); }
+
+//------------------------------------------------------------------------------
+
+/** boost::hash support. */
+std::size_t hash_value (Endpoint const& endpoint);
+
+/** Returns the endpoint represented as a string. */
+inline std::string to_string (Endpoint const& endpoint)
+ { return endpoint.to_string(); }
+
+/** Output stream conversion. */
+template
+OutputStream& operator<< (OutputStream& os, Endpoint const& endpoint)
+{
+ os << to_string (endpoint);
+ return os;
+}
+
+/** Input stream conversion. */
+std::istream& operator>> (std::istream& is, Endpoint& endpoint);
+
+}
+}
+
+//------------------------------------------------------------------------------
+
+namespace std {
+template struct hash;
+/** std::hash support. */
+template <>
+struct hash
+{
+ std::size_t operator() (beast::IP::Endpoint const& endpoint) const
+ { return hash_value (endpoint); }
+};
+}
+
+#endif
diff --git a/src/beast/beast/net/Net.cpp b/src/beast/beast/net/Net.cpp
index a176d962f5..afac1339de 100644
--- a/src/beast/beast/net/Net.cpp
+++ b/src/beast/beast/net/Net.cpp
@@ -25,3 +25,8 @@
#include "impl/DynamicBuffer.cpp"
#include "impl/IPAddress.cpp"
+#include "impl/IPAddressV4.cpp"
+#include "impl/IPAddressV6.cpp"
+#include "impl/IPEndpoint.cpp"
+
+
diff --git a/src/beast/beast/net/detail/Parse.h b/src/beast/beast/net/detail/Parse.h
new file mode 100644
index 0000000000..415f068cbd
--- /dev/null
+++ b/src/beast/beast/net/detail/Parse.h
@@ -0,0 +1,89 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_NET_DETAIL_PARSE_H_INCLUDED
+#define BEAST_NET_DETAIL_PARSE_H_INCLUDED
+
+#include
+#include
+
+namespace beast {
+namespace IP {
+
+namespace detail {
+
+/** Require and consume the specified character from the input.
+ @return `true` if the character matched.
+*/
+template
+bool expect (InputStream& is, char v)
+{
+ char c;
+ if (is.get(c) && v == c)
+ return true;
+ is.unget();
+ is.setstate (std::ios_base::failbit);
+ return false;
+}
+
+/** Used to disambiguate 8-bit integers from characters. */
+template
+struct integer_holder
+{
+ IntType* pi;
+ explicit integer_holder (IntType& i)
+ : pi (&i)
+ {
+ }
+ template
+ IntType& operator= (OtherIntType o) const
+ {
+ *pi = o;
+ return *pi;
+ }
+};
+
+/** Parse 8-bit unsigned integer. */
+template
+InputStream& operator>> (InputStream& is, integer_holder const& i)
+{
+ uint16 v;
+ is >> v;
+ if (! (v>=0 && v<=255))
+ {
+ is.setstate (std::ios_base::failbit);
+ return is;
+ }
+ i = uint8(v);
+ return is;
+}
+
+/** Free function for template argument deduction. */
+template
+integer_holder integer (IntType& i)
+{
+ return integer_holder (i);
+}
+
+}
+
+}
+}
+
+#endif
diff --git a/src/beast/beast/net/impl/IPAddress.cpp b/src/beast/beast/net/impl/IPAddress.cpp
index 5190759f5b..c8314019fc 100644
--- a/src/beast/beast/net/impl/IPAddress.cpp
+++ b/src/beast/beast/net/impl/IPAddress.cpp
@@ -17,685 +17,236 @@
*/
//==============================================================================
+#include
+
#include "../IPAddress.h"
+#include "../detail/Parse.h"
namespace beast {
+namespace IP {
-IPAddress::V4::V4 ()
- : value (0)
-{
-}
-
-IPAddress::V4::V4 (uint32 value_)
- : value (value_)
-{
-}
-
-IPAddress::V4::V4 (uint8 a, uint8 b, uint8 c, uint8 d)
- : value ((a<<24)|(b<<16)|(c<<8)|d)
-{
-}
-
-IPAddress::V4::V4 (V4 const& other)
- : value (other.value)
-{
-}
-
-IPAddress::V4& IPAddress::V4::operator= (V4 const& other)
-{
- value = other.value;
- return *this;
-}
-
-IPAddress::V4 IPAddress::V4::localBroadcastAddress ()
-{
- return V4 (0xffffffff);
-}
-
-IPAddress::V4 IPAddress::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 IPAddress::V4::getClass () const
-{
- static char const* table = "AAAABBCD";
- return table[(value&0xE0000000)>>29];
-}
-
-bool IPAddress::V4::isPublic () const
-{
- return !isPrivate() && !isBroadcast() && !isMulticast();
-}
-
-bool IPAddress::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 IPAddress::V4::isBroadcast () const
-{
- return (value == broadcastAddress().value);
-}
-
-bool IPAddress::V4::isMulticast () const
-{
- return getClass() == 'D';
-}
-
-bool IPAddress::V4::isLoopback () const
-{
- return (value&0xff000000)==0x7f000000;
-}
-
-IPAddress::V4::Proxy IPAddress::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);
- };
-};
-
-IPAddress::V4::Proxy IPAddress::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 IPAddress::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;
-}
-
-IPAddress::V4::operator std::string () const
-{
- return to_string();
-}
-
-//------------------------------------------------------------------------------
-
-IPAddress::IPAddress ()
- : m_type (none)
-{
-}
-
-IPAddress::IPAddress (V4 const& v4, uint16 port)
+Address::Address ()
: m_type (ipv4)
- , m_port (port)
- , m_v4 (v4)
{
}
-IPAddress::IPAddress (V6 const& v6, uint16 port)
+Address::Address (AddressV4 const& addr)
+ : m_type (ipv4)
+ , m_v4 (addr)
+{
+}
+
+Address::Address (AddressV6 const& addr)
: m_type (ipv6)
- , m_port (port)
- , m_v6 (v6)
+ , m_v6 (addr)
{
}
-IPAddress::IPAddress (IPAddress 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;
- };
-}
-
-IPAddress& IPAddress::operator= (IPAddress 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;
-}
-
-IPAddress IPAddress::from_string (std::string const& s)
-{
- std::stringstream is (s);
- IPAddress ep;
- is >> ep;
- if (! is.fail() && is.rdbuf()->in_avail() == 0)
- return ep;
- return IPAddress();
-}
-
-IPAddress& IPAddress::operator= (V4 const& address)
+Address& Address::operator= (AddressV4 const& addr)
{
m_type = ipv4;
- m_port = 0;
- m_v4 = address;
+ m_v6 = AddressV6();
+ m_v4 = addr;
return *this;
}
-IPAddress& IPAddress::operator= (V6 const& address)
+Address& Address::operator= (AddressV6 const& addr)
{
m_type = ipv6;
- m_port = 0;
- m_v6 = address;
+ m_v4 = AddressV4();
+ m_v6 = addr;
return *this;
}
-IPAddress IPAddress::withPort (uint16 port) const
+std::pair Address::from_string (std::string const& s)
{
- switch (m_type)
- {
- case ipv4: return IPAddress (m_v4, port);
- case ipv6: return IPAddress (m_v6, port);
- default:
- case none:
- bassertfalse;
- break;
- };
- return IPAddress();
+ std::stringstream is (s);
+ Address addr;
+ is >> addr;
+ if (! is.fail() && is.rdbuf()->in_avail() == 0)
+ return std::make_pair (addr, true);
+ return std::make_pair (Address (), false);
}
-bool IPAddress::empty () const
+std::string Address::to_string () const
{
- return m_type == none;
+ return (is_v4 ())
+ ? IP::to_string (to_v4())
+ : IP::to_string (to_v6());
}
-bool IPAddress::isNull () const
-{
- return empty ();
-}
-
-bool IPAddress::isNotNull () const
-{
- return ! empty ();
-}
-
-IPAddress::Type IPAddress::type () const
-{
- return m_type;
-}
-
-bool IPAddress::isV4 () const
-{
- return m_type == ipv4;
-}
-
-bool IPAddress::isV6 () const
-{
- return m_type == ipv6;
-}
-
-IPAddress::V4 const& IPAddress::v4 () const
+AddressV4 const& Address::to_v4 () const
{
+ if (m_type != ipv4)
+ throw std::bad_cast();
return m_v4;
}
-IPAddress::V6 const& IPAddress::v6 () const
+AddressV6 const& Address::to_v6 () const
{
+ if (m_type != ipv6)
+ throw std::bad_cast();
return m_v6;
}
-uint16 IPAddress::port () const
+bool operator== (Address const& lhs, Address const& rhs)
{
- return m_port;
-}
-
-bool IPAddress::isPublic () const
-{
- switch (m_type)
+ if (lhs.is_v4 ())
{
- case ipv4: return m_v4.isPublic();
- case ipv6: return m_v6.isPublic();
- default:
- bassertfalse;
- case none:
- break;
- };
- return false;
-}
-
-bool IPAddress::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 IPAddress::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 IPAddress::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 IPAddress::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 IPAddress::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();
-}
-
-IPAddress::operator std::string () const
-{
- return to_string();
-}
-
-//------------------------------------------------------------------------------
-
-namespace parse
-{
-
-/** Require and consume the specified character from the input.
- @return `true` if the character matched.
-*/
-bool expect (std::istream& is, char v)
-{
- char c;
- if (is.get(c) && v == c)
- return true;
-
- is.unget();
- is.setstate (std::ios_base::failbit);
- return false;
-}
-
-namespace detail
-{
-
-/** Used to disambiguate 8-bit integers from characters. */
-template
-struct integer_holder
-{
- IntType* pi;
- explicit integer_holder (IntType& i)
- : pi (&i)
- {
- }
- template
- IntType& operator= (OtherIntType o) const
- {
- *pi = o;
- return *pi;
- }
-};
-
-/** Parse 8-bit unsigned integer. */
-std::istream& operator>> (std::istream& is, integer_holder const& i)
-{
- uint16 v;
- is >> v;
- if (! (v>=0 && v<=255))
- {
- is.setstate (std::ios_base::failbit);
- return is;
- }
- i = uint8(v);
- return is;
-}
-
-}
-
-/** Free function for template argument deduction. */
-template
-detail::integer_holder integer (IntType& i)
-{
- return detail::integer_holder (i);
-}
-
-}
-
-/** Parse IPv4 address. */
-std::istream& operator>> (std::istream &is, IPAddress::V4& addr)
-{
- uint8 octets [4];
- is >> parse::integer (octets [0]);
- for (int i = 1; i < 4; ++i)
- {
- if (!is || !parse::expect (is, '.'))
- return is;
- is >> parse::integer (octets [i]);
- if (!is)
- return is;
- }
- addr = IPAddress::V4 (octets[0], octets[1], octets[2], octets[3]);
- return is;
-}
-
-/** Parse an IPAddress.
- @note Currently only IPv4 addresses are supported.
-*/
-std::istream& operator>> (std::istream &is, IPAddress& ep)
-{
- IPAddress::V4 v4;
- is >> v4;
- if (is.fail())
- return is;
-
- if (is.rdbuf()->in_avail()>0)
- {
- char c;
- is.get(c);
- if (c != ':')
- {
- is.unget();
- ep = IPAddress (v4);
- return is;
- }
-
- uint16 port;
- is >> port;
- if (is.fail())
- return is;
-
- ep = IPAddress (v4, port);
+ if (rhs.is_v4 ())
+ return lhs.to_v4() == rhs.to_v4();
}
else
{
- ep = IPAddress (v4);
+ if (rhs.is_v6 ())
+ return lhs.to_v6() == rhs.to_v6();
}
+ return false;
+}
+
+bool operator< (Address const& lhs, Address const& rhs)
+{
+ if (lhs.m_type < rhs.m_type)
+ return true;
+ if (lhs.is_v4 ())
+ return lhs.to_v4() < rhs.to_v4();
+ return lhs.to_v6() < rhs.to_v6();
+}
+
+//------------------------------------------------------------------------------
+
+bool is_loopback (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_loopback (addr.to_v4 ())
+ : is_loopback (addr.to_v6 ());
+}
+
+bool is_unspecified (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_unspecified (addr.to_v4 ())
+ : is_unspecified (addr.to_v6 ());
+}
+
+bool is_multicast (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_multicast (addr.to_v4 ())
+ : is_multicast (addr.to_v6 ());
+}
+
+bool is_private (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_private (addr.to_v4 ())
+ : is_private (addr.to_v6 ());
+}
+
+bool is_public (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? is_public (addr.to_v4 ())
+ : is_public (addr.to_v6 ());
+}
+
+//------------------------------------------------------------------------------
+
+std::size_t hash_value (Address const& addr)
+{
+ return (addr.is_v4 ())
+ ? hash_value (addr.to_v4())
+ : hash_value (addr.to_v6());
+}
+
+std::istream& operator>> (std::istream& is, Address& addr)
+{
+ // VFALCO TODO Support ipv6!
+ AddressV4 addrv4;
+ is >> addrv4;
+ addr = Address (addrv4);
return is;
}
//------------------------------------------------------------------------------
-IPAddress IPAddress::from_string_altform (std::string const& s)
-{
- // Accept the regular form if it parses
- {
- IPAddress ep (IPAddress::from_string (s));
- if (! ep.empty())
- return ep;
- }
-
- // Now try the alt form
- std::stringstream is (s);
-
- IPAddress::V4 v4;
- is >> v4;
- if (! is.fail())
- {
- IPAddress ep (v4);
-
- if (is.rdbuf()->in_avail()>0)
- {
- if (! parse::expect (is, ' '))
- return IPAddress();
-
- while (is.rdbuf()->in_avail()>0)
- {
- char c;
- is.get(c);
- if (c != ' ')
- {
- is.unget();
- break;
- }
- }
-
- uint16 port;
- is >> port;
- if (is.fail())
- return IPAddress();
-
- return ep.withPort (port);
- }
- else
- {
- // Just an address with no port
- return ep;
- }
- }
-
- // Could be V6 here...
-
- return IPAddress();
-}
-
-//------------------------------------------------------------------------------
-
-bool operator== (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs)
- { return lhs.value == rhs.value; }
-
-bool operator< (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs)
- { return lhs.value < rhs.value; }
-
-bool operator!= (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs)
- { return ! (lhs == rhs); }
-
-bool operator> (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs)
- { return rhs < lhs; }
-
-bool operator<= (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs)
- { return ! (rhs < lhs); }
-
-bool operator>= (IPAddress::V4 const& lhs, IPAddress::V4 const& rhs)
- { return ! (lhs < rhs); }
-
-//------------------------------------------------------------------------------
-
-bool operator== (IPAddress const& lhs, IPAddress const& rhs)
-{
- if (lhs.type() != rhs.type())
- return false;
- switch (lhs.type())
- {
- case IPAddress::none: return true;
- case IPAddress::ipv4:
- if (lhs.v4() != rhs.v4())
- return false;
- if (lhs.port() != rhs.port())
- return false;
- return true;
- case IPAddress::ipv6:
- default:
- bassertfalse;
- }
- return false;
-}
-
-bool operator< (IPAddress const& lhs, IPAddress const& rhs)
-{
- if (lhs.type() > rhs.type())
- return false;
- if (lhs.type() < rhs.type())
- return true;
- switch (lhs.type())
- {
- case IPAddress::none: return true;
- case IPAddress::ipv4:
- if (lhs.v4() < rhs.v4())
- return true;
- if (lhs.v4() > rhs.v4())
- return false;
- return lhs.port() < rhs.port();
- case IPAddress::ipv6:
- default:
- bassertfalse;
- }
- return false;
-}
-
-bool operator!= (IPAddress const& lhs, IPAddress const& rhs)
- { return ! (lhs == rhs); }
-
-bool operator> (IPAddress const& lhs, IPAddress const& rhs)
- { return rhs < lhs; }
-
-bool operator<= (IPAddress const& lhs, IPAddress const& rhs)
- { return ! (rhs < lhs); }
-
-bool operator>= (IPAddress const& lhs, IPAddress const& rhs)
- { return ! (lhs < rhs); }
-
-//------------------------------------------------------------------------------
-
-std::ostream& operator<< (std::ostream &os, IPAddress::V4 const& addr)
-{
- os << addr.to_string();
- return os;
-}
-
-std::ostream& operator<< (std::ostream &os, IPAddress::V6 const& addr)
-{
- os << addr.to_string();
- return os;
-}
-
-std::ostream& operator<< (std::ostream &os, IPAddress const& ep)
-{
- os << ep.to_string();
- return os;
-}
-
-//------------------------------------------------------------------------------
-
class IPAddressTests : public UnitTest
{
public:
- bool parse (char const* text, IPAddress& ep)
+ void shouldParseV4 (std::string const& s, uint32 value)
{
- std::string input (text);
- std::istringstream stream (input);
- stream >> ep;
- return !stream.fail();
+ std::pair const result (
+ AddressV4::from_string (s));
+
+ if (expect (result.second))
+ {
+ if (expect (result.first.value == value))
+ {
+ expect (to_string (result.first) == s);
+ }
+ }
}
- void shouldPass (char const* text)
+ void failParseV4 (std::string const& s)
{
- IPAddress ep;
- expect (parse (text, ep));
- expect (ep.to_string() == std::string(text));
+ unexpected (AddressV4::from_string (s).second);
}
- void shouldFail (char const* text)
+ void testAddressV4 ()
{
- IPAddress ep;
- unexpected (parse (text, ep));
+ beginTestCase ("AddressV4");
+
+ expect (AddressV4().value == 0);
+ expect (is_unspecified (AddressV4()));
+ expect (AddressV4(0x01020304).value == 0x01020304);
+ expect (AddressV4(1, 2, 3, 4).value == 0x01020304);
+
+ unexpected (is_unspecified (AddressV4(1, 2, 3, 4)));
+
+ AddressV4 const v1 (1);
+ expect (AddressV4(v1).value == 1);
+
+ {
+ AddressV4 v;
+ v = v1;
+ expect (v.value == v1.value);
+ }
+
+ {
+ AddressV4 v;
+ v [0] = 1;
+ v [1] = 2;
+ v [2] = 3;
+ v [3] = 4;
+ expect (v.value == 0x01020304);
+ }
+
+ expect (to_string (AddressV4(0x01020304)) == "1.2.3.4");
+
+ shouldParseV4 ("1.2.3.4", 0x01020304);
+ shouldParseV4 ("255.255.255.255", 0xffffffff);
+ shouldParseV4 ("0.0.0.0", 0);
+
+ failParseV4 (".");
+ failParseV4 ("..");
+ failParseV4 ("...");
+ failParseV4 ("....");
+ failParseV4 ("1");
+ failParseV4 ("1.");
+ failParseV4 ("1.2");
+ failParseV4 ("1.2.");
+ failParseV4 ("1.2.3");
+ failParseV4 ("1.2.3.");
+ failParseV4 ("256.0.0.0");
+ failParseV4 ("-1.2.3.4");
}
- void testParse ()
+ void testAddressV4Proxy ()
{
- beginTestCase ("parse");
+ beginTestCase ("AddressV4::Proxy");
- shouldPass ("0.0.0.0");
- shouldPass ("192.168.0.1");
- shouldPass ("168.127.149.132");
- shouldPass ("168.127.149.132:80");
- shouldPass ("168.127.149.132:54321");
-
- shouldFail ("");
- shouldFail ("255");
- shouldFail ("512");
- shouldFail ("1.2.3.256");
- shouldFail ("1.2.3:80");
- }
-
- void testV4Proxy ()
- {
- beginTestCase("v4 proxy");
-
- IPAddress::V4 v4 (10, 0, 0, 1);
+ AddressV4 v4 (10, 0, 0, 1);
expect (v4[0]==10);
expect (v4[1]==0);
expect (v4[2]==0);
@@ -711,43 +262,131 @@ public:
expect (v4[3]==1);
}
- void testPrint ()
+ //--------------------------------------------------------------------------
+
+ void testAddress ()
{
- beginTestCase ("addresses");
+ beginTestCase ("Address");
- IPAddress ep;
+ std::pair result (
+ Address::from_string ("1.2.3.4"));
+ expect (result.second);
+ if (expect (result.first.is_v4 ()))
+ expect (result.first.to_v4() == AddressV4 (1, 2, 3, 4));
+ }
- ep = IPAddress(IPAddress::V4(127,0,0,1)).withPort (80);
- expect (!ep.isPublic());
- expect ( ep.isPrivate());
- expect (!ep.isBroadcast());
- expect (!ep.isMulticast());
- expect ( ep.isLoopback());
- expect (ep.to_string() == "127.0.0.1:80");
+ //--------------------------------------------------------------------------
- ep = IPAddress::V4(10,0,0,1);
- expect ( ep.v4().getClass() == 'A');
- expect (!ep.isPublic());
- expect ( ep.isPrivate());
- expect (!ep.isBroadcast());
- expect (!ep.isMulticast());
- expect (!ep.isLoopback());
- expect (ep.to_string() == "10.0.0.1");
+ void testEndpoint ()
+ {
+ beginTestCase ("Endpoint");
- ep = IPAddress::V4(166,78,151,147);
- expect ( ep.isPublic());
- expect (!ep.isPrivate());
- expect (!ep.isBroadcast());
- expect (!ep.isMulticast());
- expect (!ep.isLoopback());
- expect (ep.to_string() == "166.78.151.147");
+ {
+ std::pair result (
+ Endpoint::from_string_checked ("1.2.3.4"));
+ expect (result.second);
+ if (expect (result.first.address().is_v4 ()))
+ {
+ expect (result.first.address().to_v4() ==
+ AddressV4 (1, 2, 3, 4));
+ expect (result.first.port() == 0);
+ expect (to_string (result.first) == "1.2.3.4");
+ }
+ }
+
+ {
+ std::pair result (
+ Endpoint::from_string_checked ("1.2.3.4:5"));
+ expect (result.second);
+ if (expect (result.first.address().is_v4 ()))
+ {
+ expect (result.first.address().to_v4() ==
+ AddressV4 (1, 2, 3, 4));
+ expect (result.first.port() == 5);
+ expect (to_string (result.first) == "1.2.3.4:5");
+ }
+ }
+
+ Endpoint ep;
+
+ ep = Endpoint (AddressV4 (127,0,0,1), 80);
+ expect (! is_unspecified (ep));
+ expect (! is_public (ep));
+ expect ( is_private (ep));
+ expect (! is_multicast (ep));
+ expect ( is_loopback (ep));
+ expect (to_string (ep) == "127.0.0.1:80");
+
+ ep = Endpoint (AddressV4 (10,0,0,1));
+ expect (AddressV4::get_class (ep.to_v4()) == 'A');
+ expect (! is_unspecified (ep));
+ expect (! is_public (ep));
+ expect ( is_private (ep));
+ expect (! is_multicast (ep));
+ expect (! is_loopback (ep));
+ expect (to_string (ep) == "10.0.0.1");
+
+ ep = Endpoint (AddressV4 (166,78,151,147));
+ expect (! is_unspecified (ep));
+ expect ( is_public (ep));
+ expect (! is_private (ep));
+ expect (! is_multicast (ep));
+ expect (! is_loopback (ep));
+ expect (to_string (ep) == "166.78.151.147");
+ }
+
+ //--------------------------------------------------------------------------
+
+ template
+ bool parse (char const* text, T& t)
+ {
+ std::string input (text);
+ std::istringstream stream (input);
+ stream >> t;
+ return !stream.fail();
+ }
+
+ template
+ void shouldPass (char const* text)
+ {
+ T t;
+ expect (parse (text, t));
+ expect (to_string (t) == std::string (text));
+ }
+
+ template
+ void shouldFail (char const* text)
+ {
+ T t;
+ unexpected (parse (text, t));
+ }
+
+ template
+ void testParse (char const* name)
+ {
+ beginTestCase (name);
+
+ shouldPass ("0.0.0.0");
+ shouldPass ("192.168.0.1");
+ shouldPass ("168.127.149.132");
+ shouldPass ("168.127.149.132:80");
+ shouldPass ("168.127.149.132:54321");
+
+ shouldFail ("");
+ shouldFail ("255");
+ shouldFail ("512");
+ shouldFail ("1.2.3.256");
+ shouldFail ("1.2.3:80");
}
void runTest ()
{
- testPrint();
- testParse();
- testV4Proxy();
+ testAddressV4 ();
+ testAddressV4Proxy();
+ testAddress ();
+ testEndpoint ();
+
+ testParse ("Parse Endpoint");
}
IPAddressTests () : UnitTest ("IPAddress", "beast")
@@ -758,3 +397,4 @@ public:
static IPAddressTests ipEndpointTests;
}
+}
diff --git a/src/beast/beast/net/impl/IPAddressV4.cpp b/src/beast/beast/net/impl/IPAddressV4.cpp
new file mode 100644
index 0000000000..a74daacffb
--- /dev/null
+++ b/src/beast/beast/net/impl/IPAddressV4.cpp
@@ -0,0 +1,177 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "../IPAddressV4.h"
+
+namespace beast {
+namespace IP {
+
+AddressV4::AddressV4 ()
+ : value (0)
+{
+}
+
+AddressV4::AddressV4 (uint32 value_)
+ : value (value_)
+{
+}
+
+AddressV4::AddressV4 (uint8 a, uint8 b, uint8 c, uint8 d)
+ : value ((a<<24)|(b<<16)|(c<<8)|d)
+{
+}
+
+std::pair AddressV4::from_string (std::string const& s)
+{
+ std::stringstream is (s);
+ AddressV4 addr;
+ is >> addr;
+ if (! is.fail() && is.rdbuf()->in_avail() == 0)
+ return std::make_pair (addr, true);
+ return std::make_pair (AddressV4 (), false);
+}
+
+AddressV4 AddressV4::broadcast (AddressV4 const& address)
+{
+ return broadcast (address, netmask (address));
+}
+
+AddressV4 AddressV4::broadcast (
+ AddressV4 const& address, AddressV4 const& mask)
+{
+ return AddressV4 (address.value | (mask.value ^ 0xffffffff));
+}
+
+char AddressV4::get_class (AddressV4 const& addr)
+{
+ static char const* table = "AAAABBCD";
+ return table [(addr.value & 0xE0000000) >> 29];
+}
+
+AddressV4 AddressV4::netmask (char address_class)
+{
+ switch (address_class)
+ {
+ case 'A': return AddressV4 (0xff000000);
+ case 'B': return AddressV4 (0xffff0000);
+ case 'C': return AddressV4 (0xffffff00);
+ case 'D':
+ default:
+ break;
+ }
+ return AddressV4 (0xffffffff);
+}
+
+AddressV4 AddressV4::netmask (AddressV4 const& addr)
+{
+ return netmask (get_class (addr));
+}
+
+AddressV4::Proxy AddressV4::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);
+ };
+};
+
+AddressV4::Proxy AddressV4::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);
+ };
+};
+
+//------------------------------------------------------------------------------
+
+bool is_loopback (AddressV4 const& addr)
+{
+ return (addr.value & 0xff000000) == 0x7f000000;
+}
+
+bool is_unspecified (AddressV4 const& addr)
+{
+ return addr.value == 0;
+}
+
+bool is_multicast (AddressV4 const& addr)
+{
+ return (addr.value & 0xf0000000) == 0xe0000000;
+}
+
+bool is_private (AddressV4 const& addr)
+{
+ return
+ ((addr.value & 0xff000000) == 0x0a000000) || // Prefix /8, 10. #.#.#
+ ((addr.value & 0xfff00000) == 0xac100000) || // Prefix /12 172. 16.#.# - 172.31.#.#
+ ((addr.value & 0xffff0000) == 0xc0a80000) || // Prefix /16 192.168.#.#
+ is_loopback (addr);
+}
+
+bool is_public (AddressV4 const& addr)
+{
+ return
+ ! is_private (addr) &&
+ ! is_multicast (addr) &&
+ (addr != AddressV4::broadcast (addr));
+}
+
+//------------------------------------------------------------------------------
+
+std::string to_string (AddressV4 const& addr)
+{
+ std::string s;
+ s.reserve (15);
+ s =
+ std::to_string (addr[0]) + "." +
+ std::to_string (addr[1]) + "." +
+ std::to_string (addr[2]) + "." +
+ std::to_string (addr[3]);
+ return s;
+}
+
+std::istream& operator>> (std::istream& is, AddressV4& addr)
+{
+ uint8 octet [4];
+ is >> IP::detail::integer (octet [0]);
+ for (int i = 1; i < 4; ++i)
+ {
+ if (!is || !IP::detail::expect (is, '.'))
+ return is;
+ is >> IP::detail::integer (octet [i]);
+ if (!is)
+ return is;
+ }
+ addr = AddressV4 (octet[0], octet[1], octet[2], octet[3]);
+ return is;
+}
+
+}
+}
diff --git a/src/beast/beast/net/impl/IPAddressV6.cpp b/src/beast/beast/net/impl/IPAddressV6.cpp
new file mode 100644
index 0000000000..4c9baa31d4
--- /dev/null
+++ b/src/beast/beast/net/impl/IPAddressV6.cpp
@@ -0,0 +1,79 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "../IPAddressV6.h"
+
+namespace beast {
+namespace IP {
+
+//------------------------------------------------------------------------------
+
+bool is_loopback (AddressV6 const&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return false;
+}
+
+bool is_unspecified (AddressV6 const&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return false;
+}
+
+bool is_multicast (AddressV6 const&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return false;
+}
+
+bool is_private (AddressV6 const&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return false;
+}
+
+bool is_public (AddressV6 const&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return false;
+}
+
+//------------------------------------------------------------------------------
+
+std::string to_string (AddressV6 const&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return "";
+}
+
+std::istream& operator>> (std::istream& is, AddressV6&)
+{
+ // VFALCO TODO
+ bassertfalse;
+ return is;
+}
+
+}
+}
diff --git a/src/beast/beast/net/impl/IPEndpoint.cpp b/src/beast/beast/net/impl/IPEndpoint.cpp
new file mode 100644
index 0000000000..a5815f8d71
--- /dev/null
+++ b/src/beast/beast/net/impl/IPEndpoint.cpp
@@ -0,0 +1,176 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+namespace beast {
+namespace IP {
+
+Endpoint::Endpoint ()
+ : m_port (0)
+{
+}
+
+Endpoint::Endpoint (Address const& addr, Port port)
+ : m_addr (addr)
+ , m_port (port)
+{
+}
+
+std::pair Endpoint::from_string_checked (std::string const& s)
+{
+ std::stringstream is (s);
+ Endpoint endpoint;
+ is >> endpoint;
+ if (! is.fail() && is.rdbuf()->in_avail() == 0)
+ return std::make_pair (endpoint, true);
+ return std::make_pair (Endpoint (), false);
+}
+
+Endpoint Endpoint::from_string (std::string const& s)
+{
+ std::pair const result (
+ from_string_checked (s));
+ if (result.second)
+ return result.first;
+ return Endpoint();
+}
+
+// VFALCO NOTE This is a hack to support legacy data format
+//
+Endpoint Endpoint::from_string_altform (std::string const& s)
+{
+ // Accept the regular form if it parses
+ {
+ Endpoint ep (Endpoint::from_string (s));
+ if (! is_unspecified (ep))
+ return ep;
+ }
+
+ // Now try the alt form
+ std::stringstream is (s);
+
+ AddressV4 v4;
+ is >> v4;
+ if (! is.fail())
+ {
+ Endpoint ep (v4);
+
+ if (is.rdbuf()->in_avail()>0)
+ {
+ if (! IP::detail::expect (is, ' '))
+ return Endpoint();
+
+ while (is.rdbuf()->in_avail()>0)
+ {
+ char c;
+ is.get(c);
+ if (c != ' ')
+ {
+ is.unget();
+ break;
+ }
+ }
+
+ Port port;
+ is >> port;
+ if (is.fail())
+ return Endpoint();
+
+ return ep.at_port (port);
+ }
+ else
+ {
+ // Just an address with no port
+ return ep;
+ }
+ }
+
+ // Could be V6 here...
+
+ return Endpoint();
+}
+
+std::string Endpoint::to_string () const
+{
+ std::string s (address ().to_string ());
+ if (port() != 0)
+ s = s + ":" + std::to_string (port());
+ return s;
+}
+
+bool operator== (Endpoint const& lhs, Endpoint const& rhs)
+{
+ return lhs.address() == rhs.address() &&
+ lhs.port() == rhs.port();
+}
+
+bool operator< (Endpoint const& lhs, Endpoint const& rhs)
+{
+ if (lhs.address() < rhs.address())
+ return true;
+ if (lhs.address() > rhs.address())
+ return false;
+ return lhs.port() < rhs.port();
+}
+
+//------------------------------------------------------------------------------
+
+std::size_t hash_value (Endpoint const& endpoint)
+{
+ std::size_t seed (hash_value (endpoint.address ()));
+ // boost::hash_combine()
+ seed ^= (std::hash () (endpoint.port ()))
+ + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ return seed;
+}
+
+std::istream& operator>> (std::istream& is, Endpoint& endpoint)
+{
+ // VFALCO TODO Support ipv6!
+
+ Address addr;
+ is >> addr;
+ if (is.fail())
+ return is;
+
+ if (is.rdbuf()->in_avail()>0)
+ {
+ char c;
+ is.get(c);
+ if (c != ':')
+ {
+ is.unget();
+ endpoint = Endpoint (addr);
+ return is;
+ }
+
+ Port port;
+ is >> port;
+ if (is.fail())
+ return is;
+
+ endpoint = Endpoint (addr, port);
+ return is;
+ }
+
+ endpoint = Endpoint (addr);
+ return is;
+}
+
+}
+}
diff --git a/src/beast/config/BeastConfig.h b/src/beast/config/BeastConfig.h
index ca4b091933..40d2da93f9 100644
--- a/src/beast/config/BeastConfig.h
+++ b/src/beast/config/BeastConfig.h
@@ -146,6 +146,4 @@
//#define BEAST_USE_BOOST_FEATURES 1
#endif
-//------------------------------------------------------------------------------
-
#endif