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