Add support for networks and address ranges. The following new classes have been added: - address_iterator_v4: for iterating across IPv4 addresses - address_iterator_v6: for iterating across IPv6 addresses - address_range_v4: to represent a range of IPv4 addresses - address_range_v6: to represent a range of IPv6 addresses - network_v4: for manipulating IPv4 CIDR addresses, e.g. 1.2.3.0/24 - network_v6: for manipulating IPv6 CIDR addresses, e.g. ffe0:/120 Thanks go to Oliver Kowalke for contributing to the design and providing the implementation on which this facility is based.
diff --git a/asio/include/Makefile.am b/asio/include/Makefile.am index 438a51d..8defef3 100644 --- a/asio/include/Makefile.am +++ b/asio/include/Makefile.am
@@ -321,6 +321,10 @@ asio/io_service_strand.hpp \ asio/io_service.hpp \ asio/ip/address.hpp \ + asio/ip/address_iterator_v4.hpp \ + asio/ip/address_iterator_v6.hpp \ + asio/ip/address_range_v4.hpp \ + asio/ip/address_range_v6.hpp \ asio/ip/address_v4.hpp \ asio/ip/address_v6.hpp \ asio/ip/bad_address_cast.hpp \ @@ -342,7 +346,13 @@ asio/ip/impl/address_v6.ipp \ asio/ip/impl/basic_endpoint.hpp \ asio/ip/impl/host_name.ipp \ + asio/ip/impl/network_v4.hpp \ + asio/ip/impl/network_v4.ipp \ + asio/ip/impl/network_v6.hpp \ + asio/ip/impl/network_v6.ipp \ asio/ip/multicast.hpp \ + asio/ip/network_v4.hpp \ + asio/ip/network_v6.hpp \ asio/ip/resolver_query_base.hpp \ asio/ip/resolver_service.hpp \ asio/ip/tcp.hpp \
diff --git a/asio/include/asio.hpp b/asio/include/asio.hpp index 51deb11..3811c3d 100644 --- a/asio/include/asio.hpp +++ b/asio/include/asio.hpp
@@ -64,6 +64,8 @@ #include "asio/io_service.hpp" #include "asio/io_service_strand.hpp" #include "asio/ip/address.hpp" +#include "asio/ip/address_iterator_v4.hpp" +#include "asio/ip/address_range_v4.hpp" #include "asio/ip/address_v4.hpp" #include "asio/ip/address_v6.hpp" #include "asio/ip/bad_address_cast.hpp"
diff --git a/asio/include/asio/impl/src.hpp b/asio/include/asio/impl/src.hpp index df5f886..3321103 100644 --- a/asio/include/asio/impl/src.hpp +++ b/asio/include/asio/impl/src.hpp
@@ -73,6 +73,7 @@ #include "asio/ip/impl/address_v4.ipp" #include "asio/ip/impl/address_v6.ipp" #include "asio/ip/impl/host_name.ipp" +#include "asio/ip/impl/network_v4.ipp" #include "asio/ip/detail/impl/endpoint.ipp" #include "asio/local/detail/impl/endpoint.ipp"
diff --git a/asio/include/asio/ip/address_iterator_v4.hpp b/asio/include/asio/ip/address_iterator_v4.hpp new file mode 100644 index 0000000..aac7ce4 --- /dev/null +++ b/asio/include/asio/ip/address_iterator_v4.hpp
@@ -0,0 +1,156 @@ +// +// ip/address_iterator_v4.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_ITERATOR_V4_HPP +#define ASIO_IP_ADDRESS_ITERATOR_V4_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/ip/address_v4.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// An input iterator that can be used for traversing IPv4 addresses. +/** + * In addition to satisfying the input iterator requirements, this iterator + * also supports decrement. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_iterator_v4 +{ +public: + /// The type of the elements pointed to by the iterator. + typedef address_v4 value_type; + + /// Distance between two iterators. + typedef std::ptrdiff_t difference_type; + + /// The type of a pointer to an element pointed to by the iterator. + typedef const address_v4* pointer; + + /// The type of a reference to an element pointed to by the iterator. + typedef const address_v4& reference; + + /// Denotes that the iterator satisfies the input iterator requirements. + typedef std::input_iterator_tag iterator_category; + + /// Construct an iterator that points to the specified address. + address_iterator_v4(const address_v4& addr) ASIO_NOEXCEPT + : address_(addr) + { + } + + /// Copy constructor. + address_iterator_v4(const address_iterator_v4& other) ASIO_NOEXCEPT + : address_(other.address_) + { + } + +#if defined(ASIO_HAS_MOVE) + /// Move constructor. + address_iterator_v4(address_iterator_v4&& other) ASIO_NOEXCEPT + : address_(ASIO_MOVE_CAST(address_v4)(other.address_)) + { + } +#endif // defined(ASIO_HAS_MOVE) + + /// Assignment operator. + address_iterator_v4& operator=( + const address_iterator_v4& other) ASIO_NOEXCEPT + { + address_ = other.address_; + return *this; + } + +#if defined(ASIO_HAS_MOVE) + /// Move assignment operator. + address_iterator_v4& operator=( + address_iterator_v4&& other) ASIO_NOEXCEPT + { + address_ = ASIO_MOVE_CAST(address_v4)(other.address_); + return *this; + } +#endif // defined(ASIO_HAS_MOVE) + + /// Dereference the iterator. + const address_v4& operator*() const ASIO_NOEXCEPT + { + return address_; + } + + /// Dereference the iterator. + const address_v4* operator->() const ASIO_NOEXCEPT + { + return &address_; + } + + /// Pre-increment operator. + address_iterator_v4& operator++() ASIO_NOEXCEPT + { + address_ = address_v4((address_.to_ulong() + 1) & 0xFFFFFFFF); + return *this; + } + + /// Post-increment operator. + address_iterator_v4 operator++(int) ASIO_NOEXCEPT + { + address_iterator_v4 tmp(*this); + ++*this; + return tmp; + } + + /// Pre-decrement operator. + address_iterator_v4& operator--() ASIO_NOEXCEPT + { + address_ = address_v4((address_.to_ulong() - 1) & 0xFFFFFFFF); + return *this; + } + + /// Post-decrement operator. + address_iterator_v4 operator--(int) + { + address_iterator_v4 tmp(*this); + --*this; + return tmp; + } + + /// Compare two addresses for equality. + friend bool operator==(const address_iterator_v4& a, + const address_iterator_v4& b) + { + return a.address_ == b.address_; + } + + /// Compare two addresses for inequality. + friend bool operator!=(const address_iterator_v4& a, + const address_iterator_v4& b) + { + return a.address_ != b.address_; + } + +private: + address_v4 address_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_ADDRESS_ITERATOR_V4_HPP
diff --git a/asio/include/asio/ip/address_iterator_v6.hpp b/asio/include/asio/ip/address_iterator_v6.hpp new file mode 100644 index 0000000..274c7e8 --- /dev/null +++ b/asio/include/asio/ip/address_iterator_v6.hpp
@@ -0,0 +1,177 @@ +// +// ip/address_iterator_v6.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_ITERATOR_V6_HPP +#define ASIO_IP_ADDRESS_ITERATOR_V6_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/ip/address_v6.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// An input iterator that can be used for traversing IPv6 addresses. +/** + * In addition to satisfying the input iterator requirements, this iterator + * also supports decrement. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_iterator_v6 +{ +public: + /// The type of the elements pointed to by the iterator. + typedef address_v6 value_type; + + /// Distance between two iterators. + typedef std::ptrdiff_t difference_type; + + /// The type of a pointer to an element pointed to by the iterator. + typedef const address_v6* pointer; + + /// The type of a reference to an element pointed to by the iterator. + typedef const address_v6& reference; + + /// Denotes that the iterator satisfies the input iterator requirements. + typedef std::input_iterator_tag iterator_category; + + /// Construct an iterator that points to the specified address. + address_iterator_v6(const address_v6& addr) ASIO_NOEXCEPT + : address_(addr) + { + } + + /// Copy constructor. + address_iterator_v6(const address_iterator_v6& other) ASIO_NOEXCEPT + : address_(other.address_) + { + } + +#if defined(ASIO_HAS_MOVE) + /// Move constructor. + address_iterator_v6(address_iterator_v6&& other) ASIO_NOEXCEPT + : address_(ASIO_MOVE_CAST(address_v6)(other.address_)) + { + } +#endif // defined(ASIO_HAS_MOVE) + + /// Assignment operator. + address_iterator_v6& operator=( + const address_iterator_v6& other) ASIO_NOEXCEPT + { + address_ = other.address_; + return *this; + } + +#if defined(ASIO_HAS_MOVE) + /// Move assignment operator. + address_iterator_v6& operator=( + address_iterator_v6&& other) ASIO_NOEXCEPT + { + address_ = ASIO_MOVE_CAST(address_v6)(other.address_); + return *this; + } +#endif // defined(ASIO_HAS_MOVE) + + /// Dereference the iterator. + const address_v6& operator*() const ASIO_NOEXCEPT + { + return address_; + } + + /// Dereference the iterator. + const address_v6* operator->() const ASIO_NOEXCEPT + { + return &address_; + } + + /// Pre-increment operator. + address_iterator_v6& operator++() ASIO_NOEXCEPT + { + for (int i = 15; i >= 0; --i) + { + if (address_.addr_.s6_addr[i] < 0xFF) + { + ++address_.addr_.s6_addr[i]; + break; + } + + address_.addr_.s6_addr[i] = 0; + } + + return *this; + } + + /// Post-increment operator. + address_iterator_v6 operator++(int) ASIO_NOEXCEPT + { + address_iterator_v6 tmp(*this); + ++*this; + return tmp; + } + + /// Pre-decrement operator. + address_iterator_v6& operator--() ASIO_NOEXCEPT + { + for (int i = 15; i >= 0; --i) + { + if (address_.addr_.s6_addr[i] > 0) + { + --address_.addr_.s6_addr[i]; + break; + } + + address_.addr_.s6_addr[i] = 0xFF; + } + + return *this; + } + + /// Post-decrement operator. + address_iterator_v6 operator--(int) + { + address_iterator_v6 tmp(*this); + --*this; + return tmp; + } + + /// Compare two addresses for equality. + friend bool operator==(const address_iterator_v6& a, + const address_iterator_v6& b) + { + return a.address_ == b.address_; + } + + /// Compare two addresses for inequality. + friend bool operator!=(const address_iterator_v6& a, + const address_iterator_v6& b) + { + return a.address_ != b.address_; + } + +private: + address_v6 address_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_ADDRESS_ITERATOR_V6_HPP
diff --git a/asio/include/asio/ip/address_range_v4.hpp b/asio/include/asio/ip/address_range_v4.hpp new file mode 100644 index 0000000..06f07b9 --- /dev/null +++ b/asio/include/asio/ip/address_range_v4.hpp
@@ -0,0 +1,129 @@ +// +// ip/address_range_v4.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_RANGE_V4_HPP +#define ASIO_IP_ADDRESS_RANGE_V4_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/ip/address_iterator_v4.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Represents a range of IPv4 addresses. +/** + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_range_v4 +{ +public: + /// The type of an iterator that points into the range. + typedef address_iterator_v4 iterator; + + /// Construct an empty range. + address_range_v4() ASIO_NOEXCEPT + : begin_(address_v4()), + end_(address_v4()) + { + } + + /// Construct an range that represents the given range of addresses. + explicit address_range_v4(const address_iterator_v4& first, + const address_iterator_v4& last) ASIO_NOEXCEPT + : begin_(first), + end_(last) + { + } + + /// Copy constructor. + address_range_v4(const address_range_v4& other) ASIO_NOEXCEPT + : begin_(other.begin_), + end_(other.end_) + { + } + +#if defined(ASIO_HAS_MOVE) + /// Move constructor. + address_range_v4(address_range_v4&& other) ASIO_NOEXCEPT + : begin_(ASIO_MOVE_CAST(address_iterator_v4)(other.begin_)), + end_(ASIO_MOVE_CAST(address_iterator_v4)(other.end_)) + { + } +#endif // defined(ASIO_HAS_MOVE) + + /// Assignment operator. + address_range_v4& operator=( + const address_range_v4& other) ASIO_NOEXCEPT + { + begin_ = other.begin_; + end_ = other.end_; + return *this; + } + +#if defined(ASIO_HAS_MOVE) + /// Move assignment operator. + address_range_v4& operator=( + address_range_v4&& other) ASIO_NOEXCEPT + { + begin_ = ASIO_MOVE_CAST(address_iterator_v4)(other.begin_); + end_ = ASIO_MOVE_CAST(address_iterator_v4)(other.end_); + return *this; + } +#endif // defined(ASIO_HAS_MOVE) + + /// Obtain an iterator that points to the start of the range. + iterator begin() const ASIO_NOEXCEPT + { + return begin_; + } + + /// Obtain an iterator that points to the end of the range. + iterator end() const ASIO_NOEXCEPT + { + return end_; + } + + /// Determine whether the range is empty. + bool empty() const ASIO_NOEXCEPT + { + return size() == 0; + } + + /// Return the size of the range. + std::size_t size() const ASIO_NOEXCEPT + { + return end_->to_ulong() - begin_->to_ulong(); + } + + /// Find an address in the range. + iterator find(const address_v4& addr) const ASIO_NOEXCEPT + { + return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_; + } + +private: + address_iterator_v4 begin_; + address_iterator_v4 end_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_ADDRESS_RANGE_V4_HPP
diff --git a/asio/include/asio/ip/address_range_v6.hpp b/asio/include/asio/ip/address_range_v6.hpp new file mode 100644 index 0000000..261b945 --- /dev/null +++ b/asio/include/asio/ip/address_range_v6.hpp
@@ -0,0 +1,124 @@ +// +// ip/address_range_v6.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_ADDRESS_RANGE_v6_HPP +#define ASIO_IP_ADDRESS_RANGE_v6_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/ip/address_iterator_v6.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Represents a range of IPv6 addresses. +/** + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_range_v6 +{ +public: + /// The type of an iterator that points into the range. + typedef address_iterator_v6 iterator; + + /// Construct an empty range. + address_range_v6() ASIO_NOEXCEPT + : begin_(address_v6()), + end_(address_v6()) + { + } + + /// Construct an range that represents the given range of addresses. + explicit address_range_v6(const address_iterator_v6& first, + const address_iterator_v6& last) ASIO_NOEXCEPT + : begin_(first), + end_(last) + { + } + + /// Copy constructor. + address_range_v6(const address_range_v6& other) ASIO_NOEXCEPT + : begin_(other.begin_), + end_(other.end_) + { + } + +#if defined(ASIO_HAS_MOVE) + /// Move constructor. + address_range_v6(address_range_v6&& other) ASIO_NOEXCEPT + : begin_(ASIO_MOVE_CAST(address_iterator_v6)(other.begin_)), + end_(ASIO_MOVE_CAST(address_iterator_v6)(other.end_)) + { + } +#endif // defined(ASIO_HAS_MOVE) + + /// Assignment operator. + address_range_v6& operator=( + const address_range_v6& other) ASIO_NOEXCEPT + { + begin_ = other.begin_; + end_ = other.end_; + return *this; + } + +#if defined(ASIO_HAS_MOVE) + /// Move assignment operator. + address_range_v6& operator=( + address_range_v6&& other) ASIO_NOEXCEPT + { + begin_ = ASIO_MOVE_CAST(address_iterator_v6)(other.begin_); + end_ = ASIO_MOVE_CAST(address_iterator_v6)(other.end_); + return *this; + } +#endif // defined(ASIO_HAS_MOVE) + + /// Obtain an iterator that points to the start of the range. + iterator begin() const ASIO_NOEXCEPT + { + return begin_; + } + + /// Obtain an iterator that points to the end of the range. + iterator end() const ASIO_NOEXCEPT + { + return end_; + } + + /// Determine whether the range is empty. + bool empty() const ASIO_NOEXCEPT + { + return begin_ == end_; + } + + /// Find an address in the range. + iterator find(const address_v6& addr) const ASIO_NOEXCEPT + { + return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_; + } + +private: + address_iterator_v6 begin_; + address_iterator_v6 end_; +}; + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_ADDRESS_RANGE_V6_HPP
diff --git a/asio/include/asio/ip/address_v6.hpp b/asio/include/asio/ip/address_v6.hpp index 69de767..74569e8 100644 --- a/asio/include/asio/ip/address_v6.hpp +++ b/asio/include/asio/ip/address_v6.hpp
@@ -218,6 +218,8 @@ #endif // !defined(ASIO_NO_DEPRECATED) private: + friend class address_iterator_v6; + // The underlying IPv6 address. asio::detail::in6_addr_type addr_;
diff --git a/asio/include/asio/ip/impl/network_v4.hpp b/asio/include/asio/ip/impl/network_v4.hpp new file mode 100644 index 0000000..291bb99 --- /dev/null +++ b/asio/include/asio/ip/impl/network_v4.hpp
@@ -0,0 +1,54 @@ +// +// ip/impl/network_v4.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_NETWORK_V4_HPP +#define ASIO_IP_IMPL_NETWORK_V4_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#if !defined(ASIO_NO_IOSTREAM) + +#include "asio/detail/throw_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +template <typename Elem, typename Traits> +std::basic_ostream<Elem, Traits>& operator<<( + std::basic_ostream<Elem, Traits>& os, const network_v4& addr) +{ + asio::error_code ec; + std::string s = addr.to_string(ec); + if (ec) + { + if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit) + asio::detail::throw_error(ec); + else + os.setstate(std::basic_ostream<Elem, Traits>::failbit); + } + else + for (std::string::iterator i = s.begin(); i != s.end(); ++i) + os << os.widen(*i); + return os; +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // !defined(ASIO_NO_IOSTREAM) + +#endif // ASIO_IP_IMPL_NETWORK_V4_HPP
diff --git a/asio/include/asio/ip/impl/network_v4.ipp b/asio/include/asio/ip/impl/network_v4.ipp new file mode 100644 index 0000000..bf44629 --- /dev/null +++ b/asio/include/asio/ip/impl/network_v4.ipp
@@ -0,0 +1,190 @@ +// +// ip/impl/network_v4.ipp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_NETWORK_V4_IPP +#define ASIO_IP_IMPL_NETWORK_V4_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <climits> +#include <cstdio> +#include <cstdlib> +#include <stdexcept> +#include "asio/error.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/ip/network_v4.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +network_v4::network_v4(const address_v4& addr, unsigned short prefix_len) + : address_(addr), + prefix_length_(prefix_len) +{ + if (prefix_len > 32) + { + std::out_of_range ex("prefix length too large"); + asio::detail::throw_exception(ex); + } +} + +network_v4::network_v4(const address_v4& addr, const address_v4& mask) + : address_(addr), + prefix_length_(0) +{ + address_v4::bytes_type mask_bytes = mask.to_bytes(); + bool finished = false; + for (std::size_t i = 0; i < mask_bytes.size(); ++i) + { + if (finished) + { + if (mask_bytes[i]) + { + std::invalid_argument ex("non-contiguous netmask"); + asio::detail::throw_exception(ex); + } + continue; + } + else + { + switch (mask_bytes[i]) + { + case 255: + prefix_length_ += 8; + break; + case 254: // prefix_length_ += 7 + prefix_length_ += 1; + case 252: // prefix_length_ += 6 + prefix_length_ += 1; + case 248: // prefix_length_ += 5 + prefix_length_ += 1; + case 240: // prefix_length_ += 4 + prefix_length_ += 1; + case 224: // prefix_length_ += 3 + prefix_length_ += 1; + case 192: // prefix_length_ += 2 + prefix_length_ += 1; + case 128: // prefix_length_ += 1 + prefix_length_ += 1; + case 0: // nbits += 0 + finished = true; + break; + default: + std::out_of_range ex("non-contiguous netmask"); + asio::detail::throw_exception(ex); + } + } + } +} + +address_v4 network_v4::netmask() const ASIO_NOEXCEPT +{ + uint32_t nmbits = 0xffffffff; + if (prefix_length_ == 0) + nmbits = 0; + else + nmbits = nmbits << (32 - prefix_length_); + return address_v4(nmbits); +} + +address_range_v4 network_v4::hosts() const ASIO_NOEXCEPT +{ + return is_host() + ? address_range_v4(address_, address_v4(address_.to_ulong() + 1)) + : address_range_v4(address_v4(network().to_ulong() + 1), broadcast()); +} + +bool network_v4::is_subnet_of(const network_v4& other) const +{ + if (other.prefix_length_ >= prefix_length_) + return false; // Only real subsets are allowed. + const network_v4 me(address_, other.prefix_length_); + return other.canonical() == me.canonical(); +} + +std::string network_v4::to_string() const +{ + asio::error_code ec; + std::string addr = to_string(ec); + asio::detail::throw_error(ec); + return addr; +} + +std::string network_v4::to_string(asio::error_code& ec) const +{ + ec = asio::error_code(); + char prefix_len[16]; +#if defined(ASIO_HAS_SECURE_RTL) + sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); +#else // defined(ASIO_HAS_SECURE_RTL) + sprintf(prefix_len, "/%u", prefix_length_); +#endif // defined(ASIO_HAS_SECURE_RTL) + return address_.to_string() + prefix_len; +} + +network_v4 make_network_v4(const char* str) +{ + return make_network_v4(std::string(str)); +} + +network_v4 make_network_v4(const char* str, asio::error_code& ec) +{ + return make_network_v4(std::string(str), ec); +} + +network_v4 make_network_v4(const std::string& str) +{ + asio::error_code ec; + network_v4 net = make_network_v4(str, ec); + asio::detail::throw_error(ec); + return net; +} + +network_v4 make_network_v4(const std::string& str, + asio::error_code& ec) +{ + std::string::size_type pos = str.find_first_of("/"); + + if (pos == std::string::npos) + { + ec = asio::error::invalid_argument; + return network_v4(); + } + + if (pos == str.size() - 1) + { + ec = asio::error::invalid_argument; + return network_v4(); + } + + std::string::size_type end = str.find_first_not_of("0123456789", pos + 1); + if (end != std::string::npos) + { + ec = asio::error::invalid_argument; + return network_v4(); + } + + return network_v4(make_address_v4(str.substr(0, pos)), + std::atoi(str.substr(pos + 1).c_str())); +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_IMPL_NETWORK_V4_IPP
diff --git a/asio/include/asio/ip/impl/network_v6.hpp b/asio/include/asio/ip/impl/network_v6.hpp new file mode 100644 index 0000000..29dd868 --- /dev/null +++ b/asio/include/asio/ip/impl/network_v6.hpp
@@ -0,0 +1,53 @@ +// +// ip/impl/network_v6.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_NETWORK_V6_HPP +#define ASIO_IP_IMPL_NETWORK_V6_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#if !defined(ASIO_NO_IOSTREAM) + +#include "asio/detail/throw_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +template <typename Elem, typename Traits> +std::basic_ostream<Elem, Traits>& operator<<( + std::basic_ostream<Elem, Traits>& os, const network_v6& addr) +{ + asio::error_code ec; + std::string s = addr.to_string(ec); + if (ec) + { + if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit) + asio::detail::throw_error(ec); + else + os.setstate(std::basic_ostream<Elem, Traits>::failbit); + } + else + for (std::string::iterator i = s.begin(); i != s.end(); ++i) + os << os.widen(*i); + return os; +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // !defined(ASIO_NO_IOSTREAM) + +#endif // ASIO_IP_IMPL_NETWORK_V6_HPP
diff --git a/asio/include/asio/ip/impl/network_v6.ipp b/asio/include/asio/ip/impl/network_v6.ipp new file mode 100644 index 0000000..89c8398 --- /dev/null +++ b/asio/include/asio/ip/impl/network_v6.ipp
@@ -0,0 +1,159 @@ +// +// ip/impl/network_v6.ipp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_IMPL_NETWORK_V6_IPP +#define ASIO_IP_IMPL_NETWORK_V6_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <climits> +#include <cstdio> +#include <cstdlib> +#include <stdexcept> +#include "asio/error.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/ip/network_v6.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +network_v6::network_v6(const address_v6& addr, unsigned short prefix_len) + : address_(addr), + prefix_length_(prefix_len) +{ + if (prefix_len > 128) + { + std::out_of_range ex("prefix length too large"); + asio::detail::throw_exception(ex); + } +} + +ASIO_DECL address_v6 network_v6::network() const ASIO_NOEXCEPT +{ + address_v6::bytes_type bytes(address_.to_bytes()); + for (std::size_t i = 0; i < 16; ++i) + { + if (prefix_length_ <= i * 8) + bytes[i] = 0; + else if (prefix_length_ < (i + 1) * 8) + bytes[i] &= 0xFF00 >> (prefix_length_ % 8); + } + return address_v6(bytes, address_.scope_id()); +} + +address_range_v6 network_v6::hosts() const ASIO_NOEXCEPT +{ + address_v6::bytes_type begin_bytes(address_.to_bytes()); + address_v6::bytes_type end_bytes(address_.to_bytes()); + for (std::size_t i = 0; i < 16; ++i) + { + if (prefix_length_ <= i * 8) + { + begin_bytes[i] = 0; + end_bytes[i] = 0xFF; + } + else if (prefix_length_ < (i + 1) * 8) + { + begin_bytes[i] &= 0xFF00 >> (prefix_length_ % 8); + end_bytes[i] |= 0xFF >> (prefix_length_ % 8); + } + } + return address_range_v6( + address_iterator_v6(address_v6(begin_bytes, address_.scope_id())), + ++address_iterator_v6(address_v6(end_bytes, address_.scope_id()))); +} + +bool network_v6::is_subnet_of(const network_v6& other) const +{ + if (other.prefix_length_ >= prefix_length_) + return false; // Only real subsets are allowed. + const network_v6 me(address_, other.prefix_length_); + return other.canonical() == me.canonical(); +} + +std::string network_v6::to_string() const +{ + asio::error_code ec; + std::string addr = to_string(ec); + asio::detail::throw_error(ec); + return addr; +} + +std::string network_v6::to_string(asio::error_code& ec) const +{ + ec = asio::error_code(); + char prefix_len[16]; +#if defined(ASIO_HAS_SECURE_RTL) + sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); +#else // defined(ASIO_HAS_SECURE_RTL) + sprintf(prefix_len, "/%u", prefix_length_); +#endif // defined(ASIO_HAS_SECURE_RTL) + return address_.to_string() + prefix_len; +} + +network_v6 make_network_v6(const char* str) +{ + return make_network_v6(std::string(str)); +} + +network_v6 make_network_v6(const char* str, asio::error_code& ec) +{ + return make_network_v6(std::string(str), ec); +} + +network_v6 make_network_v6(const std::string& str) +{ + asio::error_code ec; + network_v6 net = make_network_v6(str, ec); + asio::detail::throw_error(ec); + return net; +} + +network_v6 make_network_v6(const std::string& str, + asio::error_code& ec) +{ + std::string::size_type pos = str.find_first_of("/"); + + if (pos == std::string::npos) + { + ec = asio::error::invalid_argument; + return network_v6(); + } + + if (pos == str.size() - 1) + { + ec = asio::error::invalid_argument; + return network_v6(); + } + + std::string::size_type end = str.find_first_not_of("0123456789", pos + 1); + if (end != std::string::npos) + { + ec = asio::error::invalid_argument; + return network_v6(); + } + + return network_v6(make_address_v6(str.substr(0, pos)), + std::atoi(str.substr(pos + 1).c_str())); +} + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IP_IMPL_NETWORK_V6_IPP
diff --git a/asio/include/asio/ip/network_v4.hpp b/asio/include/asio/ip/network_v4.hpp new file mode 100644 index 0000000..3d1e37c --- /dev/null +++ b/asio/include/asio/ip/network_v4.hpp
@@ -0,0 +1,236 @@ +// +// ip/network_v4.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_NETWORK_V4_HPP +#define ASIO_IP_NETWORK_V4_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/error_code.hpp" +#include "asio/ip/address_range_v4.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Represents an IPv4 network. +/** + * The asio::ip::network_v4 class provides the ability to use and + * manipulate IP version 4 networks. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class network_v4 +{ +public: + /// Default constructor. + network_v4() ASIO_NOEXCEPT + : address_(), + prefix_length_(0) + { + } + + /// Construct a network based on the specified address and prefix length. + ASIO_DECL network_v4(const address_v4& addr, + unsigned short prefix_len); + + /// Construct network based on the specified address and netmask. + ASIO_DECL network_v4(const address_v4& addr, + const address_v4& mask); + + /// Copy constructor. + network_v4(const network_v4& other) ASIO_NOEXCEPT + : address_(other.address_), + prefix_length_(other.prefix_length_) + { + } + +#if defined(ASIO_HAS_MOVE) + /// Move constructor. + network_v4(network_v4&& other) ASIO_NOEXCEPT + : address_(ASIO_MOVE_CAST(address_v4)(other.address_)), + prefix_length_(other.prefix_length_) + { + } +#endif // defined(ASIO_HAS_MOVE) + + /// Assign from another network. + network_v4& operator=(const network_v4& other) ASIO_NOEXCEPT + { + address_ = other.address_; + prefix_length_ = other.prefix_length_; + return *this; + } + +#if defined(ASIO_HAS_MOVE) + /// Move-assign from another network. + network_v4& operator=(network_v4&& other) ASIO_NOEXCEPT + { + address_ = ASIO_MOVE_CAST(address_v4)(other.address_); + prefix_length_ = other.prefix_length_; + return *this; + } +#endif // defined(ASIO_HAS_MOVE) + + /// Obtain the address object specified when the network object was created. + address_v4 address() const ASIO_NOEXCEPT + { + return address_; + } + + /// Obtain the prefix length that was specified when the network object was + /// created. + unsigned short prefix_length() const ASIO_NOEXCEPT + { + return prefix_length_; + } + + /// Obtain the netmask that was specified when the network object was created. + ASIO_DECL address_v4 netmask() const ASIO_NOEXCEPT; + + /// Obtain an address object that represents the network address. + address_v4 network() const ASIO_NOEXCEPT + { + return address_v4(address_.to_ulong() & netmask().to_ulong()); + } + + /// Obtain an address object that represents the network's broadcast address. + address_v4 broadcast() const ASIO_NOEXCEPT + { + return address_v4::broadcast(network(), netmask()); + } + + /// Obtain an address range corresponding to the hosts in the network. + ASIO_DECL address_range_v4 hosts() const ASIO_NOEXCEPT; + + /// Obtain the true network address, omitting any host bits. + network_v4 canonical() const ASIO_NOEXCEPT + { + return network_v4(network(), netmask()); + } + + /// Test if network is a valid host address. + bool is_host() const ASIO_NOEXCEPT + { + return prefix_length_ == 32; + } + + /// Test if a network is a real subnet of another network. + ASIO_DECL bool is_subnet_of(const network_v4& other) const; + + /// Get the network as an address in dotted decimal format. + ASIO_DECL std::string to_string() const; + + /// Get the network as an address in dotted decimal format. + ASIO_DECL std::string to_string(asio::error_code& ec) const; + + /// Compare two networks for equality. + friend bool operator==(const network_v4& a, const network_v4& b) + { + return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_; + } + + /// Compare two networks for inequality. + friend bool operator!=(const network_v4& a, const network_v4& b) + { + return !(a == b); + } + +private: + address_v4 address_; + unsigned short prefix_length_; +}; + +/// Create an IPv4 network from an address and prefix length. +/** + * @relates address_v4 + */ +inline network_v4 make_network_v4( + const address_v4& addr, unsigned short prefix_len) +{ + return network_v4(addr, prefix_len); +} + +/// Create an IPv4 network from an address and netmask. +/** + * @relates address_v4 + */ +inline network_v4 make_network_v4( + const address_v4& addr, const address_v4& mask) +{ + return network_v4(addr, mask); +} + +/// Create an IPv4 network from a string containing IP address and prefix +/// length. +/** + * @relates network_v4 + */ +ASIO_DECL network_v4 make_network_v4(const char* str); + +/// Create an IPv4 address from an IP address string in dotted decimal form. +/** + * @relates network_v4 + */ +ASIO_DECL network_v4 make_network_v4( + const char* str, asio::error_code& ec); + +/// Create an IPv4 address from an IP address string in dotted decimal form. +/** + * @relates network_v4 + */ +ASIO_DECL network_v4 make_network_v4(const std::string& str); + +/// Create an IPv4 address from an IP address string in dotted decimal form. +/** + * @relates network_v4 + */ +ASIO_DECL network_v4 make_network_v4( + const std::string& str, asio::error_code& ec); + +#if !defined(ASIO_NO_IOSTREAM) + +/// Output a network as a string. +/** + * Used to output a human-readable string for a specified network. + * + * @param os The output stream to which the string will be written. + * + * @param net The network to be written. + * + * @return The output stream. + * + * @relates asio::ip::address_v4 + */ +template <typename Elem, typename Traits> +std::basic_ostream<Elem, Traits>& operator<<( + std::basic_ostream<Elem, Traits>& os, const network_v4& net); + +#endif // !defined(ASIO_NO_IOSTREAM) + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/ip/impl/network_v4.hpp" +#if defined(ASIO_HEADER_ONLY) +# include "asio/ip/impl/network_v4.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // ASIO_IP_NETWORK_V4_HPP
diff --git a/asio/include/asio/ip/network_v6.hpp b/asio/include/asio/ip/network_v6.hpp new file mode 100644 index 0000000..346ad0e --- /dev/null +++ b/asio/include/asio/ip/network_v6.hpp
@@ -0,0 +1,210 @@ +// +// ip/network_v6.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IP_NETWORK_V6_HPP +#define ASIO_IP_NETWORK_V6_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <string> +#include "asio/error_code.hpp" +#include "asio/ip/address_range_v6.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace ip { + +/// Represents an IPv6 network. +/** + * The asio::ip::network_v6 class provides the ability to use and + * manipulate IP version 6 networks. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class network_v6 +{ +public: + /// Default constructor. + network_v6() ASIO_NOEXCEPT + : address_(), + prefix_length_(0) + { + } + + /// Construct a network based on the specified address and prefix length. + ASIO_DECL network_v6(const address_v6& addr, + unsigned short prefix_len); + + /// Copy constructor. + network_v6(const network_v6& other) ASIO_NOEXCEPT + : address_(other.address_), + prefix_length_(other.prefix_length_) + { + } + +#if defined(ASIO_HAS_MOVE) + /// Move constructor. + network_v6(network_v6&& other) ASIO_NOEXCEPT + : address_(ASIO_MOVE_CAST(address_v6)(other.address_)), + prefix_length_(other.prefix_length_) + { + } +#endif // defined(ASIO_HAS_MOVE) + + /// Assign from another network. + network_v6& operator=(const network_v6& other) ASIO_NOEXCEPT + { + address_ = other.address_; + prefix_length_ = other.prefix_length_; + return *this; + } + +#if defined(ASIO_HAS_MOVE) + /// Move-assign from another network. + network_v6& operator=(network_v6&& other) ASIO_NOEXCEPT + { + address_ = ASIO_MOVE_CAST(address_v6)(other.address_); + prefix_length_ = other.prefix_length_; + return *this; + } +#endif // defined(ASIO_HAS_MOVE) + + /// Obtain the address object specified when the network object was created. + address_v6 address() const ASIO_NOEXCEPT + { + return address_; + } + + /// Obtain the prefix length that was specified when the network object was + /// created. + unsigned short prefix_length() const ASIO_NOEXCEPT + { + return prefix_length_; + } + + /// Obtain an address object that represents the network address. + ASIO_DECL address_v6 network() const ASIO_NOEXCEPT; + + /// Obtain an address range corresponding to the hosts in the network. + ASIO_DECL address_range_v6 hosts() const ASIO_NOEXCEPT; + + /// Obtain the true network address, omitting any host bits. + network_v6 canonical() const ASIO_NOEXCEPT + { + return network_v6(network(), prefix_length()); + } + + /// Test if network is a valid host address. + bool is_host() const ASIO_NOEXCEPT + { + return prefix_length_ == 128; + } + + /// Test if a network is a real subnet of another network. + ASIO_DECL bool is_subnet_of(const network_v6& other) const; + + /// Get the network as an address in dotted decimal format. + ASIO_DECL std::string to_string() const; + + /// Get the network as an address in dotted decimal format. + ASIO_DECL std::string to_string(asio::error_code& ec) const; + + /// Compare two networks for equality. + friend bool operator==(const network_v6& a, const network_v6& b) + { + return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_; + } + + /// Compare two networks for inequality. + friend bool operator!=(const network_v6& a, const network_v6& b) + { + return !(a == b); + } + +private: + address_v6 address_; + unsigned short prefix_length_; +}; + +/// Create an IPv6 network from an address and prefix length. +/** + * @relates address_v6 + */ +inline network_v6 make_network_v6( + const address_v6& addr, unsigned short prefix_len) +{ + return network_v6(addr, prefix_len); +} + +/// Create an IPv6 network from a string containing IP address and prefix +/// length. +/** + * @relates network_v6 + */ +ASIO_DECL network_v6 make_network_v6(const char* str); + +/// Create an IPv6 address from an IP address string in dotted decimal form. +/** + * @relates network_v6 + */ +ASIO_DECL network_v6 make_network_v6( + const char* str, asio::error_code& ec); + +/// Create an IPv6 address from an IP address string in dotted decimal form. +/** + * @relates network_v6 + */ +ASIO_DECL network_v6 make_network_v6(const std::string& str); + +/// Create an IPv6 address from an IP address string in dotted decimal form. +/** + * @relates network_v6 + */ +ASIO_DECL network_v6 make_network_v6( + const std::string& str, asio::error_code& ec); + +#if !defined(ASIO_NO_IOSTREAM) + +/// Output a network as a string. +/** + * Used to output a human-readable string for a specified network. + * + * @param os The output stream to which the string will be written. + * + * @param net The network to be written. + * + * @return The output stream. + * + * @relates asio::ip::address_v6 + */ +template <typename Elem, typename Traits> +std::basic_ostream<Elem, Traits>& operator<<( + std::basic_ostream<Elem, Traits>& os, const network_v6& net); + +#endif // !defined(ASIO_NO_IOSTREAM) + +} // namespace ip +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/ip/impl/network_v6.hpp" +#if defined(ASIO_HEADER_ONLY) +# include "asio/ip/impl/network_v6.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // ASIO_IP_NETWORK_V6_HPP
diff --git a/asio/src/tests/Makefile.am b/asio/src/tests/Makefile.am index 8fa3035..09c1a10 100644 --- a/asio/src/tests/Makefile.am +++ b/asio/src/tests/Makefile.am
@@ -40,6 +40,10 @@ unit/high_resolution_timer \ unit/io_service \ unit/ip/address \ + unit/ip/address_iterator_v4 \ + unit/ip/address_iterator_v6 \ + unit/ip/address_range_v4 \ + unit/ip/address_range_v6 \ unit/ip/address_v4 \ unit/ip/address_v6 \ unit/ip/basic_endpoint \ @@ -50,6 +54,8 @@ unit/ip/host_name \ unit/ip/icmp \ unit/ip/multicast \ + unit/ip/network_v4 \ + unit/ip/network_v6 \ unit/ip/resolver_query_base \ unit/ip/resolver_service \ unit/ip/tcp \ @@ -147,6 +153,10 @@ unit/high_resolution_timer \ unit/io_service \ unit/ip/address \ + unit/ip/address_iterator_v4 \ + unit/ip/address_iterator_v6 \ + unit/ip/address_range_v4 \ + unit/ip/address_range_v6 \ unit/ip/address_v4 \ unit/ip/address_v6 \ unit/ip/basic_endpoint \ @@ -157,6 +167,8 @@ unit/ip/host_name \ unit/ip/icmp \ unit/ip/multicast \ + unit/ip/network_v4 \ + unit/ip/network_v6 \ unit/ip/resolver_query_base \ unit/ip/resolver_service \ unit/ip/tcp \ @@ -267,6 +279,10 @@ unit_high_resolution_timer_SOURCES = unit/high_resolution_timer.cpp unit/unit_test.cpp unit_io_service_SOURCES = unit/io_service.cpp unit/unit_test.cpp unit_ip_address_SOURCES = unit/ip/address.cpp unit/unit_test.cpp +unit_ip_address_iterator_v4_SOURCES = unit/ip/address_iterator_v4.cpp unit/unit_test.cpp +unit_ip_address_iterator_v6_SOURCES = unit/ip/address_iterator_v6.cpp unit/unit_test.cpp +unit_ip_address_range_v4_SOURCES = unit/ip/address_range_v4.cpp unit/unit_test.cpp +unit_ip_address_range_v6_SOURCES = unit/ip/address_range_v6.cpp unit/unit_test.cpp unit_ip_address_v4_SOURCES = unit/ip/address_v4.cpp unit/unit_test.cpp unit_ip_address_v6_SOURCES = unit/ip/address_v6.cpp unit/unit_test.cpp unit_ip_basic_endpoint_SOURCES = unit/ip/basic_endpoint.cpp unit/unit_test.cpp @@ -277,6 +293,8 @@ unit_ip_host_name_SOURCES = unit/ip/host_name.cpp unit/unit_test.cpp unit_ip_icmp_SOURCES = unit/ip/icmp.cpp unit/unit_test.cpp unit_ip_multicast_SOURCES = unit/ip/multicast.cpp unit/unit_test.cpp +unit_ip_network_v4_SOURCES = unit/ip/network_v4.cpp unit/unit_test.cpp +unit_ip_network_v6_SOURCES = unit/ip/network_v6.cpp unit/unit_test.cpp unit_ip_resolver_query_base_SOURCES = unit/ip/resolver_query_base.cpp unit/unit_test.cpp unit_ip_resolver_service_SOURCES = unit/ip/resolver_service.cpp unit/unit_test.cpp unit_ip_tcp_SOURCES = unit/ip/tcp.cpp unit/unit_test.cpp
diff --git a/asio/src/tests/unit/ip/.gitignore b/asio/src/tests/unit/ip/.gitignore index b1b2e7b..ab157b6 100644 --- a/asio/src/tests/unit/ip/.gitignore +++ b/asio/src/tests/unit/ip/.gitignore
@@ -8,8 +8,8 @@ *.pdb *.tds address -address_v4 -address_v6 +address*_v4 +address*_v6 basic_endpoint basic_resolver basic_resolver_entry @@ -18,6 +18,8 @@ host_name icmp multicast +network_v4 +network_v6 resolver_query_base resolver_service tcp
diff --git a/asio/src/tests/unit/ip/address_iterator_v4.cpp b/asio/src/tests/unit/ip/address_iterator_v4.cpp new file mode 100644 index 0000000..931c085 --- /dev/null +++ b/asio/src/tests/unit/ip/address_iterator_v4.cpp
@@ -0,0 +1,27 @@ +// +// address_iterator_v4.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_iterator_v4.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_iterator_v4", + ASIO_TEST_CASE(null_test) +)
diff --git a/asio/src/tests/unit/ip/address_iterator_v6.cpp b/asio/src/tests/unit/ip/address_iterator_v6.cpp new file mode 100644 index 0000000..5b08adb --- /dev/null +++ b/asio/src/tests/unit/ip/address_iterator_v6.cpp
@@ -0,0 +1,27 @@ +// +// address_iterator_v6.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_iterator_v6.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_iterator_v6", + ASIO_TEST_CASE(null_test) +)
diff --git a/asio/src/tests/unit/ip/address_range_v4.cpp b/asio/src/tests/unit/ip/address_range_v4.cpp new file mode 100644 index 0000000..2c90877 --- /dev/null +++ b/asio/src/tests/unit/ip/address_range_v4.cpp
@@ -0,0 +1,27 @@ +// +// address_range_v4.cpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_range_v4.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_range_v4", + ASIO_TEST_CASE(null_test) +)
diff --git a/asio/src/tests/unit/ip/address_range_v6.cpp b/asio/src/tests/unit/ip/address_range_v6.cpp new file mode 100644 index 0000000..5f90af2 --- /dev/null +++ b/asio/src/tests/unit/ip/address_range_v6.cpp
@@ -0,0 +1,27 @@ +// +// address_range_v6.cpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_range_v6.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_range_v6", + ASIO_TEST_CASE(null_test) +)
diff --git a/asio/src/tests/unit/ip/network_v4.cpp b/asio/src/tests/unit/ip/network_v4.cpp new file mode 100644 index 0000000..8e9b5d4 --- /dev/null +++ b/asio/src/tests/unit/ip/network_v4.cpp
@@ -0,0 +1,273 @@ +// +// network_v4.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/network_v4.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +// ip_network_v4_compile test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that all public member functions on the class +// ip::network_v4 compile and link correctly. Runtime failures are ignored. + +namespace ip_network_v4_compile { + +void test() +{ + using namespace asio; + namespace ip = asio::ip; + + try + { + asio::error_code ec; + + // network_v4 constructors. + + ip::network_v4 net1(ip::make_address_v4("192.168.1.0"), 32); + ip::network_v4 net2(ip::make_address_v4("192.168.1.0"), + ip::make_address_v4("255.255.255.0")); + + // network_v4 functions. + + ip::address_v4 addr1 = net1.address(); + (void)addr1; + + unsigned short prefix_len = net1.prefix_length(); + (void)prefix_len; + + ip::address_v4 addr2 = net1.netmask(); + (void)addr2; + + ip::address_v4 addr3 = net1.network(); + (void)addr3; + + ip::address_v4 addr4 = net1.broadcast(); + (void)addr4; + + ip::address_range_v4 hosts = net1.hosts(); + (void)hosts; + + ip::network_v4 net3 = net1.canonical(); + (void)net3; + + bool b1 = net1.is_host(); + (void)b1; + + bool b2 = net1.is_subnet_of(net2); + (void)b2; + + std::string s1 = net1.to_string(); + (void)s1; + + std::string s2 = net1.to_string(ec); + (void)s2; + + // network_v4 comparisons. + + bool b3 = (net1 == net2); + (void)b3; + + bool b4 = (net1 != net2); + (void)b4; + + } + catch (std::exception&) + { + } +} + +} // namespace ip_network_v4_compile + +//------------------------------------------------------------------------------ + +// ip_network_v4_runtime test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that the various public member functions meet the +// necessary postconditions. + +namespace ip_network_v4_runtime { + +void test() +{ + using asio::ip::address_v4; + using asio::ip::make_address_v4; + using asio::ip::network_v4; + using asio::ip::make_network_v4; + + address_v4 addr = make_address_v4("1.2.3.4"); + + // calculate prefix length + + network_v4 net1(addr, make_address_v4("255.255.255.0")); + ASIO_CHECK(net1.prefix_length() == 24); + + network_v4 net2(addr, make_address_v4("255.255.255.192")); + ASIO_CHECK(net2.prefix_length() == 26); + + network_v4 net3(addr, make_address_v4("128.0.0.0")); + ASIO_CHECK(net3.prefix_length() == 1); + + std::string msg; + try + { + make_network_v4(addr, make_address_v4("255.255.255.1")); + } + catch(std::exception& ex) + { + msg = ex.what(); + } + ASIO_CHECK(msg == std::string("non-contiguous netmask")); + + msg.clear(); + try + { + make_network_v4(addr, make_address_v4("0.255.255.0")); + } + catch(std::exception& ex) + { + msg = ex.what(); + } + ASIO_CHECK(msg == std::string("non-contiguous netmask")); + + // calculate netmask + + network_v4 net4(addr, 23); + ASIO_CHECK(net4.netmask() == make_address_v4("255.255.254.0")); + + network_v4 net5(addr, 12); + ASIO_CHECK(net5.netmask() == make_address_v4("255.240.0.0")); + + network_v4 net6(addr, 24); + ASIO_CHECK(net6.netmask() == make_address_v4("255.255.255.0")); + + network_v4 net7(addr, 16); + ASIO_CHECK(net7.netmask() == make_address_v4("255.255.0.0")); + + network_v4 net8(addr, 8); + ASIO_CHECK(net8.netmask() == make_address_v4("255.0.0.0")); + + network_v4 net9(addr, 32); + ASIO_CHECK(net9.netmask() == make_address_v4("255.255.255.255")); + + network_v4 net10(addr, 1); + ASIO_CHECK(net10.netmask() == make_address_v4("128.0.0.0")); + + network_v4 net11(addr, 0); + ASIO_CHECK(net11.netmask() == make_address_v4("0.0.0.0")); + + msg.clear(); + try + { + make_network_v4(addr, 33); + } + catch(std::out_of_range& ex) + { + msg = ex.what(); + } + ASIO_CHECK(msg == std::string("prefix length too large")); + + // construct address range from address and prefix length + ASIO_CHECK(network_v4(make_address_v4("192.168.77.100"), 32).network() == make_address_v4("192.168.77.100")); + ASIO_CHECK(network_v4(make_address_v4("192.168.77.100"), 24).network() == make_address_v4("192.168.77.0")); + ASIO_CHECK(network_v4(make_address_v4("192.168.77.128"), 25).network() == make_address_v4("192.168.77.128")); + + // construct address range from string in CIDR notation + ASIO_CHECK(make_network_v4("192.168.77.100/32").network() == make_address_v4("192.168.77.100")); + ASIO_CHECK(make_network_v4("192.168.77.100/24").network() == make_address_v4("192.168.77.0")); + ASIO_CHECK(make_network_v4("192.168.77.128/25").network() == make_address_v4("192.168.77.128")); + + // prefix length + ASIO_CHECK(make_network_v4("193.99.144.80/24").prefix_length() == 24); + ASIO_CHECK(network_v4(make_address_v4("193.99.144.80"), 24).prefix_length() == 24); + ASIO_CHECK(network_v4(make_address_v4("192.168.77.0"), make_address_v4("255.255.255.0")).prefix_length() == 24); + + // to string + std::string a("192.168.77.0/32"); + ASIO_CHECK(make_network_v4(a.c_str()).to_string() == a); + ASIO_CHECK(network_v4(make_address_v4("192.168.77.10"), 24).to_string() == std::string("192.168.77.10/24")); + + // return host part + ASIO_CHECK(make_network_v4("192.168.77.11/24").address() == make_address_v4("192.168.77.11")); + + // return host in CIDR notation + ASIO_CHECK(make_network_v4("192.168.78.30/20").address().to_string() == "192.168.78.30"); + + // return network in CIDR notation + ASIO_CHECK(make_network_v4("192.168.78.30/20").canonical().to_string() == "192.168.64.0/20"); + + // is host + ASIO_CHECK(make_network_v4("192.168.77.0/32").is_host()); + ASIO_CHECK(!make_network_v4("192.168.77.0/31").is_host()); + + // is real subnet of + ASIO_CHECK(make_network_v4("192.168.0.192/24").is_subnet_of(make_network_v4("192.168.0.0/16"))); + ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.192.168/16"))); + ASIO_CHECK(make_network_v4("192.168.0.192/24").is_subnet_of(make_network_v4("192.168.192.168/16"))); + ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.0.0/16"))); + ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.0.0/23"))); + ASIO_CHECK(make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.0.0/0"))); + ASIO_CHECK(make_network_v4("192.168.0.0/32").is_subnet_of(make_network_v4("192.168.0.0/24"))); + + ASIO_CHECK(!make_network_v4("192.168.0.0/32").is_subnet_of(make_network_v4("192.168.0.0/32"))); + ASIO_CHECK(!make_network_v4("192.168.0.0/24").is_subnet_of(make_network_v4("192.168.1.0/24"))); + ASIO_CHECK(!make_network_v4("192.168.0.0/16").is_subnet_of(make_network_v4("192.168.1.0/24"))); + + network_v4 r(make_network_v4("192.168.0.0/24")); + ASIO_CHECK(!r.is_subnet_of(r)); + + network_v4 net12(make_network_v4("192.168.0.2/24")); + network_v4 net13(make_network_v4("192.168.1.1/28")); + network_v4 net14(make_network_v4("192.168.1.21/28")); + // network + ASIO_CHECK(net12.network() == make_address_v4("192.168.0.0")); + ASIO_CHECK(net13.network() == make_address_v4("192.168.1.0")); + ASIO_CHECK(net14.network() == make_address_v4("192.168.1.16")); + // netmask + ASIO_CHECK(net12.netmask() == make_address_v4("255.255.255.0")); + ASIO_CHECK(net13.netmask() == make_address_v4("255.255.255.240")); + ASIO_CHECK(net14.netmask() == make_address_v4("255.255.255.240")); + // broadcast + ASIO_CHECK(net12.broadcast() == make_address_v4("192.168.0.255")); + ASIO_CHECK(net13.broadcast() == make_address_v4("192.168.1.15")); + ASIO_CHECK(net14.broadcast() == make_address_v4("192.168.1.31")); + // iterator + ASIO_CHECK(std::distance(net12.hosts().begin(),net12.hosts().end()) == 254); + ASIO_CHECK(*net12.hosts().begin() == make_address_v4("192.168.0.1")); + ASIO_CHECK(net12.hosts().end() != net12.hosts().find(make_address_v4("192.168.0.10"))); + ASIO_CHECK(net12.hosts().end() == net12.hosts().find(make_address_v4("192.168.1.10"))); + ASIO_CHECK(std::distance(net13.hosts().begin(),net13.hosts().end()) == 14); + ASIO_CHECK(*net13.hosts().begin() == make_address_v4("192.168.1.1")); + ASIO_CHECK(net13.hosts().end() != net13.hosts().find(make_address_v4("192.168.1.14"))); + ASIO_CHECK(net13.hosts().end() == net13.hosts().find(make_address_v4("192.168.1.15"))); + ASIO_CHECK(std::distance(net14.hosts().begin(),net14.hosts().end()) == 14); + ASIO_CHECK(*net14.hosts().begin() == make_address_v4("192.168.1.17")); + ASIO_CHECK(net14.hosts().end() != net14.hosts().find(make_address_v4("192.168.1.30"))); + ASIO_CHECK(net14.hosts().end() == net14.hosts().find(make_address_v4("192.168.1.31"))); +} + +} // namespace ip_network_v4_runtime + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/network_v4", + ASIO_TEST_CASE(ip_network_v4_compile::test) + ASIO_TEST_CASE(ip_network_v4_runtime::test) +)
diff --git a/asio/src/tests/unit/ip/network_v6.cpp b/asio/src/tests/unit/ip/network_v6.cpp new file mode 100644 index 0000000..09d3861 --- /dev/null +++ b/asio/src/tests/unit/ip/network_v6.cpp
@@ -0,0 +1,198 @@ +// +// network_v6.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/network_v6.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +// ip_network_v6_compile test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that all public member functions on the class +// ip::network_v6 compile and link correctly. Runtime failures are ignored. + +namespace ip_network_v6_compile { + +void test() +{ + using namespace asio; + namespace ip = asio::ip; + + try + { + asio::error_code ec; + + // network_v6 constructors. + + ip::network_v6 net1(ip::make_address_v6("2001:370::10:7344"), 64); + ip::network_v6 net2(ip::make_address_v6("2001:370::10:7345"), 96); + + // network_v6 functions. + + ip::address_v6 addr1 = net1.address(); + (void)addr1; + + unsigned short prefix_len = net1.prefix_length(); + (void)prefix_len; + + ip::address_v6 addr3 = net1.network(); + (void)addr3; + + ip::address_range_v6 hosts = net1.hosts(); + (void)hosts; + + ip::network_v6 net3 = net1.canonical(); + (void)net3; + + bool b1 = net1.is_host(); + (void)b1; + + bool b2 = net1.is_subnet_of(net2); + (void)b2; + + std::string s1 = net1.to_string(); + (void)s1; + + std::string s2 = net1.to_string(ec); + (void)s2; + + // network_v6 comparisons. + + bool b3 = (net1 == net2); + (void)b3; + + bool b4 = (net1 != net2); + (void)b4; + + } + catch (std::exception&) + { + } +} + +} // namespace ip_network_v6_compile + +//------------------------------------------------------------------------------ + +// ip_network_v6_runtime test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that the various public member functions meet the +// necessary postconditions. + +namespace ip_network_v6_runtime { + +void test() +{ + using asio::ip::address_v6; + using asio::ip::make_address_v6; + using asio::ip::network_v6; + using asio::ip::make_network_v6; + + address_v6 addr = make_address_v6("2001:370::10:7344"); + + std::string msg; + try + { + make_network_v6(addr, 129); + } + catch(std::out_of_range& ex) + { + msg = ex.what(); + } + ASIO_CHECK(msg == std::string("prefix length too large")); + + // construct address range from address and prefix length + ASIO_CHECK(network_v6(address_v6::from_string("2001:370::10:7344"), 128).network() == address_v6::from_string("2001:370::10:7344")); + ASIO_CHECK(network_v6(address_v6::from_string("2001:370::10:7344"), 64).network() == address_v6::from_string("2001:370::")); + ASIO_CHECK(network_v6(address_v6::from_string("2001:370::10:7344"), 27).network() == address_v6::from_string("2001:360::")); + + // construct address range from string in CIDR notation + ASIO_CHECK(make_network_v6("2001:370::10:7344/128").network() == address_v6::from_string("2001:370::10:7344")); + ASIO_CHECK(make_network_v6("2001:370::10:7344/64").network() == address_v6::from_string("2001:370::")); + ASIO_CHECK(make_network_v6("2001:370::10:7344/27").network() == address_v6::from_string("2001:360::")); + + // prefix length + ASIO_CHECK(make_network_v6("2001:370::10:7344/128").prefix_length() == 128); + ASIO_CHECK(network_v6(address_v6::from_string("2001:370::10:7344"), 27).prefix_length() == 27); + + // to string + std::string a("2001:370::10:7344/64"); + ASIO_CHECK(make_network_v6(a.c_str()).to_string() == a); + ASIO_CHECK(network_v6(address_v6::from_string("2001:370::10:7344"), 27).to_string() == std::string("2001:370::10:7344/27")); + + // return host part + ASIO_CHECK(make_network_v6("2001:370::10:7344/64").address() == address_v6::from_string("2001:370::10:7344")); + ASIO_CHECK(make_network_v6("2001:370::10:7344/27").address().to_string() == "2001:370::10:7344"); + + // return network in CIDR notation + ASIO_CHECK(make_network_v6("2001:370::10:7344/27").canonical().to_string() == "2001:360::/27"); + + // is host + ASIO_CHECK(make_network_v6("2001:370::10:7344/128").is_host()); + ASIO_CHECK(!make_network_v6("2001:370::10:7344/127").is_host()); + + // is real subnet of + ASIO_CHECK(make_network_v6("2001:370::10:3744/64").is_subnet_of(make_network_v6("2001:370::/16"))); + ASIO_CHECK(make_network_v6("2001:370::/64").is_subnet_of(make_network_v6("2001:370::/16"))); + ASIO_CHECK(make_network_v6("2001:0db8:85a3::/64").is_subnet_of(make_network_v6("2001:0d00::/24"))); + + ASIO_CHECK(!make_network_v6("2001:370::10:3744/128").is_subnet_of(make_network_v6("2001:370::10:3744/128"))); + ASIO_CHECK(make_network_v6("2001:0db8:85a3::/64").is_subnet_of(make_network_v6("2001:0dc0::/24"))); + + network_v6 r(make_network_v6("2001:370::/64")); + ASIO_CHECK(!r.is_subnet_of(r)); + + network_v6 net12(make_network_v6("2001:370::10:7344/64")); + network_v6 net13(make_network_v6("2001:0db8::/127")); + network_v6 net14(make_network_v6("2001:0db8::/125")); + network_v6 net15(make_network_v6("2001:0db8::/119")); + + // network + ASIO_CHECK(net12.network() == address_v6::from_string("2001:370::")); + ASIO_CHECK(net13.network() == address_v6::from_string("2001:0db8::")); + ASIO_CHECK(net14.network() == address_v6::from_string("2001:0db8::")); + ASIO_CHECK(net15.network() == address_v6::from_string("2001:0db8::")); + + // iterator + //ASIO_CHECK(std::distance(net12.hosts().begin(),net12.hosts().end()) == 18446744073709552000); + ASIO_CHECK(std::distance(net13.hosts().begin(),net13.hosts().end()) == 2); + ASIO_CHECK(std::distance(net14.hosts().begin(),net14.hosts().end()) == 8); + ASIO_CHECK(std::distance(net15.hosts().begin(),net15.hosts().end()) == 512); + ASIO_CHECK(*net12.hosts().begin() == address_v6::from_string("2001:0370::")); + ASIO_CHECK(net12.hosts().end() != net12.hosts().find(address_v6::from_string("2001:0370::ffff:ffff:ffff:ffff"))); + ASIO_CHECK(*net13.hosts().begin() == address_v6::from_string("2001:0db8::")); + ASIO_CHECK(net13.hosts().end() != net13.hosts().find(address_v6::from_string("2001:0db8::1"))); + ASIO_CHECK(net13.hosts().end() == net13.hosts().find(address_v6::from_string("2001:0db8::2"))); + ASIO_CHECK(*net14.hosts().begin() == address_v6::from_string("2001:0db8::")); + ASIO_CHECK(net14.hosts().end() != net14.hosts().find(address_v6::from_string("2001:0db8::7"))); + ASIO_CHECK(net14.hosts().end() == net14.hosts().find(address_v6::from_string("2001:0db8::8"))); + ASIO_CHECK(*net15.hosts().begin() == address_v6::from_string("2001:0db8::")); + ASIO_CHECK(net15.hosts().end() != net15.hosts().find(address_v6::from_string("2001:0db8::01ff"))); + ASIO_CHECK(net15.hosts().end() == net15.hosts().find(address_v6::from_string("2001:0db8::0200"))); +} + +} // namespace ip_network_v6_runtime + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/network_v6", + ASIO_TEST_CASE(ip_network_v6_compile::test) + ASIO_TEST_CASE(ip_network_v6_runtime::test) +)