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