Change ip::address default constructor to be not-an-address.
diff --git a/asio/include/asio/ip/address.hpp b/asio/include/asio/ip/address.hpp index 3b79837..9aeafd5 100644 --- a/asio/include/asio/ip/address.hpp +++ b/asio/include/asio/ip/address.hpp
@@ -179,7 +179,7 @@ } // The type of the address. - enum { ipv4, ipv6 } type_; + enum { none, ipv4, ipv6 } type_; // The underlying IPv4 address. asio::ip::address_v4 ipv4_address_;
diff --git a/asio/include/asio/ip/basic_endpoint.hpp b/asio/include/asio/ip/basic_endpoint.hpp index 60dcbfa..d9a0569 100644 --- a/asio/include/asio/ip/basic_endpoint.hpp +++ b/asio/include/asio/ip/basic_endpoint.hpp
@@ -124,9 +124,9 @@ /// The protocol associated with the endpoint. protocol_type protocol() const { - if (impl_.is_v4()) - return InternetProtocol::v4(); - return InternetProtocol::v6(); + if (impl_.is_v6()) + return InternetProtocol::v6(); + return InternetProtocol::v4(); } /// Get the underlying endpoint in the native type.
diff --git a/asio/include/asio/ip/detail/endpoint.hpp b/asio/include/asio/ip/detail/endpoint.hpp index 630908f..ff46dcd 100644 --- a/asio/include/asio/ip/detail/endpoint.hpp +++ b/asio/include/asio/ip/detail/endpoint.hpp
@@ -111,6 +111,12 @@ return data_.base.sa_family == ASIO_OS_DEF(AF_INET); } + // Determine whether the endpoint is IPv6. + bool is_v6() const + { + return data_.base.sa_family == ASIO_OS_DEF(AF_INET6); + } + #if !defined(ASIO_NO_IOSTREAM) // Convert to a string. ASIO_DECL std::string to_string(asio::error_code& ec) const;
diff --git a/asio/include/asio/ip/detail/impl/endpoint.ipp b/asio/include/asio/ip/detail/impl/endpoint.ipp index aa8c47f..01a4de5 100644 --- a/asio/include/asio/ip/detail/impl/endpoint.ipp +++ b/asio/include/asio/ip/detail/impl/endpoint.ipp
@@ -50,7 +50,7 @@ asio::detail::socket_ops::host_to_network_short(port_num); data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); } - else + else if (family == ASIO_OS_DEF(AF_INET6)) { data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6); data_.v6.sin6_port = @@ -66,6 +66,13 @@ data_.v6.sin6_addr.s6_addr[14] = 0, data_.v6.sin6_addr.s6_addr[15] = 0; data_.v6.sin6_scope_id = 0; } + else + { + data_.v4.sin_family = ASIO_OS_DEF(AF_UNSPEC); + data_.v4.sin_port = + asio::detail::socket_ops::host_to_network_short(port_num); + data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); + } } endpoint::endpoint(const asio::ip::address& addr, @@ -83,7 +90,7 @@ static_cast<asio::detail::u_long_type>( address_cast<address_v4>(addr).to_ulong())); } - else + else if (addr.is_v6()) { data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6); data_.v6.sin6_port = @@ -96,11 +103,18 @@ static_cast<asio::detail::u_long_type>( v6_addr.scope_id()); } + else + { + data_.v4.sin_family = ASIO_OS_DEF(AF_UNSPEC); + data_.v4.sin_port = + asio::detail::socket_ops::host_to_network_short(port_num); + data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); + } } void endpoint::resize(std::size_t new_size) { - if (new_size > sizeof(asio::detail::sockaddr_storage_type)) + if (new_size > sizeof(data_)) { asio::error_code ec(asio::error::invalid_argument); asio::detail::throw_error(ec); @@ -109,28 +123,28 @@ unsigned short endpoint::port() const { - if (is_v4()) + if (is_v6()) { return asio::detail::socket_ops::network_to_host_short( - data_.v4.sin_port); + data_.v6.sin6_port); } else { return asio::detail::socket_ops::network_to_host_short( - data_.v6.sin6_port); + data_.v4.sin_port); } } void endpoint::port(unsigned short port_num) { - if (is_v4()) + if (is_v6()) { - data_.v4.sin_port + data_.v6.sin6_port = asio::detail::socket_ops::host_to_network_short(port_num); } else { - data_.v6.sin6_port + data_.v4.sin_port = asio::detail::socket_ops::host_to_network_short(port_num); } } @@ -144,7 +158,7 @@ asio::detail::socket_ops::network_to_host_long( data_.v4.sin_addr.s_addr)); } - else + else if (is_v6()) { asio::ip::address_v6::bytes_type bytes; #if defined(ASIO_HAS_STD_ARRAY) @@ -154,6 +168,10 @@ #endif // defined(ASIO_HAS_STD_ARRAY) return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); } + else + { + return asio::ip::address(); + } } void endpoint::address(const asio::ip::address& addr)
diff --git a/asio/include/asio/ip/impl/address.ipp b/asio/include/asio/ip/impl/address.ipp index 8170053..5f4e0de 100644 --- a/asio/include/asio/ip/impl/address.ipp +++ b/asio/include/asio/ip/impl/address.ipp
@@ -30,7 +30,7 @@ namespace ip { address::address() - : type_(ipv4), + : type_(none), ipv4_address_(), ipv6_address_() { @@ -158,46 +158,81 @@ std::string address::to_string() const { - if (type_ == ipv6) + switch (type_) + { + case ipv4: + return ipv4_address_.to_string(); + case ipv6: return ipv6_address_.to_string(); - return ipv4_address_.to_string(); + default: + bad_address_cast ex; + asio::detail::throw_exception(ex); + return std::string(); + } } std::string address::to_string(asio::error_code& ec) const { - if (type_ == ipv6) + switch (type_) + { + case ipv4: + return ipv4_address_.to_string(ec); + case ipv6: return ipv6_address_.to_string(ec); - return ipv4_address_.to_string(ec); + default: + ec = asio::error::invalid_argument; + return std::string(); + } } bool address::is_loopback() const { - return (type_ == ipv4) - ? ipv4_address_.is_loopback() - : ipv6_address_.is_loopback(); + switch (type_) + { + case ipv4: + return ipv4_address_.is_loopback(); + case ipv6: + return ipv6_address_.is_loopback(); + default: + return false; + } } bool address::is_unspecified() const { - return (type_ == ipv4) - ? ipv4_address_.is_unspecified() - : ipv6_address_.is_unspecified(); + switch (type_) + { + case ipv4: + return ipv4_address_.is_unspecified(); + case ipv6: + return ipv6_address_.is_unspecified(); + default: + return false; + } } bool address::is_multicast() const { - return (type_ == ipv4) - ? ipv4_address_.is_multicast() - : ipv6_address_.is_multicast(); + switch (type_) + { + case ipv4: + return ipv4_address_.is_multicast(); + case ipv6: + return ipv6_address_.is_multicast(); + default: + return false; + } } bool operator==(const address& a1, const address& a2) { if (a1.type_ != a2.type_) return false; + if (a1.type_ == address::ipv4) + return a1.ipv4_address_ == a2.ipv4_address_; if (a1.type_ == address::ipv6) return a1.ipv6_address_ == a2.ipv6_address_; - return a1.ipv4_address_ == a2.ipv4_address_; + return true; } bool operator<(const address& a1, const address& a2) @@ -206,9 +241,11 @@ return true; if (a1.type_ > a2.type_) return false; + if (a1.type_ == address::ipv4) + return a1.ipv4_address_ < a2.ipv4_address_; if (a1.type_ == address::ipv6) return a1.ipv6_address_ < a2.ipv6_address_; - return a1.ipv4_address_ < a2.ipv4_address_; + return false; } } // namespace ip