Home | History | Annotate | Line # | Download | only in experimental
      1 // <experimental/internet> -*- C++ -*-
      2 
      3 // Copyright (C) 2015-2024 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file experimental/internet
     26  *  This is a TS C++ Library header.
     27  *  @ingroup networking-ts
     28  */
     29 
     30 #ifndef _GLIBCXX_EXPERIMENTAL_INTERNET
     31 #define _GLIBCXX_EXPERIMENTAL_INTERNET
     32 
     33 #pragma GCC system_header
     34 
     35 #include <bits/requires_hosted.h> // experimental is currently omitted
     36 
     37 #if __cplusplus >= 201402L
     38 
     39 #include <experimental/netfwd>
     40 #include <experimental/io_context>
     41 #include <experimental/bits/net.h>
     42 #include <array>
     43 #include <forward_list>
     44 #include <sstream>
     45 #include <cstdint>
     46 #include <experimental/string_view>
     47 #include <bits/charconv.h>
     48 #ifdef _GLIBCXX_HAVE_UNISTD_H
     49 # include <unistd.h>
     50 #endif
     51 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
     52 # include <sys/socket.h>	// AF_INET, AF_INET6, SOCK_DGRAM, SOCK_STREAM
     53 #endif
     54 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
     55 # include <arpa/inet.h>		// inet_ntop
     56 #endif
     57 #ifdef _GLIBCXX_HAVE_NETINET_IN_H
     58 # include <netinet/in.h>	// IPPROTO_IP, IPPROTO_IPV6, in_addr, in6_addr
     59 #endif
     60 #ifdef _GLIBCXX_HAVE_NETINET_TCP_H
     61 # include <netinet/tcp.h>	// TCP_NODELAY
     62 #endif
     63 #ifdef _GLIBCXX_HAVE_NETDB_H
     64 # include <netdb.h>		// getaddrinfo etc.
     65 #endif
     66 
     67 #if defined _WIN32 && __has_include(<ws2tcpip.h>)
     68 # include <ws2tcpip.h>
     69 #endif
     70 
     71 namespace std _GLIBCXX_VISIBILITY(default)
     72 {
     73 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     74 namespace experimental
     75 {
     76 namespace net
     77 {
     78 inline namespace v1
     79 {
     80 namespace ip
     81 {
     82   /** @addtogroup networking-ts
     83    *  @{
     84    */
     85 
     86   /** Error codes for resolver errors.
     87    * @{
     88    */
     89 
     90   enum class resolver_errc : int {
     91 #ifdef _GLIBCXX_HAVE_NETDB_H
     92     host_not_found = EAI_NONAME,
     93     host_not_found_try_again = EAI_AGAIN,
     94     service_not_found = EAI_SERVICE
     95     // N.B. POSIX defines additional errors that have no enumerator here:
     96     // EAI_BADFLAGS, EAI_FAIL, EAI_FAMILY, EAI_MEMORY, EAI_SOCKTYPE, EAI_SYSTEM
     97     // Some C libraries define additional errors:
     98     // EAI_BADHINTS, EAI_OVERFLOW, EAI_PROTOCOL
     99     // Some C libraries define additional (obsolete?) errors:
    100     // EAI_ADDRFAMILY, EAI_NODATA
    101 #endif
    102   };
    103 
    104   /// Error category for resolver errors.
    105   inline const error_category& resolver_category() noexcept // TODO non-inline
    106   {
    107     struct __cat : error_category
    108     {
    109       const char* name() const noexcept { return "resolver"; }
    110       std::string message(int __e) const {
    111 #ifdef _GLIBCXX_HAVE_NETDB_H
    112 	  return ::gai_strerror(__e);
    113 #else
    114 	  return "name resolution requires <netdb.h>";
    115 #endif
    116       }
    117       virtual void __message(int) { } // TODO dual ABI XXX
    118     };
    119     static __cat __c;
    120     return __c;
    121   }
    122 
    123   inline error_code make_error_code(resolver_errc __e) noexcept
    124   { return error_code(static_cast<int>(__e), resolver_category()); }
    125 
    126   inline error_condition make_error_condition(resolver_errc __e) noexcept
    127   { return error_condition(static_cast<int>(__e), resolver_category()); }
    128 
    129   /// @cond undocumented
    130   inline error_code
    131   __make_resolver_error_code(int __ai_err,
    132 			     [[__maybe_unused__]] int __sys_err) noexcept
    133   {
    134 #ifdef EAI_SYSTEM
    135     if (__builtin_expect(__ai_err == EAI_SYSTEM, 0))
    136       return error_code(__sys_err, std::generic_category());
    137 #endif
    138     return error_code(__ai_err, resolver_category());
    139   }
    140   /// @endcond
    141 
    142   /// @}
    143 
    144   using port_type = uint_least16_t;	///< Type used for port numbers.
    145   using scope_id_type = uint_least32_t;	///< Type used for IPv6 scope IDs.
    146 
    147   /// Convenience alias for constraining allocators for strings.
    148   template<typename _Alloc>
    149     using __string_with
    150       = enable_if_t<std::is_same<typename _Alloc::value_type, char>::value,
    151 		    std::basic_string<char, std::char_traits<char>, _Alloc>>;
    152 
    153   constexpr errc
    154   __unsupported_err() noexcept
    155   {
    156 #if defined EAFNOSUPPORT
    157     return std::errc::address_family_not_supported;
    158 #else
    159     return std::errc::operation_not_supported;
    160 #endif
    161   }
    162 
    163   /** Tag indicating conversion between IPv4 and IPv4-mapped IPv6 addresses.
    164    * @{
    165    */
    166 
    167   struct v4_mapped_t {};
    168   constexpr v4_mapped_t v4_mapped;
    169 
    170   /// @}
    171 
    172   /// An IPv4 address.
    173   class address_v4
    174   {
    175   public:
    176     // types:
    177     using uint_type = uint_least32_t;
    178 
    179     struct bytes_type : array<unsigned char, 4>
    180     {
    181       template<typename... _Tp>
    182 	explicit constexpr
    183 	bytes_type(_Tp... __tp)
    184 	: array<unsigned char, 4>{{static_cast<unsigned char>(__tp)...}}
    185 	{
    186 #if UCHAR_MAX > 0xFF
    187 	  for (auto __b : *this)
    188 	    if (__b > 0xFF)
    189 	      __throw_out_of_range("invalid address_v4::bytes_type value");
    190 #endif
    191 	}
    192     };
    193 
    194     // constructors:
    195     constexpr address_v4() noexcept : _M_addr(0) { }
    196 
    197     constexpr address_v4(const address_v4& a) noexcept = default;
    198 
    199     constexpr
    200     address_v4(const bytes_type& __b)
    201 #if __has_builtin(__builtin_bit_cast)
    202     : _M_addr(__builtin_bit_cast(uint_type, __b))
    203 #else
    204     : _M_addr(_S_hton_32((__b[0] << 24) | (__b[1] << 16)
    205 			   | (__b[2] << 8) | __b[3]))
    206 #endif
    207     { }
    208 
    209     explicit constexpr
    210     address_v4(uint_type __val) : _M_addr(_S_hton_32(__val))
    211     {
    212 #if UINT_LEAST32_MAX > 0xFFFFFFFF
    213       if (__val > 0xFFFFFFFF)
    214 	__throw_out_of_range("invalid address_v4::uint_type value");
    215 #endif
    216     }
    217 
    218     // assignment:
    219     address_v4& operator=(const address_v4& a) noexcept = default;
    220 
    221     // members:
    222     constexpr bool is_unspecified() const noexcept { return to_uint() == 0; }
    223 
    224     constexpr bool
    225     is_loopback() const noexcept
    226     { return (to_uint() & 0xFF000000) == 0x7F000000; }
    227 
    228     constexpr bool
    229     is_multicast() const noexcept
    230     { return (to_uint() & 0xF0000000) == 0xE0000000; }
    231 
    232     constexpr bytes_type
    233     to_bytes() const noexcept
    234     {
    235 #if __has_builtin(__builtin_bit_cast)
    236       return __builtin_bit_cast(bytes_type, _M_addr);
    237 #else
    238       auto __host = to_uint();
    239       return bytes_type{
    240 	(__host >> 24) & 0xFF,
    241 	(__host >> 16) & 0xFF,
    242 	(__host >> 8) & 0xFF,
    243 	__host & 0xFF
    244       };
    245 #endif
    246     }
    247 
    248     constexpr uint_type
    249     to_uint() const noexcept { return _S_ntoh_32(_M_addr); }
    250 
    251     template<typename _Allocator = allocator<char>>
    252       __string_with<_Allocator>
    253       to_string(const _Allocator& __a = _Allocator()) const
    254       {
    255 	auto __write = [__addr = to_uint()](char* __p, size_t) {
    256 	  auto __to_chars = [](char* __p, uint8_t __v) {
    257 	    unsigned __n = __v >= 100u ? 3 : __v >= 10u ? 2 : 1;
    258 	    std::__detail::__to_chars_10_impl(__p, __n, __v);
    259 	    return __p + __n;
    260 	  };
    261 	  const auto __begin = __p;
    262 	  __p = __to_chars(__p, uint8_t(__addr >> 24));
    263 	  for (int __i = 2; __i >= 0; __i--) {
    264 	    *__p++ = '.';
    265 	    __p = __to_chars(__p, uint8_t(__addr >> (__i * 8)));
    266 	  }
    267 	  return __p - __begin;
    268 	};
    269 	__string_with<_Allocator> __str(__a);
    270 #if __cpp_lib_string_resize_and_overwrite
    271 	__str.resize_and_overwrite(15, __write);
    272 #else
    273 	__str.resize(15);
    274 	__str.resize(__write(&__str.front(), 15));
    275 #endif
    276 	return __str;
    277       }
    278 
    279     // static members:
    280     static constexpr address_v4 any() noexcept { return address_v4{}; }
    281 
    282     static constexpr
    283     address_v4 loopback() noexcept { return address_v4{0x7F000001}; }
    284 
    285     static constexpr
    286     address_v4 broadcast() noexcept { return address_v4{0xFFFFFFFF}; }
    287 
    288   private:
    289     template<typename _InternetProtocol>
    290       friend class basic_endpoint;
    291 
    292     friend address_v4 make_address_v4(const char*, error_code&) noexcept;
    293 
    294 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    295     static constexpr uint16_t _S_hton_16(uint16_t __h) { return __h; }
    296     static constexpr uint16_t _S_ntoh_16(uint16_t __n) { return __n; }
    297     static constexpr uint32_t _S_hton_32(uint32_t __h) { return __h; }
    298     static constexpr uint32_t _S_ntoh_32(uint32_t __n) { return __n; }
    299 #else
    300     static constexpr uint16_t
    301     _S_hton_16(uint16_t __h) { return __builtin_bswap16(__h); }
    302 
    303     static constexpr uint16_t
    304     _S_ntoh_16(uint16_t __n) { return __builtin_bswap16(__n); }
    305 
    306     static constexpr uint32_t
    307     _S_hton_32(uint32_t __h) { return __builtin_bswap32(__h); }
    308 
    309     static constexpr uint32_t
    310     _S_ntoh_32(uint32_t __n) { return __builtin_bswap32(__n); }
    311 #endif
    312 
    313 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
    314     in_addr_t _M_addr; // network byte order
    315 #else
    316     uint32_t _M_addr;
    317 #endif
    318   };
    319 
    320   /// An IPv6 address.
    321   class address_v6
    322   {
    323   public:
    324     // types:
    325     struct bytes_type : array<unsigned char, 16>
    326     {
    327       template<typename... _Tp>
    328 	explicit constexpr
    329 	bytes_type(_Tp... __t)
    330 	: array<unsigned char, 16>{{static_cast<unsigned char>(__t)...}}
    331 	{ }
    332     };
    333 
    334     // constructors:
    335     constexpr address_v6() noexcept : _M_bytes(), _M_scope_id() { }
    336 
    337     constexpr address_v6(const address_v6& __a) noexcept = default;
    338 
    339     constexpr
    340     address_v6(const bytes_type& __bytes, scope_id_type __scope = 0)
    341     : _M_bytes(__bytes), _M_scope_id(__scope)
    342     { }
    343 
    344     // assignment:
    345     address_v6& operator=(const address_v6& __a) noexcept = default;
    346 
    347     // members:
    348     void scope_id(scope_id_type __id) noexcept { _M_scope_id = __id; }
    349 
    350     constexpr scope_id_type scope_id() const noexcept { return _M_scope_id; }
    351 
    352     constexpr bool
    353     is_unspecified() const noexcept
    354     {
    355       for (int __i = 0; __i < 16; ++__i)
    356 	if (_M_bytes[__i] != 0x00)
    357 	  return false;
    358       return _M_scope_id == 0;
    359     }
    360 
    361     constexpr bool
    362     is_loopback() const noexcept
    363     {
    364       for (int __i = 0; __i < 15; ++__i)
    365 	if (_M_bytes[__i] != 0x00)
    366 	  return false;
    367       return _M_bytes[15] == 0x01 && _M_scope_id == 0;
    368     }
    369 
    370     constexpr bool
    371     is_multicast() const noexcept { return _M_bytes[0] == 0xFF; }
    372 
    373     constexpr bool
    374     is_link_local() const noexcept
    375     { return _M_bytes[0] == 0xFE && (_M_bytes[1] & 0xC0) == 0x80; }
    376 
    377     constexpr bool
    378     is_site_local() const noexcept
    379     { return _M_bytes[0] == 0xFE && (_M_bytes[1] & 0xC0) == 0xC0; }
    380 
    381     constexpr bool
    382     is_v4_mapped() const noexcept
    383     {
    384       const bytes_type& __b = _M_bytes;
    385       return __b[0] == 0 && __b[1] == 0 && __b[ 2] == 0    && __b[ 3] == 0
    386 	  && __b[4] == 0 && __b[5] == 0 && __b[ 6] == 0    && __b[ 7] == 0
    387 	  && __b[8] == 0 && __b[9] == 0 && __b[10] == 0xFF && __b[11] == 0xFF;
    388     }
    389 
    390     constexpr bool
    391     is_multicast_node_local() const noexcept
    392     { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x01; }
    393 
    394     constexpr bool
    395     is_multicast_link_local() const noexcept
    396     { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x02; }
    397 
    398     constexpr bool
    399     is_multicast_site_local() const noexcept
    400     { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x05; }
    401 
    402     constexpr bool
    403     is_multicast_org_local() const noexcept
    404     { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x08; }
    405 
    406     constexpr bool
    407     is_multicast_global() const noexcept
    408     { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x0b; }
    409 
    410     constexpr bytes_type to_bytes() const noexcept { return _M_bytes; }
    411 
    412     template<typename _Allocator = allocator<char>>
    413       __string_with<_Allocator>
    414       to_string(const _Allocator& __a = _Allocator()) const
    415       {
    416 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
    417 	__string_with<_Allocator> __str(__a);
    418 	__str.resize(INET6_ADDRSTRLEN + (_M_scope_id ? 11 : 0));
    419 	char* const __p = &__str.front();
    420 	if (inet_ntop(AF_INET6, &_M_bytes, __p, __str.size()))
    421 	  {
    422 	    auto __end = __str.find('\0');
    423 	    if (unsigned long __scope = _M_scope_id)
    424 	      {
    425 		__end +=
    426 #if _GLIBCXX_USE_C99_STDIO
    427 		  __builtin_snprintf(__p + __end, __str.size() - __end,
    428 				     "%%%lu", __scope);
    429 #else
    430 		  __builtin_sprintf(__p + __end, "%%%lu", __scope);
    431 #endif
    432 	      }
    433 	    __str.erase(__end);
    434 	  }
    435 	else
    436 	  __str.resize(0);
    437 	return __str;
    438 #else
    439 	std::__throw_system_error((int)__unsupported_err());
    440 #endif
    441       }
    442 
    443     // static members:
    444 
    445     static constexpr address_v6
    446     any() noexcept
    447     {
    448       return {};
    449     }
    450 
    451     static constexpr address_v6
    452     loopback() noexcept
    453     {
    454       return {bytes_type{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}};
    455     }
    456 
    457   private:
    458     template<typename _InternetProtocol>
    459       friend class basic_endpoint;
    460 
    461     friend constexpr bool
    462     operator==(const address_v6&, const address_v6&) noexcept;
    463 
    464     friend constexpr bool
    465     operator< (const address_v6&, const address_v6&) noexcept;
    466 
    467     bytes_type _M_bytes;
    468     scope_id_type _M_scope_id;
    469   };
    470 
    471   /// Exception type thrown on misuse of IPv4 addresses as IPv6 or vice versa.
    472   class bad_address_cast : public bad_cast
    473   {
    474   public:
    475     bad_address_cast() { }
    476 
    477     const char* what() const noexcept { return "bad address cast"; }
    478   };
    479 
    480   /// An IPv4 or IPv6 address.
    481   class address
    482   {
    483   public:
    484     // constructors:
    485     constexpr address() noexcept : _M_v4(), _M_is_v4(true) { }
    486 
    487 #if __cpp_constexpr_dynamic_alloc
    488     constexpr
    489 #endif
    490     address(const address& __a) noexcept : _M_uninit(), _M_is_v4(__a._M_is_v4)
    491     {
    492       if (_M_is_v4)
    493 	std::_Construct(std::addressof(_M_v4), __a.to_v4());
    494       else
    495 	std::_Construct(std::addressof(_M_v6), __a.to_v6());
    496     }
    497 
    498     constexpr
    499     address(const address_v4& __a) noexcept : _M_v4(__a), _M_is_v4(true) { }
    500 
    501     constexpr
    502     address(const address_v6& __a) noexcept : _M_v6(__a), _M_is_v4(false) { }
    503 
    504     // assignment:
    505     address&
    506     operator=(const address& __a) noexcept
    507     {
    508       if (__a._M_is_v4)
    509 	*this = __a.to_v4();
    510       else
    511 	*this = __a.to_v6();
    512       return *this;
    513     }
    514 
    515     address&
    516     operator=(const address_v4& __a) noexcept
    517     {
    518       std::_Construct(std::addressof(_M_v4), __a);
    519       _M_is_v4 = true;
    520       return *this;
    521     }
    522 
    523     address&
    524     operator=(const address_v6& __a) noexcept
    525     {
    526       std::_Construct(std::addressof(_M_v6), __a);
    527       _M_is_v4 = false;
    528       return *this;
    529     }
    530 
    531     // members:
    532 
    533     constexpr bool is_v4() const noexcept { return _M_is_v4; }
    534     constexpr bool is_v6() const noexcept { return !_M_is_v4; }
    535 
    536     constexpr address_v4
    537     to_v4() const
    538     {
    539       if (!is_v4())
    540 	_GLIBCXX_THROW_OR_ABORT(bad_address_cast());
    541       return _M_v4;
    542     }
    543 
    544     constexpr address_v6
    545     to_v6() const
    546     {
    547       if (!is_v6())
    548 	_GLIBCXX_THROW_OR_ABORT(bad_address_cast());
    549       return _M_v6;
    550     }
    551 
    552     constexpr bool
    553     is_unspecified() const noexcept
    554     { return _M_is_v4 ? _M_v4.is_unspecified() : _M_v6.is_unspecified(); }
    555 
    556     constexpr bool
    557     is_loopback() const noexcept
    558     { return _M_is_v4 ? _M_v4.is_loopback() : _M_v6.is_loopback(); }
    559 
    560     constexpr bool
    561     is_multicast() const noexcept
    562     { return _M_is_v4 ? _M_v4.is_multicast() : _M_v6.is_multicast(); }
    563 
    564     template<typename _Allocator = allocator<char>>
    565       __string_with<_Allocator>
    566       to_string(const _Allocator& __a = _Allocator()) const
    567       {
    568 	if (_M_is_v4)
    569 	  return to_v4().to_string(__a);
    570 	return to_v6().to_string(__a);
    571       }
    572 
    573   private:
    574     template<typename _InternetProtocol>
    575       friend class basic_endpoint;
    576 
    577     friend constexpr bool
    578     operator==(const address&, const address&) noexcept;
    579 
    580     friend constexpr bool
    581     operator<(const address&, const address&) noexcept;
    582 
    583     union {
    584       address_v4 _M_v4;
    585       address_v6 _M_v6;
    586       bool	 _M_uninit;
    587     };
    588     bool _M_is_v4;
    589   };
    590 
    591   /** ip::address_v4 comparisons
    592    * @{
    593    */
    594 
    595   constexpr bool
    596   operator==(const address_v4& __a, const address_v4& __b) noexcept
    597   { return __a.to_uint() == __b.to_uint(); }
    598 
    599   constexpr bool
    600   operator!=(const address_v4& __a, const address_v4& __b) noexcept
    601   { return !(__a == __b); }
    602 
    603   constexpr bool
    604   operator< (const address_v4& __a, const address_v4& __b) noexcept
    605   { return __a.to_uint() < __b.to_uint(); }
    606 
    607   constexpr bool
    608   operator> (const address_v4& __a, const address_v4& __b) noexcept
    609   { return __b < __a; }
    610 
    611   constexpr bool
    612   operator<=(const address_v4& __a, const address_v4& __b) noexcept
    613   { return !(__b < __a); }
    614 
    615   constexpr bool
    616   operator>=(const address_v4& __a, const address_v4& __b) noexcept
    617   { return !(__a < __b); }
    618 
    619   /// @}
    620 
    621   /** ip::address_v6 comparisons
    622    * @{
    623    */
    624 
    625   constexpr bool
    626   operator==(const address_v6& __a, const address_v6& __b) noexcept
    627   {
    628     const auto& __aa = __a._M_bytes;
    629     const auto& __bb = __b._M_bytes;
    630     int __i = 0;
    631     for (; __i < 16 && __aa[__i] == __bb[__i]; ++__i)
    632       ;
    633     return __i == 16 ? __a.scope_id() == __b.scope_id() : false;
    634   }
    635 
    636   constexpr bool
    637   operator!=(const address_v6& __a, const address_v6& __b) noexcept
    638   { return !(__a == __b); }
    639 
    640   constexpr bool
    641   operator< (const address_v6& __a, const address_v6& __b) noexcept
    642   {
    643     const auto& __aa = __a._M_bytes;
    644     const auto& __bb = __b._M_bytes;
    645     int __i = 0;
    646     for (; __i < 16 && __aa[__i] == __bb[__i]; ++__i)
    647       ;
    648     return __i == 16 ? __a.scope_id() < __b.scope_id() : __aa[__i] < __bb[__i];
    649   }
    650 
    651   constexpr bool
    652   operator> (const address_v6& __a, const address_v6& __b) noexcept
    653   { return __b < __a; }
    654 
    655   constexpr bool
    656   operator<=(const address_v6& __a, const address_v6& __b) noexcept
    657   { return !(__b < __a); }
    658 
    659   constexpr bool
    660   operator>=(const address_v6& __a, const address_v6& __b) noexcept
    661   { return !(__a < __b); }
    662 
    663   /// @}
    664 
    665   /** ip::address comparisons
    666    * @{
    667    */
    668 
    669   constexpr bool
    670   operator==(const address& __a, const address& __b) noexcept
    671   {
    672     if (__a.is_v4())
    673       return __b.is_v4() ? __a._M_v4 == __b._M_v4 : false;
    674     return __b.is_v4() ? false : __a._M_v6 == __b._M_v6;
    675   }
    676 
    677   constexpr bool
    678   operator!=(const address& __a, const address& __b) noexcept
    679   { return !(__a == __b); }
    680 
    681   constexpr bool
    682   operator< (const address& __a, const address& __b) noexcept
    683   {
    684     if (__a.is_v4())
    685       return __b.is_v4() ? __a._M_v4 < __b._M_v4 : true;
    686     return __b.is_v4() ? false : __a._M_v6 < __b._M_v6;
    687   }
    688 
    689   constexpr bool
    690   operator> (const address& __a, const address& __b) noexcept
    691   { return __b < __a; }
    692 
    693   constexpr bool
    694   operator<=(const address& __a, const address& __b) noexcept
    695   { return !(__b < __a); }
    696 
    697   constexpr bool
    698   operator>=(const address& __a, const address& __b) noexcept
    699   { return !(__a < __b); }
    700 
    701   /// @}
    702 
    703   /** ip::address_v4 creation
    704    * @{
    705    */
    706 
    707   constexpr address_v4
    708   make_address_v4(const address_v4::bytes_type& __b)
    709   { return address_v4{__b}; }
    710 
    711   constexpr address_v4
    712   make_address_v4(address_v4::uint_type __val)
    713   { return address_v4{__val}; }
    714 
    715   constexpr address_v4
    716   make_address_v4(v4_mapped_t, const address_v6& __a)
    717   {
    718     if (!__a.is_v4_mapped())
    719       _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
    720 
    721     const auto __v6b = __a.to_bytes();
    722     return address_v4::bytes_type(__v6b[12], __v6b[13], __v6b[14], __v6b[15]);
    723   }
    724 
    725   inline address_v4
    726   make_address_v4(const char* __str, error_code& __ec) noexcept
    727   {
    728 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
    729     address_v4 __a;
    730     const int __res = ::inet_pton(AF_INET, __str, &__a._M_addr);
    731     if (__res == 1)
    732       {
    733 	__ec.clear();
    734 	return __a;
    735       }
    736     if (__res == 0)
    737       __ec = std::make_error_code(std::errc::invalid_argument);
    738     else
    739       __ec.assign(errno, generic_category());
    740 #else
    741     __ec = std::make_error_code(__unsupported_err());
    742 #endif
    743     return {};
    744   }
    745 
    746   inline address_v4
    747   make_address_v4(const char* __str)
    748   { return make_address_v4(__str, __throw_on_error{"make_address_v4"}); }
    749 
    750   inline address_v4
    751   make_address_v4(const string& __str, error_code& __ec) noexcept
    752   { return make_address_v4(__str.c_str(), __ec); }
    753 
    754   inline address_v4
    755   make_address_v4(const string& __str)
    756   { return make_address_v4(__str.c_str()); }
    757 
    758   inline address_v4
    759   make_address_v4(string_view __str, error_code& __ec) noexcept
    760   {
    761     char __buf[16]; // INET_ADDRSTRLEN isn't defined on Windows
    762     auto __len = __str.copy(__buf, sizeof(__buf));
    763     if (__len == sizeof(__buf))
    764       {
    765 	__ec = std::make_error_code(std::errc::invalid_argument);
    766 	return {};
    767       }
    768     __ec.clear();
    769     __buf[__len] = '\0';
    770     return make_address_v4(__buf, __ec);
    771   }
    772 
    773   inline address_v4
    774   make_address_v4(string_view __str)
    775   { return make_address_v4(__str, __throw_on_error{"make_address_v4"}); }
    776 
    777   /// @}
    778 
    779   /** ip::address_v6 creation
    780    * @{
    781    */
    782 
    783   constexpr address_v6
    784   make_address_v6(const address_v6::bytes_type& __b, scope_id_type __scope = 0)
    785   { return address_v6{__b, __scope}; }
    786 
    787   constexpr address_v6
    788   make_address_v6(v4_mapped_t, const address_v4& __a) noexcept
    789   {
    790     const address_v4::bytes_type __v4b = __a.to_bytes();
    791     address_v6::bytes_type __v6b(0, 0, 0, 0, 0, 0, 0, 0,
    792 				 0, 0, 0xFF, 0xFF,
    793 				 __v4b[0], __v4b[1], __v4b[2], __v4b[3]);
    794     return address_v6(__v6b);
    795   }
    796 
    797   inline address_v6
    798   __make_address_v6(const char* __addr, const char* __scope, error_code& __ec)
    799   {
    800 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
    801     address_v6::bytes_type __b;
    802     const int __res = ::inet_pton(AF_INET6, __addr, __b.data());
    803     if (__res == 1)
    804       {
    805 	__ec.clear();
    806 	if (!__scope)
    807 	  {
    808 	    return { __b };
    809 	  }
    810 
    811 	char* __eptr;
    812 	unsigned long __val = std::strtoul(__scope, &__eptr, 10);
    813 	if (__eptr != __scope && !*__eptr
    814 	    && __val <= numeric_limits<scope_id_type>::max())
    815 	  {
    816 	    return { __b, static_cast<scope_id_type>(__val) };
    817 	  }
    818 	__ec = std::make_error_code(std::errc::invalid_argument);
    819       }
    820     else if (__res == 0)
    821       __ec = std::make_error_code(std::errc::invalid_argument);
    822     else
    823       __ec.assign(errno, generic_category());
    824 #else
    825     __ec = std::make_error_code(__unsupported_err());
    826 #endif
    827     return {};
    828   }
    829 
    830   inline address_v6
    831   make_address_v6(const char* __str, error_code& __ec) noexcept
    832   {
    833     auto __p = __builtin_strchr(__str, '%');
    834     if (__p == nullptr)
    835       return __make_address_v6(__str, nullptr, __ec);
    836     char __buf[64];
    837     char* __out = __buf;
    838     bool __skip_leading_zero = true;
    839     while (__str < __p && __out < std::end(__buf))
    840       {
    841 	if (!__skip_leading_zero || *__str != '0')
    842 	  {
    843 	    if (*__str == ':' || *__str == '.')
    844 	      __skip_leading_zero = true;
    845 	    else
    846 	      __skip_leading_zero = false;
    847 	    *__out = *__str;
    848 	  }
    849 	__str++;
    850       }
    851     if (__out == std::end(__buf))
    852       {
    853 	__ec = std::make_error_code(std::errc::invalid_argument);
    854 	return {};
    855       }
    856     else
    857       {
    858 	*__out = '\0';
    859 	return __make_address_v6(__buf, __p + 1, __ec);
    860       }
    861   }
    862 
    863   inline address_v6
    864   make_address_v6(const char* __str)
    865   { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
    866 
    867   inline address_v6
    868   make_address_v6(const string& __str, error_code& __ec) noexcept
    869   {
    870     auto __pos = __str.find('%');
    871     if (__pos == string::npos)
    872       return __make_address_v6(__str.c_str(), nullptr, __ec);
    873     char __buf[64];
    874     char* __out = __buf;
    875     bool __skip_leading_zero = true;
    876     size_t __n = 0;
    877     while (__n < __pos && __out < std::end(__buf))
    878       {
    879 	if (!__skip_leading_zero || __str[__n] != '0')
    880 	  {
    881 	    if (__str[__n] == ':' || __str[__n] == '.')
    882 	      __skip_leading_zero = true;
    883 	    else
    884 	      __skip_leading_zero = false;
    885 	    *__out = __str[__n];
    886 	  }
    887 	__n++;
    888       }
    889     if (__out == std::end(__buf))
    890       {
    891 	__ec = std::make_error_code(std::errc::invalid_argument);
    892 	return {};
    893       }
    894     else
    895       {
    896 	*__out = '\0';
    897 	return __make_address_v6(__buf, __str.c_str() + __pos + 1, __ec);
    898       }
    899   }
    900 
    901   inline address_v6
    902   make_address_v6(const string& __str)
    903   { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
    904 
    905   inline address_v6
    906   make_address_v6(string_view __str, error_code& __ec) noexcept
    907   {
    908     char __buf[64];
    909     char* __out = __buf;
    910     char* __scope = nullptr;
    911     bool __skip_leading_zero = true;
    912     size_t __n = 0;
    913     while (__n < __str.length() && __out < std::end(__buf))
    914       {
    915 	if (__str[__n] == '%')
    916 	  {
    917 	    if (__scope)
    918 	      __out = std::end(__buf);
    919 	    else
    920 	      {
    921 		*__out = '\0';
    922 		__scope = ++__out;
    923 		__skip_leading_zero = true;
    924 	      }
    925 	  }
    926 	else if (!__skip_leading_zero || __str[__n] != '0')
    927 	  {
    928 	    if (__str[__n] == ':' || __str[__n] == '.')
    929 	      __skip_leading_zero = true;
    930 	    else
    931 	      __skip_leading_zero = false;
    932 	    *__out = __str[__n];
    933 	    __out++;
    934 	  }
    935 	__n++;
    936       }
    937     if (__out == std::end(__buf))
    938       {
    939 	__ec = std::make_error_code(std::errc::invalid_argument);
    940 	return {};
    941       }
    942     else
    943       {
    944 	*__out = '\0';
    945 	return __make_address_v6(__buf, __scope, __ec);
    946       }
    947   }
    948 
    949   inline address_v6
    950   make_address_v6(string_view __str)
    951   { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
    952 
    953   /// @}
    954 
    955   /** ip::address creation
    956    * @{
    957    */
    958 
    959   inline address
    960   make_address(const char* __str, error_code& __ec) noexcept
    961   {
    962     address __a;
    963     address_v6 __v6a = make_address_v6(__str, __ec);
    964     if (!__ec)
    965       __a = __v6a;
    966     else
    967     {
    968       address_v4 __v4a = make_address_v4(__str, __ec);
    969       if (!__ec)
    970 	__a = __v4a;
    971     }
    972     return __a;
    973   }
    974 
    975   inline address
    976   make_address(const char* __str)
    977   { return make_address(__str, __throw_on_error{"make_address"}); }
    978 
    979   inline address
    980   make_address(const string& __str, error_code& __ec) noexcept
    981   { return make_address(__str.c_str(), __ec); }
    982 
    983   inline address
    984   make_address(const string& __str)
    985   { return make_address(__str, __throw_on_error{"make_address"}); }
    986 
    987   inline address
    988   make_address(string_view __str, error_code& __ec) noexcept
    989   {
    990     if (__str.rfind('\0') != string_view::npos)
    991       return make_address(__str.data(), __ec);
    992     return make_address(__str.to_string(), __ec); // TODO don't allocate
    993   }
    994 
    995   inline address
    996   make_address(string_view __str)
    997   { return make_address(__str, __throw_on_error{"make_address"}); }
    998 
    999   /// @}
   1000 
   1001   /// ip::address I/O
   1002   template<typename _CharT, typename _Traits>
   1003     inline basic_ostream<_CharT, _Traits>&
   1004     operator<<(basic_ostream<_CharT, _Traits>& __os, const address& __a)
   1005     { return __os << __a.to_string(); }
   1006 
   1007   /// ip::address_v4 I/O
   1008   template<typename _CharT, typename _Traits>
   1009     inline basic_ostream<_CharT, _Traits>&
   1010     operator<<(basic_ostream<_CharT, _Traits>& __os, const address_v4& __a)
   1011     { return __os << __a.to_string(); }
   1012 
   1013   /// ip::address_v6 I/O
   1014   template<typename _CharT, typename _Traits>
   1015     inline basic_ostream<_CharT, _Traits>&
   1016     operator<<(basic_ostream<_CharT, _Traits>& __os, const address_v6& __a)
   1017     { return __os << __a.to_string(); }
   1018 
   1019   template<typename> class basic_address_iterator; // not defined
   1020 
   1021   template<> class basic_address_iterator<address_v4>
   1022   {
   1023   public:
   1024     // types:
   1025     using value_type = address_v4;
   1026     using difference_type = ptrdiff_t;
   1027     using pointer = const address_v4*;
   1028     using reference = const address_v4&;
   1029     using iterator_category = input_iterator_tag;
   1030 
   1031     // constructors:
   1032     basic_address_iterator(const address_v4& __a) noexcept
   1033     : _M_address(__a) { }
   1034 
   1035     // members:
   1036     reference operator*() const noexcept { return _M_address; }
   1037     pointer operator->() const noexcept { return &_M_address; }
   1038 
   1039     basic_address_iterator&
   1040     operator++() noexcept
   1041     {
   1042       _M_address = value_type(_M_address.to_uint() + 1);
   1043       return *this;
   1044     }
   1045 
   1046     basic_address_iterator operator++(int) noexcept
   1047     {
   1048       auto __tmp = *this;
   1049       ++*this;
   1050       return __tmp;
   1051     }
   1052 
   1053     basic_address_iterator& operator--() noexcept
   1054     {
   1055       _M_address = value_type(_M_address.to_uint() - 1);
   1056       return *this;
   1057     }
   1058 
   1059     basic_address_iterator
   1060     operator--(int) noexcept
   1061     {
   1062       auto __tmp = *this;
   1063       --*this;
   1064       return __tmp;
   1065     }
   1066 
   1067     bool
   1068     operator==(const basic_address_iterator& __rhs) const noexcept
   1069     { return _M_address == __rhs._M_address; }
   1070 
   1071     bool
   1072     operator!=(const basic_address_iterator& __rhs) const noexcept
   1073     { return _M_address != __rhs._M_address; }
   1074 
   1075   private:
   1076     address_v4 _M_address;
   1077   };
   1078 
   1079   using address_v4_iterator = basic_address_iterator<address_v4>;
   1080 
   1081   template<> class basic_address_iterator<address_v6>
   1082   {
   1083   public:
   1084     // types:
   1085     using value_type = address_v6;
   1086     using difference_type = ptrdiff_t;
   1087     using pointer = const address_v6*;
   1088     using reference = const address_v6&;
   1089     using iterator_category = input_iterator_tag;
   1090 
   1091     // constructors:
   1092     basic_address_iterator(const address_v6& __a) noexcept
   1093     : _M_address(__a) { }
   1094 
   1095     // members:
   1096     reference operator*() const noexcept { return _M_address; }
   1097     pointer operator->() const noexcept { return &_M_address; }
   1098 
   1099     basic_address_iterator&
   1100     operator++() noexcept; // TODO
   1101 
   1102     basic_address_iterator
   1103     operator++(int) noexcept
   1104     {
   1105       auto __tmp = *this;
   1106       ++*this;
   1107       return __tmp;
   1108     }
   1109 
   1110     basic_address_iterator&
   1111     operator--() noexcept; // TODO
   1112 
   1113     basic_address_iterator
   1114     operator--(int) noexcept
   1115     {
   1116       auto __tmp = *this;
   1117       --*this;
   1118       return __tmp;
   1119     }
   1120 
   1121     bool
   1122     operator==(const basic_address_iterator& __rhs) const noexcept
   1123     { return _M_address == __rhs._M_address; }
   1124 
   1125     bool
   1126     operator!=(const basic_address_iterator& __rhs) const noexcept
   1127     { return _M_address != __rhs._M_address; }
   1128 
   1129   private:
   1130     address_v6 _M_address;
   1131   };
   1132 
   1133   using address_v6_iterator = basic_address_iterator<address_v6>;
   1134 
   1135   template<typename> class basic_address_range; // not defined
   1136 
   1137   /** An IPv6 address range.
   1138    * @{
   1139    */
   1140 
   1141   template<> class basic_address_range<address_v4>
   1142   {
   1143   public:
   1144     // types:
   1145 
   1146     using iterator = basic_address_iterator<address_v4>;
   1147 
   1148     // constructors:
   1149 
   1150     basic_address_range() noexcept : _M_begin({}), _M_end({}) { }
   1151 
   1152     basic_address_range(const address_v4& __first,
   1153                         const address_v4& __last) noexcept
   1154     : _M_begin(__first), _M_end(__last) { }
   1155 
   1156     // members:
   1157 
   1158     iterator begin() const noexcept { return _M_begin; }
   1159     iterator end() const noexcept { return _M_end; }
   1160     _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_begin == _M_end; }
   1161 
   1162     size_t
   1163     size() const noexcept { return _M_end->to_uint() - _M_begin->to_uint(); }
   1164 
   1165     iterator
   1166     find(const address_v4& __addr) const noexcept
   1167     {
   1168       if (*_M_begin <= __addr && __addr < *_M_end)
   1169 	return iterator{__addr};
   1170       return end();
   1171     }
   1172 
   1173   private:
   1174     iterator _M_begin;
   1175     iterator _M_end;
   1176   };
   1177 
   1178   using address_v4_range = basic_address_range<address_v4>;
   1179 
   1180   /// @}
   1181 
   1182   /** An IPv6 address range.
   1183    * @{
   1184    */
   1185 
   1186   template<> class basic_address_range<address_v6>
   1187   {
   1188   public:
   1189     // types:
   1190 
   1191     using iterator = basic_address_iterator<address_v6>;
   1192 
   1193     // constructors:
   1194 
   1195     basic_address_range() noexcept : _M_begin({}), _M_end({}) { }
   1196     basic_address_range(const address_v6& __first,
   1197                         const address_v6& __last) noexcept
   1198     : _M_begin(__first), _M_end(__last) { }
   1199 
   1200     // members:
   1201 
   1202     iterator begin() const noexcept { return _M_begin; }
   1203     iterator end() const noexcept { return _M_end; }
   1204     _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_begin == _M_end; }
   1205 
   1206     iterator
   1207     find(const address_v6& __addr) const noexcept
   1208     {
   1209       if (*_M_begin <= __addr && __addr < *_M_end)
   1210 	return iterator{__addr};
   1211       return end();
   1212     }
   1213 
   1214   private:
   1215     iterator _M_begin;
   1216     iterator _M_end;
   1217   };
   1218 
   1219   using address_v6_range = basic_address_range<address_v6>;
   1220 
   1221   /// @}
   1222 
   1223   constexpr bool
   1224   operator==(const network_v4& __a, const network_v4& __b) noexcept;
   1225 
   1226   constexpr bool
   1227   operator==(const network_v6& __a, const network_v6& __b) noexcept;
   1228 
   1229 
   1230   /// An IPv4 network address.
   1231   class network_v4
   1232   {
   1233   public:
   1234     // constructors:
   1235     constexpr network_v4() noexcept : _M_addr(), _M_prefix_len(0) { }
   1236 
   1237     constexpr
   1238     network_v4(const address_v4& __addr, int __prefix_len)
   1239     : _M_addr(__addr), _M_prefix_len(__prefix_len)
   1240     {
   1241       if (_M_prefix_len < 0 || _M_prefix_len > 32)
   1242 	__throw_out_of_range("network_v4: invalid prefix length");
   1243     }
   1244 
   1245     constexpr
   1246     network_v4(const address_v4& __addr, const address_v4& __mask)
   1247     : _M_addr(__addr), _M_prefix_len(__builtin_popcount(__mask.to_uint()))
   1248     {
   1249       if (_M_prefix_len != 0)
   1250 	{
   1251 	  address_v4::uint_type __mask_uint = __mask.to_uint();
   1252 	  if (__builtin_ctz(__mask_uint) != (32 - _M_prefix_len))
   1253 	    __throw_invalid_argument("network_v4: invalid mask");
   1254 	  if ((__mask_uint & 0x80000000) == 0)
   1255 	    __throw_invalid_argument("network_v4: invalid mask");
   1256 	}
   1257     }
   1258 
   1259     // members:
   1260 
   1261     constexpr address_v4 address() const noexcept { return _M_addr; }
   1262     constexpr int prefix_length() const noexcept { return _M_prefix_len; }
   1263 
   1264     constexpr address_v4
   1265     netmask() const noexcept
   1266     {
   1267       address_v4 __m;
   1268       if (_M_prefix_len)
   1269 	__m = address_v4(0xFFFFFFFFu << (32 - _M_prefix_len));
   1270       return __m;
   1271     }
   1272 
   1273     constexpr address_v4
   1274     network() const noexcept
   1275     { return address_v4{_M_addr.to_uint() & netmask().to_uint()}; }
   1276 
   1277     constexpr address_v4
   1278     broadcast() const noexcept
   1279     {
   1280       auto __b = _M_addr.to_uint();
   1281       if (_M_prefix_len < 32)
   1282 	__b |= 0xFFFFFFFFu >> _M_prefix_len;
   1283       return address_v4{__b};
   1284     }
   1285 
   1286     address_v4_range
   1287     hosts() const noexcept
   1288     {
   1289       if (is_host())
   1290 	return { address(), *++address_v4_iterator(address()) };
   1291       return { network(), broadcast() };
   1292     }
   1293 
   1294     constexpr network_v4
   1295     canonical() const noexcept
   1296     { return network_v4(network(), prefix_length()); }
   1297 
   1298     constexpr bool is_host() const noexcept { return _M_prefix_len == 32; }
   1299 
   1300     constexpr bool
   1301     is_subnet_of(const network_v4& __other) const noexcept
   1302     {
   1303       if (__other.prefix_length() < prefix_length())
   1304 	{
   1305 	  network_v4 __net(address(), __other.prefix_length());
   1306 	  return __net.canonical() == __other.canonical();
   1307 	}
   1308       return false;
   1309     }
   1310 
   1311     template<typename _Allocator = allocator<char>>
   1312       __string_with<_Allocator>
   1313       to_string(const _Allocator& __a = _Allocator()) const
   1314       {
   1315 	auto __str = address().to_string(__a);
   1316 	const unsigned __addrlen = __str.length();
   1317 	const unsigned __preflenlen = _M_prefix_len >= 10 ? 2 : 1;
   1318 	__str.resize(__addrlen + 1 + __preflenlen);
   1319 	__str[__addrlen] = '/';
   1320 	std::__detail::__to_chars_10_impl(&__str.front() + __addrlen + 1,
   1321 					  __preflenlen,
   1322 					  (unsigned char)_M_prefix_len);
   1323 	return __str;
   1324       }
   1325 
   1326   private:
   1327     address_v4 _M_addr;
   1328     int _M_prefix_len;
   1329   };
   1330 
   1331   /// An IPv6 network address.
   1332   class network_v6
   1333   {
   1334   public:
   1335     // constructors:
   1336     constexpr network_v6() noexcept : _M_addr(), _M_prefix_len(0) { }
   1337 
   1338     constexpr
   1339     network_v6(const address_v6& __addr, int __prefix_len)
   1340     : _M_addr(__addr), _M_prefix_len(__prefix_len)
   1341     {
   1342       if (_M_prefix_len < 0 || _M_prefix_len > 128)
   1343 	__throw_out_of_range("network_v6: invalid prefix length");
   1344     }
   1345 
   1346     // members:
   1347     constexpr address_v6 address() const noexcept { return _M_addr; }
   1348     constexpr int prefix_length() const noexcept { return _M_prefix_len; }
   1349 
   1350     _GLIBCXX17_CONSTEXPR address_v6
   1351     network() const noexcept
   1352     {
   1353       address_v6::bytes_type __bytes = _M_addr.to_bytes();
   1354       int __nbytes = (_M_prefix_len + 7) / 8;
   1355       for (int __n = __nbytes; __n < 16; ++__n)
   1356 	__bytes[__n] = 0;
   1357       if (int __zbits = (__nbytes * 8) - _M_prefix_len)
   1358 	__bytes[__nbytes - 1] &= 0xFF << __zbits;
   1359       return address_v6(__bytes, _M_addr.scope_id());
   1360     }
   1361 
   1362     address_v6_range
   1363     hosts() const noexcept
   1364     {
   1365       if (is_host())
   1366 	return { address(), *++address_v6_iterator(address()) };
   1367 
   1368       address_v6::bytes_type __bytes = _M_addr.to_bytes();
   1369       int __nbytes = (_M_prefix_len + 7) / 8;
   1370       for (int __n = __nbytes; __n < 16; ++__n)
   1371 	__bytes[__n] = 0xFF;
   1372       if (int __bits = (__nbytes * 8) - _M_prefix_len)
   1373 	__bytes[__nbytes - 1] |= (1 << __bits) - 1;
   1374       address_v6 __last(__bytes, _M_addr.scope_id());
   1375       return { network(), *++address_v6_iterator(__last) };
   1376     }
   1377 
   1378     _GLIBCXX17_CONSTEXPR network_v6
   1379     canonical() const noexcept
   1380     { return network_v6{network(), prefix_length()}; }
   1381 
   1382     constexpr bool is_host() const noexcept { return _M_prefix_len == 128; }
   1383 
   1384     constexpr bool
   1385     is_subnet_of(const network_v6& __other) const noexcept
   1386     {
   1387       if (__other.prefix_length() < prefix_length())
   1388 	{
   1389 	  network_v6 __net(address(), __other.prefix_length());
   1390 	  return __net.canonical() == __other.canonical();
   1391 	}
   1392       return false;
   1393     }
   1394 
   1395     template<typename _Allocator = allocator<char>>
   1396       __string_with<_Allocator>
   1397       to_string(const _Allocator& __a = _Allocator()) const
   1398       {
   1399 	return address().to_string(__a) + '/'
   1400 		 + std::to_string(prefix_length()).c_str();
   1401       }
   1402 
   1403   private:
   1404     address_v6 _M_addr;
   1405     int _M_prefix_len;
   1406   };
   1407 
   1408 
   1409   /** ip::network_v4 comparisons
   1410    * @{
   1411    */
   1412 
   1413   constexpr bool
   1414   operator==(const network_v4& __a, const network_v4& __b) noexcept
   1415   {
   1416     return __a.address() == __b.address()
   1417       && __a.prefix_length() == __b.prefix_length();
   1418   }
   1419 
   1420   constexpr bool
   1421   operator!=(const network_v4& __a, const network_v4& __b) noexcept
   1422   { return !(__a == __b); }
   1423 
   1424   /// @}
   1425 
   1426   /** ip::network_v6 comparisons
   1427    * @{
   1428    */
   1429 
   1430   constexpr bool
   1431   operator==(const network_v6& __a, const network_v6& __b) noexcept
   1432   {
   1433     return __a.address() == __b.address()
   1434       && __a.prefix_length() == __b.prefix_length();
   1435   }
   1436 
   1437   constexpr bool
   1438   operator!=(const network_v6& __a, const network_v6& __b) noexcept
   1439   { return !(__a == __b); }
   1440 
   1441   /// @}
   1442 
   1443   /** ip::network_v4 creation
   1444    * @{
   1445    */
   1446 
   1447   inline network_v4
   1448   make_network_v4(const address_v4& __a, int __prefix_len)
   1449   { return network_v4{__a, __prefix_len}; }
   1450 
   1451   inline network_v4
   1452   make_network_v4(const address_v4& __a, const address_v4& __mask)
   1453   { return network_v4{ __a, __mask }; }
   1454 
   1455   network_v4 make_network_v4(const char*, error_code&) noexcept; // TODO
   1456 
   1457   inline network_v4
   1458   make_network_v4(const char* __str)
   1459   { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
   1460 
   1461   network_v4 make_network_v4(const string&, error_code&) noexcept; // TODO
   1462 
   1463   inline network_v4
   1464   make_network_v4(const string& __str)
   1465   { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
   1466 
   1467   network_v4 make_network_v4(string_view, error_code&) noexcept; // TODO
   1468 
   1469   inline network_v4
   1470   make_network_v4(string_view __str)
   1471   { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
   1472 
   1473   /// @}
   1474 
   1475   /** ip::network_v6 creation
   1476    * @{
   1477    */
   1478 
   1479   inline network_v6
   1480   make_network_v6(const address_v6& __a, int __prefix_len)
   1481   { return network_v6{__a, __prefix_len}; }
   1482 
   1483   network_v6 make_network_v6(const char*, error_code&) noexcept; // TODO
   1484 
   1485   inline network_v6
   1486   make_network_v6(const char* __str)
   1487   { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
   1488 
   1489   network_v6 make_network_v6(const string&, error_code&) noexcept; // TODO
   1490 
   1491   inline network_v6
   1492   make_network_v6(const string& __str)
   1493   { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
   1494 
   1495   network_v6 make_network_v6(string_view, error_code&) noexcept; // TODO
   1496 
   1497   inline network_v6
   1498   make_network_v6(string_view __str)
   1499   { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
   1500 
   1501   /// @}
   1502 
   1503   /// ip::network_v4 I/O
   1504   template<typename _CharT, typename _Traits>
   1505     inline basic_ostream<_CharT, _Traits>&
   1506     operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v4& __net)
   1507     { return __os << __net.to_string(); }
   1508 
   1509   /// ip::network_v6 I/O
   1510   template<typename _CharT, typename _Traits>
   1511     inline basic_ostream<_CharT, _Traits>&
   1512     operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v6& __net)
   1513     { return __os << __net.to_string(); }
   1514 
   1515 #if defined IPPROTO_TCP || defined  IPPROTO_UDP
   1516   /// An IP endpoint.
   1517   template<typename _InternetProtocol>
   1518     class basic_endpoint
   1519     {
   1520     public:
   1521       // types:
   1522       using protocol_type = _InternetProtocol;
   1523 
   1524       // constructors:
   1525 
   1526       _GLIBCXX20_CONSTEXPR
   1527       basic_endpoint() noexcept : _M_data()
   1528       {
   1529 	_M_data._M_v4.sin_family = protocol_type::v4().family();
   1530 	// If in_addr contains a union, make the correct member active:
   1531 	if (std::__is_constant_evaluated())
   1532 	  std::_Construct(&_M_data._M_v4.sin_addr.s_addr);
   1533       }
   1534 
   1535       _GLIBCXX20_CONSTEXPR
   1536       basic_endpoint(const protocol_type& __proto,
   1537 		     port_type __port_num) noexcept
   1538       : _M_data()
   1539       {
   1540 	if (__proto == protocol_type::v4())
   1541 	  {
   1542 	    _M_data._M_v4.sin_family = protocol_type::v4().family();
   1543 	    _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
   1544 	    if (std::__is_constant_evaluated())
   1545 	      std::_Construct(&_M_data._M_v4.sin_addr.s_addr);
   1546 	  }
   1547 	else if (__proto == protocol_type::v6())
   1548 	  {
   1549 	    std::_Construct(&_M_data._M_v6);
   1550 	    _M_data._M_v6.sin6_family = __proto.family();
   1551 	    _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num);
   1552 	    _M_data._M_v6.sin6_scope_id = 0;
   1553 	    if (std::__is_constant_evaluated())
   1554 	      std::_Construct(&_M_data._M_v6.sin6_addr.s6_addr);
   1555 	  }
   1556 	else
   1557 	  {
   1558 	    __glibcxx_assert(__proto == protocol_type::v4()
   1559 			       || __proto == protocol_type::v6());
   1560 
   1561 	  }
   1562       }
   1563 
   1564       _GLIBCXX20_CONSTEXPR
   1565       basic_endpoint(const ip::address& __addr,
   1566 		     port_type __port_num) noexcept
   1567       : _M_data()
   1568       {
   1569 	if (__addr.is_v4())
   1570 	  {
   1571 	    _M_data._M_v4.sin_family = protocol_type::v4().family();
   1572 	    _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
   1573 	    std::_Construct(&_M_data._M_v4.sin_addr.s_addr,
   1574 			    __addr._M_v4._M_addr);
   1575 	  }
   1576 	else
   1577 	  {
   1578 	    std::_Construct(&_M_data._M_v6);
   1579 	    _M_data._M_v6.sin6_family = protocol_type::v6().family();
   1580 	    _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num);
   1581 	    if (std::__is_constant_evaluated())
   1582 	      std::_Construct(&_M_data._M_v6.sin6_addr.s6_addr);
   1583 	    uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr;
   1584 	    for (int __i = 0; __i < 16; ++__i)
   1585 	      __s6a[__i] = __addr._M_v6._M_bytes[__i];
   1586 	    _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
   1587 	  }
   1588       }
   1589 
   1590       // members:
   1591 
   1592       constexpr protocol_type protocol() const noexcept
   1593       {
   1594 	return _M_is_v6() ? protocol_type::v6() : protocol_type::v4();
   1595       }
   1596 
   1597       constexpr ip::address
   1598       address() const noexcept
   1599       {
   1600 	if (_M_is_v6())
   1601 	  {
   1602 	    address_v6 __v6;
   1603 	    const uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr;
   1604 	    for (int __i = 0; __i < 16; ++__i)
   1605 	      __v6._M_bytes[__i] = __s6a[__i];
   1606 	    __v6._M_scope_id = _M_data._M_v6.sin6_scope_id;
   1607 	    return __v6;
   1608 	  }
   1609 	else
   1610 	  {
   1611 	    address_v4 __v4;
   1612 	    __v4._M_addr = _M_data._M_v4.sin_addr.s_addr;
   1613 	    return __v4;
   1614 	  }
   1615       }
   1616 
   1617       void
   1618       address(const ip::address& __addr) noexcept
   1619       {
   1620 	if (__addr.is_v6())
   1621 	  {
   1622 	    std::_Construct(&_M_data._M_v6);
   1623 	    _M_data._M_v6.sin6_family = protocol_type::v6().family();
   1624 	    __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
   1625 			     __addr._M_v6._M_bytes.data(), 16);
   1626 	    _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
   1627 	  }
   1628 	else
   1629 	  {
   1630 	    std::_Construct(&_M_data._M_v4);
   1631 	    _M_data._M_v4.sin_family = protocol_type::v4().family();
   1632 	    _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
   1633 	  }
   1634       }
   1635 
   1636       constexpr port_type
   1637       port() const noexcept
   1638       {
   1639 	port_type __p = 0;
   1640 	if (_M_is_v6())
   1641 	  __p = _M_data._M_v6.sin6_port;
   1642 	else
   1643 	  __p = _M_data._M_v4.sin_port;
   1644 	return address_v4::_S_ntoh_16(__p);
   1645       }
   1646 
   1647       void
   1648       port(port_type __port_num) noexcept
   1649       {
   1650 	__port_num = address_v4::_S_hton_16(__port_num);
   1651 	if (_M_is_v6())
   1652 	  _M_data._M_v6.sin6_port = __port_num;
   1653 	else
   1654 	  _M_data._M_v4.sin_port = __port_num;
   1655       }
   1656 
   1657       void* data() noexcept { return &_M_data; }
   1658 
   1659       const void* data() const noexcept { return &_M_data; }
   1660 
   1661       constexpr size_t
   1662       size() const noexcept
   1663       { return _M_is_v6() ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); }
   1664 
   1665       void
   1666       resize(size_t __s)
   1667       {
   1668 	if (__s != size())
   1669 	  __throw_length_error("net::ip::basic_endpoint::resize");
   1670       }
   1671 
   1672       constexpr size_t capacity() const noexcept { return sizeof(_M_data); }
   1673 
   1674     private:
   1675       union
   1676       {
   1677 	sockaddr_in	_M_v4;
   1678 	sockaddr_in6	_M_v6;
   1679       } _M_data;
   1680 
   1681       constexpr bool
   1682       _M_is_v6() const noexcept
   1683       {
   1684 	// For constexpr eval we can just detect which union member is active.
   1685 	// i.e. emulate P2641R1's std::is_active_member(&_M_data._M_v6)).
   1686 	if (std::__is_constant_evaluated())
   1687 	  return __builtin_constant_p(_M_data._M_v6.sin6_family);
   1688 	return _M_data._M_v6.sin6_family == AF_INET6;
   1689       }
   1690     };
   1691 
   1692   /** basic_endpoint comparisons
   1693    * @{
   1694    */
   1695 
   1696   template<typename _InternetProtocol>
   1697     constexpr bool
   1698     operator==(const basic_endpoint<_InternetProtocol>& __a,
   1699 	       const basic_endpoint<_InternetProtocol>& __b)
   1700     { return __a.address() == __b.address() && __a.port() == __b.port(); }
   1701 
   1702   template<typename _InternetProtocol>
   1703     constexpr bool
   1704     operator!=(const basic_endpoint<_InternetProtocol>& __a,
   1705 	       const basic_endpoint<_InternetProtocol>& __b)
   1706     { return !(__a == __b); }
   1707 
   1708   template<typename _InternetProtocol>
   1709     constexpr bool
   1710     operator< (const basic_endpoint<_InternetProtocol>& __a,
   1711 	       const basic_endpoint<_InternetProtocol>& __b)
   1712     {
   1713       return __a.address() < __b.address()
   1714 	|| (!(__b.address() < __a.address()) && __a.port() < __b.port());
   1715     }
   1716 
   1717   template<typename _InternetProtocol>
   1718     constexpr bool
   1719     operator> (const basic_endpoint<_InternetProtocol>& __a,
   1720 	       const basic_endpoint<_InternetProtocol>& __b)
   1721     { return __b < __a; }
   1722 
   1723   template<typename _InternetProtocol>
   1724     constexpr bool
   1725     operator<=(const basic_endpoint<_InternetProtocol>& __a,
   1726 	       const basic_endpoint<_InternetProtocol>& __b)
   1727     { return !(__b < __a); }
   1728 
   1729   template<typename _InternetProtocol>
   1730     constexpr bool
   1731     operator>=(const basic_endpoint<_InternetProtocol>& __a,
   1732 	       const basic_endpoint<_InternetProtocol>& __b)
   1733     { return !(__a < __b); }
   1734 
   1735   /// @}
   1736 
   1737   /// basic_endpoint I/O
   1738   template<typename _CharT, typename _Traits, typename _InternetProtocol>
   1739     inline basic_ostream<_CharT, _Traits>&
   1740     operator<<(basic_ostream<_CharT, _Traits>& __os,
   1741 	       const basic_endpoint<_InternetProtocol>& __ep)
   1742     {
   1743       basic_ostringstream<_CharT, _Traits> __ss;
   1744       if (__ep.protocol()
   1745 	  == basic_endpoint<_InternetProtocol>::protocol_type::v6())
   1746 	__ss << '[' << __ep.address() << ']';
   1747       else
   1748 	__ss << __ep.address();
   1749       __ss << ':' << __ep.port();
   1750       __os << __ss.str();
   1751       return __os;
   1752     }
   1753 
   1754   /** Type representing a single result of name/address resolution.
   1755    * @{
   1756    */
   1757 
   1758   template<typename _InternetProtocol>
   1759     class basic_resolver_entry
   1760     {
   1761     public:
   1762       // types:
   1763       using protocol_type = _InternetProtocol;
   1764       using endpoint_type = typename _InternetProtocol::endpoint;
   1765 
   1766       // constructors:
   1767       basic_resolver_entry() { }
   1768 
   1769       basic_resolver_entry(const endpoint_type& __ep,
   1770 			   string_view __h, string_view __s)
   1771       : _M_ep(__ep), _M_host(__h), _M_svc(__s) { }
   1772 
   1773       // members:
   1774       endpoint_type endpoint() const { return _M_ep; }
   1775       operator endpoint_type() const { return _M_ep; }
   1776 
   1777       template<typename _Allocator = allocator<char>>
   1778 	__string_with<_Allocator>
   1779 	host_name(const _Allocator& __a = _Allocator()) const
   1780 	{ return { _M_host, __a }; }
   1781 
   1782       template<typename _Allocator = allocator<char>>
   1783 	__string_with<_Allocator>
   1784 	service_name(const _Allocator& __a = _Allocator()) const
   1785 	{ return { _M_svc, __a }; }
   1786 
   1787     private:
   1788       basic_endpoint<_InternetProtocol> _M_ep;
   1789       string _M_host;
   1790       string _M_svc;
   1791     };
   1792 
   1793   template<typename _InternetProtocol>
   1794     inline bool
   1795     operator==(const basic_resolver_entry<_InternetProtocol>& __a,
   1796 	       const basic_resolver_entry<_InternetProtocol>& __b)
   1797     {
   1798       return __a.endpoint() == __b.endpoint()
   1799 	&& __a.host_name() == __b.host_name()
   1800 	&& __a.service_name() == __b.service_name();
   1801     }
   1802 
   1803   template<typename _InternetProtocol>
   1804     inline bool
   1805     operator!=(const basic_resolver_entry<_InternetProtocol>& __a,
   1806 	       const basic_resolver_entry<_InternetProtocol>& __b)
   1807     { return !(__a == __b); }
   1808 
   1809   /// @}
   1810 
   1811   /** Base class defining flags for name/address resolution.
   1812    * @{
   1813    */
   1814 
   1815   class resolver_base
   1816   {
   1817   public:
   1818     enum flags : int { };
   1819     static constexpr flags passive		= (flags)AI_PASSIVE;
   1820     static constexpr flags canonical_name	= (flags)AI_CANONNAME;
   1821     static constexpr flags numeric_host		= (flags)AI_NUMERICHOST;
   1822 #ifdef AI_NUMERICSERV
   1823     static constexpr flags numeric_service	= (flags)AI_NUMERICSERV;
   1824 #endif
   1825 #ifdef AI_V4MAPPED
   1826     static constexpr flags v4_mapped		= (flags)AI_V4MAPPED;
   1827 #endif
   1828 #ifdef AI_ALL
   1829     static constexpr flags all_matching		= (flags)AI_ALL;
   1830 #endif
   1831 #ifdef AI_ADDRCONFIG
   1832     static constexpr flags address_configured	= (flags)AI_ADDRCONFIG;
   1833 #endif
   1834 
   1835     friend constexpr flags
   1836     operator&(flags __f1, flags __f2) noexcept
   1837     { return flags( int(__f1) & int(__f2) ); }
   1838 
   1839     friend constexpr flags
   1840     operator|(flags __f1, flags __f2) noexcept
   1841     { return flags( int(__f1) | int(__f2) ); }
   1842 
   1843     friend constexpr flags
   1844     operator^(flags __f1, flags __f2) noexcept
   1845     { return flags( int(__f1) ^ int(__f2) ); }
   1846 
   1847     friend constexpr flags
   1848     operator~(flags __f) noexcept
   1849     { return flags( ~int(__f) ); }
   1850 
   1851     friend constexpr flags&
   1852     operator&=(flags& __f1, flags __f2) noexcept
   1853     { return __f1 = (__f1 & __f2); }
   1854 
   1855     friend constexpr flags&
   1856     operator|=(flags& __f1, flags __f2) noexcept
   1857     { return __f1 = (__f1 | __f2); }
   1858 
   1859     friend constexpr flags&
   1860     operator^=(flags& __f1, flags __f2) noexcept
   1861     { return __f1 = (__f1 ^ __f2); }
   1862 
   1863   protected:
   1864     resolver_base() = default;
   1865     ~resolver_base() = default;
   1866   };
   1867 
   1868   // TODO define resolver_base::flags static constants in .so for C++14 mode
   1869 
   1870   /// @}
   1871 
   1872   /** Container for results of name/address resolution.
   1873    * @{
   1874    */
   1875 
   1876   template<typename _InternetProtocol>
   1877     class basic_resolver_results
   1878     {
   1879     public:
   1880       // types:
   1881       using protocol_type = _InternetProtocol;
   1882       using endpoint_type = typename protocol_type::endpoint;
   1883       using value_type = basic_resolver_entry<protocol_type>;
   1884       using const_reference = const value_type&;
   1885       using reference = value_type&;
   1886       using const_iterator = typename forward_list<value_type>::const_iterator;
   1887       using iterator = const_iterator;
   1888       using difference_type = ptrdiff_t;
   1889       using size_type = size_t;
   1890 
   1891       // construct / copy / destroy:
   1892 
   1893       basic_resolver_results() = default;
   1894 
   1895       basic_resolver_results(const basic_resolver_results&) = default;
   1896 
   1897       basic_resolver_results(basic_resolver_results&&) noexcept = default;
   1898 
   1899       basic_resolver_results&
   1900       operator=(const basic_resolver_results&) = default;
   1901 
   1902       basic_resolver_results&
   1903       operator=(basic_resolver_results&&) = default;
   1904 
   1905       ~basic_resolver_results() = default;
   1906 
   1907       // size:
   1908       size_type size() const noexcept { return _M_size; }
   1909       size_type max_size() const noexcept { return _M_results.max_size(); }
   1910 
   1911       _GLIBCXX_NODISCARD bool
   1912       empty() const noexcept { return _M_results.empty(); }
   1913 
   1914       // element access:
   1915       const_iterator begin() const { return _M_results.begin(); }
   1916       const_iterator end() const { return _M_results.end(); }
   1917       const_iterator cbegin() const { return _M_results.begin(); }
   1918       const_iterator cend() const { return _M_results.end(); }
   1919 
   1920       // swap:
   1921       void
   1922       swap(basic_resolver_results& __that) noexcept
   1923       { _M_results.swap(__that._M_results); }
   1924 
   1925     private:
   1926       friend class basic_resolver<protocol_type>;
   1927 
   1928       basic_resolver_results(string_view, string_view, resolver_base::flags,
   1929 			     error_code&, protocol_type* = nullptr);
   1930 
   1931       basic_resolver_results(const endpoint_type&, error_code&);
   1932 
   1933       forward_list<value_type> _M_results;
   1934       size_t _M_size = 0;
   1935     };
   1936 
   1937   template<typename _InternetProtocol>
   1938     inline bool
   1939     operator==(const basic_resolver_results<_InternetProtocol>& __a,
   1940 	       const basic_resolver_results<_InternetProtocol>& __b)
   1941     {
   1942       return __a.size() == __b.size()
   1943 	&& std::equal(__a.begin(), __a.end(), __b.begin());
   1944     }
   1945 
   1946   template<typename _InternetProtocol>
   1947     inline bool
   1948     operator!=(const basic_resolver_results<_InternetProtocol>& __a,
   1949 	       const basic_resolver_results<_InternetProtocol>& __b)
   1950     { return !(__a == __b); }
   1951 
   1952   /// @}
   1953 
   1954   /// Perform name/address resolution.
   1955   template<typename _InternetProtocol>
   1956     class basic_resolver : public resolver_base
   1957     {
   1958     public:
   1959       // types:
   1960 
   1961       using executor_type = io_context::executor_type;
   1962       using protocol_type = _InternetProtocol;
   1963       using endpoint_type = typename _InternetProtocol::endpoint;
   1964       using results_type = basic_resolver_results<_InternetProtocol>;
   1965 
   1966       // construct / copy / destroy:
   1967 
   1968       explicit basic_resolver(io_context& __ctx) : _M_ctx(&__ctx) { }
   1969 
   1970       basic_resolver(const basic_resolver&) = delete;
   1971 
   1972       basic_resolver(basic_resolver&& __rhs) noexcept
   1973       : _M_ctx(__rhs._M_ctx)
   1974       { } // TODO move state/tasks etc.
   1975 
   1976       ~basic_resolver() { cancel(); }
   1977 
   1978       basic_resolver& operator=(const basic_resolver&) = delete;
   1979 
   1980       basic_resolver& operator=(basic_resolver&& __rhs)
   1981       {
   1982 	cancel();
   1983 	_M_ctx = __rhs._M_ctx;
   1984 	// TODO move state/tasks etc.
   1985 	return *this;
   1986       }
   1987 
   1988       // basic_resolver operations:
   1989 
   1990       executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
   1991 
   1992       void cancel() { } // TODO
   1993 
   1994       results_type
   1995       resolve(string_view __host_name, string_view __service_name)
   1996       {
   1997 	return resolve(__host_name, __service_name, resolver_base::flags(),
   1998 		       __throw_on_error{"basic_resolver::resolve"});
   1999       }
   2000 
   2001       results_type
   2002       resolve(string_view __host_name, string_view __service_name,
   2003 	      error_code& __ec)
   2004       {
   2005 	return resolve(__host_name, __service_name, resolver_base::flags(),
   2006 		       __ec);
   2007       }
   2008 
   2009       results_type
   2010       resolve(string_view __host_name, string_view __service_name, flags __f)
   2011       {
   2012 	return resolve(__host_name, __service_name, __f,
   2013 		       __throw_on_error{"basic_resolver::resolve"});
   2014       }
   2015 
   2016       results_type
   2017       resolve(string_view __host_name, string_view __service_name, flags __f,
   2018 	      error_code& __ec)
   2019       { return {__host_name, __service_name, __f, __ec}; }
   2020 
   2021       template<typename _CompletionToken>
   2022 	__deduced_t<_CompletionToken, void(error_code, results_type)>
   2023 	async_resolve(string_view __host_name, string_view __service_name,
   2024 		      _CompletionToken&& __token)
   2025 	{
   2026 	  return async_resolve(__host_name, __service_name,
   2027 			       resolver_base::flags(),
   2028 			       forward<_CompletionToken>(__token));
   2029 	}
   2030 
   2031       template<typename _CompletionToken>
   2032 	__deduced_t<_CompletionToken, void(error_code, results_type)>
   2033 	async_resolve(string_view __host_name, string_view __service_name,
   2034 		      flags __f, _CompletionToken&& __token); // TODO
   2035 
   2036       results_type
   2037       resolve(const protocol_type& __protocol,
   2038 	      string_view __host_name, string_view __service_name)
   2039       {
   2040 	return resolve(__protocol, __host_name, __service_name,
   2041 		       resolver_base::flags(),
   2042 		       __throw_on_error{"basic_resolver::resolve"});
   2043       }
   2044 
   2045       results_type
   2046       resolve(const protocol_type& __protocol,
   2047 	      string_view __host_name, string_view __service_name,
   2048 	      error_code& __ec)
   2049       {
   2050 	return resolve(__protocol, __host_name, __service_name,
   2051 		       resolver_base::flags(), __ec);
   2052       }
   2053 
   2054       results_type
   2055       resolve(const protocol_type& __protocol,
   2056 	      string_view __host_name, string_view __service_name, flags __f)
   2057       {
   2058 	return resolve(__protocol, __host_name, __service_name, __f,
   2059 		       __throw_on_error{"basic_resolver::resolve"});
   2060       }
   2061 
   2062       results_type
   2063       resolve(const protocol_type& __protocol,
   2064 	      string_view __host_name, string_view __service_name,
   2065 	      flags __f, error_code& __ec)
   2066       { return {__host_name, __service_name, __f, __ec, &__protocol}; }
   2067 
   2068       template<typename _CompletionToken>
   2069 	__deduced_t<_CompletionToken, void(error_code, results_type)>
   2070 	async_resolve(const protocol_type& __protocol,
   2071 		      string_view __host_name, string_view __service_name,
   2072 		      _CompletionToken&& __token)
   2073 	{
   2074 	  return async_resolve(__protocol, __host_name, __service_name,
   2075 			       resolver_base::flags(),
   2076 			       forward<_CompletionToken>(__token));
   2077 	}
   2078 
   2079       template<typename _CompletionToken>
   2080 	__deduced_t<_CompletionToken, void(error_code, results_type)>
   2081 	async_resolve(const protocol_type& __protocol,
   2082 		      string_view __host_name, string_view __service_name,
   2083 		      flags __f, _CompletionToken&& __token); // TODO
   2084 
   2085       results_type
   2086       resolve(const endpoint_type& __ep)
   2087       { return resolve(__ep, __throw_on_error{"basic_resolver::resolve"}); }
   2088 
   2089       results_type
   2090       resolve(const endpoint_type& __ep, error_code& __ec)
   2091       { return { __ep, __ec }; }
   2092 
   2093       template<typename _CompletionToken> // TODO
   2094 	__deduced_t<_CompletionToken, void(error_code, results_type)>
   2095 	async_resolve(const endpoint_type& __ep, _CompletionToken&& __token);
   2096 
   2097     private:
   2098       io_context* _M_ctx;
   2099     };
   2100 
   2101   /// Private constructor to synchronously resolve host and service names.
   2102   template<typename _InternetProtocol>
   2103     basic_resolver_results<_InternetProtocol>::
   2104     basic_resolver_results(string_view __host_name, string_view __service_name,
   2105 			   resolver_base::flags __f, error_code& __ec,
   2106 			   protocol_type* __protocol)
   2107     {
   2108 #ifdef _GLIBCXX_HAVE_NETDB_H
   2109       string __host;
   2110       const char* __h = __host_name.data()
   2111 	? (__host = __host_name.to_string()).c_str()
   2112 	: nullptr;
   2113       string __svc;
   2114       const char* __s = __service_name.data()
   2115 	? (__svc = __service_name.to_string()).c_str()
   2116 	: nullptr;
   2117 
   2118       ::addrinfo __hints{ };
   2119       __hints.ai_flags = static_cast<int>(__f);
   2120       if (__protocol)
   2121 	{
   2122 	  __hints.ai_family = __protocol->family();
   2123 	  __hints.ai_socktype = __protocol->type();
   2124 	  __hints.ai_protocol = __protocol->protocol();
   2125 	}
   2126       else
   2127 	{
   2128 	  auto __p = endpoint_type{}.protocol();
   2129 	  __hints.ai_family = AF_UNSPEC;
   2130 	  __hints.ai_socktype = __p.type();
   2131 	  __hints.ai_protocol = __p.protocol();
   2132 	}
   2133 
   2134       struct __scoped_addrinfo
   2135       {
   2136 	~__scoped_addrinfo() { if (_M_p) ::freeaddrinfo(_M_p); }
   2137 	::addrinfo* _M_p = nullptr;
   2138       } __sai;
   2139 
   2140       if (int __err = ::getaddrinfo(__h, __s, &__hints, &__sai._M_p))
   2141 	{
   2142 	  __ec = ip::__make_resolver_error_code(__err, errno);
   2143 	  return;
   2144 	}
   2145       __ec.clear();
   2146 
   2147       endpoint_type __ep;
   2148       auto __tail = _M_results.before_begin();
   2149       for (auto __ai = __sai._M_p; __ai != nullptr; __ai = __ai->ai_next)
   2150 	{
   2151 	  if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6)
   2152 	    {
   2153 	      if (__ai->ai_addrlen <= __ep.capacity())
   2154 		__builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen);
   2155 	      __ep.resize(__ai->ai_addrlen);
   2156 	      __tail = _M_results.emplace_after(__tail, __ep, __host, __svc);
   2157 	      _M_size++;
   2158 	    }
   2159 	}
   2160 #else
   2161       __ec = std::make_error_code(errc::operation_not_supported);
   2162 #endif
   2163     }
   2164 
   2165   /// Private constructor to synchronously resolve an endpoint.
   2166   template<typename _InternetProtocol>
   2167     basic_resolver_results<_InternetProtocol>::
   2168     basic_resolver_results(const endpoint_type& __ep, error_code& __ec)
   2169     {
   2170 #ifdef _GLIBCXX_HAVE_NETDB_H
   2171       char __host_name[1025];	// glibc NI_MAXHOST
   2172       char __service_name[32];  // glibc NI_MAXSERV
   2173       int __flags = 0;
   2174       if (__ep.protocol().type() == SOCK_DGRAM)
   2175 	__flags |= NI_DGRAM;
   2176       auto __sa = static_cast<const sockaddr*>(__ep.data());
   2177       int __err = ::getnameinfo(__sa, __ep.size(),
   2178 				__host_name, sizeof(__host_name),
   2179 				__service_name, sizeof(__service_name),
   2180 				__flags);
   2181       if (__err)
   2182 	{
   2183 	  __flags |= NI_NUMERICSERV;
   2184 	  __err = ::getnameinfo(__sa, __ep.size(),
   2185 				__host_name, sizeof(__host_name),
   2186 				__service_name, sizeof(__service_name),
   2187 				__flags);
   2188 	}
   2189       if (__err)
   2190 	__ec = ip::__make_resolver_error_code(__err, errno);
   2191       else
   2192 	{
   2193 	  __ec.clear();
   2194 	  _M_results.emplace_front(__ep, __host_name, __service_name);
   2195 	  _M_size = 1;
   2196 	}
   2197 #else
   2198       __ec = std::make_error_code(errc::operation_not_supported);
   2199 #endif
   2200     }
   2201 #endif // IPPROTO_TCP || IPPROTO_UDP
   2202 
   2203   /** The name of the local host.
   2204    * @{
   2205    */
   2206 
   2207   template<typename _Allocator>
   2208     __string_with<_Allocator>
   2209     host_name(const _Allocator& __a, error_code& __ec)
   2210     {
   2211 #ifdef HOST_NAME_MAX
   2212       constexpr size_t __maxlen = HOST_NAME_MAX;
   2213 #else
   2214       constexpr size_t __maxlen = 256;
   2215 #endif
   2216       char __buf[__maxlen + 1];
   2217       if (::gethostname(__buf, __maxlen) == -1)
   2218 	__ec.assign(errno, generic_category());
   2219       __buf[__maxlen] = '\0';
   2220       return { __buf, __a };
   2221     }
   2222 
   2223   template<typename _Allocator>
   2224     inline __string_with<_Allocator>
   2225     host_name(const _Allocator& __a)
   2226     { return host_name(__a, __throw_on_error{"host_name"}); }
   2227 
   2228   inline string
   2229   host_name(error_code& __ec)
   2230   { return host_name(std::allocator<char>{}, __ec); }
   2231 
   2232   inline string
   2233   host_name()
   2234   { return host_name(std::allocator<char>{}, __throw_on_error{"host_name"}); }
   2235 
   2236   /// @}
   2237 
   2238 #ifdef IPPROTO_TCP
   2239   /// The TCP byte-stream protocol.
   2240   class tcp
   2241   {
   2242   public:
   2243     // types:
   2244     using endpoint = basic_endpoint<tcp>;	 ///< A TCP endpoint.
   2245     using resolver = basic_resolver<tcp>;	 ///< A TCP resolver.
   2246     using socket = basic_stream_socket<tcp>;	 ///< A TCP socket.
   2247     using acceptor = basic_socket_acceptor<tcp>; ///< A TCP acceptor.
   2248     using iostream = basic_socket_iostream<tcp>; ///< A TCP iostream.
   2249 
   2250 #ifdef TCP_NODELAY
   2251     /// Disable coalescing of small segments (i.e. the Nagle algorithm).
   2252     struct no_delay : __sockopt_crtp<no_delay, bool>
   2253     {
   2254       using __sockopt_crtp::__sockopt_crtp;
   2255       using __sockopt_crtp::operator=;
   2256 
   2257       static const int _S_level = IPPROTO_TCP;
   2258       static const int _S_name = TCP_NODELAY;
   2259     };
   2260 #endif
   2261 
   2262     // static members:
   2263 
   2264     /// A protocol object representing IPv4 TCP.
   2265     static constexpr tcp v4() noexcept { return tcp(AF_INET); }
   2266     /// A protocol object representing IPv6 TCP.
   2267     static constexpr tcp v6() noexcept { return tcp(AF_INET6); }
   2268 
   2269     tcp() = delete;
   2270 
   2271     constexpr int family() const noexcept { return _M_family; }
   2272     constexpr int type() const noexcept { return SOCK_STREAM; }
   2273     constexpr int protocol() const noexcept { return IPPROTO_TCP; }
   2274 
   2275   private:
   2276     constexpr explicit tcp(int __family) : _M_family(__family) { }
   2277 
   2278     int _M_family;
   2279   };
   2280 
   2281   /** tcp comparisons
   2282    * @{
   2283    */
   2284 
   2285   constexpr bool
   2286   operator==(const tcp& __a, const tcp& __b) noexcept
   2287   { return __a.family() == __b.family(); }
   2288 
   2289   constexpr bool
   2290   operator!=(const tcp& __a, const tcp& __b) noexcept
   2291   { return !(__a == __b); }
   2292 
   2293   /// @}
   2294 #endif // IPPROTO_TCP
   2295 
   2296 #ifdef IPPROTO_UDP
   2297   /// The UDP datagram protocol.
   2298   class udp
   2299   {
   2300   public:
   2301     // types:
   2302     using endpoint = basic_endpoint<udp>;
   2303     using resolver = basic_resolver<udp>;
   2304     using socket = basic_datagram_socket<udp>;
   2305 
   2306     // static members:
   2307     static constexpr udp v4() noexcept { return udp(AF_INET); }
   2308     static constexpr udp v6() noexcept { return udp(AF_INET6); }
   2309 
   2310     udp() = delete;
   2311 
   2312     constexpr int family() const noexcept { return _M_family; }
   2313     constexpr int type() const noexcept { return SOCK_DGRAM; }
   2314     constexpr int protocol() const noexcept { return IPPROTO_UDP; }
   2315 
   2316   private:
   2317     constexpr explicit udp(int __family) : _M_family(__family) { }
   2318 
   2319     int _M_family;
   2320   };
   2321 
   2322   /** udp comparisons
   2323    * @{
   2324    */
   2325 
   2326   constexpr bool
   2327   operator==(const udp& __a, const udp& __b) noexcept
   2328   { return __a.family() == __b.family(); }
   2329 
   2330   constexpr bool
   2331   operator!=(const udp& __a, const udp& __b) noexcept
   2332   { return !(__a == __b); }
   2333 
   2334   /// @}
   2335 #endif // IPPROTO_UDP
   2336 
   2337 #if defined IPPROTO_IP && defined IPPROTO_IPV6
   2338 
   2339   /// Restrict a socket created for an IPv6 protocol to IPv6 only.
   2340   class v6_only : public __sockopt_crtp<v6_only, bool>
   2341   {
   2342   public:
   2343     using __sockopt_crtp::__sockopt_crtp;
   2344     using __sockopt_crtp::operator=;
   2345 
   2346   private:
   2347     friend __sockopt_crtp<v6_only, bool>;
   2348     static const int _S_level = IPPROTO_IPV6;
   2349     static const int _S_name = IPV6_V6ONLY;
   2350   };
   2351 
   2352   namespace unicast
   2353   {
   2354     /// Set the default number of hops (TTL) for outbound datagrams.
   2355     class hops : public __sockopt_crtp<hops>
   2356     {
   2357     public:
   2358       using __sockopt_crtp::__sockopt_crtp;
   2359       using __sockopt_crtp::operator=;
   2360 
   2361       template<typename _Protocol>
   2362 	int
   2363 	level(const _Protocol& __p) const noexcept
   2364 	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
   2365 
   2366       template<typename _Protocol>
   2367 	int
   2368 	name(const _Protocol& __p) const noexcept
   2369 	{ return __p.family() == AF_INET6 ? IPV6_UNICAST_HOPS : IP_TTL; }
   2370     };
   2371   } // namespace unicast
   2372 
   2373   namespace multicast
   2374   {
   2375     class __mcastopt
   2376     {
   2377     public:
   2378       explicit
   2379       __mcastopt(const address& __grp) noexcept
   2380       : __mcastopt(__grp.is_v4() ? __mcastopt(__grp.to_v4()) : __mcastopt(__grp.to_v6()))
   2381       { }
   2382 
   2383       explicit
   2384       __mcastopt(const address_v4& __grp,
   2385 		 const address_v4& __iface = address_v4::any()) noexcept
   2386       {
   2387 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   2388 	_M_v4.imr_multiaddr.s_addr = __grp.to_uint();
   2389 	_M_v4.imr_interface.s_addr = __iface.to_uint();
   2390 #else
   2391 	_M_v4.imr_multiaddr.s_addr = __builtin_bswap32(__grp.to_uint());
   2392 	_M_v4.imr_interface.s_addr = __builtin_bswap32(__iface.to_uint());
   2393 #endif
   2394       }
   2395 
   2396       explicit
   2397       __mcastopt(const address_v6& __grp, unsigned int __iface = 0) noexcept
   2398       {
   2399 	const auto __addr = __grp.to_bytes();
   2400 	__builtin_memcpy(_M_v6.ipv6mr_multiaddr.s6_addr, __addr.data(), 16);
   2401 	_M_v6.ipv6mr_interface = __iface;
   2402       }
   2403 
   2404       template<typename _Protocol>
   2405 	int
   2406 	level(const _Protocol& __p) const noexcept
   2407 	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
   2408 
   2409       template<typename _Protocol>
   2410 	const void*
   2411 	data(const _Protocol& __p) const noexcept
   2412 	{ return __p.family() == AF_INET6 ? &_M_v6 : &_M_v4; }
   2413 
   2414       template<typename _Protocol>
   2415 	size_t
   2416 	size(const _Protocol& __p) const noexcept
   2417 	{ return __p.family() == AF_INET6 ? sizeof(_M_v6) : sizeof(_M_v4); }
   2418 
   2419     private:
   2420       ipv6_mreq _M_v6 = {};
   2421       ip_mreq _M_v4 = {};
   2422     };
   2423 
   2424     /// Request that a socket joins a multicast group.
   2425     class join_group : private __mcastopt
   2426     {
   2427     public:
   2428       using __mcastopt::__mcastopt;
   2429       using __mcastopt::level;
   2430       using __mcastopt::data;
   2431       using __mcastopt::size;
   2432 
   2433       template<typename _Protocol>
   2434 	int
   2435 	name(const _Protocol& __p) const noexcept
   2436 	{
   2437 	  if (__p.family() == AF_INET6)
   2438 	    return IPV6_JOIN_GROUP;
   2439 	  return IP_ADD_MEMBERSHIP;
   2440 	}
   2441     };
   2442 
   2443     /// Request that a socket leaves a multicast group.
   2444     class leave_group : private __mcastopt
   2445     {
   2446     public:
   2447       using __mcastopt::__mcastopt;
   2448       using __mcastopt::level;
   2449       using __mcastopt::data;
   2450       using __mcastopt::size;
   2451 
   2452       template<typename _Protocol>
   2453 	int
   2454 	name(const _Protocol& __p) const noexcept
   2455 	{
   2456 	  if (__p.family() == AF_INET6)
   2457 	    return IPV6_LEAVE_GROUP;
   2458 	  return IP_DROP_MEMBERSHIP;
   2459 	}
   2460     };
   2461 
   2462     /// Specify the network interface for outgoing multicast datagrams.
   2463     class outbound_interface
   2464     {
   2465     public:
   2466       explicit
   2467       outbound_interface(const address_v4& __v4) noexcept
   2468       {
   2469 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   2470 	_M_v4.s_addr = __v4.to_uint();
   2471 #else
   2472 	_M_v4.s_addr = __builtin_bswap32(__v4.to_uint());
   2473 #endif
   2474       }
   2475 
   2476       explicit
   2477       outbound_interface(unsigned int __v6) noexcept
   2478       : _M_v4(), _M_v6(__v6)
   2479       { }
   2480 
   2481       template<typename _Protocol>
   2482 	int
   2483 	level(const _Protocol& __p) const noexcept
   2484 	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
   2485 
   2486       template<typename _Protocol>
   2487 	int
   2488 	name(const _Protocol& __p) const noexcept
   2489 	{
   2490 	  return __p.family() == AF_INET6
   2491 	    ? IPV6_MULTICAST_IF : IP_MULTICAST_IF;
   2492 	}
   2493 
   2494       template<typename _Protocol>
   2495 	const void*
   2496 	data(const _Protocol& __p) const noexcept
   2497 	{ return __p.family() == AF_INET6 ? &_M_v6 : &_M_v4; }
   2498 
   2499       template<typename _Protocol>
   2500 	size_t
   2501 	size(const _Protocol& __p) const noexcept
   2502 	{ return __p.family() == AF_INET6 ? sizeof(_M_v6) : sizeof(_M_v4); }
   2503 
   2504     private:
   2505       in_addr _M_v4;
   2506       unsigned _M_v6 = 0;
   2507     };
   2508 
   2509     /// Set the default number of hops (TTL) for outbound datagrams.
   2510     class hops : public __sockopt_crtp<hops>
   2511     {
   2512     public:
   2513       using __sockopt_crtp::__sockopt_crtp;
   2514       using __sockopt_crtp::operator=;
   2515 
   2516       template<typename _Protocol>
   2517 	int
   2518 	level(const _Protocol& __p) const noexcept
   2519 	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
   2520 
   2521       template<typename _Protocol>
   2522 	int
   2523 	name(const _Protocol& __p) const noexcept
   2524 	{
   2525 	  return __p.family() == AF_INET6
   2526 	    ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL;
   2527 	}
   2528     };
   2529 
   2530     /// Set whether datagrams are delivered back to the local application.
   2531     class enable_loopback : public __sockopt_crtp<enable_loopback, bool>
   2532     {
   2533     public:
   2534       using __sockopt_crtp::__sockopt_crtp;
   2535       using __sockopt_crtp::operator=;
   2536 
   2537       template<typename _Protocol>
   2538 	int
   2539 	level(const _Protocol& __p) const noexcept
   2540 	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
   2541 
   2542       template<typename _Protocol>
   2543 	int
   2544 	name(const _Protocol& __p) const noexcept
   2545 	{
   2546 	  return __p.family() == AF_INET6
   2547 	    ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP;
   2548 	}
   2549     };
   2550 
   2551   } // namespace multicast
   2552 
   2553 #endif // IPPROTO_IP && IPPROTO_IPV6
   2554 
   2555   /// @}
   2556 
   2557 } // namespace ip
   2558 } // namespace v1
   2559 } // namespace net
   2560 } // namespace experimental
   2561 
   2562   template<>
   2563     struct is_error_condition_enum<experimental::net::v1::ip::resolver_errc>
   2564     : public true_type {};
   2565 
   2566   // hash support
   2567   template<typename _Tp> struct hash;
   2568   template<>
   2569     struct hash<experimental::net::v1::ip::address>
   2570     : __hash_base<size_t, experimental::net::v1::ip::address>
   2571     {
   2572       size_t
   2573       operator()(const experimental::net::v1::ip::address& __a) const
   2574       {
   2575 	if (__a.is_v4())
   2576 	  return _Hash_impl::hash(__a.to_v4());
   2577 	else
   2578 	  return _Hash_impl::hash(__a.to_v6());
   2579       }
   2580     };
   2581 
   2582   template<>
   2583     struct hash<experimental::net::v1::ip::address_v4>
   2584     : __hash_base<size_t, experimental::net::v1::ip::address_v4>
   2585     {
   2586       size_t
   2587       operator()(const experimental::net::v1::ip::address_v4& __a) const
   2588       { return _Hash_impl::hash(__a.to_bytes()); }
   2589     };
   2590 
   2591   template<> struct hash<experimental::net::v1::ip::address_v6>
   2592     : __hash_base<size_t, experimental::net::v1::ip::address_v6>
   2593     {
   2594       size_t
   2595       operator()(const experimental::net::v1::ip::address_v6& __a) const
   2596       { return _Hash_impl::hash(__a.to_bytes()); }
   2597     };
   2598 
   2599 _GLIBCXX_END_NAMESPACE_VERSION
   2600 } // namespace std
   2601 
   2602 #endif // C++14
   2603 
   2604 #endif // _GLIBCXX_EXPERIMENTAL_INTERNET
   2605