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