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