1 // <experimental/internet> -*- C++ -*-
3 // Copyright (C) 2015-2019 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 /** @file experimental/internet
26 * This is a TS C++ Library header.
29 #ifndef _GLIBCXX_EXPERIMENTAL_INTERNET
30 #define _GLIBCXX_EXPERIMENTAL_INTERNET
32 #pragma GCC system_header
34 #if __cplusplus >= 201402L
36 #include <experimental/netfwd>
37 #include <experimental/io_context>
38 #include <experimental/bits/net.h>
40 #include <forward_list>
43 #include <experimental/string_view>
44 #ifdef _GLIBCXX_HAVE_UNISTD_H
47 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
48 # include <sys/socket.h> // AF_INET, AF_INET6, SOCK_DGRAM, SOCK_STREAM
50 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
51 # include <arpa/inet.h> // inet_ntop
53 #ifdef _GLIBCXX_HAVE_NETINET_TCP_H
54 # include <netinet/tcp.h> // TCP_NODELAY
56 #ifdef _GLIBCXX_HAVE_NETDB_H
57 # include <netdb.h> // getaddrinfo etc.
60 namespace std _GLIBCXX_VISIBILITY(default)
62 _GLIBCXX_BEGIN_NAMESPACE_VERSION
63 namespace experimental
77 #ifdef _GLIBCXX_HAVE_NETDB_H
78 /** Error codes for resolver errors.
82 enum class resolver_errc : int {
83 host_not_found = EAI_NONAME,
84 host_not_found_try_again = EAI_AGAIN,
85 service_not_found = EAI_SERVICE
88 /// Error category for resolver errors.
89 inline const error_category& resolver_category() noexcept // TODO non-inline
91 struct __cat : error_category
93 const char* name() const noexcept { return "resolver"; }
94 std::string message(int __e) const { return ::gai_strerror(__e); }
95 virtual void __message(int) { } // TODO dual ABI XXX
101 error_code make_error_code(resolver_errc __e) noexcept
102 { return error_code(static_cast<int>(__e), resolver_category()); }
104 error_condition make_error_condition(resolver_errc __e) noexcept
105 { return error_condition(static_cast<int>(__e), resolver_category()); }
110 typedef uint_least16_t port_type; ///< Type used for port numbers.
111 typedef uint_least32_t scope_id_type; ///< Type used for IPv6 scope IDs.
113 /// Convenience alias for constraining allocators for strings.
114 template<typename _Alloc>
116 = enable_if_t<std::is_same<typename _Alloc::value_type, char>::value,
117 std::basic_string<char, std::char_traits<char>, _Alloc>>;
119 /** Tag indicating conversion between IPv4 and IPv4-mapped IPv6 addresses.
123 struct v4_mapped_t {};
124 constexpr v4_mapped_t v4_mapped;
133 typedef uint_least32_t uint_type;
135 struct bytes_type : array<unsigned char, 4>
137 template<typename... _Tp>
139 bytes_type(_Tp... __tp)
140 : array<unsigned char, 4>{{static_cast<unsigned char>(__tp)...}}
143 for (auto __b : *this)
145 __throw_out_of_range("invalid address_v4::bytes_type value");
151 constexpr address_v4() noexcept : _M_addr(0) { }
153 constexpr address_v4(const address_v4& a) noexcept = default;
156 address_v4(const bytes_type& __b)
157 : _M_addr((__b[0] << 24) | (__b[1] << 16) | (__b[2] << 8) | __b[3])
161 address_v4(uint_type __val) : _M_addr(_S_hton_32(__val))
163 #if UINT_LEAST32_MAX > 0xFFFFFFFF
164 if (__val > 0xFFFFFFFF)
165 __throw_out_of_range("invalid address_v4::uint_type value");
170 address_v4& operator=(const address_v4& a) noexcept = default;
173 constexpr bool is_unspecified() const noexcept { return to_uint() == 0; }
176 is_loopback() const noexcept
177 { return (to_uint() & 0xFF000000) == 0x7F000000; }
180 is_multicast() const noexcept
181 { return (to_uint() & 0xF0000000) == 0xE0000000; }
184 to_bytes() const noexcept
187 (_M_addr >> 24) & 0xFF,
188 (_M_addr >> 16) & 0xFF,
189 (_M_addr >> 8) & 0xFF,
195 to_uint() const noexcept { return _S_ntoh_32(_M_addr); }
197 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
198 template<typename _Allocator = allocator<char>>
199 __string_with<_Allocator>
200 to_string(const _Allocator& __a = _Allocator()) const
202 __string_with<_Allocator> __str(__a);
203 __str.resize(INET6_ADDRSTRLEN);
204 if (inet_ntop(AF_INET, &_M_addr, &__str.front(), __str.size()))
205 __str.erase(__str.find('\0'));
213 static constexpr address_v4 any() noexcept { return address_v4{}; }
216 address_v4 loopback() noexcept { return address_v4{0x7F000001}; }
219 address_v4 broadcast() noexcept { return address_v4{0xFFFFFFFF}; }
222 template<typename _InternetProtocol>
223 friend class basic_endpoint;
225 friend address_v4 make_address_v4(const char*, error_code&) noexcept;
227 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
228 static constexpr uint16_t _S_hton_16(uint16_t __h) { return __h; }
229 static constexpr uint16_t _S_ntoh_16(uint16_t __n) { return __n; }
230 static constexpr uint32_t _S_hton_32(uint32_t __h) { return __h; }
231 static constexpr uint32_t _S_ntoh_32(uint32_t __n) { return __n; }
233 static constexpr uint16_t
234 _S_hton_16(uint16_t __h) { return __builtin_bswap16(__h); }
236 static constexpr uint16_t
237 _S_ntoh_16(uint16_t __n) { return __builtin_bswap16(__n); }
239 static constexpr uint32_t
240 _S_hton_32(uint32_t __h) { return __builtin_bswap32(__h); }
242 static constexpr uint32_t
243 _S_ntoh_32(uint32_t __n) { return __builtin_bswap32(__n); }
246 in_addr_t _M_addr; // network byte order
254 struct bytes_type : array<unsigned char, 16>
256 template<typename... _Tp> explicit constexpr bytes_type(_Tp... __t)
257 : array<unsigned char, 16>{{static_cast<unsigned char>(__t)...}} { }
261 constexpr address_v6() noexcept : _M_bytes(), _M_scope_id() { }
263 constexpr address_v6(const address_v6& __a) noexcept = default;
266 address_v6(const bytes_type& __bytes, scope_id_type __scope = 0)
267 : _M_bytes(__bytes), _M_scope_id(__scope)
271 address_v6& operator=(const address_v6& __a) noexcept = default;
274 void scope_id(scope_id_type __id) noexcept { _M_scope_id = __id; }
276 constexpr scope_id_type scope_id() const noexcept { return _M_scope_id; }
279 is_unspecified() const noexcept
281 for (int __i = 0; __i < 16; ++__i)
282 if (_M_bytes[__i] != 0x00)
284 return _M_scope_id == 0;
288 is_loopback() const noexcept
290 for (int __i = 0; __i < 15; ++__i)
291 if (_M_bytes[__i] != 0x00)
293 return _M_bytes[15] == 0x01 && _M_scope_id == 0;
297 is_multicast() const noexcept { return _M_bytes[0] == 0xFF; }
300 is_link_local() const noexcept
301 { return _M_bytes[0] == 0xFE && (_M_bytes[1] & 0xC0) == 0x80; }
304 is_site_local() const noexcept
305 { return _M_bytes[0] == 0xFE && (_M_bytes[1] & 0xC0) == 0xC0; }
308 is_v4_mapped() const noexcept
310 const bytes_type& __b = _M_bytes;
311 return __b[0] == 0 && __b[1] == 0 && __b[ 2] == 0 && __b[ 3] == 0
312 && __b[4] == 0 && __b[5] == 0 && __b[ 6] == 0 && __b[ 7] == 0
313 && __b[8] == 0 && __b[9] == 0 && __b[10] == 0xFF && __b[11] == 0xFF;
317 is_multicast_node_local() const noexcept
318 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x01; }
321 is_multicast_link_local() const noexcept
322 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x02; }
325 is_multicast_site_local() const noexcept
326 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x05; }
329 is_multicast_org_local() const noexcept
330 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x08; }
333 is_multicast_global() const noexcept
334 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x0b; }
336 constexpr bytes_type to_bytes() const noexcept { return _M_bytes; }
338 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
339 template<typename _Allocator = allocator<char>>
340 __string_with<_Allocator>
341 to_string(const _Allocator& __a = _Allocator()) const
343 __string_with<_Allocator> __str(__a);
344 __str.resize(INET6_ADDRSTRLEN);
345 if (inet_ntop(AF_INET6, &_M_bytes, &__str.front(), __str.size()))
346 __str.erase(__str.find('\0'));
354 static constexpr address_v6
358 __builtin_memcpy(&__addr._M_bytes, in6addr_any.s6_addr, 16);
362 static constexpr address_v6
366 __builtin_memcpy(&__addr._M_bytes, in6addr_loopback.s6_addr, 16);
371 template<typename _InternetProtocol>
372 friend class basic_endpoint;
374 friend constexpr bool
375 operator==(const address_v6&, const address_v6&) noexcept;
377 friend constexpr bool
378 operator< (const address_v6&, const address_v6&) noexcept;
381 scope_id_type _M_scope_id;
384 /// Exception type thrown on misuse of IPv4 addresses as IPv6 or vice versa.
385 class bad_address_cast : public bad_cast
388 bad_address_cast() { }
390 const char* what() const noexcept { return "bad address cast"; }
393 /// An IPv4 or IPv6 address.
398 constexpr address() noexcept : _M_v4(), _M_is_v4(true) { }
401 address(const address& __a) noexcept : _M_uninit(), _M_is_v4(__a._M_is_v4)
404 ::new (std::addressof(_M_v4)) address_v4(__a.to_v4());
406 ::new (std::addressof(_M_v6)) address_v6(__a.to_v6());
410 address(const address_v4& __a) noexcept : _M_v4(__a), _M_is_v4(true) { }
413 address(const address_v6& __a) noexcept : _M_v6(__a), _M_is_v4(false) { }
417 operator=(const address& __a) noexcept
427 operator=(const address_v4& __a) noexcept
429 ::new (std::addressof(_M_v4)) address_v4(__a);
435 operator=(const address_v6& __a) noexcept
437 ::new (std::addressof(_M_v6)) address_v6(__a);
444 constexpr bool is_v4() const noexcept { return _M_is_v4; }
445 constexpr bool is_v6() const noexcept { return !_M_is_v4; }
451 _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
459 _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
464 is_unspecified() const noexcept
465 { return _M_is_v4 ? _M_v4.is_unspecified() : _M_v6.is_unspecified(); }
468 is_loopback() const noexcept
469 { return _M_is_v4 ? _M_v4.is_loopback() : _M_v6.is_loopback(); }
472 is_multicast() const noexcept
473 { return _M_is_v4 ? _M_v4.is_multicast() : _M_v6.is_multicast(); }
475 template<typename _Allocator = allocator<char>>
476 __string_with<_Allocator>
477 to_string(const _Allocator& __a = _Allocator()) const
480 return to_v4().to_string(__a);
481 return to_v6().to_string(__a);
485 template<typename _InternetProtocol>
486 friend class basic_endpoint;
488 friend constexpr bool
489 operator==(const address&, const address&) noexcept;
491 friend constexpr bool
492 operator<(const address&, const address&) noexcept;
502 /** ip::address_v4 comparisons
507 operator==(const address_v4& __a, const address_v4& __b) noexcept
508 { return __a.to_uint() == __b.to_uint(); }
511 operator!=(const address_v4& __a, const address_v4& __b) noexcept
512 { return !(__a == __b); }
515 operator< (const address_v4& __a, const address_v4& __b) noexcept
516 { return __a.to_uint() < __b.to_uint(); }
519 operator> (const address_v4& __a, const address_v4& __b) noexcept
520 { return __b < __a; }
523 operator<=(const address_v4& __a, const address_v4& __b) noexcept
524 { return !(__b < __a); }
527 operator>=(const address_v4& __a, const address_v4& __b) noexcept
528 { return !(__a < __b); }
532 /** ip::address_v6 comparisons
537 operator==(const address_v6& __a, const address_v6& __b) noexcept
539 const auto& __aa = __a._M_bytes;
540 const auto& __bb = __b._M_bytes;
542 for (; __aa[__i] == __bb[__i] && __i < 16; ++__i)
544 return __i == 16 ? __a.scope_id() == __b.scope_id() : false;
548 operator!=(const address_v6& __a, const address_v6& __b) noexcept
549 { return !(__a == __b); }
552 operator< (const address_v6& __a, const address_v6& __b) noexcept
554 const auto& __aa = __a._M_bytes;
555 const auto& __bb = __b._M_bytes;
557 for (; __aa[__i] == __bb[__i] && __i < 16; ++__i)
559 return __i == 16 ? __a.scope_id() < __b.scope_id() : __aa[__i] < __bb[__i];
563 operator> (const address_v6& __a, const address_v6& __b) noexcept
564 { return __b < __a; }
567 operator<=(const address_v6& __a, const address_v6& __b) noexcept
568 { return !(__b < __a); }
571 operator>=(const address_v6& __a, const address_v6& __b) noexcept
572 { return !(__a < __b); }
576 /** ip::address comparisons
581 operator==(const address& __a, const address& __b) noexcept
584 return __b.is_v4() ? __a._M_v4 == __b._M_v4 : false;
585 return __b.is_v4() ? false : __a._M_v6 == __b._M_v6;
589 operator!=(const address& __a, const address& __b) noexcept
590 { return !(__a == __b); }
593 operator< (const address& __a, const address& __b) noexcept
596 return __b.is_v4() ? __a._M_v4 < __b._M_v4 : true;
597 return __b.is_v4() ? false : __a._M_v6 < __b._M_v6;
601 operator> (const address& __a, const address& __b) noexcept
602 { return __b < __a; }
605 operator<=(const address& __a, const address& __b) noexcept
606 { return !(__b < __a); }
609 operator>=(const address& __a, const address& __b) noexcept
610 { return !(__a < __b); }
614 /** ip::address_v4 creation
619 make_address_v4(const address_v4::bytes_type& __b)
620 { return address_v4{__b}; }
623 make_address_v4(address_v4::uint_type __val)
624 { return address_v4{__val}; }
627 make_address_v4(v4_mapped_t, const address_v6& __a)
629 if (!__a.is_v4_mapped())
630 _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
632 const auto __v6b = __a.to_bytes();
633 return address_v4::bytes_type(__v6b[12], __v6b[13], __v6b[14], __v6b[15]);
637 make_address_v4(const char* __str, error_code& __ec) noexcept
640 const int __res = ::inet_pton(AF_INET, __str, &__a._M_addr);
647 __ec = std::make_error_code(std::errc::invalid_argument);
649 __ec.assign(errno, generic_category());
654 make_address_v4(const char* __str)
655 { return make_address_v4(__str, __throw_on_error{"make_address_v4"}); }
658 make_address_v4(const string& __str, error_code& __ec) noexcept
659 { return make_address_v4(__str.c_str(), __ec); }
662 make_address_v4(const string& __str)
663 { return make_address_v4(__str.c_str()); }
666 make_address_v4(string_view __str, error_code& __ec) noexcept
668 char __buf[INET_ADDRSTRLEN];
669 auto __len = __str.copy(__buf, sizeof(__buf));
670 if (__len == sizeof(__buf))
672 __ec = std::make_error_code(std::errc::invalid_argument);
677 return make_address_v4(__buf, __ec);
681 make_address_v4(string_view __str)
682 { return make_address_v4(__str, __throw_on_error{"make_address_v4"}); }
686 /** ip::address_v6 creation
691 make_address_v6(const address_v6::bytes_type& __b, scope_id_type __scope = 0)
692 { return address_v6{__b, __scope}; }
695 make_address_v6(v4_mapped_t, const address_v4& __a) noexcept
697 const address_v4::bytes_type __v4b = __a.to_bytes();
698 address_v6::bytes_type __v6b(0, 0, 0, 0, 0, 0, 0, 0,
700 __v4b[0], __v4b[1], __v4b[2], __v4b[3]);
701 return address_v6(__v6b);
705 __make_address_v6(const char* __addr, const char* __scope, error_code& __ec)
707 address_v6::bytes_type __b;
708 int __res = ::inet_pton(AF_INET6, __addr, __b.data());
718 unsigned long __val = std::strtoul(__scope, &__eptr, 10);
719 if (__eptr != __scope && !*__eptr
720 && __val <= numeric_limits<scope_id_type>::max())
722 return { __b, static_cast<scope_id_type>(__val) };
724 __ec = std::make_error_code(std::errc::invalid_argument);
727 __ec = std::make_error_code(std::errc::invalid_argument);
729 __ec.assign(errno, generic_category());
734 make_address_v6(const char* __str, error_code& __ec) noexcept
736 auto __p = __builtin_strchr(__str, '%');
738 return __make_address_v6(__str, nullptr, __ec);
741 bool __skip_leading_zero = true;
742 while (__str < __p && __out < std::end(__buf))
744 if (!__skip_leading_zero || *__str != '0')
746 if (*__str == ':' || *__str == '.')
747 __skip_leading_zero = true;
749 __skip_leading_zero = false;
754 if (__out == std::end(__buf))
755 __ec = std::make_error_code(std::errc::invalid_argument);
759 return __make_address_v6(__buf, __p + 1, __ec);
764 make_address_v6(const char* __str)
765 { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
768 make_address_v6(const string& __str, error_code& __ec) noexcept
770 auto __pos = __str.find('%');
771 if (__pos == string::npos)
772 return __make_address_v6(__str.c_str(), nullptr, __ec);
775 bool __skip_leading_zero = true;
777 while (__n < __pos && __out < std::end(__buf))
779 if (!__skip_leading_zero || __str[__n] != '0')
781 if (__str[__n] == ':' || __str[__n] == '.')
782 __skip_leading_zero = true;
784 __skip_leading_zero = false;
789 if (__out == std::end(__buf))
790 __ec = std::make_error_code(std::errc::invalid_argument);
794 return __make_address_v6(__buf, __str.c_str() + __pos + 1, __ec);
799 make_address_v6(const string& __str)
800 { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
803 make_address_v6(string_view __str, error_code& __ec) noexcept
807 char* __scope = nullptr;
808 bool __skip_leading_zero = true;
810 while (__n < __str.length() && __out < std::end(__buf))
812 if (__str[__n] == '%')
815 __out = std::end(__buf);
820 __skip_leading_zero = true;
823 else if (!__skip_leading_zero || __str[__n] != '0')
825 if (__str[__n] == ':' || __str[__n] == '.')
826 __skip_leading_zero = true;
828 __skip_leading_zero = false;
834 if (__out == std::end(__buf))
835 __ec = std::make_error_code(std::errc::invalid_argument);
839 return __make_address_v6(__buf, __scope, __ec);
844 make_address_v6(string_view __str)
845 { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
849 /** ip::address creation
854 make_address(const char* __str, error_code& __ec) noexcept
857 address_v6 __v6a = make_address_v6(__str, __ec);
862 address_v4 __v4a = make_address_v4(__str, __ec);
870 make_address(const char* __str)
871 { return make_address(__str, __throw_on_error{"make_address"}); }
874 make_address(const string& __str, error_code& __ec) noexcept; // TODO
877 make_address(const string& __str)
878 { return make_address(__str, __throw_on_error{"make_address"}); }
881 make_address(string_view __str, error_code& __ec) noexcept
883 if (__str.rfind('\0') != string_view::npos)
884 return make_address(__str.data(), __ec);
885 return make_address(__str.to_string(), __ec); // TODO don't allocate
889 make_address(string_view __str)
890 { return make_address(__str, __throw_on_error{"make_address"}); }
895 template<typename _CharT, typename _Traits>
896 inline basic_ostream<_CharT, _Traits>&
897 operator<<(basic_ostream<_CharT, _Traits>& __os, const address& __a)
898 { return __os << __a.to_string(); }
900 /// ip::address_v4 I/O
901 template<typename _CharT, typename _Traits>
902 inline basic_ostream<_CharT, _Traits>&
903 operator<<(basic_ostream<_CharT, _Traits>& __os, const address_v4& __a)
904 { return __os << __a.to_string(); }
906 /// ip::address_v6 I/O
907 template<typename _CharT, typename _Traits>
908 inline basic_ostream<_CharT, _Traits>&
909 operator<<(basic_ostream<_CharT, _Traits>& __os, const address_v6& __a)
910 { return __os << __a.to_string(); }
912 template<typename> class basic_address_iterator; // not defined
914 template<> class basic_address_iterator<address_v4>
918 typedef address_v4 value_type;
919 typedef ptrdiff_t difference_type;
920 typedef const address_v4* pointer;
921 typedef const address_v4& reference;
922 typedef input_iterator_tag iterator_category;
925 basic_address_iterator(const address_v4& __a) noexcept
926 : _M_address(__a) { }
929 reference operator*() const noexcept { return _M_address; }
930 pointer operator->() const noexcept { return &_M_address; }
932 basic_address_iterator&
933 operator++() noexcept
935 _M_address = value_type(_M_address.to_uint() + 1);
939 basic_address_iterator operator++(int) noexcept
946 basic_address_iterator& operator--() noexcept
948 _M_address = value_type(_M_address.to_uint() - 1);
952 basic_address_iterator
953 operator--(int) noexcept
961 operator==(const basic_address_iterator& __rhs) const noexcept
962 { return _M_address == __rhs._M_address; }
965 operator!=(const basic_address_iterator& __rhs) const noexcept
966 { return _M_address != __rhs._M_address; }
969 address_v4 _M_address;
972 typedef basic_address_iterator<address_v4> address_v4_iterator;
974 template<> class basic_address_iterator<address_v6>
978 typedef address_v6 value_type;
979 typedef ptrdiff_t difference_type;
980 typedef const address_v6* pointer;
981 typedef const address_v6& reference;
982 typedef input_iterator_tag iterator_category;
985 basic_address_iterator(const address_v6& __a) noexcept
986 : _M_address(__a) { }
989 reference operator*() const noexcept { return _M_address; }
990 pointer operator->() const noexcept { return &_M_address; }
992 basic_address_iterator&
993 operator++() noexcept; // TODO
995 basic_address_iterator
996 operator++(int) noexcept
1003 basic_address_iterator&
1004 operator--() noexcept; // TODO
1006 basic_address_iterator
1007 operator--(int) noexcept
1015 operator==(const basic_address_iterator& __rhs) const noexcept
1016 { return _M_address == __rhs._M_address; }
1019 operator!=(const basic_address_iterator& __rhs) const noexcept
1020 { return _M_address != __rhs._M_address; }
1023 address_v6 _M_address;
1026 typedef basic_address_iterator<address_v6> address_v6_iterator;
1028 template<typename> class basic_address_range; // not defined
1030 /** An IPv6 address range.
1034 template<> class basic_address_range<address_v4>
1039 typedef basic_address_iterator<address_v4> iterator;
1043 basic_address_range() noexcept : _M_begin({}), _M_end({}) { }
1045 basic_address_range(const address_v4& __first,
1046 const address_v4& __last) noexcept
1047 : _M_begin(__first), _M_end(__last) { }
1051 iterator begin() const noexcept { return _M_begin; }
1052 iterator end() const noexcept { return _M_end; }
1053 _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_begin == _M_end; }
1056 size() const noexcept { return _M_end->to_uint() - _M_begin->to_uint(); }
1059 find(const address_v4& __addr) const noexcept
1061 if (*_M_begin <= __addr && __addr < *_M_end)
1062 return iterator{__addr};
1071 typedef basic_address_range<address_v4> address_v4_range;
1075 /** An IPv6 address range.
1079 template<> class basic_address_range<address_v6>
1084 typedef basic_address_iterator<address_v6> iterator;
1088 basic_address_range() noexcept : _M_begin({}), _M_end({}) { }
1089 basic_address_range(const address_v6& __first,
1090 const address_v6& __last) noexcept
1091 : _M_begin(__first), _M_end(__last) { }
1095 iterator begin() const noexcept { return _M_begin; }
1096 iterator end() const noexcept { return _M_end; }
1097 _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_begin == _M_end; }
1100 find(const address_v6& __addr) const noexcept
1102 if (*_M_begin <= __addr && __addr < *_M_end)
1103 return iterator{__addr};
1112 typedef basic_address_range<address_v6> address_v6_range;
1115 operator==(const network_v4& __a, const network_v4& __b) noexcept;
1118 operator==(const network_v6& __a, const network_v6& __b) noexcept;
1122 /// An IPv4 network address.
1127 constexpr network_v4() noexcept : _M_addr(), _M_prefix_len(0) { }
1130 network_v4(const address_v4& __addr, int __prefix_len)
1131 : _M_addr(__addr), _M_prefix_len(__prefix_len)
1133 if (_M_prefix_len < 0 || _M_prefix_len > 32)
1134 __throw_out_of_range("network_v4: invalid prefix length");
1138 network_v4(const address_v4& __addr, const address_v4& __mask)
1139 : _M_addr(__addr), _M_prefix_len(__builtin_popcount(__mask.to_uint()))
1141 if (_M_prefix_len != 0)
1143 address_v4::uint_type __mask_uint = __mask.to_uint();
1144 if (__builtin_ctz(__mask_uint) != (32 - _M_prefix_len))
1145 __throw_invalid_argument("network_v4: invalid mask");
1146 if ((__mask_uint & 0x80000000) == 0)
1147 __throw_invalid_argument("network_v4: invalid mask");
1153 constexpr address_v4 address() const noexcept { return _M_addr; }
1154 constexpr int prefix_length() const noexcept { return _M_prefix_len; }
1156 constexpr address_v4
1157 netmask() const noexcept
1159 address_v4::uint_type __val = address_v4::broadcast().to_uint();
1160 __val >>= (32 - _M_prefix_len);
1161 __val <<= (32 - _M_prefix_len);
1162 return address_v4{__val};
1165 constexpr address_v4
1166 network() const noexcept
1167 { return address_v4{_M_addr.to_uint() & netmask().to_uint()}; }
1169 constexpr address_v4
1170 broadcast() const noexcept
1171 { return address_v4{_M_addr.to_uint() | ~netmask().to_uint()}; }
1174 hosts() const noexcept
1177 return { address(), *++address_v4_iterator(address()) };
1178 return { network(), broadcast() };
1181 constexpr network_v4
1182 canonical() const noexcept
1183 { return network_v4(network(), prefix_length()); }
1185 constexpr bool is_host() const noexcept { return _M_prefix_len == 32; }
1188 is_subnet_of(const network_v4& __other) const noexcept
1190 if (__other.prefix_length() < prefix_length())
1192 network_v4 __net(address(), __other.prefix_length());
1193 return __net.canonical() == __other.canonical();
1198 template<typename _Allocator = allocator<char>>
1199 __string_with<_Allocator>
1200 to_string(const _Allocator& __a = _Allocator()) const
1202 return address().to_string(__a) + '/'
1203 + std::to_string(prefix_length());
1211 /// An IPv6 network address.
1216 constexpr network_v6() noexcept : _M_addr(), _M_prefix_len(0) { }
1219 network_v6(const address_v6& __addr, int __prefix_len)
1220 : _M_addr(__addr), _M_prefix_len(__prefix_len)
1222 if (_M_prefix_len < 0 || _M_prefix_len > 128)
1223 __throw_out_of_range("network_v6: invalid prefix length");
1227 constexpr address_v6 address() const noexcept { return _M_addr; }
1228 constexpr int prefix_length() const noexcept { return _M_prefix_len; }
1230 constexpr address_v6 network() const noexcept; // TODO
1233 hosts() const noexcept
1236 return { address(), *++address_v6_iterator(address()) };
1237 return {}; // { network(), XXX broadcast() XXX }; // TODO
1240 constexpr network_v6
1241 canonical() const noexcept
1242 { return network_v6{network(), prefix_length()}; }
1244 constexpr bool is_host() const noexcept { return _M_prefix_len == 128; }
1247 is_subnet_of(const network_v6& __other) const noexcept
1249 if (__other.prefix_length() < prefix_length())
1251 network_v6 __net(address(), __other.prefix_length());
1252 return __net.canonical() == __other.canonical();
1257 template<typename _Allocator = allocator<char>>
1258 __string_with<_Allocator>
1259 to_string(const _Allocator& __a = _Allocator()) const
1261 return address().to_string(__a) + '/'
1262 + std::to_string(prefix_length());
1271 /** ip::network_v4 comparisons
1276 operator==(const network_v4& __a, const network_v4& __b) noexcept
1278 return __a.address() == __b.address()
1279 && __a.prefix_length() == __b.prefix_length();
1283 operator!=(const network_v4& __a, const network_v4& __b) noexcept
1284 { return !(__a == __b); }
1288 /** ip::network_v6 comparisons
1293 operator==(const network_v6& __a, const network_v6& __b) noexcept
1295 return __a.address() == __b.address()
1296 && __a.prefix_length() == __b.prefix_length();
1300 operator!=(const network_v6& __a, const network_v6& __b) noexcept
1301 { return !(__a == __b); }
1305 /** ip::network_v4 creation
1310 make_network_v4(const address_v4& __a, int __prefix_len)
1311 { return network_v4{__a, __prefix_len}; }
1314 make_network_v4(const address_v4& __a, const address_v4& __mask)
1315 { return network_v4{ __a, __mask }; }
1317 network_v4 make_network_v4(const char*, error_code&) noexcept; // TODO
1320 make_network_v4(const char* __str)
1321 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1323 network_v4 make_network_v4(const string&, error_code&) noexcept; // TODO
1326 make_network_v4(const string& __str)
1327 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1329 network_v4 make_network_v4(string_view, error_code&) noexcept; // TODO
1332 make_network_v4(string_view __str)
1333 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1337 /** ip::network_v6 creation
1342 make_network_v6(const address_v6& __a, int __prefix_len)
1343 { return network_v6{__a, __prefix_len}; }
1345 network_v6 make_network_v6(const char*, error_code&) noexcept; // TODO
1348 make_network_v6(const char* __str)
1349 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1351 network_v6 make_network_v6(const string&, error_code&) noexcept; // TODO
1354 make_network_v6(const string& __str)
1355 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1357 network_v6 make_network_v6(string_view, error_code&) noexcept; // TODO
1360 make_network_v6(string_view __str)
1361 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1365 /// ip::network_v4 I/O
1366 template<typename _CharT, typename _Traits>
1367 inline basic_ostream<_CharT, _Traits>&
1368 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v4& __net)
1369 { return __os << __net.to_string(); }
1371 /// ip::network_v6 I/O
1372 template<typename _CharT, typename _Traits>
1373 inline basic_ostream<_CharT, _Traits>&
1374 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v6& __net)
1375 { return __os << __net.to_string(); }
1378 template<typename _InternetProtocol>
1379 class basic_endpoint
1383 typedef _InternetProtocol protocol_type;
1388 basic_endpoint() noexcept : _M_data()
1389 { _M_data._M_v4.sin_family = protocol_type::v4().family(); }
1392 basic_endpoint(const protocol_type& __proto,
1393 port_type __port_num) noexcept
1396 __glibcxx_assert(__proto == protocol_type::v4()
1397 || __proto == protocol_type::v6());
1399 _M_data._M_v4.sin_family = __proto.family();
1400 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
1404 basic_endpoint(const ip::address& __addr,
1405 port_type __port_num) noexcept
1410 _M_data._M_v4.sin_family = protocol_type::v4().family();
1411 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
1412 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
1417 _M_data._M_v6.sin6_family = protocol_type::v6().family();
1418 _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num);
1419 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
1420 __addr._M_v6._M_bytes.data(), 16);
1421 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
1426 constexpr protocol_type protocol() const noexcept
1428 return _M_data._M_v4.sin_family == AF_INET6
1429 ? protocol_type::v6() : protocol_type::v4();
1432 constexpr ip::address
1433 address() const noexcept
1436 if (protocol().family() == AF_INET6)
1438 __builtin_memcpy(&__addr._M_v6._M_bytes,
1439 _M_data._M_v6.sin6_addr.s6_addr, 16);
1440 __addr._M_is_v4 = false;
1444 __builtin_memcpy(&__addr._M_v4._M_addr,
1445 &_M_data._M_v4.sin_addr.s_addr, 4);
1451 address(const ip::address& __addr) noexcept
1456 _M_data._M_v6.sin6_family = protocol_type::v6().family();
1457 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
1458 __addr._M_v6._M_bytes.data(), 16);
1459 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
1463 _M_data._M_v4.sin_family = protocol_type::v4().family();
1464 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
1469 port() const noexcept
1470 { return address_v4::_S_ntoh_16(_M_data._M_v4.sin_port); }
1473 port(port_type __port_num) noexcept
1474 { _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); }
1476 void* data() noexcept { return &_M_data; }
1477 const void* data() const noexcept { return &_M_data; }
1478 constexpr size_t size() const noexcept
1480 return protocol().family() == AF_INET6
1481 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);
1487 if ((protocol().family() == AF_INET6 && __s != sizeof(sockaddr_in6))
1488 || (protocol().family() == AF_INET && __s != sizeof(sockaddr_in)))
1489 __throw_length_error("net::ip::basic_endpoint::resize");
1492 constexpr size_t capacity() const noexcept { return sizeof(_M_data); }
1502 /** basic_endpoint comparisons
1506 template<typename _InternetProtocol>
1508 operator==(const basic_endpoint<_InternetProtocol>& __a,
1509 const basic_endpoint<_InternetProtocol>& __b)
1510 { return __a.address() == __b.address() && __a.port() == __b.port(); }
1512 template<typename _InternetProtocol>
1514 operator!=(const basic_endpoint<_InternetProtocol>& __a,
1515 const basic_endpoint<_InternetProtocol>& __b)
1516 { return !(__a == __b); }
1518 template<typename _InternetProtocol>
1520 operator< (const basic_endpoint<_InternetProtocol>& __a,
1521 const basic_endpoint<_InternetProtocol>& __b)
1523 return __a.address() < __b.address()
1524 || (!(__b.address() < __a.address()) && __a.port() < __b.port());
1527 template<typename _InternetProtocol>
1529 operator> (const basic_endpoint<_InternetProtocol>& __a,
1530 const basic_endpoint<_InternetProtocol>& __b)
1531 { return __b < __a; }
1533 template<typename _InternetProtocol>
1535 operator<=(const basic_endpoint<_InternetProtocol>& __a,
1536 const basic_endpoint<_InternetProtocol>& __b)
1537 { return !(__b < __a); }
1539 template<typename _InternetProtocol>
1541 operator>=(const basic_endpoint<_InternetProtocol>& __a,
1542 const basic_endpoint<_InternetProtocol>& __b)
1543 { return !(__a < __b); }
1547 /// basic_endpoint I/O
1548 template<typename _CharT, typename _Traits, typename _InternetProtocol>
1549 inline basic_ostream<_CharT, _Traits>&
1550 operator<<(basic_ostream<_CharT, _Traits>& __os,
1551 const basic_endpoint<_InternetProtocol>& __ep)
1553 basic_ostringstream<_CharT, _Traits> __ss;
1555 == basic_endpoint<_InternetProtocol>::protocol_type::v6())
1556 __ss << '[' << __ep.address() << ']';
1558 __ss << __ep.address();
1559 __ss << ':' << __ep.port();
1564 /** Type representing a single result of name/address resolution.
1568 template<typename _InternetProtocol>
1569 class basic_resolver_entry
1573 typedef _InternetProtocol protocol_type;
1574 typedef typename _InternetProtocol::endpoint endpoint_type;
1577 basic_resolver_entry() { }
1579 basic_resolver_entry(const endpoint_type& __ep,
1580 string_view __h, string_view __s)
1581 : _M_ep(__ep), _M_host(__h), _M_svc(__s) { }
1584 endpoint_type endpoint() const { return _M_ep; }
1585 operator endpoint_type() const { return _M_ep; }
1587 template<typename _Allocator = allocator<char>>
1588 __string_with<_Allocator>
1589 host_name(const _Allocator& __a = _Allocator()) const
1590 { return { _M_host, __a }; }
1592 template<typename _Allocator = allocator<char>>
1593 __string_with<_Allocator>
1594 service_name(const _Allocator& __a = _Allocator()) const
1595 { return { _M_svc, __a }; }
1598 basic_endpoint<_InternetProtocol> _M_ep;
1603 template<typename _InternetProtocol>
1605 operator==(const basic_resolver_entry<_InternetProtocol>& __a,
1606 const basic_resolver_entry<_InternetProtocol>& __b)
1608 return __a.endpoint() == __b.endpoint()
1609 && __a.host_name() == __b.host_name()
1610 && __a.service_name() == __b.service_name();
1613 template<typename _InternetProtocol>
1615 operator!=(const basic_resolver_entry<_InternetProtocol>& __a,
1616 const basic_resolver_entry<_InternetProtocol>& __b)
1617 { return !(__a == __b); }
1621 /** Base class defining flags for name/address resolution.
1630 __flags_passive = AI_PASSIVE,
1631 __flags_canonical_name = AI_CANONNAME,
1632 __flags_numeric_host = AI_NUMERICHOST,
1633 #ifdef AI_NUMERICSERV
1634 __flags_numeric_service = AI_NUMERICSERV,
1636 __flags_v4_mapped = AI_V4MAPPED,
1637 __flags_all_matching = AI_ALL,
1638 __flags_address_configured = AI_ADDRCONFIG
1640 static constexpr flags passive = __flags_passive;
1641 static constexpr flags canonical_name = __flags_canonical_name;
1642 static constexpr flags numeric_host = __flags_numeric_host;
1643 #ifdef AI_NUMERICSERV
1644 static constexpr flags numeric_service = __flags_numeric_service;
1646 static constexpr flags v4_mapped = __flags_v4_mapped;
1647 static constexpr flags all_matching = __flags_all_matching;
1648 static constexpr flags address_configured = __flags_address_configured;
1651 resolver_base() = default;
1652 ~resolver_base() = default;
1655 constexpr resolver_base::flags
1656 operator&(resolver_base::flags __f1, resolver_base::flags __f2)
1657 { return resolver_base::flags( int(__f1) & int(__f2) ); }
1659 constexpr resolver_base::flags
1660 operator|(resolver_base::flags __f1, resolver_base::flags __f2)
1661 { return resolver_base::flags( int(__f1) | int(__f2) ); }
1663 constexpr resolver_base::flags
1664 operator^(resolver_base::flags __f1, resolver_base::flags __f2)
1665 { return resolver_base::flags( int(__f1) ^ int(__f2) ); }
1667 constexpr resolver_base::flags
1668 operator~(resolver_base::flags __f)
1669 { return resolver_base::flags( ~int(__f) ); }
1671 inline resolver_base::flags&
1672 operator&=(resolver_base::flags& __f1, resolver_base::flags __f2)
1673 { return __f1 = (__f1 & __f2); }
1675 inline resolver_base::flags&
1676 operator|=(resolver_base::flags& __f1, resolver_base::flags __f2)
1677 { return __f1 = (__f1 | __f2); }
1679 inline resolver_base::flags&
1680 operator^=(resolver_base::flags& __f1, resolver_base::flags __f2)
1681 { return __f1 = (__f1 ^ __f2); }
1683 // TODO define resolver_base::flags static constants for C++14 mode
1687 /** Container for results of name/address resolution.
1691 template<typename _InternetProtocol>
1692 class basic_resolver_results
1696 typedef _InternetProtocol protocol_type;
1697 typedef typename protocol_type::endpoint endpoint_type;
1698 typedef basic_resolver_entry<protocol_type> value_type;
1699 typedef const value_type& const_reference;
1700 typedef value_type& reference;
1701 typedef typename forward_list<value_type>::const_iterator const_iterator;
1702 typedef const_iterator iterator;
1703 typedef ptrdiff_t difference_type;
1704 typedef size_t size_type;
1706 // construct / copy / destroy:
1708 basic_resolver_results() = default;
1710 basic_resolver_results(const basic_resolver_results&) = default;
1712 basic_resolver_results(basic_resolver_results&&) noexcept = default;
1714 basic_resolver_results&
1715 operator=(const basic_resolver_results&) = default;
1717 basic_resolver_results&
1718 operator=(basic_resolver_results&&) = default;
1720 ~basic_resolver_results() = default;
1723 size_type size() const noexcept { return _M_size; }
1724 size_type max_size() const noexcept { return _M_results.max_size(); }
1725 _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_results.empty(); }
1728 const_iterator begin() const { return _M_results.begin(); }
1729 const_iterator end() const { return _M_results.end(); }
1730 const_iterator cbegin() const { return _M_results.begin(); }
1731 const_iterator cend() const { return _M_results.end(); }
1735 swap(basic_resolver_results& __that) noexcept
1736 { _M_results.swap(__that._M_results); }
1739 friend class basic_resolver<protocol_type>;
1741 basic_resolver_results(string_view, string_view, resolver_base::flags,
1742 error_code&, protocol_type* = nullptr);
1744 basic_resolver_results(const endpoint_type&, error_code&);
1746 forward_list<value_type> _M_results;
1750 template<typename _InternetProtocol>
1752 operator==(const basic_resolver_results<_InternetProtocol>& __a,
1753 const basic_resolver_results<_InternetProtocol>& __b)
1755 return __a.size() == __b.size()
1756 && std::equal(__a.begin(), __a.end(), __b.begin());
1759 template<typename _InternetProtocol>
1761 operator!=(const basic_resolver_results<_InternetProtocol>& __a,
1762 const basic_resolver_results<_InternetProtocol>& __b)
1763 { return !(__a == __b); }
1767 /// Perform name/address resolution.
1768 template<typename _InternetProtocol>
1769 class basic_resolver : public resolver_base
1774 typedef io_context::executor_type executor_type;
1775 typedef _InternetProtocol protocol_type;
1776 typedef typename _InternetProtocol::endpoint endpoint_type;
1777 typedef basic_resolver_results<_InternetProtocol> results_type;
1779 // construct / copy / destroy:
1781 explicit basic_resolver(io_context& __ctx) : _M_ctx(&__ctx) { }
1783 basic_resolver(const basic_resolver&) = delete;
1785 basic_resolver(basic_resolver&& __rhs) noexcept
1786 : _M_ctx(__rhs._M_ctx)
1787 { } // TODO move state/tasks etc.
1789 ~basic_resolver() { cancel(); }
1791 basic_resolver& operator=(const basic_resolver&) = delete;
1793 basic_resolver& operator=(basic_resolver&& __rhs)
1796 _M_ctx = __rhs._M_ctx;
1797 // TODO move state/tasks etc.
1801 // basic_resolver operations:
1803 executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
1805 void cancel() { } // TODO
1808 resolve(string_view __host_name, string_view __service_name)
1810 return resolve(__host_name, __service_name, resolver_base::flags(),
1811 __throw_on_error{"basic_resolver::resolve"});
1815 resolve(string_view __host_name, string_view __service_name,
1818 return resolve(__host_name, __service_name, resolver_base::flags(),
1823 resolve(string_view __host_name, string_view __service_name, flags __f)
1825 return resolve(__host_name, __service_name, __f,
1826 __throw_on_error{"basic_resolver::resolve"});
1830 resolve(string_view __host_name, string_view __service_name, flags __f,
1832 { return {__host_name, __service_name, __f, __ec}; }
1834 template<typename _CompletionToken>
1835 __deduced_t<_CompletionToken, void(error_code, results_type)>
1836 async_resolve(string_view __host_name, string_view __service_name,
1837 _CompletionToken&& __token)
1839 return async_resolve(__host_name, __service_name,
1840 resolver_base::flags(),
1841 forward<_CompletionToken>(__token));
1844 template<typename _CompletionToken>
1845 __deduced_t<_CompletionToken, void(error_code, results_type)>
1846 async_resolve(string_view __host_name, string_view __service_name,
1847 flags __f, _CompletionToken&& __token); // TODO
1850 resolve(const protocol_type& __protocol,
1851 string_view __host_name, string_view __service_name)
1853 return resolve(__protocol, __host_name, __service_name,
1854 resolver_base::flags(),
1855 __throw_on_error{"basic_resolver::resolve"});
1859 resolve(const protocol_type& __protocol,
1860 string_view __host_name, string_view __service_name,
1863 return resolve(__protocol, __host_name, __service_name,
1864 resolver_base::flags(), __ec);
1868 resolve(const protocol_type& __protocol,
1869 string_view __host_name, string_view __service_name, flags __f)
1871 return resolve(__protocol, __host_name, __service_name, __f,
1872 __throw_on_error{"basic_resolver::resolve"});
1876 resolve(const protocol_type& __protocol,
1877 string_view __host_name, string_view __service_name,
1878 flags __f, error_code& __ec)
1879 { return {__host_name, __service_name, __f, __ec, &__protocol}; }
1881 template<typename _CompletionToken>
1882 __deduced_t<_CompletionToken, void(error_code, results_type)>
1883 async_resolve(const protocol_type& __protocol,
1884 string_view __host_name, string_view __service_name,
1885 _CompletionToken&& __token)
1887 return async_resolve(__protocol, __host_name, __service_name,
1888 resolver_base::flags(),
1889 forward<_CompletionToken>(__token));
1892 template<typename _CompletionToken>
1893 __deduced_t<_CompletionToken, void(error_code, results_type)>
1894 async_resolve(const protocol_type& __protocol,
1895 string_view __host_name, string_view __service_name,
1896 flags __f, _CompletionToken&& __token); // TODO
1899 resolve(const endpoint_type& __ep)
1900 { return resolve(__ep, __throw_on_error{"basic_resolver::resolve"}); }
1903 resolve(const endpoint_type& __ep, error_code& __ec)
1904 { return { __ep, __ec }; }
1906 template<typename _CompletionToken> // TODO
1907 __deduced_t<_CompletionToken, void(error_code, results_type)>
1908 async_resolve(const endpoint_type& __ep, _CompletionToken&& __token);
1914 /// Private constructor to synchronously resolve host and service names.
1915 template<typename _InternetProtocol>
1916 basic_resolver_results<_InternetProtocol>::
1917 basic_resolver_results(string_view __host_name, string_view __service_name,
1918 resolver_base::flags __f, error_code& __ec,
1919 protocol_type* __protocol)
1921 #ifdef _GLIBCXX_HAVE_NETDB_H
1923 const char* __h = __host_name.data()
1924 ? (__host = __host_name.to_string()).c_str()
1927 const char* __s = __service_name.data()
1928 ? (__svc = __service_name.to_string()).c_str()
1931 ::addrinfo __hints{ };
1932 __hints.ai_flags = static_cast<int>(__f);
1935 __hints.ai_family = __protocol->family();
1936 __hints.ai_socktype = __protocol->type();
1937 __hints.ai_protocol = __protocol->protocol();
1941 auto __p = endpoint_type{}.protocol();
1942 __hints.ai_family = AF_UNSPEC;
1943 __hints.ai_socktype = __p.type();
1944 __hints.ai_protocol = __p.protocol();
1947 struct __scoped_addrinfo
1949 ~__scoped_addrinfo() { if (_M_p) ::freeaddrinfo(_M_p); }
1950 ::addrinfo* _M_p = nullptr;
1953 if (int __err = ::getaddrinfo(__h, __s, &__hints, &__sai._M_p))
1955 __ec.assign(__err, resolver_category());
1961 auto __tail = _M_results.before_begin();
1962 for (auto __ai = __sai._M_p; __ai != nullptr; __ai = __ai->ai_next)
1964 if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6)
1966 if (__ai->ai_addrlen <= __ep.capacity())
1967 __builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen);
1968 __ep.resize(__ai->ai_addrlen);
1969 __tail = _M_results.emplace_after(__tail, __ep, __host, __svc);
1974 __ec = std::make_error_code(errc::operation_not_supported);
1978 /// Private constructor to synchronously resolve an endpoint.
1979 template<typename _InternetProtocol>
1980 basic_resolver_results<_InternetProtocol>::
1981 basic_resolver_results(const endpoint_type& __ep, error_code& __ec)
1983 #ifdef _GLIBCXX_HAVE_NETDB_H
1984 char __host_name[256];
1985 char __service_name[128];
1987 if (__ep.protocol().type() == SOCK_DGRAM)
1988 __flags |= NI_DGRAM;
1989 auto __sa = static_cast<const sockaddr*>(__ep.data());
1990 int __err = ::getnameinfo(__sa, __ep.size(),
1991 __host_name, sizeof(__host_name),
1992 __service_name, sizeof(__service_name),
1996 __flags |= NI_NUMERICSERV;
1997 __err = ::getnameinfo(__sa, __ep.size(),
1998 __host_name, sizeof(__host_name),
1999 __service_name, sizeof(__service_name),
2003 __ec.assign(__err, resolver_category());
2007 _M_results.emplace_front(__ep, __host_name, __service_name);
2011 __ec = std::make_error_code(errc::operation_not_supported);
2015 /** The name of the local host.
2019 template<typename _Allocator>
2020 __string_with<_Allocator>
2021 host_name(const _Allocator& __a, error_code& __ec)
2023 #ifdef HOST_NAME_MAX
2024 constexpr size_t __maxlen = HOST_NAME_MAX;
2026 constexpr size_t __maxlen = 256;
2028 char __buf[__maxlen + 1];
2029 if (::gethostname(__buf, __maxlen) == -1)
2030 __ec.assign(errno, generic_category());
2031 __buf[__maxlen] = '\0';
2032 return { __buf, __a };
2035 template<typename _Allocator>
2036 inline __string_with<_Allocator>
2037 host_name(const _Allocator& __a)
2038 { return host_name(__a, __throw_on_error{"host_name"}); }
2041 host_name(error_code& __ec)
2042 { return host_name(std::allocator<char>{}, __ec); }
2046 { return host_name(std::allocator<char>{}, __throw_on_error{"host_name"}); }
2050 /// The TCP byte-stream protocol.
2055 typedef basic_endpoint<tcp> endpoint; ///< A TCP endpoint.
2056 typedef basic_resolver<tcp> resolver; ///< A TCP resolver.
2057 typedef basic_stream_socket<tcp> socket; ///< A TCP socket.
2058 typedef basic_socket_acceptor<tcp> acceptor; ///< A TCP acceptor.
2059 typedef basic_socket_iostream<tcp> iostream; /// A TCP iostream.
2061 #ifdef _GLIBCXX_HAVE_NETINET_TCP_H
2062 /// Disable coalescing of small segments (i.e. the Nagle algorithm).
2063 struct no_delay : __sockopt_crtp<no_delay, bool>
2065 using __sockopt_crtp::__sockopt_crtp;
2067 static const int _S_level = IPPROTO_TCP;
2068 static const int _S_name = TCP_NODELAY;
2074 /// A protocol object representing IPv4 TCP.
2075 static constexpr tcp v4() noexcept { return tcp(AF_INET); }
2076 /// A protocol object representing IPv6 TCP.
2077 static constexpr tcp v6() noexcept { return tcp(AF_INET6); }
2081 constexpr int family() const noexcept { return _M_family; }
2082 constexpr int type() const noexcept { return SOCK_STREAM; }
2083 constexpr int protocol() const noexcept { return IPPROTO_TCP; }
2086 constexpr explicit tcp(int __family) : _M_family(__family) { }
2096 operator==(const tcp& __a, const tcp& __b)
2097 { return __a.family() == __b.family(); }
2100 operator!=(const tcp& __a, const tcp& __b)
2101 { return !(__a == __b); }
2105 /// The UDP datagram protocol.
2110 typedef basic_endpoint<udp> endpoint;
2111 typedef basic_resolver<udp> resolver;
2112 typedef basic_datagram_socket<udp> socket;
2115 static constexpr udp v4() noexcept { return udp(AF_INET); }
2116 static constexpr udp v6() noexcept { return udp(AF_INET6); }
2120 constexpr int family() const noexcept { return _M_family; }
2121 constexpr int type() const noexcept { return SOCK_DGRAM; }
2122 constexpr int protocol() const noexcept { return IPPROTO_UDP; }
2125 constexpr explicit udp(int __family) : _M_family(__family) { }
2135 operator==(const udp& __a, const udp& __b)
2136 { return __a.family() == __b.family(); }
2139 operator!=(const udp& __a, const udp& __b)
2140 { return !(__a == __b); }
2144 /// Restrict a socket created for an IPv6 protocol to IPv6 only.
2145 struct v6_only : __sockopt_crtp<v6_only, bool>
2147 using __sockopt_crtp::__sockopt_crtp;
2149 static const int _S_level = IPPROTO_IPV6;
2150 static const int _S_name = IPV6_V6ONLY;
2155 /// Set the default number of hops (TTL) for outbound datagrams.
2156 struct hops : __sockopt_crtp<hops>
2158 using __sockopt_crtp::__sockopt_crtp;
2160 template<typename _Protocol>
2162 level(const _Protocol& __p) const noexcept
2163 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2165 template<typename _Protocol>
2167 name(const _Protocol& __p) const noexcept
2168 { return __p.family() == AF_INET6 ? IPV6_UNICAST_HOPS : IP_TTL; }
2170 } // namespace unicast
2174 /// Request that a socket joins a multicast group.
2178 join_group(const address&);
2181 join_group(const address_v4&, const address_v4& = address_v4::any());
2184 join_group(const address_v6&, unsigned int = 0);
2186 template<typename _Protocol>
2188 level(const _Protocol& __p) const noexcept
2189 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2191 template<typename _Protocol>
2193 name(const _Protocol& __p) const noexcept
2195 return __p.family() == AF_INET6
2196 ? IPV6_JOIN_GROUP : IP_ADD_MEMBERSHIP;
2198 template<typename _Protocol>
2200 data(const _Protocol&) noexcept
2201 { return std::addressof(_M_value); }
2203 template<typename _Protocol>
2205 data(const _Protocol&) const noexcept
2206 { return std::addressof(_M_value); }
2208 template<typename _Protocol>
2210 size(const _Protocol& __p) const noexcept
2212 return __p.family() == AF_INET6
2213 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2216 template<typename _Protocol>
2218 resize(const _Protocol& __p, size_t __s)
2220 if (__s != size(__p))
2221 __throw_length_error("invalid value for socket option resize");
2232 /// Request that a socket leaves a multicast group.
2236 leave_group(const address&);
2239 leave_group(const address_v4&, const address_v4& = address_v4::any());
2242 leave_group(const address_v6&, unsigned int = 0);
2244 template<typename _Protocol>
2246 level(const _Protocol& __p) const noexcept
2247 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2249 template<typename _Protocol>
2251 name(const _Protocol& __p) const noexcept
2253 return __p.family() == AF_INET6
2254 ? IPV6_LEAVE_GROUP : IP_DROP_MEMBERSHIP;
2256 template<typename _Protocol>
2258 data(const _Protocol&) noexcept
2259 { return std::addressof(_M_value); }
2261 template<typename _Protocol>
2263 data(const _Protocol&) const noexcept
2264 { return std::addressof(_M_value); }
2266 template<typename _Protocol>
2268 size(const _Protocol& __p) const noexcept
2270 return __p.family() == AF_INET6
2271 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2274 template<typename _Protocol>
2276 resize(const _Protocol& __p, size_t __s)
2278 if (__s != size(__p))
2279 __throw_length_error("invalid value for socket option resize");
2290 /// Specify the network interface for outgoing multicast datagrams.
2291 class outbound_interface
2294 outbound_interface(const address_v4&);
2297 outbound_interface(unsigned int);
2299 template<typename _Protocol>
2301 level(const _Protocol& __p) const noexcept
2302 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2304 template<typename _Protocol>
2306 name(const _Protocol& __p) const noexcept
2308 return __p.family() == AF_INET6
2309 ? IPV6_MULTICAST_IF : IP_MULTICAST_IF;
2312 template<typename _Protocol>
2314 data(const _Protocol&) const noexcept
2315 { return std::addressof(_M_value); }
2317 template<typename _Protocol>
2319 size(const _Protocol& __p) const noexcept
2321 return __p.family() == AF_INET6
2322 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2332 /// Set the default number of hops (TTL) for outbound datagrams.
2333 struct hops : __sockopt_crtp<hops>
2335 using __sockopt_crtp::__sockopt_crtp;
2337 template<typename _Protocol>
2339 level(const _Protocol& __p) const noexcept
2340 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2342 template<typename _Protocol>
2344 name(const _Protocol& __p) const noexcept
2346 return __p.family() == AF_INET6
2347 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL;
2351 /// Set whether datagrams are delivered back to the local application.
2352 struct enable_loopback : __sockopt_crtp<enable_loopback>
2354 using __sockopt_crtp::__sockopt_crtp;
2356 template<typename _Protocol>
2358 level(const _Protocol& __p) const noexcept
2359 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2361 template<typename _Protocol>
2363 name(const _Protocol& __p) const noexcept
2365 return __p.family() == AF_INET6
2366 ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP;
2370 } // namespace multicast
2377 } // namespace experimental
2380 struct is_error_condition_enum<experimental::net::v1::ip::resolver_errc>
2381 : public true_type {};
2384 template<typename _Tp> struct hash;
2386 struct hash<experimental::net::v1::ip::address>
2387 : __hash_base<size_t, experimental::net::v1::ip::address>
2390 operator()(const argument_type& __a) const
2393 return _Hash_impl::hash(__a.to_v4());
2395 return _Hash_impl::hash(__a.to_v6());
2400 struct hash<experimental::net::v1::ip::address_v4>
2401 : __hash_base<size_t, experimental::net::v1::ip::address_v4>
2404 operator()(const argument_type& __a) const
2405 { return _Hash_impl::hash(__a.to_bytes()); }
2408 template<> struct hash<experimental::net::v1::ip::address_v6>
2409 : __hash_base<size_t, experimental::net::v1::ip::address_v6>
2412 operator()(const argument_type& __a) const
2413 { return _Hash_impl::hash(__a.to_bytes()); }
2416 _GLIBCXX_END_NAMESPACE_VERSION
2421 #endif // _GLIBCXX_EXPERIMENTAL_INTERNET