1 // <experimental/internet> -*- C++ -*- 2 3 // Copyright (C) 2015-2024 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file experimental/internet 26 * This is a TS C++ Library header. 27 * @ingroup networking-ts 28 */ 29 30 #ifndef _GLIBCXX_EXPERIMENTAL_INTERNET 31 #define _GLIBCXX_EXPERIMENTAL_INTERNET 32 33 #pragma GCC system_header 34 35 #include <bits/requires_hosted.h> // experimental is currently omitted 36 37 #if __cplusplus >= 201402L 38 39 #include <experimental/netfwd> 40 #include <experimental/io_context> 41 #include <experimental/bits/net.h> 42 #include <array> 43 #include <forward_list> 44 #include <sstream> 45 #include <cstdint> 46 #include <experimental/string_view> 47 #include <bits/charconv.h> 48 #ifdef _GLIBCXX_HAVE_UNISTD_H 49 # include <unistd.h> 50 #endif 51 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 52 # include <sys/socket.h> // AF_INET, AF_INET6, SOCK_DGRAM, SOCK_STREAM 53 #endif 54 #ifdef _GLIBCXX_HAVE_ARPA_INET_H 55 # include <arpa/inet.h> // inet_ntop 56 #endif 57 #ifdef _GLIBCXX_HAVE_NETINET_IN_H 58 # include <netinet/in.h> // IPPROTO_IP, IPPROTO_IPV6, in_addr, in6_addr 59 #endif 60 #ifdef _GLIBCXX_HAVE_NETINET_TCP_H 61 # include <netinet/tcp.h> // TCP_NODELAY 62 #endif 63 #ifdef _GLIBCXX_HAVE_NETDB_H 64 # include <netdb.h> // getaddrinfo etc. 65 #endif 66 67 #if defined _WIN32 && __has_include(<ws2tcpip.h>) 68 # include <ws2tcpip.h> 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 <netdb.h>"; 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<int>(__e), resolver_category()); } 125 126 inline error_condition make_error_condition(resolver_errc __e) noexcept 127 { return error_condition(static_cast<int>(__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<typename _Alloc> 149 using __string_with 150 = enable_if_t<std::is_same<typename _Alloc::value_type, char>::value, 151 std::basic_string<char, std::char_traits<char>, _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<unsigned char, 4> 180 { 181 template<typename... _Tp> 182 explicit constexpr 183 bytes_type(_Tp... __tp) 184 : array<unsigned char, 4>{{static_cast<unsigned char>(__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<typename _Allocator = allocator<char>> 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<typename _InternetProtocol> 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<unsigned char, 16> 326 { 327 template<typename... _Tp> 328 explicit constexpr 329 bytes_type(_Tp... __t) 330 : array<unsigned char, 16>{{static_cast<unsigned char>(__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<typename _Allocator = allocator<char>> 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<typename _InternetProtocol> 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<typename _Allocator = allocator<char>> 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<typename _InternetProtocol> 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<scope_id_type>::max()) 815 { 816 return { __b, static_cast<scope_id_type>(__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<typename _CharT, typename _Traits> 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<typename _CharT, typename _Traits> 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<typename _CharT, typename _Traits> 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<typename> class basic_address_iterator; // not defined 1020 1021 template<> class basic_address_iterator<address_v4> 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<address_v4>; 1080 1081 template<> class basic_address_iterator<address_v6> 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<address_v6>; 1134 1135 template<typename> class basic_address_range; // not defined 1136 1137 /** An IPv6 address range. 1138 * @{ 1139 */ 1140 1141 template<> class basic_address_range<address_v4> 1142 { 1143 public: 1144 // types: 1145 1146 using iterator = basic_address_iterator<address_v4>; 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<address_v4>; 1179 1180 /// @} 1181 1182 /** An IPv6 address range. 1183 * @{ 1184 */ 1185 1186 template<> class basic_address_range<address_v6> 1187 { 1188 public: 1189 // types: 1190 1191 using iterator = basic_address_iterator<address_v6>; 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<address_v6>; 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<typename _Allocator = allocator<char>> 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 __preflenlen = _M_prefix_len >= 10 ? 2 : 1; 1318 __str.resize(__addrlen + 1 + __preflenlen); 1319 __str[__addrlen] = '/'; 1320 std::__detail::__to_chars_10_impl(&__str.front() + __addrlen + 1, 1321 __preflenlen, 1322 (unsigned char)_M_prefix_len); 1323 return __str; 1324 } 1325 1326 private: 1327 address_v4 _M_addr; 1328 int _M_prefix_len; 1329 }; 1330 1331 /// An IPv6 network address. 1332 class network_v6 1333 { 1334 public: 1335 // constructors: 1336 constexpr network_v6() noexcept : _M_addr(), _M_prefix_len(0) { } 1337 1338 constexpr 1339 network_v6(const address_v6& __addr, int __prefix_len) 1340 : _M_addr(__addr), _M_prefix_len(__prefix_len) 1341 { 1342 if (_M_prefix_len < 0 || _M_prefix_len > 128) 1343 __throw_out_of_range("network_v6: invalid prefix length"); 1344 } 1345 1346 // members: 1347 constexpr address_v6 address() const noexcept { return _M_addr; } 1348 constexpr int prefix_length() const noexcept { return _M_prefix_len; } 1349 1350 _GLIBCXX17_CONSTEXPR address_v6 1351 network() const noexcept 1352 { 1353 address_v6::bytes_type __bytes = _M_addr.to_bytes(); 1354 int __nbytes = (_M_prefix_len + 7) / 8; 1355 for (int __n = __nbytes; __n < 16; ++__n) 1356 __bytes[__n] = 0; 1357 if (int __zbits = (__nbytes * 8) - _M_prefix_len) 1358 __bytes[__nbytes - 1] &= 0xFF << __zbits; 1359 return address_v6(__bytes, _M_addr.scope_id()); 1360 } 1361 1362 address_v6_range 1363 hosts() const noexcept 1364 { 1365 if (is_host()) 1366 return { address(), *++address_v6_iterator(address()) }; 1367 1368 address_v6::bytes_type __bytes = _M_addr.to_bytes(); 1369 int __nbytes = (_M_prefix_len + 7) / 8; 1370 for (int __n = __nbytes; __n < 16; ++__n) 1371 __bytes[__n] = 0xFF; 1372 if (int __bits = (__nbytes * 8) - _M_prefix_len) 1373 __bytes[__nbytes - 1] |= (1 << __bits) - 1; 1374 address_v6 __last(__bytes, _M_addr.scope_id()); 1375 return { network(), *++address_v6_iterator(__last) }; 1376 } 1377 1378 _GLIBCXX17_CONSTEXPR network_v6 1379 canonical() const noexcept 1380 { return network_v6{network(), prefix_length()}; } 1381 1382 constexpr bool is_host() const noexcept { return _M_prefix_len == 128; } 1383 1384 constexpr bool 1385 is_subnet_of(const network_v6& __other) const noexcept 1386 { 1387 if (__other.prefix_length() < prefix_length()) 1388 { 1389 network_v6 __net(address(), __other.prefix_length()); 1390 return __net.canonical() == __other.canonical(); 1391 } 1392 return false; 1393 } 1394 1395 template<typename _Allocator = allocator<char>> 1396 __string_with<_Allocator> 1397 to_string(const _Allocator& __a = _Allocator()) const 1398 { 1399 return address().to_string(__a) + '/' 1400 + std::to_string(prefix_length()).c_str(); 1401 } 1402 1403 private: 1404 address_v6 _M_addr; 1405 int _M_prefix_len; 1406 }; 1407 1408 1409 /** ip::network_v4 comparisons 1410 * @{ 1411 */ 1412 1413 constexpr bool 1414 operator==(const network_v4& __a, const network_v4& __b) noexcept 1415 { 1416 return __a.address() == __b.address() 1417 && __a.prefix_length() == __b.prefix_length(); 1418 } 1419 1420 constexpr bool 1421 operator!=(const network_v4& __a, const network_v4& __b) noexcept 1422 { return !(__a == __b); } 1423 1424 /// @} 1425 1426 /** ip::network_v6 comparisons 1427 * @{ 1428 */ 1429 1430 constexpr bool 1431 operator==(const network_v6& __a, const network_v6& __b) noexcept 1432 { 1433 return __a.address() == __b.address() 1434 && __a.prefix_length() == __b.prefix_length(); 1435 } 1436 1437 constexpr bool 1438 operator!=(const network_v6& __a, const network_v6& __b) noexcept 1439 { return !(__a == __b); } 1440 1441 /// @} 1442 1443 /** ip::network_v4 creation 1444 * @{ 1445 */ 1446 1447 inline network_v4 1448 make_network_v4(const address_v4& __a, int __prefix_len) 1449 { return network_v4{__a, __prefix_len}; } 1450 1451 inline network_v4 1452 make_network_v4(const address_v4& __a, const address_v4& __mask) 1453 { return network_v4{ __a, __mask }; } 1454 1455 network_v4 make_network_v4(const char*, error_code&) noexcept; // TODO 1456 1457 inline network_v4 1458 make_network_v4(const char* __str) 1459 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); } 1460 1461 network_v4 make_network_v4(const string&, error_code&) noexcept; // TODO 1462 1463 inline network_v4 1464 make_network_v4(const string& __str) 1465 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); } 1466 1467 network_v4 make_network_v4(string_view, error_code&) noexcept; // TODO 1468 1469 inline network_v4 1470 make_network_v4(string_view __str) 1471 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); } 1472 1473 /// @} 1474 1475 /** ip::network_v6 creation 1476 * @{ 1477 */ 1478 1479 inline network_v6 1480 make_network_v6(const address_v6& __a, int __prefix_len) 1481 { return network_v6{__a, __prefix_len}; } 1482 1483 network_v6 make_network_v6(const char*, error_code&) noexcept; // TODO 1484 1485 inline network_v6 1486 make_network_v6(const char* __str) 1487 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); } 1488 1489 network_v6 make_network_v6(const string&, error_code&) noexcept; // TODO 1490 1491 inline network_v6 1492 make_network_v6(const string& __str) 1493 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); } 1494 1495 network_v6 make_network_v6(string_view, error_code&) noexcept; // TODO 1496 1497 inline network_v6 1498 make_network_v6(string_view __str) 1499 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); } 1500 1501 /// @} 1502 1503 /// ip::network_v4 I/O 1504 template<typename _CharT, typename _Traits> 1505 inline basic_ostream<_CharT, _Traits>& 1506 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v4& __net) 1507 { return __os << __net.to_string(); } 1508 1509 /// ip::network_v6 I/O 1510 template<typename _CharT, typename _Traits> 1511 inline basic_ostream<_CharT, _Traits>& 1512 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v6& __net) 1513 { return __os << __net.to_string(); } 1514 1515 #if defined IPPROTO_TCP || defined IPPROTO_UDP 1516 /// An IP endpoint. 1517 template<typename _InternetProtocol> 1518 class basic_endpoint 1519 { 1520 public: 1521 // types: 1522 using protocol_type = _InternetProtocol; 1523 1524 // constructors: 1525 1526 _GLIBCXX20_CONSTEXPR 1527 basic_endpoint() noexcept : _M_data() 1528 { 1529 _M_data._M_v4.sin_family = protocol_type::v4().family(); 1530 // If in_addr contains a union, make the correct member active: 1531 if (std::__is_constant_evaluated()) 1532 std::_Construct(&_M_data._M_v4.sin_addr.s_addr); 1533 } 1534 1535 _GLIBCXX20_CONSTEXPR 1536 basic_endpoint(const protocol_type& __proto, 1537 port_type __port_num) noexcept 1538 : _M_data() 1539 { 1540 if (__proto == protocol_type::v4()) 1541 { 1542 _M_data._M_v4.sin_family = protocol_type::v4().family(); 1543 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); 1544 if (std::__is_constant_evaluated()) 1545 std::_Construct(&_M_data._M_v4.sin_addr.s_addr); 1546 } 1547 else if (__proto == protocol_type::v6()) 1548 { 1549 std::_Construct(&_M_data._M_v6); 1550 _M_data._M_v6.sin6_family = __proto.family(); 1551 _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); 1552 _M_data._M_v6.sin6_scope_id = 0; 1553 if (std::__is_constant_evaluated()) 1554 std::_Construct(&_M_data._M_v6.sin6_addr.s6_addr); 1555 } 1556 else 1557 { 1558 __glibcxx_assert(__proto == protocol_type::v4() 1559 || __proto == protocol_type::v6()); 1560 1561 } 1562 } 1563 1564 _GLIBCXX20_CONSTEXPR 1565 basic_endpoint(const ip::address& __addr, 1566 port_type __port_num) noexcept 1567 : _M_data() 1568 { 1569 if (__addr.is_v4()) 1570 { 1571 _M_data._M_v4.sin_family = protocol_type::v4().family(); 1572 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); 1573 std::_Construct(&_M_data._M_v4.sin_addr.s_addr, 1574 __addr._M_v4._M_addr); 1575 } 1576 else 1577 { 1578 std::_Construct(&_M_data._M_v6); 1579 _M_data._M_v6.sin6_family = protocol_type::v6().family(); 1580 _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); 1581 if (std::__is_constant_evaluated()) 1582 std::_Construct(&_M_data._M_v6.sin6_addr.s6_addr); 1583 uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr; 1584 for (int __i = 0; __i < 16; ++__i) 1585 __s6a[__i] = __addr._M_v6._M_bytes[__i]; 1586 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; 1587 } 1588 } 1589 1590 // members: 1591 1592 constexpr protocol_type protocol() const noexcept 1593 { 1594 return _M_is_v6() ? protocol_type::v6() : protocol_type::v4(); 1595 } 1596 1597 constexpr ip::address 1598 address() const noexcept 1599 { 1600 if (_M_is_v6()) 1601 { 1602 address_v6 __v6; 1603 const uint8_t* __s6a = _M_data._M_v6.sin6_addr.s6_addr; 1604 for (int __i = 0; __i < 16; ++__i) 1605 __v6._M_bytes[__i] = __s6a[__i]; 1606 __v6._M_scope_id = _M_data._M_v6.sin6_scope_id; 1607 return __v6; 1608 } 1609 else 1610 { 1611 address_v4 __v4; 1612 __v4._M_addr = _M_data._M_v4.sin_addr.s_addr; 1613 return __v4; 1614 } 1615 } 1616 1617 void 1618 address(const ip::address& __addr) noexcept 1619 { 1620 if (__addr.is_v6()) 1621 { 1622 std::_Construct(&_M_data._M_v6); 1623 _M_data._M_v6.sin6_family = protocol_type::v6().family(); 1624 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr, 1625 __addr._M_v6._M_bytes.data(), 16); 1626 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; 1627 } 1628 else 1629 { 1630 std::_Construct(&_M_data._M_v4); 1631 _M_data._M_v4.sin_family = protocol_type::v4().family(); 1632 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr; 1633 } 1634 } 1635 1636 constexpr port_type 1637 port() const noexcept 1638 { 1639 port_type __p = 0; 1640 if (_M_is_v6()) 1641 __p = _M_data._M_v6.sin6_port; 1642 else 1643 __p = _M_data._M_v4.sin_port; 1644 return address_v4::_S_ntoh_16(__p); 1645 } 1646 1647 void 1648 port(port_type __port_num) noexcept 1649 { 1650 __port_num = address_v4::_S_hton_16(__port_num); 1651 if (_M_is_v6()) 1652 _M_data._M_v6.sin6_port = __port_num; 1653 else 1654 _M_data._M_v4.sin_port = __port_num; 1655 } 1656 1657 void* data() noexcept { return &_M_data; } 1658 1659 const void* data() const noexcept { return &_M_data; } 1660 1661 constexpr size_t 1662 size() const noexcept 1663 { return _M_is_v6() ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); } 1664 1665 void 1666 resize(size_t __s) 1667 { 1668 if (__s != size()) 1669 __throw_length_error("net::ip::basic_endpoint::resize"); 1670 } 1671 1672 constexpr size_t capacity() const noexcept { return sizeof(_M_data); } 1673 1674 private: 1675 union 1676 { 1677 sockaddr_in _M_v4; 1678 sockaddr_in6 _M_v6; 1679 } _M_data; 1680 1681 constexpr bool 1682 _M_is_v6() const noexcept 1683 { 1684 // For constexpr eval we can just detect which union member is active. 1685 // i.e. emulate P2641R1's std::is_active_member(&_M_data._M_v6)). 1686 if (std::__is_constant_evaluated()) 1687 return __builtin_constant_p(_M_data._M_v6.sin6_family); 1688 return _M_data._M_v6.sin6_family == AF_INET6; 1689 } 1690 }; 1691 1692 /** basic_endpoint comparisons 1693 * @{ 1694 */ 1695 1696 template<typename _InternetProtocol> 1697 constexpr bool 1698 operator==(const basic_endpoint<_InternetProtocol>& __a, 1699 const basic_endpoint<_InternetProtocol>& __b) 1700 { return __a.address() == __b.address() && __a.port() == __b.port(); } 1701 1702 template<typename _InternetProtocol> 1703 constexpr bool 1704 operator!=(const basic_endpoint<_InternetProtocol>& __a, 1705 const basic_endpoint<_InternetProtocol>& __b) 1706 { return !(__a == __b); } 1707 1708 template<typename _InternetProtocol> 1709 constexpr bool 1710 operator< (const basic_endpoint<_InternetProtocol>& __a, 1711 const basic_endpoint<_InternetProtocol>& __b) 1712 { 1713 return __a.address() < __b.address() 1714 || (!(__b.address() < __a.address()) && __a.port() < __b.port()); 1715 } 1716 1717 template<typename _InternetProtocol> 1718 constexpr bool 1719 operator> (const basic_endpoint<_InternetProtocol>& __a, 1720 const basic_endpoint<_InternetProtocol>& __b) 1721 { return __b < __a; } 1722 1723 template<typename _InternetProtocol> 1724 constexpr bool 1725 operator<=(const basic_endpoint<_InternetProtocol>& __a, 1726 const basic_endpoint<_InternetProtocol>& __b) 1727 { return !(__b < __a); } 1728 1729 template<typename _InternetProtocol> 1730 constexpr bool 1731 operator>=(const basic_endpoint<_InternetProtocol>& __a, 1732 const basic_endpoint<_InternetProtocol>& __b) 1733 { return !(__a < __b); } 1734 1735 /// @} 1736 1737 /// basic_endpoint I/O 1738 template<typename _CharT, typename _Traits, typename _InternetProtocol> 1739 inline basic_ostream<_CharT, _Traits>& 1740 operator<<(basic_ostream<_CharT, _Traits>& __os, 1741 const basic_endpoint<_InternetProtocol>& __ep) 1742 { 1743 basic_ostringstream<_CharT, _Traits> __ss; 1744 if (__ep.protocol() 1745 == basic_endpoint<_InternetProtocol>::protocol_type::v6()) 1746 __ss << '[' << __ep.address() << ']'; 1747 else 1748 __ss << __ep.address(); 1749 __ss << ':' << __ep.port(); 1750 __os << __ss.str(); 1751 return __os; 1752 } 1753 1754 /** Type representing a single result of name/address resolution. 1755 * @{ 1756 */ 1757 1758 template<typename _InternetProtocol> 1759 class basic_resolver_entry 1760 { 1761 public: 1762 // types: 1763 using protocol_type = _InternetProtocol; 1764 using endpoint_type = typename _InternetProtocol::endpoint; 1765 1766 // constructors: 1767 basic_resolver_entry() { } 1768 1769 basic_resolver_entry(const endpoint_type& __ep, 1770 string_view __h, string_view __s) 1771 : _M_ep(__ep), _M_host(__h), _M_svc(__s) { } 1772 1773 // members: 1774 endpoint_type endpoint() const { return _M_ep; } 1775 operator endpoint_type() const { return _M_ep; } 1776 1777 template<typename _Allocator = allocator<char>> 1778 __string_with<_Allocator> 1779 host_name(const _Allocator& __a = _Allocator()) const 1780 { return { _M_host, __a }; } 1781 1782 template<typename _Allocator = allocator<char>> 1783 __string_with<_Allocator> 1784 service_name(const _Allocator& __a = _Allocator()) const 1785 { return { _M_svc, __a }; } 1786 1787 private: 1788 basic_endpoint<_InternetProtocol> _M_ep; 1789 string _M_host; 1790 string _M_svc; 1791 }; 1792 1793 template<typename _InternetProtocol> 1794 inline bool 1795 operator==(const basic_resolver_entry<_InternetProtocol>& __a, 1796 const basic_resolver_entry<_InternetProtocol>& __b) 1797 { 1798 return __a.endpoint() == __b.endpoint() 1799 && __a.host_name() == __b.host_name() 1800 && __a.service_name() == __b.service_name(); 1801 } 1802 1803 template<typename _InternetProtocol> 1804 inline bool 1805 operator!=(const basic_resolver_entry<_InternetProtocol>& __a, 1806 const basic_resolver_entry<_InternetProtocol>& __b) 1807 { return !(__a == __b); } 1808 1809 /// @} 1810 1811 /** Base class defining flags for name/address resolution. 1812 * @{ 1813 */ 1814 1815 class resolver_base 1816 { 1817 public: 1818 enum flags : int { }; 1819 static constexpr flags passive = (flags)AI_PASSIVE; 1820 static constexpr flags canonical_name = (flags)AI_CANONNAME; 1821 static constexpr flags numeric_host = (flags)AI_NUMERICHOST; 1822 #ifdef AI_NUMERICSERV 1823 static constexpr flags numeric_service = (flags)AI_NUMERICSERV; 1824 #endif 1825 #ifdef AI_V4MAPPED 1826 static constexpr flags v4_mapped = (flags)AI_V4MAPPED; 1827 #endif 1828 #ifdef AI_ALL 1829 static constexpr flags all_matching = (flags)AI_ALL; 1830 #endif 1831 #ifdef AI_ADDRCONFIG 1832 static constexpr flags address_configured = (flags)AI_ADDRCONFIG; 1833 #endif 1834 1835 friend constexpr flags 1836 operator&(flags __f1, flags __f2) noexcept 1837 { return flags( int(__f1) & int(__f2) ); } 1838 1839 friend constexpr flags 1840 operator|(flags __f1, flags __f2) noexcept 1841 { return flags( int(__f1) | int(__f2) ); } 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 __f) noexcept 1849 { return flags( ~int(__f) ); } 1850 1851 friend constexpr flags& 1852 operator&=(flags& __f1, flags __f2) noexcept 1853 { return __f1 = (__f1 & __f2); } 1854 1855 friend constexpr flags& 1856 operator|=(flags& __f1, flags __f2) noexcept 1857 { return __f1 = (__f1 | __f2); } 1858 1859 friend constexpr flags& 1860 operator^=(flags& __f1, flags __f2) noexcept 1861 { return __f1 = (__f1 ^ __f2); } 1862 1863 protected: 1864 resolver_base() = default; 1865 ~resolver_base() = default; 1866 }; 1867 1868 // TODO define resolver_base::flags static constants in .so for C++14 mode 1869 1870 /// @} 1871 1872 /** Container for results of name/address resolution. 1873 * @{ 1874 */ 1875 1876 template<typename _InternetProtocol> 1877 class basic_resolver_results 1878 { 1879 public: 1880 // types: 1881 using protocol_type = _InternetProtocol; 1882 using endpoint_type = typename protocol_type::endpoint; 1883 using value_type = basic_resolver_entry<protocol_type>; 1884 using const_reference = const value_type&; 1885 using reference = value_type&; 1886 using const_iterator = typename forward_list<value_type>::const_iterator; 1887 using iterator = const_iterator; 1888 using difference_type = ptrdiff_t; 1889 using size_type = size_t; 1890 1891 // construct / copy / destroy: 1892 1893 basic_resolver_results() = default; 1894 1895 basic_resolver_results(const basic_resolver_results&) = default; 1896 1897 basic_resolver_results(basic_resolver_results&&) noexcept = default; 1898 1899 basic_resolver_results& 1900 operator=(const basic_resolver_results&) = default; 1901 1902 basic_resolver_results& 1903 operator=(basic_resolver_results&&) = default; 1904 1905 ~basic_resolver_results() = default; 1906 1907 // size: 1908 size_type size() const noexcept { return _M_size; } 1909 size_type max_size() const noexcept { return _M_results.max_size(); } 1910 1911 _GLIBCXX_NODISCARD bool 1912 empty() const noexcept { return _M_results.empty(); } 1913 1914 // element access: 1915 const_iterator begin() const { return _M_results.begin(); } 1916 const_iterator end() const { return _M_results.end(); } 1917 const_iterator cbegin() const { return _M_results.begin(); } 1918 const_iterator cend() const { return _M_results.end(); } 1919 1920 // swap: 1921 void 1922 swap(basic_resolver_results& __that) noexcept 1923 { _M_results.swap(__that._M_results); } 1924 1925 private: 1926 friend class basic_resolver<protocol_type>; 1927 1928 basic_resolver_results(string_view, string_view, resolver_base::flags, 1929 error_code&, protocol_type* = nullptr); 1930 1931 basic_resolver_results(const endpoint_type&, error_code&); 1932 1933 forward_list<value_type> _M_results; 1934 size_t _M_size = 0; 1935 }; 1936 1937 template<typename _InternetProtocol> 1938 inline bool 1939 operator==(const basic_resolver_results<_InternetProtocol>& __a, 1940 const basic_resolver_results<_InternetProtocol>& __b) 1941 { 1942 return __a.size() == __b.size() 1943 && std::equal(__a.begin(), __a.end(), __b.begin()); 1944 } 1945 1946 template<typename _InternetProtocol> 1947 inline bool 1948 operator!=(const basic_resolver_results<_InternetProtocol>& __a, 1949 const basic_resolver_results<_InternetProtocol>& __b) 1950 { return !(__a == __b); } 1951 1952 /// @} 1953 1954 /// Perform name/address resolution. 1955 template<typename _InternetProtocol> 1956 class basic_resolver : public resolver_base 1957 { 1958 public: 1959 // types: 1960 1961 using executor_type = io_context::executor_type; 1962 using protocol_type = _InternetProtocol; 1963 using endpoint_type = typename _InternetProtocol::endpoint; 1964 using results_type = basic_resolver_results<_InternetProtocol>; 1965 1966 // construct / copy / destroy: 1967 1968 explicit basic_resolver(io_context& __ctx) : _M_ctx(&__ctx) { } 1969 1970 basic_resolver(const basic_resolver&) = delete; 1971 1972 basic_resolver(basic_resolver&& __rhs) noexcept 1973 : _M_ctx(__rhs._M_ctx) 1974 { } // TODO move state/tasks etc. 1975 1976 ~basic_resolver() { cancel(); } 1977 1978 basic_resolver& operator=(const basic_resolver&) = delete; 1979 1980 basic_resolver& operator=(basic_resolver&& __rhs) 1981 { 1982 cancel(); 1983 _M_ctx = __rhs._M_ctx; 1984 // TODO move state/tasks etc. 1985 return *this; 1986 } 1987 1988 // basic_resolver operations: 1989 1990 executor_type get_executor() noexcept { return _M_ctx->get_executor(); } 1991 1992 void cancel() { } // TODO 1993 1994 results_type 1995 resolve(string_view __host_name, string_view __service_name) 1996 { 1997 return resolve(__host_name, __service_name, resolver_base::flags(), 1998 __throw_on_error{"basic_resolver::resolve"}); 1999 } 2000 2001 results_type 2002 resolve(string_view __host_name, string_view __service_name, 2003 error_code& __ec) 2004 { 2005 return resolve(__host_name, __service_name, resolver_base::flags(), 2006 __ec); 2007 } 2008 2009 results_type 2010 resolve(string_view __host_name, string_view __service_name, flags __f) 2011 { 2012 return resolve(__host_name, __service_name, __f, 2013 __throw_on_error{"basic_resolver::resolve"}); 2014 } 2015 2016 results_type 2017 resolve(string_view __host_name, string_view __service_name, flags __f, 2018 error_code& __ec) 2019 { return {__host_name, __service_name, __f, __ec}; } 2020 2021 template<typename _CompletionToken> 2022 __deduced_t<_CompletionToken, void(error_code, results_type)> 2023 async_resolve(string_view __host_name, string_view __service_name, 2024 _CompletionToken&& __token) 2025 { 2026 return async_resolve(__host_name, __service_name, 2027 resolver_base::flags(), 2028 forward<_CompletionToken>(__token)); 2029 } 2030 2031 template<typename _CompletionToken> 2032 __deduced_t<_CompletionToken, void(error_code, results_type)> 2033 async_resolve(string_view __host_name, string_view __service_name, 2034 flags __f, _CompletionToken&& __token); // TODO 2035 2036 results_type 2037 resolve(const protocol_type& __protocol, 2038 string_view __host_name, string_view __service_name) 2039 { 2040 return resolve(__protocol, __host_name, __service_name, 2041 resolver_base::flags(), 2042 __throw_on_error{"basic_resolver::resolve"}); 2043 } 2044 2045 results_type 2046 resolve(const protocol_type& __protocol, 2047 string_view __host_name, string_view __service_name, 2048 error_code& __ec) 2049 { 2050 return resolve(__protocol, __host_name, __service_name, 2051 resolver_base::flags(), __ec); 2052 } 2053 2054 results_type 2055 resolve(const protocol_type& __protocol, 2056 string_view __host_name, string_view __service_name, flags __f) 2057 { 2058 return resolve(__protocol, __host_name, __service_name, __f, 2059 __throw_on_error{"basic_resolver::resolve"}); 2060 } 2061 2062 results_type 2063 resolve(const protocol_type& __protocol, 2064 string_view __host_name, string_view __service_name, 2065 flags __f, error_code& __ec) 2066 { return {__host_name, __service_name, __f, __ec, &__protocol}; } 2067 2068 template<typename _CompletionToken> 2069 __deduced_t<_CompletionToken, void(error_code, results_type)> 2070 async_resolve(const protocol_type& __protocol, 2071 string_view __host_name, string_view __service_name, 2072 _CompletionToken&& __token) 2073 { 2074 return async_resolve(__protocol, __host_name, __service_name, 2075 resolver_base::flags(), 2076 forward<_CompletionToken>(__token)); 2077 } 2078 2079 template<typename _CompletionToken> 2080 __deduced_t<_CompletionToken, void(error_code, results_type)> 2081 async_resolve(const protocol_type& __protocol, 2082 string_view __host_name, string_view __service_name, 2083 flags __f, _CompletionToken&& __token); // TODO 2084 2085 results_type 2086 resolve(const endpoint_type& __ep) 2087 { return resolve(__ep, __throw_on_error{"basic_resolver::resolve"}); } 2088 2089 results_type 2090 resolve(const endpoint_type& __ep, error_code& __ec) 2091 { return { __ep, __ec }; } 2092 2093 template<typename _CompletionToken> // TODO 2094 __deduced_t<_CompletionToken, void(error_code, results_type)> 2095 async_resolve(const endpoint_type& __ep, _CompletionToken&& __token); 2096 2097 private: 2098 io_context* _M_ctx; 2099 }; 2100 2101 /// Private constructor to synchronously resolve host and service names. 2102 template<typename _InternetProtocol> 2103 basic_resolver_results<_InternetProtocol>:: 2104 basic_resolver_results(string_view __host_name, string_view __service_name, 2105 resolver_base::flags __f, error_code& __ec, 2106 protocol_type* __protocol) 2107 { 2108 #ifdef _GLIBCXX_HAVE_NETDB_H 2109 string __host; 2110 const char* __h = __host_name.data() 2111 ? (__host = __host_name.to_string()).c_str() 2112 : nullptr; 2113 string __svc; 2114 const char* __s = __service_name.data() 2115 ? (__svc = __service_name.to_string()).c_str() 2116 : nullptr; 2117 2118 ::addrinfo __hints{ }; 2119 __hints.ai_flags = static_cast<int>(__f); 2120 if (__protocol) 2121 { 2122 __hints.ai_family = __protocol->family(); 2123 __hints.ai_socktype = __protocol->type(); 2124 __hints.ai_protocol = __protocol->protocol(); 2125 } 2126 else 2127 { 2128 auto __p = endpoint_type{}.protocol(); 2129 __hints.ai_family = AF_UNSPEC; 2130 __hints.ai_socktype = __p.type(); 2131 __hints.ai_protocol = __p.protocol(); 2132 } 2133 2134 struct __scoped_addrinfo 2135 { 2136 ~__scoped_addrinfo() { if (_M_p) ::freeaddrinfo(_M_p); } 2137 ::addrinfo* _M_p = nullptr; 2138 } __sai; 2139 2140 if (int __err = ::getaddrinfo(__h, __s, &__hints, &__sai._M_p)) 2141 { 2142 __ec = ip::__make_resolver_error_code(__err, errno); 2143 return; 2144 } 2145 __ec.clear(); 2146 2147 endpoint_type __ep; 2148 auto __tail = _M_results.before_begin(); 2149 for (auto __ai = __sai._M_p; __ai != nullptr; __ai = __ai->ai_next) 2150 { 2151 if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6) 2152 { 2153 if (__ai->ai_addrlen <= __ep.capacity()) 2154 __builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen); 2155 __ep.resize(__ai->ai_addrlen); 2156 __tail = _M_results.emplace_after(__tail, __ep, __host, __svc); 2157 _M_size++; 2158 } 2159 } 2160 #else 2161 __ec = std::make_error_code(errc::operation_not_supported); 2162 #endif 2163 } 2164 2165 /// Private constructor to synchronously resolve an endpoint. 2166 template<typename _InternetProtocol> 2167 basic_resolver_results<_InternetProtocol>:: 2168 basic_resolver_results(const endpoint_type& __ep, error_code& __ec) 2169 { 2170 #ifdef _GLIBCXX_HAVE_NETDB_H 2171 char __host_name[1025]; // glibc NI_MAXHOST 2172 char __service_name[32]; // glibc NI_MAXSERV 2173 int __flags = 0; 2174 if (__ep.protocol().type() == SOCK_DGRAM) 2175 __flags |= NI_DGRAM; 2176 auto __sa = static_cast<const sockaddr*>(__ep.data()); 2177 int __err = ::getnameinfo(__sa, __ep.size(), 2178 __host_name, sizeof(__host_name), 2179 __service_name, sizeof(__service_name), 2180 __flags); 2181 if (__err) 2182 { 2183 __flags |= NI_NUMERICSERV; 2184 __err = ::getnameinfo(__sa, __ep.size(), 2185 __host_name, sizeof(__host_name), 2186 __service_name, sizeof(__service_name), 2187 __flags); 2188 } 2189 if (__err) 2190 __ec = ip::__make_resolver_error_code(__err, errno); 2191 else 2192 { 2193 __ec.clear(); 2194 _M_results.emplace_front(__ep, __host_name, __service_name); 2195 _M_size = 1; 2196 } 2197 #else 2198 __ec = std::make_error_code(errc::operation_not_supported); 2199 #endif 2200 } 2201 #endif // IPPROTO_TCP || IPPROTO_UDP 2202 2203 /** The name of the local host. 2204 * @{ 2205 */ 2206 2207 template<typename _Allocator> 2208 __string_with<_Allocator> 2209 host_name(const _Allocator& __a, error_code& __ec) 2210 { 2211 #ifdef HOST_NAME_MAX 2212 constexpr size_t __maxlen = HOST_NAME_MAX; 2213 #else 2214 constexpr size_t __maxlen = 256; 2215 #endif 2216 char __buf[__maxlen + 1]; 2217 if (::gethostname(__buf, __maxlen) == -1) 2218 __ec.assign(errno, generic_category()); 2219 __buf[__maxlen] = '\0'; 2220 return { __buf, __a }; 2221 } 2222 2223 template<typename _Allocator> 2224 inline __string_with<_Allocator> 2225 host_name(const _Allocator& __a) 2226 { return host_name(__a, __throw_on_error{"host_name"}); } 2227 2228 inline string 2229 host_name(error_code& __ec) 2230 { return host_name(std::allocator<char>{}, __ec); } 2231 2232 inline string 2233 host_name() 2234 { return host_name(std::allocator<char>{}, __throw_on_error{"host_name"}); } 2235 2236 /// @} 2237 2238 #ifdef IPPROTO_TCP 2239 /// The TCP byte-stream protocol. 2240 class tcp 2241 { 2242 public: 2243 // types: 2244 using endpoint = basic_endpoint<tcp>; ///< A TCP endpoint. 2245 using resolver = basic_resolver<tcp>; ///< A TCP resolver. 2246 using socket = basic_stream_socket<tcp>; ///< A TCP socket. 2247 using acceptor = basic_socket_acceptor<tcp>; ///< A TCP acceptor. 2248 using iostream = basic_socket_iostream<tcp>; ///< A TCP iostream. 2249 2250 #ifdef TCP_NODELAY 2251 /// Disable coalescing of small segments (i.e. the Nagle algorithm). 2252 struct no_delay : __sockopt_crtp<no_delay, bool> 2253 { 2254 using __sockopt_crtp::__sockopt_crtp; 2255 using __sockopt_crtp::operator=; 2256 2257 static const int _S_level = IPPROTO_TCP; 2258 static const int _S_name = TCP_NODELAY; 2259 }; 2260 #endif 2261 2262 // static members: 2263 2264 /// A protocol object representing IPv4 TCP. 2265 static constexpr tcp v4() noexcept { return tcp(AF_INET); } 2266 /// A protocol object representing IPv6 TCP. 2267 static constexpr tcp v6() noexcept { return tcp(AF_INET6); } 2268 2269 tcp() = delete; 2270 2271 constexpr int family() const noexcept { return _M_family; } 2272 constexpr int type() const noexcept { return SOCK_STREAM; } 2273 constexpr int protocol() const noexcept { return IPPROTO_TCP; } 2274 2275 private: 2276 constexpr explicit tcp(int __family) : _M_family(__family) { } 2277 2278 int _M_family; 2279 }; 2280 2281 /** tcp comparisons 2282 * @{ 2283 */ 2284 2285 constexpr bool 2286 operator==(const tcp& __a, const tcp& __b) noexcept 2287 { return __a.family() == __b.family(); } 2288 2289 constexpr bool 2290 operator!=(const tcp& __a, const tcp& __b) noexcept 2291 { return !(__a == __b); } 2292 2293 /// @} 2294 #endif // IPPROTO_TCP 2295 2296 #ifdef IPPROTO_UDP 2297 /// The UDP datagram protocol. 2298 class udp 2299 { 2300 public: 2301 // types: 2302 using endpoint = basic_endpoint<udp>; 2303 using resolver = basic_resolver<udp>; 2304 using socket = basic_datagram_socket<udp>; 2305 2306 // static members: 2307 static constexpr udp v4() noexcept { return udp(AF_INET); } 2308 static constexpr udp v6() noexcept { return udp(AF_INET6); } 2309 2310 udp() = delete; 2311 2312 constexpr int family() const noexcept { return _M_family; } 2313 constexpr int type() const noexcept { return SOCK_DGRAM; } 2314 constexpr int protocol() const noexcept { return IPPROTO_UDP; } 2315 2316 private: 2317 constexpr explicit udp(int __family) : _M_family(__family) { } 2318 2319 int _M_family; 2320 }; 2321 2322 /** udp comparisons 2323 * @{ 2324 */ 2325 2326 constexpr bool 2327 operator==(const udp& __a, const udp& __b) noexcept 2328 { return __a.family() == __b.family(); } 2329 2330 constexpr bool 2331 operator!=(const udp& __a, const udp& __b) noexcept 2332 { return !(__a == __b); } 2333 2334 /// @} 2335 #endif // IPPROTO_UDP 2336 2337 #if defined IPPROTO_IP && defined IPPROTO_IPV6 2338 2339 /// Restrict a socket created for an IPv6 protocol to IPv6 only. 2340 class v6_only : public __sockopt_crtp<v6_only, bool> 2341 { 2342 public: 2343 using __sockopt_crtp::__sockopt_crtp; 2344 using __sockopt_crtp::operator=; 2345 2346 private: 2347 friend __sockopt_crtp<v6_only, bool>; 2348 static const int _S_level = IPPROTO_IPV6; 2349 static const int _S_name = IPV6_V6ONLY; 2350 }; 2351 2352 namespace unicast 2353 { 2354 /// Set the default number of hops (TTL) for outbound datagrams. 2355 class hops : public __sockopt_crtp<hops> 2356 { 2357 public: 2358 using __sockopt_crtp::__sockopt_crtp; 2359 using __sockopt_crtp::operator=; 2360 2361 template<typename _Protocol> 2362 int 2363 level(const _Protocol& __p) const noexcept 2364 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2365 2366 template<typename _Protocol> 2367 int 2368 name(const _Protocol& __p) const noexcept 2369 { return __p.family() == AF_INET6 ? IPV6_UNICAST_HOPS : IP_TTL; } 2370 }; 2371 } // namespace unicast 2372 2373 namespace multicast 2374 { 2375 class __mcastopt 2376 { 2377 public: 2378 explicit 2379 __mcastopt(const address& __grp) noexcept 2380 : __mcastopt(__grp.is_v4() ? __mcastopt(__grp.to_v4()) : __mcastopt(__grp.to_v6())) 2381 { } 2382 2383 explicit 2384 __mcastopt(const address_v4& __grp, 2385 const address_v4& __iface = address_v4::any()) noexcept 2386 { 2387 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 2388 _M_v4.imr_multiaddr.s_addr = __grp.to_uint(); 2389 _M_v4.imr_interface.s_addr = __iface.to_uint(); 2390 #else 2391 _M_v4.imr_multiaddr.s_addr = __builtin_bswap32(__grp.to_uint()); 2392 _M_v4.imr_interface.s_addr = __builtin_bswap32(__iface.to_uint()); 2393 #endif 2394 } 2395 2396 explicit 2397 __mcastopt(const address_v6& __grp, unsigned int __iface = 0) noexcept 2398 { 2399 const auto __addr = __grp.to_bytes(); 2400 __builtin_memcpy(_M_v6.ipv6mr_multiaddr.s6_addr, __addr.data(), 16); 2401 _M_v6.ipv6mr_interface = __iface; 2402 } 2403 2404 template<typename _Protocol> 2405 int 2406 level(const _Protocol& __p) const noexcept 2407 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2408 2409 template<typename _Protocol> 2410 const void* 2411 data(const _Protocol& __p) const noexcept 2412 { return __p.family() == AF_INET6 ? &_M_v6 : &_M_v4; } 2413 2414 template<typename _Protocol> 2415 size_t 2416 size(const _Protocol& __p) const noexcept 2417 { return __p.family() == AF_INET6 ? sizeof(_M_v6) : sizeof(_M_v4); } 2418 2419 private: 2420 ipv6_mreq _M_v6 = {}; 2421 ip_mreq _M_v4 = {}; 2422 }; 2423 2424 /// Request that a socket joins a multicast group. 2425 class join_group : private __mcastopt 2426 { 2427 public: 2428 using __mcastopt::__mcastopt; 2429 using __mcastopt::level; 2430 using __mcastopt::data; 2431 using __mcastopt::size; 2432 2433 template<typename _Protocol> 2434 int 2435 name(const _Protocol& __p) const noexcept 2436 { 2437 if (__p.family() == AF_INET6) 2438 return IPV6_JOIN_GROUP; 2439 return IP_ADD_MEMBERSHIP; 2440 } 2441 }; 2442 2443 /// Request that a socket leaves a multicast group. 2444 class leave_group : private __mcastopt 2445 { 2446 public: 2447 using __mcastopt::__mcastopt; 2448 using __mcastopt::level; 2449 using __mcastopt::data; 2450 using __mcastopt::size; 2451 2452 template<typename _Protocol> 2453 int 2454 name(const _Protocol& __p) const noexcept 2455 { 2456 if (__p.family() == AF_INET6) 2457 return IPV6_LEAVE_GROUP; 2458 return IP_DROP_MEMBERSHIP; 2459 } 2460 }; 2461 2462 /// Specify the network interface for outgoing multicast datagrams. 2463 class outbound_interface 2464 { 2465 public: 2466 explicit 2467 outbound_interface(const address_v4& __v4) noexcept 2468 { 2469 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 2470 _M_v4.s_addr = __v4.to_uint(); 2471 #else 2472 _M_v4.s_addr = __builtin_bswap32(__v4.to_uint()); 2473 #endif 2474 } 2475 2476 explicit 2477 outbound_interface(unsigned int __v6) noexcept 2478 : _M_v4(), _M_v6(__v6) 2479 { } 2480 2481 template<typename _Protocol> 2482 int 2483 level(const _Protocol& __p) const noexcept 2484 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2485 2486 template<typename _Protocol> 2487 int 2488 name(const _Protocol& __p) const noexcept 2489 { 2490 return __p.family() == AF_INET6 2491 ? IPV6_MULTICAST_IF : IP_MULTICAST_IF; 2492 } 2493 2494 template<typename _Protocol> 2495 const void* 2496 data(const _Protocol& __p) const noexcept 2497 { return __p.family() == AF_INET6 ? &_M_v6 : &_M_v4; } 2498 2499 template<typename _Protocol> 2500 size_t 2501 size(const _Protocol& __p) const noexcept 2502 { return __p.family() == AF_INET6 ? sizeof(_M_v6) : sizeof(_M_v4); } 2503 2504 private: 2505 in_addr _M_v4; 2506 unsigned _M_v6 = 0; 2507 }; 2508 2509 /// Set the default number of hops (TTL) for outbound datagrams. 2510 class hops : public __sockopt_crtp<hops> 2511 { 2512 public: 2513 using __sockopt_crtp::__sockopt_crtp; 2514 using __sockopt_crtp::operator=; 2515 2516 template<typename _Protocol> 2517 int 2518 level(const _Protocol& __p) const noexcept 2519 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2520 2521 template<typename _Protocol> 2522 int 2523 name(const _Protocol& __p) const noexcept 2524 { 2525 return __p.family() == AF_INET6 2526 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL; 2527 } 2528 }; 2529 2530 /// Set whether datagrams are delivered back to the local application. 2531 class enable_loopback : public __sockopt_crtp<enable_loopback, bool> 2532 { 2533 public: 2534 using __sockopt_crtp::__sockopt_crtp; 2535 using __sockopt_crtp::operator=; 2536 2537 template<typename _Protocol> 2538 int 2539 level(const _Protocol& __p) const noexcept 2540 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2541 2542 template<typename _Protocol> 2543 int 2544 name(const _Protocol& __p) const noexcept 2545 { 2546 return __p.family() == AF_INET6 2547 ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP; 2548 } 2549 }; 2550 2551 } // namespace multicast 2552 2553 #endif // IPPROTO_IP && IPPROTO_IPV6 2554 2555 /// @} 2556 2557 } // namespace ip 2558 } // namespace v1 2559 } // namespace net 2560 } // namespace experimental 2561 2562 template<> 2563 struct is_error_condition_enum<experimental::net::v1::ip::resolver_errc> 2564 : public true_type {}; 2565 2566 // hash support 2567 template<typename _Tp> struct hash; 2568 template<> 2569 struct hash<experimental::net::v1::ip::address> 2570 : __hash_base<size_t, experimental::net::v1::ip::address> 2571 { 2572 size_t 2573 operator()(const experimental::net::v1::ip::address& __a) const 2574 { 2575 if (__a.is_v4()) 2576 return _Hash_impl::hash(__a.to_v4()); 2577 else 2578 return _Hash_impl::hash(__a.to_v6()); 2579 } 2580 }; 2581 2582 template<> 2583 struct hash<experimental::net::v1::ip::address_v4> 2584 : __hash_base<size_t, experimental::net::v1::ip::address_v4> 2585 { 2586 size_t 2587 operator()(const experimental::net::v1::ip::address_v4& __a) const 2588 { return _Hash_impl::hash(__a.to_bytes()); } 2589 }; 2590 2591 template<> struct hash<experimental::net::v1::ip::address_v6> 2592 : __hash_base<size_t, experimental::net::v1::ip::address_v6> 2593 { 2594 size_t 2595 operator()(const experimental::net::v1::ip::address_v6& __a) const 2596 { return _Hash_impl::hash(__a.to_bytes()); } 2597 }; 2598 2599 _GLIBCXX_END_NAMESPACE_VERSION 2600 } // namespace std 2601 2602 #endif // C++14 2603 2604 #endif // _GLIBCXX_EXPERIMENTAL_INTERNET 2605