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  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  bool
1138  operator==(const network_v4& __a, const network_v4& __b) noexcept;
1139
1140  bool
1141  operator==(const network_v6& __a, const network_v6& __b) noexcept;
1142
1143  /// @}
1144
1145  /// An IPv4 network address.
1146  class network_v4
1147  {
1148  public:
1149    // constructors:
1150    constexpr network_v4() noexcept : _M_addr(), _M_prefix_len(0) { }
1151
1152    constexpr
1153    network_v4(const address_v4& __addr, int __prefix_len)
1154    : _M_addr(__addr), _M_prefix_len(__prefix_len)
1155    {
1156      if (_M_prefix_len < 0 || _M_prefix_len > 32)
1157	__throw_out_of_range("network_v4: invalid prefix length");
1158    }
1159
1160    constexpr
1161    network_v4(const address_v4& __addr, const address_v4& __mask)
1162    : _M_addr(__addr), _M_prefix_len(__builtin_popcount(__mask.to_uint()))
1163    {
1164      if (_M_prefix_len != 0)
1165	{
1166	  address_v4::uint_type __mask_uint = __mask.to_uint();
1167	  if (__builtin_ctz(__mask_uint) != (32 - _M_prefix_len))
1168	    __throw_invalid_argument("network_v4: invalid mask");
1169	  if ((__mask_uint & 0x80000000) == 0)
1170	    __throw_invalid_argument("network_v4: invalid mask");
1171	}
1172    }
1173
1174    // members:
1175
1176    constexpr address_v4 address() const noexcept { return _M_addr; }
1177    constexpr int prefix_length() const noexcept { return _M_prefix_len; }
1178
1179    constexpr address_v4
1180    netmask() const noexcept
1181    {
1182      address_v4::uint_type __val = address_v4::broadcast().to_uint();
1183      __val >>= (32 - _M_prefix_len);
1184      __val <<= (32 - _M_prefix_len);
1185      return address_v4{__val};
1186    }
1187
1188    constexpr address_v4
1189    network() const noexcept
1190    { return address_v4{_M_addr.to_uint() & netmask().to_uint()}; }
1191
1192    constexpr address_v4
1193    broadcast() const noexcept
1194    { return address_v4{_M_addr.to_uint() | ~netmask().to_uint()}; }
1195
1196    address_v4_range
1197    hosts() const noexcept
1198    {
1199      if (is_host())
1200	return { address(), *++address_v4_iterator(address()) };
1201      return { network(), broadcast() };
1202    }
1203
1204    constexpr network_v4
1205    canonical() const noexcept
1206    { return network_v4(network(), prefix_length()); }
1207
1208    constexpr bool is_host() const noexcept { return _M_prefix_len == 32; }
1209
1210    constexpr bool
1211    is_subnet_of(const network_v4& __other) const noexcept
1212    {
1213      if (__other.prefix_length() < prefix_length())
1214	{
1215	  network_v4 __net(address(), __other.prefix_length());
1216	  return __net.canonical() == __other.canonical();
1217	}
1218      return false;
1219    }
1220
1221    template<typename _Allocator = allocator<char>>
1222      __string_with<_Allocator>
1223      to_string(const _Allocator& __a = _Allocator()) const
1224      {
1225	return address().to_string(__a) + '/'
1226	  + std::to_string(prefix_length());
1227      }
1228
1229  private:
1230    address_v4 _M_addr;
1231    int _M_prefix_len;
1232  };
1233
1234  /// An IPv6 network address.
1235  class network_v6
1236  {
1237  public:
1238    // constructors:
1239    constexpr network_v6() noexcept : _M_addr(), _M_prefix_len(0) { }
1240
1241    constexpr
1242    network_v6(const address_v6& __addr, int __prefix_len)
1243    : _M_addr(__addr), _M_prefix_len(__prefix_len)
1244    {
1245      if (_M_prefix_len < 0 || _M_prefix_len > 128)
1246	__throw_out_of_range("network_v6: invalid prefix length");
1247    }
1248
1249    // members:
1250    constexpr address_v6 address() const noexcept { return _M_addr; }
1251    constexpr int prefix_length() const noexcept { return _M_prefix_len; }
1252
1253    constexpr address_v6 network() const noexcept; // TODO
1254
1255    address_v6_range
1256    hosts() const noexcept
1257    {
1258      if (is_host())
1259	return { address(), *++address_v6_iterator(address()) };
1260      return {}; // { network(), XXX broadcast() XXX }; // TODO
1261    }
1262
1263    constexpr network_v6
1264    canonical() const noexcept
1265    { return network_v6{network(), prefix_length()}; }
1266
1267    constexpr bool is_host() const noexcept { return _M_prefix_len == 128; }
1268
1269    constexpr bool
1270    is_subnet_of(const network_v6& __other) const noexcept
1271    {
1272      if (__other.prefix_length() < prefix_length())
1273	{
1274	  network_v6 __net(address(), __other.prefix_length());
1275	  return __net.canonical() == __other.canonical();
1276	}
1277      return false;
1278    }
1279
1280    template<typename _Allocator = allocator<char>>
1281      __string_with<_Allocator>
1282      to_string(const _Allocator& __a = _Allocator()) const
1283      {
1284	return address().to_string(__a) + '/'
1285	  + std::to_string(prefix_length());
1286      }
1287
1288  private:
1289    address_v6 _M_addr;
1290    int _M_prefix_len;
1291  };
1292
1293
1294  /** ip::network_v4 comparisons
1295   * @{
1296   */
1297
1298  inline bool
1299  operator==(const network_v4& __a, const network_v4& __b) noexcept
1300  {
1301    return __a.address() == __b.address()
1302      && __a.prefix_length() == __b.prefix_length();
1303  }
1304
1305  inline bool
1306  operator!=(const network_v4& __a, const network_v4& __b) noexcept
1307  { return !(__a == __b); }
1308
1309  /// @}
1310
1311  /** ip::network_v6 comparisons
1312   * @{
1313   */
1314
1315  inline bool
1316  operator==(const network_v6& __a, const network_v6& __b) noexcept
1317  {
1318    return __a.address() == __b.address()
1319      && __a.prefix_length() == __b.prefix_length();
1320  }
1321
1322  inline bool
1323  operator!=(const network_v6& __a, const network_v6& __b) noexcept
1324  { return !(__a == __b); }
1325
1326  /// @}
1327
1328  /** ip::network_v4 creation
1329   * @{
1330   */
1331
1332  inline network_v4
1333  make_network_v4(const address_v4& __a, int __prefix_len)
1334  { return network_v4{__a, __prefix_len}; }
1335
1336  inline network_v4
1337  make_network_v4(const address_v4& __a, const address_v4& __mask)
1338  { return network_v4{ __a, __mask }; }
1339
1340  network_v4 make_network_v4(const char*, error_code&) noexcept; // TODO
1341
1342  inline network_v4
1343  make_network_v4(const char* __str)
1344  { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1345
1346  network_v4 make_network_v4(const string&, error_code&) noexcept; // TODO
1347
1348  inline network_v4
1349  make_network_v4(const string& __str)
1350  { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1351
1352  network_v4 make_network_v4(string_view, error_code&) noexcept; // TODO
1353
1354  inline network_v4
1355  make_network_v4(string_view __str)
1356  { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1357
1358  /// @}
1359
1360  /** ip::network_v6 creation
1361   * @{
1362   */
1363
1364  inline network_v6
1365  make_network_v6(const address_v6& __a, int __prefix_len)
1366  { return network_v6{__a, __prefix_len}; }
1367
1368  network_v6 make_network_v6(const char*, error_code&) noexcept; // TODO
1369
1370  inline network_v6
1371  make_network_v6(const char* __str)
1372  { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1373
1374  network_v6 make_network_v6(const string&, error_code&) noexcept; // TODO
1375
1376  inline network_v6
1377  make_network_v6(const string& __str)
1378  { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1379
1380  network_v6 make_network_v6(string_view, error_code&) noexcept; // TODO
1381
1382  inline network_v6
1383  make_network_v6(string_view __str)
1384  { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1385
1386  /// @}
1387
1388  /// ip::network_v4 I/O
1389  template<typename _CharT, typename _Traits>
1390    inline basic_ostream<_CharT, _Traits>&
1391    operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v4& __net)
1392    { return __os << __net.to_string(); }
1393
1394  /// ip::network_v6 I/O
1395  template<typename _CharT, typename _Traits>
1396    inline basic_ostream<_CharT, _Traits>&
1397    operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v6& __net)
1398    { return __os << __net.to_string(); }
1399
1400  /// An IP endpoint.
1401  template<typename _InternetProtocol>
1402    class basic_endpoint
1403    {
1404    public:
1405      // types:
1406      typedef _InternetProtocol protocol_type;
1407
1408      // constructors:
1409
1410      constexpr
1411      basic_endpoint() noexcept : _M_data()
1412      { _M_data._M_v4.sin_family = protocol_type::v4().family(); }
1413
1414      constexpr
1415      basic_endpoint(const protocol_type& __proto,
1416		     port_type __port_num) noexcept
1417      : _M_data()
1418      {
1419	__glibcxx_assert(__proto == protocol_type::v4()
1420			  || __proto == protocol_type::v6());
1421
1422	_M_data._M_v4.sin_family = __proto.family();
1423	_M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
1424      }
1425
1426      constexpr
1427      basic_endpoint(const ip::address& __addr,
1428		     port_type __port_num) noexcept
1429      : _M_data()
1430      {
1431	if (__addr.is_v4())
1432	  {
1433	    _M_data._M_v4.sin_family = protocol_type::v4().family();
1434	    _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
1435	    _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
1436	  }
1437	else
1438	  {
1439	    _M_data._M_v6 = {};
1440	    _M_data._M_v6.sin6_family = protocol_type::v6().family();
1441	    _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num);
1442	    __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
1443			     __addr._M_v6._M_bytes.data(), 16);
1444	    _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
1445	  }
1446      }
1447
1448      // members:
1449      constexpr protocol_type protocol() const noexcept
1450      {
1451	return _M_data._M_v4.sin_family == AF_INET6
1452	  ? protocol_type::v6() : protocol_type::v4();
1453      }
1454
1455      constexpr ip::address
1456      address() const noexcept
1457      {
1458	ip::address __addr;
1459	if (protocol().family() == AF_INET6)
1460	  {
1461	    __builtin_memcpy(&__addr._M_v6._M_bytes,
1462			     _M_data._M_v6.sin6_addr.s6_addr, 16);
1463	    __addr._M_is_v4 = false;
1464	  }
1465	else
1466	  {
1467	    __builtin_memcpy(&__addr._M_v4._M_addr,
1468			     &_M_data._M_v4.sin_addr.s_addr, 4);
1469	  }
1470	return __addr;
1471      }
1472
1473      void
1474      address(const ip::address& __addr) noexcept
1475      {
1476	if (__addr.is_v6())
1477	  {
1478	    _M_data._M_v6 = {};
1479	    _M_data._M_v6.sin6_family = protocol_type::v6().family();
1480	    __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
1481			     __addr._M_v6._M_bytes.data(), 16);
1482	    _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
1483	  }
1484	else
1485	  {
1486	    _M_data._M_v4.sin_family = protocol_type::v4().family();
1487	    _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
1488	  }
1489      }
1490
1491      constexpr port_type
1492      port() const noexcept
1493      { return address_v4::_S_ntoh_16(_M_data._M_v4.sin_port); }
1494
1495      void
1496      port(port_type __port_num) noexcept
1497      { _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); }
1498
1499      void* data() noexcept { return &_M_data; }
1500      const void* data() const noexcept { return &_M_data; }
1501      constexpr size_t size() const noexcept
1502      {
1503	return protocol().family() == AF_INET6
1504	  ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);
1505      }
1506
1507      void
1508      resize(size_t __s)
1509      {
1510	if ((protocol().family() == AF_INET6 && __s != sizeof(sockaddr_in6))
1511	    || (protocol().family() == AF_INET && __s != sizeof(sockaddr_in)))
1512	  __throw_length_error("net::ip::basic_endpoint::resize");
1513      }
1514
1515      constexpr size_t capacity() const noexcept { return sizeof(_M_data); }
1516
1517    private:
1518      union
1519      {
1520	sockaddr_in	_M_v4;
1521	sockaddr_in6	_M_v6;
1522      } _M_data;
1523    };
1524
1525  /** basic_endpoint comparisons
1526   * @{
1527   */
1528
1529  template<typename _InternetProtocol>
1530    inline bool
1531    operator==(const basic_endpoint<_InternetProtocol>& __a,
1532	       const basic_endpoint<_InternetProtocol>& __b)
1533    { return __a.address() == __b.address() && __a.port() == __b.port(); }
1534
1535  template<typename _InternetProtocol>
1536    inline bool
1537    operator!=(const basic_endpoint<_InternetProtocol>& __a,
1538	       const basic_endpoint<_InternetProtocol>& __b)
1539    { return !(__a == __b); }
1540
1541  template<typename _InternetProtocol>
1542    inline bool
1543    operator< (const basic_endpoint<_InternetProtocol>& __a,
1544	       const basic_endpoint<_InternetProtocol>& __b)
1545    {
1546      return __a.address() < __b.address()
1547	|| (!(__b.address() < __a.address()) && __a.port() < __b.port());
1548    }
1549
1550  template<typename _InternetProtocol>
1551    inline bool
1552    operator> (const basic_endpoint<_InternetProtocol>& __a,
1553	       const basic_endpoint<_InternetProtocol>& __b)
1554    { return __b < __a; }
1555
1556  template<typename _InternetProtocol>
1557    inline bool
1558    operator<=(const basic_endpoint<_InternetProtocol>& __a,
1559	       const basic_endpoint<_InternetProtocol>& __b)
1560    { return !(__b < __a); }
1561
1562  template<typename _InternetProtocol>
1563    inline bool
1564    operator>=(const basic_endpoint<_InternetProtocol>& __a,
1565	       const basic_endpoint<_InternetProtocol>& __b)
1566    { return !(__a < __b); }
1567
1568  /// @}
1569
1570  /// basic_endpoint I/O
1571  template<typename _CharT, typename _Traits, typename _InternetProtocol>
1572    inline basic_ostream<_CharT, _Traits>&
1573    operator<<(basic_ostream<_CharT, _Traits>& __os,
1574	       const basic_endpoint<_InternetProtocol>& __ep)
1575    {
1576      basic_ostringstream<_CharT, _Traits> __ss;
1577      if (__ep.protocol()
1578	  == basic_endpoint<_InternetProtocol>::protocol_type::v6())
1579	__ss << '[' << __ep.address() << ']';
1580      else
1581	__ss << __ep.address();
1582      __ss << ':' << __ep.port();
1583      __os << __ss.str();
1584      return __os;
1585    }
1586
1587  /** Type representing a single result of name/address resolution.
1588   * @{
1589   */
1590
1591  template<typename _InternetProtocol>
1592    class basic_resolver_entry
1593    {
1594    public:
1595      // types:
1596      typedef _InternetProtocol protocol_type;
1597      typedef typename _InternetProtocol::endpoint endpoint_type;
1598
1599      // constructors:
1600      basic_resolver_entry() { }
1601
1602      basic_resolver_entry(const endpoint_type& __ep,
1603			   string_view __h, string_view __s)
1604      : _M_ep(__ep), _M_host(__h), _M_svc(__s) { }
1605
1606      // members:
1607      endpoint_type endpoint() const { return _M_ep; }
1608      operator endpoint_type() const { return _M_ep; }
1609
1610      template<typename _Allocator = allocator<char>>
1611	__string_with<_Allocator>
1612	host_name(const _Allocator& __a = _Allocator()) const
1613	{ return { _M_host, __a }; }
1614
1615      template<typename _Allocator = allocator<char>>
1616	__string_with<_Allocator>
1617	service_name(const _Allocator& __a = _Allocator()) const
1618	{ return { _M_svc, __a }; }
1619
1620    private:
1621      basic_endpoint<_InternetProtocol> _M_ep;
1622      string _M_host;
1623      string _M_svc;
1624    };
1625
1626  template<typename _InternetProtocol>
1627    inline bool
1628    operator==(const basic_resolver_entry<_InternetProtocol>& __a,
1629	       const basic_resolver_entry<_InternetProtocol>& __b)
1630    {
1631      return __a.endpoint() == __b.endpoint()
1632	&& __a.host_name() == __b.host_name()
1633	&& __a.service_name() == __b.service_name();
1634    }
1635
1636  template<typename _InternetProtocol>
1637    inline bool
1638    operator!=(const basic_resolver_entry<_InternetProtocol>& __a,
1639	       const basic_resolver_entry<_InternetProtocol>& __b)
1640    { return !(__a == __b); }
1641
1642  /// @}
1643
1644  /** Base class defining flags for name/address resolution.
1645   * @{
1646   */
1647
1648  class resolver_base
1649  {
1650  public:
1651    enum flags : int
1652    {
1653      __flags_passive			= AI_PASSIVE,
1654      __flags_canonical_name		= AI_CANONNAME,
1655      __flags_numeric_host		= AI_NUMERICHOST,
1656#ifdef AI_NUMERICSERV
1657      __flags_numeric_service		= AI_NUMERICSERV,
1658#endif
1659      __flags_v4_mapped			= AI_V4MAPPED,
1660      __flags_all_matching		= AI_ALL,
1661      __flags_address_configured	= AI_ADDRCONFIG
1662    };
1663    static constexpr flags passive		= __flags_passive;
1664    static constexpr flags canonical_name	= __flags_canonical_name;
1665    static constexpr flags numeric_host		= __flags_numeric_host;
1666#ifdef AI_NUMERICSERV
1667    static constexpr flags numeric_service	= __flags_numeric_service;
1668#endif
1669    static constexpr flags v4_mapped		= __flags_v4_mapped;
1670    static constexpr flags all_matching		= __flags_all_matching;
1671    static constexpr flags address_configured	= __flags_address_configured;
1672
1673  protected:
1674    resolver_base() = default;
1675    ~resolver_base() = default;
1676  };
1677
1678  constexpr resolver_base::flags
1679  operator&(resolver_base::flags __f1, resolver_base::flags __f2)
1680  { return resolver_base::flags( int(__f1) & int(__f2) ); }
1681
1682  constexpr resolver_base::flags
1683  operator|(resolver_base::flags __f1, resolver_base::flags __f2)
1684  { return resolver_base::flags( int(__f1) | int(__f2) ); }
1685
1686  constexpr resolver_base::flags
1687  operator^(resolver_base::flags __f1, resolver_base::flags __f2)
1688  { return resolver_base::flags( int(__f1) ^ int(__f2) ); }
1689
1690  constexpr resolver_base::flags
1691  operator~(resolver_base::flags __f)
1692  { return resolver_base::flags( ~int(__f) ); }
1693
1694  inline resolver_base::flags&
1695  operator&=(resolver_base::flags& __f1, resolver_base::flags __f2)
1696  { return __f1 = (__f1 & __f2); }
1697
1698  inline resolver_base::flags&
1699  operator|=(resolver_base::flags& __f1, resolver_base::flags __f2)
1700  { return __f1 = (__f1 | __f2); }
1701
1702  inline resolver_base::flags&
1703  operator^=(resolver_base::flags& __f1, resolver_base::flags __f2)
1704  { return __f1 = (__f1 ^ __f2); }
1705
1706  // TODO define resolver_base::flags static constants for C++14 mode
1707
1708  /// @}
1709
1710  /** Container for results of name/address resolution.
1711   * @{
1712   */
1713
1714  template<typename _InternetProtocol>
1715    class basic_resolver_results
1716    {
1717    public:
1718      // types:
1719      typedef _InternetProtocol protocol_type;
1720      typedef typename protocol_type::endpoint endpoint_type;
1721      typedef basic_resolver_entry<protocol_type> value_type;
1722      typedef const value_type& const_reference;
1723      typedef value_type& reference;
1724      typedef typename forward_list<value_type>::const_iterator const_iterator;
1725      typedef const_iterator iterator;
1726      typedef ptrdiff_t difference_type;
1727      typedef size_t size_type;
1728
1729      // construct / copy / destroy:
1730
1731      basic_resolver_results() = default;
1732
1733      basic_resolver_results(const basic_resolver_results&) = default;
1734
1735      basic_resolver_results(basic_resolver_results&&) noexcept = default;
1736
1737      basic_resolver_results&
1738      operator=(const basic_resolver_results&) = default;
1739
1740      basic_resolver_results&
1741      operator=(basic_resolver_results&&) = default;
1742
1743      ~basic_resolver_results() = default;
1744
1745      // size:
1746      size_type size() const noexcept { return _M_size; }
1747      size_type max_size() const noexcept { return _M_results.max_size(); }
1748      _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_results.empty(); }
1749
1750      // element access:
1751      const_iterator begin() const { return _M_results.begin(); }
1752      const_iterator end() const { return _M_results.end(); }
1753      const_iterator cbegin() const { return _M_results.begin(); }
1754      const_iterator cend() const { return _M_results.end(); }
1755
1756      // swap:
1757      void
1758      swap(basic_resolver_results& __that) noexcept
1759      { _M_results.swap(__that._M_results); }
1760
1761    private:
1762      friend class basic_resolver<protocol_type>;
1763
1764      basic_resolver_results(string_view, string_view, resolver_base::flags,
1765			     error_code&, protocol_type* = nullptr);
1766
1767      basic_resolver_results(const endpoint_type&, error_code&);
1768
1769      forward_list<value_type> _M_results;
1770      size_t _M_size = 0;
1771    };
1772
1773  template<typename _InternetProtocol>
1774    inline bool
1775    operator==(const basic_resolver_results<_InternetProtocol>& __a,
1776	       const basic_resolver_results<_InternetProtocol>& __b)
1777    {
1778      return __a.size() == __b.size()
1779	&& std::equal(__a.begin(), __a.end(), __b.begin());
1780    }
1781
1782  template<typename _InternetProtocol>
1783    inline bool
1784    operator!=(const basic_resolver_results<_InternetProtocol>& __a,
1785	       const basic_resolver_results<_InternetProtocol>& __b)
1786    { return !(__a == __b); }
1787
1788  /// @}
1789
1790  /// Perform name/address resolution.
1791  template<typename _InternetProtocol>
1792    class basic_resolver : public resolver_base
1793    {
1794    public:
1795      // types:
1796
1797      typedef io_context::executor_type executor_type;
1798      typedef _InternetProtocol protocol_type;
1799      typedef typename _InternetProtocol::endpoint endpoint_type;
1800      typedef basic_resolver_results<_InternetProtocol> results_type;
1801
1802      // construct / copy / destroy:
1803
1804      explicit basic_resolver(io_context& __ctx) : _M_ctx(&__ctx) { }
1805
1806      basic_resolver(const basic_resolver&) = delete;
1807
1808      basic_resolver(basic_resolver&& __rhs) noexcept
1809      : _M_ctx(__rhs._M_ctx)
1810      { } // TODO move state/tasks etc.
1811
1812      ~basic_resolver() { cancel(); }
1813
1814      basic_resolver& operator=(const basic_resolver&) = delete;
1815
1816      basic_resolver& operator=(basic_resolver&& __rhs)
1817      {
1818	cancel();
1819	_M_ctx = __rhs._M_ctx;
1820	// TODO move state/tasks etc.
1821	return *this;
1822      }
1823
1824      // basic_resolver operations:
1825
1826      executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
1827
1828      void cancel() { } // TODO
1829
1830      results_type
1831      resolve(string_view __host_name, string_view __service_name)
1832      {
1833	return resolve(__host_name, __service_name, resolver_base::flags(),
1834		       __throw_on_error{"basic_resolver::resolve"});
1835      }
1836
1837      results_type
1838      resolve(string_view __host_name, string_view __service_name,
1839	      error_code& __ec)
1840      {
1841	return resolve(__host_name, __service_name, resolver_base::flags(),
1842		       __ec);
1843      }
1844
1845      results_type
1846      resolve(string_view __host_name, string_view __service_name, flags __f)
1847      {
1848	return resolve(__host_name, __service_name, __f,
1849		       __throw_on_error{"basic_resolver::resolve"});
1850      }
1851
1852      results_type
1853      resolve(string_view __host_name, string_view __service_name, flags __f,
1854	      error_code& __ec)
1855      { return {__host_name, __service_name, __f, __ec}; }
1856
1857      template<typename _CompletionToken>
1858	__deduced_t<_CompletionToken, void(error_code, results_type)>
1859	async_resolve(string_view __host_name, string_view __service_name,
1860		      _CompletionToken&& __token)
1861	{
1862	  return async_resolve(__host_name, __service_name,
1863			       resolver_base::flags(),
1864			       forward<_CompletionToken>(__token));
1865	}
1866
1867      template<typename _CompletionToken>
1868	__deduced_t<_CompletionToken, void(error_code, results_type)>
1869	async_resolve(string_view __host_name, string_view __service_name,
1870		      flags __f, _CompletionToken&& __token); // TODO
1871
1872      results_type
1873      resolve(const protocol_type& __protocol,
1874	      string_view __host_name, string_view __service_name)
1875      {
1876	return resolve(__protocol, __host_name, __service_name,
1877		       resolver_base::flags(),
1878		       __throw_on_error{"basic_resolver::resolve"});
1879      }
1880
1881      results_type
1882      resolve(const protocol_type& __protocol,
1883	      string_view __host_name, string_view __service_name,
1884	      error_code& __ec)
1885      {
1886	return resolve(__protocol, __host_name, __service_name,
1887		       resolver_base::flags(), __ec);
1888      }
1889
1890      results_type
1891      resolve(const protocol_type& __protocol,
1892	      string_view __host_name, string_view __service_name, flags __f)
1893      {
1894	return resolve(__protocol, __host_name, __service_name, __f,
1895		       __throw_on_error{"basic_resolver::resolve"});
1896      }
1897
1898      results_type
1899      resolve(const protocol_type& __protocol,
1900	      string_view __host_name, string_view __service_name,
1901	      flags __f, error_code& __ec)
1902      { return {__host_name, __service_name, __f, __ec, &__protocol}; }
1903
1904      template<typename _CompletionToken>
1905	__deduced_t<_CompletionToken, void(error_code, results_type)>
1906	async_resolve(const protocol_type& __protocol,
1907		      string_view __host_name, string_view __service_name,
1908		      _CompletionToken&& __token)
1909	{
1910	  return async_resolve(__protocol, __host_name, __service_name,
1911			       resolver_base::flags(),
1912			       forward<_CompletionToken>(__token));
1913	}
1914
1915      template<typename _CompletionToken>
1916	__deduced_t<_CompletionToken, void(error_code, results_type)>
1917	async_resolve(const protocol_type& __protocol,
1918		      string_view __host_name, string_view __service_name,
1919		      flags __f, _CompletionToken&& __token); // TODO
1920
1921      results_type
1922      resolve(const endpoint_type& __ep)
1923      { return resolve(__ep, __throw_on_error{"basic_resolver::resolve"}); }
1924
1925      results_type
1926      resolve(const endpoint_type& __ep, error_code& __ec)
1927      { return { __ep, __ec }; }
1928
1929      template<typename _CompletionToken> // TODO
1930	__deduced_t<_CompletionToken, void(error_code, results_type)>
1931	async_resolve(const endpoint_type& __ep, _CompletionToken&& __token);
1932
1933    private:
1934      io_context* _M_ctx;
1935    };
1936
1937  /// Private constructor to synchronously resolve host and service names.
1938  template<typename _InternetProtocol>
1939    basic_resolver_results<_InternetProtocol>::
1940    basic_resolver_results(string_view __host_name, string_view __service_name,
1941			   resolver_base::flags __f, error_code& __ec,
1942			   protocol_type* __protocol)
1943    {
1944#ifdef _GLIBCXX_HAVE_NETDB_H
1945      string __host;
1946      const char* __h = __host_name.data()
1947	? (__host = __host_name.to_string()).c_str()
1948	: nullptr;
1949      string __svc;
1950      const char* __s = __service_name.data()
1951	? (__svc = __service_name.to_string()).c_str()
1952	: nullptr;
1953
1954      ::addrinfo __hints{ };
1955      __hints.ai_flags = static_cast<int>(__f);
1956      if (__protocol)
1957	{
1958	  __hints.ai_family = __protocol->family();
1959	  __hints.ai_socktype = __protocol->type();
1960	  __hints.ai_protocol = __protocol->protocol();
1961	}
1962      else
1963	{
1964	  auto __p = endpoint_type{}.protocol();
1965	  __hints.ai_family = AF_UNSPEC;
1966	  __hints.ai_socktype = __p.type();
1967	  __hints.ai_protocol = __p.protocol();
1968	}
1969
1970      struct __scoped_addrinfo
1971      {
1972	~__scoped_addrinfo() { if (_M_p) ::freeaddrinfo(_M_p); }
1973	::addrinfo* _M_p = nullptr;
1974      } __sai;
1975
1976      if (int __err = ::getaddrinfo(__h, __s, &__hints, &__sai._M_p))
1977	{
1978	  __ec.assign(__err, resolver_category());
1979	  return;
1980	}
1981      __ec.clear();
1982
1983      endpoint_type __ep;
1984      auto __tail = _M_results.before_begin();
1985      for (auto __ai = __sai._M_p; __ai != nullptr; __ai = __ai->ai_next)
1986	{
1987	  if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6)
1988	    {
1989	      if (__ai->ai_addrlen <= __ep.capacity())
1990		__builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen);
1991	      __ep.resize(__ai->ai_addrlen);
1992	      __tail = _M_results.emplace_after(__tail, __ep, __host, __svc);
1993	      _M_size++;
1994	    }
1995	}
1996#else
1997      __ec = std::make_error_code(errc::operation_not_supported);
1998#endif
1999    }
2000
2001  /// Private constructor to synchronously resolve an endpoint.
2002  template<typename _InternetProtocol>
2003    basic_resolver_results<_InternetProtocol>::
2004    basic_resolver_results(const endpoint_type& __ep, error_code& __ec)
2005    {
2006#ifdef _GLIBCXX_HAVE_NETDB_H
2007      char __host_name[256];
2008      char __service_name[128];
2009      int __flags = 0;
2010      if (__ep.protocol().type() == SOCK_DGRAM)
2011	__flags |= NI_DGRAM;
2012      auto __sa = static_cast<const sockaddr*>(__ep.data());
2013      int __err = ::getnameinfo(__sa, __ep.size(),
2014				__host_name, sizeof(__host_name),
2015				__service_name, sizeof(__service_name),
2016				__flags);
2017      if (__err)
2018	{
2019	  __flags |= NI_NUMERICSERV;
2020	  __err = ::getnameinfo(__sa, __ep.size(),
2021				__host_name, sizeof(__host_name),
2022				__service_name, sizeof(__service_name),
2023				__flags);
2024	}
2025      if (__err)
2026	__ec.assign(__err, resolver_category());
2027      else
2028	{
2029	  __ec.clear();
2030	  _M_results.emplace_front(__ep, __host_name, __service_name);
2031	  _M_size = 1;
2032	}
2033#else
2034      __ec = std::make_error_code(errc::operation_not_supported);
2035#endif
2036    }
2037
2038  /** The name of the local host.
2039   * @{
2040   */
2041
2042  template<typename _Allocator>
2043    __string_with<_Allocator>
2044    host_name(const _Allocator& __a, error_code& __ec)
2045    {
2046#ifdef HOST_NAME_MAX
2047      constexpr size_t __maxlen = HOST_NAME_MAX;
2048#else
2049      constexpr size_t __maxlen = 256;
2050#endif
2051      char __buf[__maxlen + 1];
2052      if (::gethostname(__buf, __maxlen) == -1)
2053	__ec.assign(errno, generic_category());
2054      __buf[__maxlen] = '\0';
2055      return { __buf, __a };
2056    }
2057
2058  template<typename _Allocator>
2059    inline __string_with<_Allocator>
2060    host_name(const _Allocator& __a)
2061    { return host_name(__a, __throw_on_error{"host_name"}); }
2062
2063  inline string
2064  host_name(error_code& __ec)
2065  { return host_name(std::allocator<char>{}, __ec); }
2066
2067  inline string
2068  host_name()
2069  { return host_name(std::allocator<char>{}, __throw_on_error{"host_name"}); }
2070
2071  /// @}
2072
2073  /// The TCP byte-stream protocol.
2074  class tcp
2075  {
2076  public:
2077    // types:
2078    typedef basic_endpoint<tcp> endpoint;	 ///< A TCP endpoint.
2079    typedef basic_resolver<tcp> resolver;	 ///< A TCP resolver.
2080    typedef basic_stream_socket<tcp> socket;	 ///< A TCP socket.
2081    typedef basic_socket_acceptor<tcp> acceptor; ///< A TCP acceptor.
2082    typedef basic_socket_iostream<tcp> iostream; /// A TCP iostream.
2083
2084#ifdef _GLIBCXX_HAVE_NETINET_TCP_H
2085    /// Disable coalescing of small segments (i.e. the Nagle algorithm).
2086    struct no_delay : __sockopt_crtp<no_delay, bool>
2087    {
2088      using __sockopt_crtp::__sockopt_crtp;
2089
2090      static const int _S_level = IPPROTO_TCP;
2091      static const int _S_name = TCP_NODELAY;
2092    };
2093#endif
2094
2095    // static members:
2096
2097    /// A protocol object representing IPv4 TCP.
2098    static constexpr tcp v4() noexcept { return tcp(AF_INET); }
2099    /// A protocol object representing IPv6 TCP.
2100    static constexpr tcp v6() noexcept { return tcp(AF_INET6); }
2101
2102    tcp() = delete;
2103
2104    constexpr int family() const noexcept { return _M_family; }
2105    constexpr int type() const noexcept { return SOCK_STREAM; }
2106    constexpr int protocol() const noexcept { return IPPROTO_TCP; }
2107
2108  private:
2109    constexpr explicit tcp(int __family) : _M_family(__family) { }
2110
2111    int _M_family;
2112  };
2113
2114  /** tcp comparisons
2115   * @{
2116   */
2117
2118  inline bool
2119  operator==(const tcp& __a, const tcp& __b)
2120  { return __a.family() == __b.family(); }
2121
2122  inline bool
2123  operator!=(const tcp& __a, const tcp& __b)
2124  { return !(__a == __b); }
2125
2126  /// @}
2127
2128  /// The UDP datagram protocol.
2129  class udp
2130  {
2131  public:
2132    // types:
2133    typedef basic_endpoint<udp> endpoint;
2134    typedef basic_resolver<udp> resolver;
2135    typedef basic_datagram_socket<udp> socket;
2136
2137    // static members:
2138    static constexpr udp v4() noexcept { return udp(AF_INET); }
2139    static constexpr udp v6() noexcept { return udp(AF_INET6); }
2140
2141    udp() = delete;
2142
2143    constexpr int family() const noexcept { return _M_family; }
2144    constexpr int type() const noexcept { return SOCK_DGRAM; }
2145    constexpr int protocol() const noexcept { return IPPROTO_UDP; }
2146
2147  private:
2148    constexpr explicit udp(int __family) : _M_family(__family) { }
2149
2150    int _M_family;
2151  };
2152
2153  /** udp comparisons
2154   * @{
2155   */
2156
2157  inline bool
2158  operator==(const udp& __a, const udp& __b)
2159  { return __a.family() == __b.family(); }
2160
2161  inline bool
2162  operator!=(const udp& __a, const udp& __b)
2163  { return !(__a == __b); }
2164
2165  /// @}
2166
2167  /// Restrict a socket created for an IPv6 protocol to IPv6 only.
2168  struct v6_only : __sockopt_crtp<v6_only, bool>
2169  {
2170    using __sockopt_crtp::__sockopt_crtp;
2171
2172    static const int _S_level = IPPROTO_IPV6;
2173    static const int _S_name = IPV6_V6ONLY;
2174  };
2175
2176  namespace unicast
2177  {
2178    /// Set the default number of hops (TTL) for outbound datagrams.
2179    struct hops : __sockopt_crtp<hops>
2180    {
2181      using __sockopt_crtp::__sockopt_crtp;
2182
2183      template<typename _Protocol>
2184	int
2185	level(const _Protocol& __p) const noexcept
2186	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2187
2188      template<typename _Protocol>
2189	int
2190	name(const _Protocol& __p) const noexcept
2191	{ return __p.family() == AF_INET6 ? IPV6_UNICAST_HOPS : IP_TTL; }
2192    };
2193  } // namespace unicast
2194
2195  namespace multicast
2196  {
2197    /// Request that a socket joins a multicast group.
2198    struct join_group
2199    {
2200      explicit
2201      join_group(const address&);
2202
2203      explicit
2204      join_group(const address_v4&, const address_v4& = address_v4::any());
2205
2206      explicit
2207      join_group(const address_v6&, unsigned int = 0);
2208
2209      template<typename _Protocol>
2210	int
2211	level(const _Protocol& __p) const noexcept
2212	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2213
2214      template<typename _Protocol>
2215	int
2216	name(const _Protocol& __p) const noexcept
2217	{
2218	  return __p.family() == AF_INET6
2219	    ? IPV6_JOIN_GROUP : IP_ADD_MEMBERSHIP;
2220	}
2221      template<typename _Protocol>
2222	void*
2223	data(const _Protocol&) noexcept
2224	{ return std::addressof(_M_value); }
2225
2226      template<typename _Protocol>
2227	const void*
2228	data(const _Protocol&) const noexcept
2229	{ return std::addressof(_M_value); }
2230
2231      template<typename _Protocol>
2232	size_t
2233	size(const _Protocol& __p) const noexcept
2234	{
2235	  return __p.family() == AF_INET6
2236	    ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2237	}
2238
2239      template<typename _Protocol>
2240	void
2241	resize(const _Protocol& __p, size_t __s)
2242	{
2243	  if (__s != size(__p))
2244	    __throw_length_error("invalid value for socket option resize");
2245	}
2246
2247    protected:
2248      union
2249      {
2250	ipv6_mreq _M_v6;
2251	ip_mreq _M_v4;
2252      } _M_value;
2253    };
2254
2255    /// Request that a socket leaves a multicast group.
2256    struct leave_group
2257    {
2258      explicit
2259      leave_group(const address&);
2260
2261      explicit
2262      leave_group(const address_v4&, const address_v4& = address_v4::any());
2263
2264      explicit
2265      leave_group(const address_v6&, unsigned int = 0);
2266
2267      template<typename _Protocol>
2268	int
2269	level(const _Protocol& __p) const noexcept
2270	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2271
2272      template<typename _Protocol>
2273	int
2274	name(const _Protocol& __p) const noexcept
2275	{
2276	  return __p.family() == AF_INET6
2277	    ? IPV6_LEAVE_GROUP : IP_DROP_MEMBERSHIP;
2278	}
2279      template<typename _Protocol>
2280	void*
2281	data(const _Protocol&) noexcept
2282	{ return std::addressof(_M_value); }
2283
2284      template<typename _Protocol>
2285	const void*
2286	data(const _Protocol&) const noexcept
2287	{ return std::addressof(_M_value); }
2288
2289      template<typename _Protocol>
2290	size_t
2291	size(const _Protocol& __p) const noexcept
2292	{
2293	  return __p.family() == AF_INET6
2294	    ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2295	}
2296
2297      template<typename _Protocol>
2298	void
2299	resize(const _Protocol& __p, size_t __s)
2300	{
2301	  if (__s != size(__p))
2302	    __throw_length_error("invalid value for socket option resize");
2303	}
2304
2305    protected:
2306      union
2307      {
2308	ipv6_mreq _M_v6;
2309	ip_mreq _M_v4;
2310      } _M_value;
2311    };
2312
2313    /// Specify the network interface for outgoing multicast datagrams.
2314    class outbound_interface
2315    {
2316      explicit
2317      outbound_interface(const address_v4&);
2318
2319      explicit
2320      outbound_interface(unsigned int);
2321
2322      template<typename _Protocol>
2323	int
2324	level(const _Protocol& __p) const noexcept
2325	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2326
2327      template<typename _Protocol>
2328	int
2329	name(const _Protocol& __p) const noexcept
2330	{
2331	  return __p.family() == AF_INET6
2332	    ? IPV6_MULTICAST_IF : IP_MULTICAST_IF;
2333	}
2334
2335      template<typename _Protocol>
2336	const void*
2337	data(const _Protocol&) const noexcept
2338	{ return std::addressof(_M_value); }
2339
2340      template<typename _Protocol>
2341	size_t
2342	size(const _Protocol& __p) const noexcept
2343	{
2344	  return __p.family() == AF_INET6
2345	    ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2346	}
2347
2348    protected:
2349      union {
2350	unsigned _M_v6;
2351	in_addr _M_v4;
2352      } _M_value;
2353    };
2354
2355    /// Set the default number of hops (TTL) for outbound datagrams.
2356    struct hops : __sockopt_crtp<hops>
2357    {
2358      using __sockopt_crtp::__sockopt_crtp;
2359
2360      template<typename _Protocol>
2361	int
2362	level(const _Protocol& __p) const noexcept
2363	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2364
2365      template<typename _Protocol>
2366	int
2367	name(const _Protocol& __p) const noexcept
2368	{
2369	  return __p.family() == AF_INET6
2370	    ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL;
2371	}
2372    };
2373
2374    /// Set whether datagrams are delivered back to the local application.
2375    struct enable_loopback : __sockopt_crtp<enable_loopback>
2376    {
2377      using __sockopt_crtp::__sockopt_crtp;
2378
2379      template<typename _Protocol>
2380	int
2381	level(const _Protocol& __p) const noexcept
2382	{ return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2383
2384      template<typename _Protocol>
2385	int
2386	name(const _Protocol& __p) const noexcept
2387	{
2388	  return __p.family() == AF_INET6
2389	    ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP;
2390	}
2391    };
2392
2393  } // namespace multicast
2394
2395  /// @}
2396
2397} // namespace ip
2398} // namespace v1
2399} // namespace net
2400} // namespace experimental
2401
2402  template<>
2403    struct is_error_condition_enum<experimental::net::v1::ip::resolver_errc>
2404    : public true_type {};
2405
2406  // hash support
2407  template<typename _Tp> struct hash;
2408  template<>
2409    struct hash<experimental::net::v1::ip::address>
2410    : __hash_base<size_t, experimental::net::v1::ip::address>
2411    {
2412      size_t
2413      operator()(const argument_type& __a) const
2414      {
2415	if (__a.is_v4())
2416	  return _Hash_impl::hash(__a.to_v4());
2417	else
2418	  return _Hash_impl::hash(__a.to_v6());
2419      }
2420    };
2421
2422  template<>
2423    struct hash<experimental::net::v1::ip::address_v4>
2424    : __hash_base<size_t, experimental::net::v1::ip::address_v4>
2425    {
2426      size_t
2427      operator()(const argument_type& __a) const
2428      { return _Hash_impl::hash(__a.to_bytes()); }
2429    };
2430
2431  template<> struct hash<experimental::net::v1::ip::address_v6>
2432    : __hash_base<size_t, experimental::net::v1::ip::address_v6>
2433    {
2434      size_t
2435      operator()(const argument_type& __a) const
2436      { return _Hash_impl::hash(__a.to_bytes()); }
2437    };
2438
2439_GLIBCXX_END_NAMESPACE_VERSION
2440} // namespace std
2441
2442#endif // C++14
2443
2444#endif // _GLIBCXX_EXPERIMENTAL_INTERNET
2445