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