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