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