1// <experimental/internet> -*- C++ -*- 2 3// Copyright (C) 2015-2019 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 */ 28 29#ifndef _GLIBCXX_EXPERIMENTAL_INTERNET 30#define _GLIBCXX_EXPERIMENTAL_INTERNET 31 32#pragma GCC system_header 33 34#if __cplusplus >= 201402L 35 36#include <experimental/netfwd> 37#include <experimental/io_context> 38#include <experimental/bits/net.h> 39#include <array> 40#include <forward_list> 41#include <sstream> 42#include <cstdint> 43#include <experimental/string_view> 44#ifdef _GLIBCXX_HAVE_UNISTD_H 45# include <unistd.h> 46#endif 47#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 48# include <sys/socket.h> // AF_INET, AF_INET6, SOCK_DGRAM, SOCK_STREAM 49#endif 50#ifdef _GLIBCXX_HAVE_ARPA_INET_H 51# include <arpa/inet.h> // inet_ntop 52#endif 53#ifdef _GLIBCXX_HAVE_NETINET_IN_H 54# include <netinet/in.h> // IPPROTO_IP 55#endif 56#ifdef _GLIBCXX_HAVE_NETINET_TCP_H 57# include <netinet/tcp.h> // TCP_NODELAY 58#endif 59#ifdef _GLIBCXX_HAVE_NETDB_H 60# include <netdb.h> // getaddrinfo etc. 61#endif 62 63namespace std _GLIBCXX_VISIBILITY(default) 64{ 65_GLIBCXX_BEGIN_NAMESPACE_VERSION 66namespace experimental 67{ 68namespace net 69{ 70inline namespace v1 71{ 72namespace ip 73{ 74 75 /** 76 * @ingroup networking 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 typedef uint_least16_t port_type; ///< Type used for port numbers. 114 typedef uint_least32_t scope_id_type; ///< 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 typedef uint_least32_t uint_type; 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 typedef address_v4 value_type; 942 typedef ptrdiff_t difference_type; 943 typedef const address_v4* pointer; 944 typedef const address_v4& reference; 945 typedef input_iterator_tag iterator_category; 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 typedef basic_address_iterator<address_v4> address_v4_iterator; 996 997 template<> class basic_address_iterator<address_v6> 998 { 999 public: 1000 // types: 1001 typedef address_v6 value_type; 1002 typedef ptrdiff_t difference_type; 1003 typedef const address_v6* pointer; 1004 typedef const address_v6& reference; 1005 typedef input_iterator_tag iterator_category; 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 typedef basic_address_iterator<address_v6> address_v6_iterator; 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 typedef basic_address_iterator<address_v4> iterator; 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 typedef basic_address_range<address_v4> address_v4_range; 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 typedef basic_address_iterator<address_v6> iterator; 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 typedef basic_address_range<address_v6> address_v6_range; 1136 1137 bool 1138 operator==(const network_v4& __a, const network_v4& __b) noexcept; 1139 1140 bool 1141 operator==(const network_v6& __a, const network_v6& __b) noexcept; 1142 1143 /// @} 1144 1145 /// An IPv4 network address. 1146 class network_v4 1147 { 1148 public: 1149 // constructors: 1150 constexpr network_v4() noexcept : _M_addr(), _M_prefix_len(0) { } 1151 1152 constexpr 1153 network_v4(const address_v4& __addr, int __prefix_len) 1154 : _M_addr(__addr), _M_prefix_len(__prefix_len) 1155 { 1156 if (_M_prefix_len < 0 || _M_prefix_len > 32) 1157 __throw_out_of_range("network_v4: invalid prefix length"); 1158 } 1159 1160 constexpr 1161 network_v4(const address_v4& __addr, const address_v4& __mask) 1162 : _M_addr(__addr), _M_prefix_len(__builtin_popcount(__mask.to_uint())) 1163 { 1164 if (_M_prefix_len != 0) 1165 { 1166 address_v4::uint_type __mask_uint = __mask.to_uint(); 1167 if (__builtin_ctz(__mask_uint) != (32 - _M_prefix_len)) 1168 __throw_invalid_argument("network_v4: invalid mask"); 1169 if ((__mask_uint & 0x80000000) == 0) 1170 __throw_invalid_argument("network_v4: invalid mask"); 1171 } 1172 } 1173 1174 // members: 1175 1176 constexpr address_v4 address() const noexcept { return _M_addr; } 1177 constexpr int prefix_length() const noexcept { return _M_prefix_len; } 1178 1179 constexpr address_v4 1180 netmask() const noexcept 1181 { 1182 address_v4::uint_type __val = address_v4::broadcast().to_uint(); 1183 __val >>= (32 - _M_prefix_len); 1184 __val <<= (32 - _M_prefix_len); 1185 return address_v4{__val}; 1186 } 1187 1188 constexpr address_v4 1189 network() const noexcept 1190 { return address_v4{_M_addr.to_uint() & netmask().to_uint()}; } 1191 1192 constexpr address_v4 1193 broadcast() const noexcept 1194 { return address_v4{_M_addr.to_uint() | ~netmask().to_uint()}; } 1195 1196 address_v4_range 1197 hosts() const noexcept 1198 { 1199 if (is_host()) 1200 return { address(), *++address_v4_iterator(address()) }; 1201 return { network(), broadcast() }; 1202 } 1203 1204 constexpr network_v4 1205 canonical() const noexcept 1206 { return network_v4(network(), prefix_length()); } 1207 1208 constexpr bool is_host() const noexcept { return _M_prefix_len == 32; } 1209 1210 constexpr bool 1211 is_subnet_of(const network_v4& __other) const noexcept 1212 { 1213 if (__other.prefix_length() < prefix_length()) 1214 { 1215 network_v4 __net(address(), __other.prefix_length()); 1216 return __net.canonical() == __other.canonical(); 1217 } 1218 return false; 1219 } 1220 1221 template<typename _Allocator = allocator<char>> 1222 __string_with<_Allocator> 1223 to_string(const _Allocator& __a = _Allocator()) const 1224 { 1225 return address().to_string(__a) + '/' 1226 + std::to_string(prefix_length()); 1227 } 1228 1229 private: 1230 address_v4 _M_addr; 1231 int _M_prefix_len; 1232 }; 1233 1234 /// An IPv6 network address. 1235 class network_v6 1236 { 1237 public: 1238 // constructors: 1239 constexpr network_v6() noexcept : _M_addr(), _M_prefix_len(0) { } 1240 1241 constexpr 1242 network_v6(const address_v6& __addr, int __prefix_len) 1243 : _M_addr(__addr), _M_prefix_len(__prefix_len) 1244 { 1245 if (_M_prefix_len < 0 || _M_prefix_len > 128) 1246 __throw_out_of_range("network_v6: invalid prefix length"); 1247 } 1248 1249 // members: 1250 constexpr address_v6 address() const noexcept { return _M_addr; } 1251 constexpr int prefix_length() const noexcept { return _M_prefix_len; } 1252 1253 constexpr address_v6 network() const noexcept; // TODO 1254 1255 address_v6_range 1256 hosts() const noexcept 1257 { 1258 if (is_host()) 1259 return { address(), *++address_v6_iterator(address()) }; 1260 return {}; // { network(), XXX broadcast() XXX }; // TODO 1261 } 1262 1263 constexpr network_v6 1264 canonical() const noexcept 1265 { return network_v6{network(), prefix_length()}; } 1266 1267 constexpr bool is_host() const noexcept { return _M_prefix_len == 128; } 1268 1269 constexpr bool 1270 is_subnet_of(const network_v6& __other) const noexcept 1271 { 1272 if (__other.prefix_length() < prefix_length()) 1273 { 1274 network_v6 __net(address(), __other.prefix_length()); 1275 return __net.canonical() == __other.canonical(); 1276 } 1277 return false; 1278 } 1279 1280 template<typename _Allocator = allocator<char>> 1281 __string_with<_Allocator> 1282 to_string(const _Allocator& __a = _Allocator()) const 1283 { 1284 return address().to_string(__a) + '/' 1285 + std::to_string(prefix_length()); 1286 } 1287 1288 private: 1289 address_v6 _M_addr; 1290 int _M_prefix_len; 1291 }; 1292 1293 1294 /** ip::network_v4 comparisons 1295 * @{ 1296 */ 1297 1298 inline bool 1299 operator==(const network_v4& __a, const network_v4& __b) noexcept 1300 { 1301 return __a.address() == __b.address() 1302 && __a.prefix_length() == __b.prefix_length(); 1303 } 1304 1305 inline bool 1306 operator!=(const network_v4& __a, const network_v4& __b) noexcept 1307 { return !(__a == __b); } 1308 1309 /// @} 1310 1311 /** ip::network_v6 comparisons 1312 * @{ 1313 */ 1314 1315 inline bool 1316 operator==(const network_v6& __a, const network_v6& __b) noexcept 1317 { 1318 return __a.address() == __b.address() 1319 && __a.prefix_length() == __b.prefix_length(); 1320 } 1321 1322 inline bool 1323 operator!=(const network_v6& __a, const network_v6& __b) noexcept 1324 { return !(__a == __b); } 1325 1326 /// @} 1327 1328 /** ip::network_v4 creation 1329 * @{ 1330 */ 1331 1332 inline network_v4 1333 make_network_v4(const address_v4& __a, int __prefix_len) 1334 { return network_v4{__a, __prefix_len}; } 1335 1336 inline network_v4 1337 make_network_v4(const address_v4& __a, const address_v4& __mask) 1338 { return network_v4{ __a, __mask }; } 1339 1340 network_v4 make_network_v4(const char*, error_code&) noexcept; // TODO 1341 1342 inline network_v4 1343 make_network_v4(const char* __str) 1344 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); } 1345 1346 network_v4 make_network_v4(const string&, error_code&) noexcept; // TODO 1347 1348 inline network_v4 1349 make_network_v4(const string& __str) 1350 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); } 1351 1352 network_v4 make_network_v4(string_view, error_code&) noexcept; // TODO 1353 1354 inline network_v4 1355 make_network_v4(string_view __str) 1356 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); } 1357 1358 /// @} 1359 1360 /** ip::network_v6 creation 1361 * @{ 1362 */ 1363 1364 inline network_v6 1365 make_network_v6(const address_v6& __a, int __prefix_len) 1366 { return network_v6{__a, __prefix_len}; } 1367 1368 network_v6 make_network_v6(const char*, error_code&) noexcept; // TODO 1369 1370 inline network_v6 1371 make_network_v6(const char* __str) 1372 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); } 1373 1374 network_v6 make_network_v6(const string&, error_code&) noexcept; // TODO 1375 1376 inline network_v6 1377 make_network_v6(const string& __str) 1378 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); } 1379 1380 network_v6 make_network_v6(string_view, error_code&) noexcept; // TODO 1381 1382 inline network_v6 1383 make_network_v6(string_view __str) 1384 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); } 1385 1386 /// @} 1387 1388 /// ip::network_v4 I/O 1389 template<typename _CharT, typename _Traits> 1390 inline basic_ostream<_CharT, _Traits>& 1391 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v4& __net) 1392 { return __os << __net.to_string(); } 1393 1394 /// ip::network_v6 I/O 1395 template<typename _CharT, typename _Traits> 1396 inline basic_ostream<_CharT, _Traits>& 1397 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v6& __net) 1398 { return __os << __net.to_string(); } 1399 1400 /// An IP endpoint. 1401 template<typename _InternetProtocol> 1402 class basic_endpoint 1403 { 1404 public: 1405 // types: 1406 typedef _InternetProtocol protocol_type; 1407 1408 // constructors: 1409 1410 constexpr 1411 basic_endpoint() noexcept : _M_data() 1412 { _M_data._M_v4.sin_family = protocol_type::v4().family(); } 1413 1414 constexpr 1415 basic_endpoint(const protocol_type& __proto, 1416 port_type __port_num) noexcept 1417 : _M_data() 1418 { 1419 __glibcxx_assert(__proto == protocol_type::v4() 1420 || __proto == protocol_type::v6()); 1421 1422 _M_data._M_v4.sin_family = __proto.family(); 1423 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); 1424 } 1425 1426 constexpr 1427 basic_endpoint(const ip::address& __addr, 1428 port_type __port_num) noexcept 1429 : _M_data() 1430 { 1431 if (__addr.is_v4()) 1432 { 1433 _M_data._M_v4.sin_family = protocol_type::v4().family(); 1434 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); 1435 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr; 1436 } 1437 else 1438 { 1439 _M_data._M_v6 = {}; 1440 _M_data._M_v6.sin6_family = protocol_type::v6().family(); 1441 _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num); 1442 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr, 1443 __addr._M_v6._M_bytes.data(), 16); 1444 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; 1445 } 1446 } 1447 1448 // members: 1449 constexpr protocol_type protocol() const noexcept 1450 { 1451 return _M_data._M_v4.sin_family == AF_INET6 1452 ? protocol_type::v6() : protocol_type::v4(); 1453 } 1454 1455 constexpr ip::address 1456 address() const noexcept 1457 { 1458 ip::address __addr; 1459 if (protocol().family() == AF_INET6) 1460 { 1461 __builtin_memcpy(&__addr._M_v6._M_bytes, 1462 _M_data._M_v6.sin6_addr.s6_addr, 16); 1463 __addr._M_is_v4 = false; 1464 } 1465 else 1466 { 1467 __builtin_memcpy(&__addr._M_v4._M_addr, 1468 &_M_data._M_v4.sin_addr.s_addr, 4); 1469 } 1470 return __addr; 1471 } 1472 1473 void 1474 address(const ip::address& __addr) noexcept 1475 { 1476 if (__addr.is_v6()) 1477 { 1478 _M_data._M_v6 = {}; 1479 _M_data._M_v6.sin6_family = protocol_type::v6().family(); 1480 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr, 1481 __addr._M_v6._M_bytes.data(), 16); 1482 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id; 1483 } 1484 else 1485 { 1486 _M_data._M_v4.sin_family = protocol_type::v4().family(); 1487 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr; 1488 } 1489 } 1490 1491 constexpr port_type 1492 port() const noexcept 1493 { return address_v4::_S_ntoh_16(_M_data._M_v4.sin_port); } 1494 1495 void 1496 port(port_type __port_num) noexcept 1497 { _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); } 1498 1499 void* data() noexcept { return &_M_data; } 1500 const void* data() const noexcept { return &_M_data; } 1501 constexpr size_t size() const noexcept 1502 { 1503 return protocol().family() == AF_INET6 1504 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); 1505 } 1506 1507 void 1508 resize(size_t __s) 1509 { 1510 if ((protocol().family() == AF_INET6 && __s != sizeof(sockaddr_in6)) 1511 || (protocol().family() == AF_INET && __s != sizeof(sockaddr_in))) 1512 __throw_length_error("net::ip::basic_endpoint::resize"); 1513 } 1514 1515 constexpr size_t capacity() const noexcept { return sizeof(_M_data); } 1516 1517 private: 1518 union 1519 { 1520 sockaddr_in _M_v4; 1521 sockaddr_in6 _M_v6; 1522 } _M_data; 1523 }; 1524 1525 /** basic_endpoint comparisons 1526 * @{ 1527 */ 1528 1529 template<typename _InternetProtocol> 1530 inline bool 1531 operator==(const basic_endpoint<_InternetProtocol>& __a, 1532 const basic_endpoint<_InternetProtocol>& __b) 1533 { return __a.address() == __b.address() && __a.port() == __b.port(); } 1534 1535 template<typename _InternetProtocol> 1536 inline bool 1537 operator!=(const basic_endpoint<_InternetProtocol>& __a, 1538 const basic_endpoint<_InternetProtocol>& __b) 1539 { return !(__a == __b); } 1540 1541 template<typename _InternetProtocol> 1542 inline bool 1543 operator< (const basic_endpoint<_InternetProtocol>& __a, 1544 const basic_endpoint<_InternetProtocol>& __b) 1545 { 1546 return __a.address() < __b.address() 1547 || (!(__b.address() < __a.address()) && __a.port() < __b.port()); 1548 } 1549 1550 template<typename _InternetProtocol> 1551 inline bool 1552 operator> (const basic_endpoint<_InternetProtocol>& __a, 1553 const basic_endpoint<_InternetProtocol>& __b) 1554 { return __b < __a; } 1555 1556 template<typename _InternetProtocol> 1557 inline bool 1558 operator<=(const basic_endpoint<_InternetProtocol>& __a, 1559 const basic_endpoint<_InternetProtocol>& __b) 1560 { return !(__b < __a); } 1561 1562 template<typename _InternetProtocol> 1563 inline bool 1564 operator>=(const basic_endpoint<_InternetProtocol>& __a, 1565 const basic_endpoint<_InternetProtocol>& __b) 1566 { return !(__a < __b); } 1567 1568 /// @} 1569 1570 /// basic_endpoint I/O 1571 template<typename _CharT, typename _Traits, typename _InternetProtocol> 1572 inline basic_ostream<_CharT, _Traits>& 1573 operator<<(basic_ostream<_CharT, _Traits>& __os, 1574 const basic_endpoint<_InternetProtocol>& __ep) 1575 { 1576 basic_ostringstream<_CharT, _Traits> __ss; 1577 if (__ep.protocol() 1578 == basic_endpoint<_InternetProtocol>::protocol_type::v6()) 1579 __ss << '[' << __ep.address() << ']'; 1580 else 1581 __ss << __ep.address(); 1582 __ss << ':' << __ep.port(); 1583 __os << __ss.str(); 1584 return __os; 1585 } 1586 1587 /** Type representing a single result of name/address resolution. 1588 * @{ 1589 */ 1590 1591 template<typename _InternetProtocol> 1592 class basic_resolver_entry 1593 { 1594 public: 1595 // types: 1596 typedef _InternetProtocol protocol_type; 1597 typedef typename _InternetProtocol::endpoint endpoint_type; 1598 1599 // constructors: 1600 basic_resolver_entry() { } 1601 1602 basic_resolver_entry(const endpoint_type& __ep, 1603 string_view __h, string_view __s) 1604 : _M_ep(__ep), _M_host(__h), _M_svc(__s) { } 1605 1606 // members: 1607 endpoint_type endpoint() const { return _M_ep; } 1608 operator endpoint_type() const { return _M_ep; } 1609 1610 template<typename _Allocator = allocator<char>> 1611 __string_with<_Allocator> 1612 host_name(const _Allocator& __a = _Allocator()) const 1613 { return { _M_host, __a }; } 1614 1615 template<typename _Allocator = allocator<char>> 1616 __string_with<_Allocator> 1617 service_name(const _Allocator& __a = _Allocator()) const 1618 { return { _M_svc, __a }; } 1619 1620 private: 1621 basic_endpoint<_InternetProtocol> _M_ep; 1622 string _M_host; 1623 string _M_svc; 1624 }; 1625 1626 template<typename _InternetProtocol> 1627 inline bool 1628 operator==(const basic_resolver_entry<_InternetProtocol>& __a, 1629 const basic_resolver_entry<_InternetProtocol>& __b) 1630 { 1631 return __a.endpoint() == __b.endpoint() 1632 && __a.host_name() == __b.host_name() 1633 && __a.service_name() == __b.service_name(); 1634 } 1635 1636 template<typename _InternetProtocol> 1637 inline bool 1638 operator!=(const basic_resolver_entry<_InternetProtocol>& __a, 1639 const basic_resolver_entry<_InternetProtocol>& __b) 1640 { return !(__a == __b); } 1641 1642 /// @} 1643 1644 /** Base class defining flags for name/address resolution. 1645 * @{ 1646 */ 1647 1648 class resolver_base 1649 { 1650 public: 1651 enum flags : int 1652 { 1653 __flags_passive = AI_PASSIVE, 1654 __flags_canonical_name = AI_CANONNAME, 1655 __flags_numeric_host = AI_NUMERICHOST, 1656#ifdef AI_NUMERICSERV 1657 __flags_numeric_service = AI_NUMERICSERV, 1658#endif 1659 __flags_v4_mapped = AI_V4MAPPED, 1660 __flags_all_matching = AI_ALL, 1661 __flags_address_configured = AI_ADDRCONFIG 1662 }; 1663 static constexpr flags passive = __flags_passive; 1664 static constexpr flags canonical_name = __flags_canonical_name; 1665 static constexpr flags numeric_host = __flags_numeric_host; 1666#ifdef AI_NUMERICSERV 1667 static constexpr flags numeric_service = __flags_numeric_service; 1668#endif 1669 static constexpr flags v4_mapped = __flags_v4_mapped; 1670 static constexpr flags all_matching = __flags_all_matching; 1671 static constexpr flags address_configured = __flags_address_configured; 1672 1673 protected: 1674 resolver_base() = default; 1675 ~resolver_base() = default; 1676 }; 1677 1678 constexpr resolver_base::flags 1679 operator&(resolver_base::flags __f1, resolver_base::flags __f2) 1680 { return resolver_base::flags( int(__f1) & int(__f2) ); } 1681 1682 constexpr resolver_base::flags 1683 operator|(resolver_base::flags __f1, resolver_base::flags __f2) 1684 { return resolver_base::flags( int(__f1) | int(__f2) ); } 1685 1686 constexpr resolver_base::flags 1687 operator^(resolver_base::flags __f1, resolver_base::flags __f2) 1688 { return resolver_base::flags( int(__f1) ^ int(__f2) ); } 1689 1690 constexpr resolver_base::flags 1691 operator~(resolver_base::flags __f) 1692 { return resolver_base::flags( ~int(__f) ); } 1693 1694 inline resolver_base::flags& 1695 operator&=(resolver_base::flags& __f1, resolver_base::flags __f2) 1696 { return __f1 = (__f1 & __f2); } 1697 1698 inline resolver_base::flags& 1699 operator|=(resolver_base::flags& __f1, resolver_base::flags __f2) 1700 { return __f1 = (__f1 | __f2); } 1701 1702 inline resolver_base::flags& 1703 operator^=(resolver_base::flags& __f1, resolver_base::flags __f2) 1704 { return __f1 = (__f1 ^ __f2); } 1705 1706 // TODO define resolver_base::flags static constants for C++14 mode 1707 1708 /// @} 1709 1710 /** Container for results of name/address resolution. 1711 * @{ 1712 */ 1713 1714 template<typename _InternetProtocol> 1715 class basic_resolver_results 1716 { 1717 public: 1718 // types: 1719 typedef _InternetProtocol protocol_type; 1720 typedef typename protocol_type::endpoint endpoint_type; 1721 typedef basic_resolver_entry<protocol_type> value_type; 1722 typedef const value_type& const_reference; 1723 typedef value_type& reference; 1724 typedef typename forward_list<value_type>::const_iterator const_iterator; 1725 typedef const_iterator iterator; 1726 typedef ptrdiff_t difference_type; 1727 typedef size_t size_type; 1728 1729 // construct / copy / destroy: 1730 1731 basic_resolver_results() = default; 1732 1733 basic_resolver_results(const basic_resolver_results&) = default; 1734 1735 basic_resolver_results(basic_resolver_results&&) noexcept = default; 1736 1737 basic_resolver_results& 1738 operator=(const basic_resolver_results&) = default; 1739 1740 basic_resolver_results& 1741 operator=(basic_resolver_results&&) = default; 1742 1743 ~basic_resolver_results() = default; 1744 1745 // size: 1746 size_type size() const noexcept { return _M_size; } 1747 size_type max_size() const noexcept { return _M_results.max_size(); } 1748 _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_results.empty(); } 1749 1750 // element access: 1751 const_iterator begin() const { return _M_results.begin(); } 1752 const_iterator end() const { return _M_results.end(); } 1753 const_iterator cbegin() const { return _M_results.begin(); } 1754 const_iterator cend() const { return _M_results.end(); } 1755 1756 // swap: 1757 void 1758 swap(basic_resolver_results& __that) noexcept 1759 { _M_results.swap(__that._M_results); } 1760 1761 private: 1762 friend class basic_resolver<protocol_type>; 1763 1764 basic_resolver_results(string_view, string_view, resolver_base::flags, 1765 error_code&, protocol_type* = nullptr); 1766 1767 basic_resolver_results(const endpoint_type&, error_code&); 1768 1769 forward_list<value_type> _M_results; 1770 size_t _M_size = 0; 1771 }; 1772 1773 template<typename _InternetProtocol> 1774 inline bool 1775 operator==(const basic_resolver_results<_InternetProtocol>& __a, 1776 const basic_resolver_results<_InternetProtocol>& __b) 1777 { 1778 return __a.size() == __b.size() 1779 && std::equal(__a.begin(), __a.end(), __b.begin()); 1780 } 1781 1782 template<typename _InternetProtocol> 1783 inline bool 1784 operator!=(const basic_resolver_results<_InternetProtocol>& __a, 1785 const basic_resolver_results<_InternetProtocol>& __b) 1786 { return !(__a == __b); } 1787 1788 /// @} 1789 1790 /// Perform name/address resolution. 1791 template<typename _InternetProtocol> 1792 class basic_resolver : public resolver_base 1793 { 1794 public: 1795 // types: 1796 1797 typedef io_context::executor_type executor_type; 1798 typedef _InternetProtocol protocol_type; 1799 typedef typename _InternetProtocol::endpoint endpoint_type; 1800 typedef basic_resolver_results<_InternetProtocol> results_type; 1801 1802 // construct / copy / destroy: 1803 1804 explicit basic_resolver(io_context& __ctx) : _M_ctx(&__ctx) { } 1805 1806 basic_resolver(const basic_resolver&) = delete; 1807 1808 basic_resolver(basic_resolver&& __rhs) noexcept 1809 : _M_ctx(__rhs._M_ctx) 1810 { } // TODO move state/tasks etc. 1811 1812 ~basic_resolver() { cancel(); } 1813 1814 basic_resolver& operator=(const basic_resolver&) = delete; 1815 1816 basic_resolver& operator=(basic_resolver&& __rhs) 1817 { 1818 cancel(); 1819 _M_ctx = __rhs._M_ctx; 1820 // TODO move state/tasks etc. 1821 return *this; 1822 } 1823 1824 // basic_resolver operations: 1825 1826 executor_type get_executor() noexcept { return _M_ctx->get_executor(); } 1827 1828 void cancel() { } // TODO 1829 1830 results_type 1831 resolve(string_view __host_name, string_view __service_name) 1832 { 1833 return resolve(__host_name, __service_name, resolver_base::flags(), 1834 __throw_on_error{"basic_resolver::resolve"}); 1835 } 1836 1837 results_type 1838 resolve(string_view __host_name, string_view __service_name, 1839 error_code& __ec) 1840 { 1841 return resolve(__host_name, __service_name, resolver_base::flags(), 1842 __ec); 1843 } 1844 1845 results_type 1846 resolve(string_view __host_name, string_view __service_name, flags __f) 1847 { 1848 return resolve(__host_name, __service_name, __f, 1849 __throw_on_error{"basic_resolver::resolve"}); 1850 } 1851 1852 results_type 1853 resolve(string_view __host_name, string_view __service_name, flags __f, 1854 error_code& __ec) 1855 { return {__host_name, __service_name, __f, __ec}; } 1856 1857 template<typename _CompletionToken> 1858 __deduced_t<_CompletionToken, void(error_code, results_type)> 1859 async_resolve(string_view __host_name, string_view __service_name, 1860 _CompletionToken&& __token) 1861 { 1862 return async_resolve(__host_name, __service_name, 1863 resolver_base::flags(), 1864 forward<_CompletionToken>(__token)); 1865 } 1866 1867 template<typename _CompletionToken> 1868 __deduced_t<_CompletionToken, void(error_code, results_type)> 1869 async_resolve(string_view __host_name, string_view __service_name, 1870 flags __f, _CompletionToken&& __token); // TODO 1871 1872 results_type 1873 resolve(const protocol_type& __protocol, 1874 string_view __host_name, string_view __service_name) 1875 { 1876 return resolve(__protocol, __host_name, __service_name, 1877 resolver_base::flags(), 1878 __throw_on_error{"basic_resolver::resolve"}); 1879 } 1880 1881 results_type 1882 resolve(const protocol_type& __protocol, 1883 string_view __host_name, string_view __service_name, 1884 error_code& __ec) 1885 { 1886 return resolve(__protocol, __host_name, __service_name, 1887 resolver_base::flags(), __ec); 1888 } 1889 1890 results_type 1891 resolve(const protocol_type& __protocol, 1892 string_view __host_name, string_view __service_name, flags __f) 1893 { 1894 return resolve(__protocol, __host_name, __service_name, __f, 1895 __throw_on_error{"basic_resolver::resolve"}); 1896 } 1897 1898 results_type 1899 resolve(const protocol_type& __protocol, 1900 string_view __host_name, string_view __service_name, 1901 flags __f, error_code& __ec) 1902 { return {__host_name, __service_name, __f, __ec, &__protocol}; } 1903 1904 template<typename _CompletionToken> 1905 __deduced_t<_CompletionToken, void(error_code, results_type)> 1906 async_resolve(const protocol_type& __protocol, 1907 string_view __host_name, string_view __service_name, 1908 _CompletionToken&& __token) 1909 { 1910 return async_resolve(__protocol, __host_name, __service_name, 1911 resolver_base::flags(), 1912 forward<_CompletionToken>(__token)); 1913 } 1914 1915 template<typename _CompletionToken> 1916 __deduced_t<_CompletionToken, void(error_code, results_type)> 1917 async_resolve(const protocol_type& __protocol, 1918 string_view __host_name, string_view __service_name, 1919 flags __f, _CompletionToken&& __token); // TODO 1920 1921 results_type 1922 resolve(const endpoint_type& __ep) 1923 { return resolve(__ep, __throw_on_error{"basic_resolver::resolve"}); } 1924 1925 results_type 1926 resolve(const endpoint_type& __ep, error_code& __ec) 1927 { return { __ep, __ec }; } 1928 1929 template<typename _CompletionToken> // TODO 1930 __deduced_t<_CompletionToken, void(error_code, results_type)> 1931 async_resolve(const endpoint_type& __ep, _CompletionToken&& __token); 1932 1933 private: 1934 io_context* _M_ctx; 1935 }; 1936 1937 /// Private constructor to synchronously resolve host and service names. 1938 template<typename _InternetProtocol> 1939 basic_resolver_results<_InternetProtocol>:: 1940 basic_resolver_results(string_view __host_name, string_view __service_name, 1941 resolver_base::flags __f, error_code& __ec, 1942 protocol_type* __protocol) 1943 { 1944#ifdef _GLIBCXX_HAVE_NETDB_H 1945 string __host; 1946 const char* __h = __host_name.data() 1947 ? (__host = __host_name.to_string()).c_str() 1948 : nullptr; 1949 string __svc; 1950 const char* __s = __service_name.data() 1951 ? (__svc = __service_name.to_string()).c_str() 1952 : nullptr; 1953 1954 ::addrinfo __hints{ }; 1955 __hints.ai_flags = static_cast<int>(__f); 1956 if (__protocol) 1957 { 1958 __hints.ai_family = __protocol->family(); 1959 __hints.ai_socktype = __protocol->type(); 1960 __hints.ai_protocol = __protocol->protocol(); 1961 } 1962 else 1963 { 1964 auto __p = endpoint_type{}.protocol(); 1965 __hints.ai_family = AF_UNSPEC; 1966 __hints.ai_socktype = __p.type(); 1967 __hints.ai_protocol = __p.protocol(); 1968 } 1969 1970 struct __scoped_addrinfo 1971 { 1972 ~__scoped_addrinfo() { if (_M_p) ::freeaddrinfo(_M_p); } 1973 ::addrinfo* _M_p = nullptr; 1974 } __sai; 1975 1976 if (int __err = ::getaddrinfo(__h, __s, &__hints, &__sai._M_p)) 1977 { 1978 __ec.assign(__err, resolver_category()); 1979 return; 1980 } 1981 __ec.clear(); 1982 1983 endpoint_type __ep; 1984 auto __tail = _M_results.before_begin(); 1985 for (auto __ai = __sai._M_p; __ai != nullptr; __ai = __ai->ai_next) 1986 { 1987 if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6) 1988 { 1989 if (__ai->ai_addrlen <= __ep.capacity()) 1990 __builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen); 1991 __ep.resize(__ai->ai_addrlen); 1992 __tail = _M_results.emplace_after(__tail, __ep, __host, __svc); 1993 _M_size++; 1994 } 1995 } 1996#else 1997 __ec = std::make_error_code(errc::operation_not_supported); 1998#endif 1999 } 2000 2001 /// Private constructor to synchronously resolve an endpoint. 2002 template<typename _InternetProtocol> 2003 basic_resolver_results<_InternetProtocol>:: 2004 basic_resolver_results(const endpoint_type& __ep, error_code& __ec) 2005 { 2006#ifdef _GLIBCXX_HAVE_NETDB_H 2007 char __host_name[256]; 2008 char __service_name[128]; 2009 int __flags = 0; 2010 if (__ep.protocol().type() == SOCK_DGRAM) 2011 __flags |= NI_DGRAM; 2012 auto __sa = static_cast<const sockaddr*>(__ep.data()); 2013 int __err = ::getnameinfo(__sa, __ep.size(), 2014 __host_name, sizeof(__host_name), 2015 __service_name, sizeof(__service_name), 2016 __flags); 2017 if (__err) 2018 { 2019 __flags |= NI_NUMERICSERV; 2020 __err = ::getnameinfo(__sa, __ep.size(), 2021 __host_name, sizeof(__host_name), 2022 __service_name, sizeof(__service_name), 2023 __flags); 2024 } 2025 if (__err) 2026 __ec.assign(__err, resolver_category()); 2027 else 2028 { 2029 __ec.clear(); 2030 _M_results.emplace_front(__ep, __host_name, __service_name); 2031 _M_size = 1; 2032 } 2033#else 2034 __ec = std::make_error_code(errc::operation_not_supported); 2035#endif 2036 } 2037 2038 /** The name of the local host. 2039 * @{ 2040 */ 2041 2042 template<typename _Allocator> 2043 __string_with<_Allocator> 2044 host_name(const _Allocator& __a, error_code& __ec) 2045 { 2046#ifdef HOST_NAME_MAX 2047 constexpr size_t __maxlen = HOST_NAME_MAX; 2048#else 2049 constexpr size_t __maxlen = 256; 2050#endif 2051 char __buf[__maxlen + 1]; 2052 if (::gethostname(__buf, __maxlen) == -1) 2053 __ec.assign(errno, generic_category()); 2054 __buf[__maxlen] = '\0'; 2055 return { __buf, __a }; 2056 } 2057 2058 template<typename _Allocator> 2059 inline __string_with<_Allocator> 2060 host_name(const _Allocator& __a) 2061 { return host_name(__a, __throw_on_error{"host_name"}); } 2062 2063 inline string 2064 host_name(error_code& __ec) 2065 { return host_name(std::allocator<char>{}, __ec); } 2066 2067 inline string 2068 host_name() 2069 { return host_name(std::allocator<char>{}, __throw_on_error{"host_name"}); } 2070 2071 /// @} 2072 2073 /// The TCP byte-stream protocol. 2074 class tcp 2075 { 2076 public: 2077 // types: 2078 typedef basic_endpoint<tcp> endpoint; ///< A TCP endpoint. 2079 typedef basic_resolver<tcp> resolver; ///< A TCP resolver. 2080 typedef basic_stream_socket<tcp> socket; ///< A TCP socket. 2081 typedef basic_socket_acceptor<tcp> acceptor; ///< A TCP acceptor. 2082 typedef basic_socket_iostream<tcp> iostream; /// A TCP iostream. 2083 2084#ifdef _GLIBCXX_HAVE_NETINET_TCP_H 2085 /// Disable coalescing of small segments (i.e. the Nagle algorithm). 2086 struct no_delay : __sockopt_crtp<no_delay, bool> 2087 { 2088 using __sockopt_crtp::__sockopt_crtp; 2089 2090 static const int _S_level = IPPROTO_TCP; 2091 static const int _S_name = TCP_NODELAY; 2092 }; 2093#endif 2094 2095 // static members: 2096 2097 /// A protocol object representing IPv4 TCP. 2098 static constexpr tcp v4() noexcept { return tcp(AF_INET); } 2099 /// A protocol object representing IPv6 TCP. 2100 static constexpr tcp v6() noexcept { return tcp(AF_INET6); } 2101 2102 tcp() = delete; 2103 2104 constexpr int family() const noexcept { return _M_family; } 2105 constexpr int type() const noexcept { return SOCK_STREAM; } 2106 constexpr int protocol() const noexcept { return IPPROTO_TCP; } 2107 2108 private: 2109 constexpr explicit tcp(int __family) : _M_family(__family) { } 2110 2111 int _M_family; 2112 }; 2113 2114 /** tcp comparisons 2115 * @{ 2116 */ 2117 2118 inline bool 2119 operator==(const tcp& __a, const tcp& __b) 2120 { return __a.family() == __b.family(); } 2121 2122 inline bool 2123 operator!=(const tcp& __a, const tcp& __b) 2124 { return !(__a == __b); } 2125 2126 /// @} 2127 2128 /// The UDP datagram protocol. 2129 class udp 2130 { 2131 public: 2132 // types: 2133 typedef basic_endpoint<udp> endpoint; 2134 typedef basic_resolver<udp> resolver; 2135 typedef basic_datagram_socket<udp> socket; 2136 2137 // static members: 2138 static constexpr udp v4() noexcept { return udp(AF_INET); } 2139 static constexpr udp v6() noexcept { return udp(AF_INET6); } 2140 2141 udp() = delete; 2142 2143 constexpr int family() const noexcept { return _M_family; } 2144 constexpr int type() const noexcept { return SOCK_DGRAM; } 2145 constexpr int protocol() const noexcept { return IPPROTO_UDP; } 2146 2147 private: 2148 constexpr explicit udp(int __family) : _M_family(__family) { } 2149 2150 int _M_family; 2151 }; 2152 2153 /** udp comparisons 2154 * @{ 2155 */ 2156 2157 inline bool 2158 operator==(const udp& __a, const udp& __b) 2159 { return __a.family() == __b.family(); } 2160 2161 inline bool 2162 operator!=(const udp& __a, const udp& __b) 2163 { return !(__a == __b); } 2164 2165 /// @} 2166 2167 /// Restrict a socket created for an IPv6 protocol to IPv6 only. 2168 struct v6_only : __sockopt_crtp<v6_only, bool> 2169 { 2170 using __sockopt_crtp::__sockopt_crtp; 2171 2172 static const int _S_level = IPPROTO_IPV6; 2173 static const int _S_name = IPV6_V6ONLY; 2174 }; 2175 2176 namespace unicast 2177 { 2178 /// Set the default number of hops (TTL) for outbound datagrams. 2179 struct hops : __sockopt_crtp<hops> 2180 { 2181 using __sockopt_crtp::__sockopt_crtp; 2182 2183 template<typename _Protocol> 2184 int 2185 level(const _Protocol& __p) const noexcept 2186 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2187 2188 template<typename _Protocol> 2189 int 2190 name(const _Protocol& __p) const noexcept 2191 { return __p.family() == AF_INET6 ? IPV6_UNICAST_HOPS : IP_TTL; } 2192 }; 2193 } // namespace unicast 2194 2195 namespace multicast 2196 { 2197 /// Request that a socket joins a multicast group. 2198 struct join_group 2199 { 2200 explicit 2201 join_group(const address&); 2202 2203 explicit 2204 join_group(const address_v4&, const address_v4& = address_v4::any()); 2205 2206 explicit 2207 join_group(const address_v6&, unsigned int = 0); 2208 2209 template<typename _Protocol> 2210 int 2211 level(const _Protocol& __p) const noexcept 2212 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2213 2214 template<typename _Protocol> 2215 int 2216 name(const _Protocol& __p) const noexcept 2217 { 2218 return __p.family() == AF_INET6 2219 ? IPV6_JOIN_GROUP : IP_ADD_MEMBERSHIP; 2220 } 2221 template<typename _Protocol> 2222 void* 2223 data(const _Protocol&) noexcept 2224 { return std::addressof(_M_value); } 2225 2226 template<typename _Protocol> 2227 const void* 2228 data(const _Protocol&) const noexcept 2229 { return std::addressof(_M_value); } 2230 2231 template<typename _Protocol> 2232 size_t 2233 size(const _Protocol& __p) const noexcept 2234 { 2235 return __p.family() == AF_INET6 2236 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4); 2237 } 2238 2239 template<typename _Protocol> 2240 void 2241 resize(const _Protocol& __p, size_t __s) 2242 { 2243 if (__s != size(__p)) 2244 __throw_length_error("invalid value for socket option resize"); 2245 } 2246 2247 protected: 2248 union 2249 { 2250 ipv6_mreq _M_v6; 2251 ip_mreq _M_v4; 2252 } _M_value; 2253 }; 2254 2255 /// Request that a socket leaves a multicast group. 2256 struct leave_group 2257 { 2258 explicit 2259 leave_group(const address&); 2260 2261 explicit 2262 leave_group(const address_v4&, const address_v4& = address_v4::any()); 2263 2264 explicit 2265 leave_group(const address_v6&, unsigned int = 0); 2266 2267 template<typename _Protocol> 2268 int 2269 level(const _Protocol& __p) const noexcept 2270 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2271 2272 template<typename _Protocol> 2273 int 2274 name(const _Protocol& __p) const noexcept 2275 { 2276 return __p.family() == AF_INET6 2277 ? IPV6_LEAVE_GROUP : IP_DROP_MEMBERSHIP; 2278 } 2279 template<typename _Protocol> 2280 void* 2281 data(const _Protocol&) noexcept 2282 { return std::addressof(_M_value); } 2283 2284 template<typename _Protocol> 2285 const void* 2286 data(const _Protocol&) const noexcept 2287 { return std::addressof(_M_value); } 2288 2289 template<typename _Protocol> 2290 size_t 2291 size(const _Protocol& __p) const noexcept 2292 { 2293 return __p.family() == AF_INET6 2294 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4); 2295 } 2296 2297 template<typename _Protocol> 2298 void 2299 resize(const _Protocol& __p, size_t __s) 2300 { 2301 if (__s != size(__p)) 2302 __throw_length_error("invalid value for socket option resize"); 2303 } 2304 2305 protected: 2306 union 2307 { 2308 ipv6_mreq _M_v6; 2309 ip_mreq _M_v4; 2310 } _M_value; 2311 }; 2312 2313 /// Specify the network interface for outgoing multicast datagrams. 2314 class outbound_interface 2315 { 2316 explicit 2317 outbound_interface(const address_v4&); 2318 2319 explicit 2320 outbound_interface(unsigned int); 2321 2322 template<typename _Protocol> 2323 int 2324 level(const _Protocol& __p) const noexcept 2325 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2326 2327 template<typename _Protocol> 2328 int 2329 name(const _Protocol& __p) const noexcept 2330 { 2331 return __p.family() == AF_INET6 2332 ? IPV6_MULTICAST_IF : IP_MULTICAST_IF; 2333 } 2334 2335 template<typename _Protocol> 2336 const void* 2337 data(const _Protocol&) const noexcept 2338 { return std::addressof(_M_value); } 2339 2340 template<typename _Protocol> 2341 size_t 2342 size(const _Protocol& __p) const noexcept 2343 { 2344 return __p.family() == AF_INET6 2345 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4); 2346 } 2347 2348 protected: 2349 union { 2350 unsigned _M_v6; 2351 in_addr _M_v4; 2352 } _M_value; 2353 }; 2354 2355 /// Set the default number of hops (TTL) for outbound datagrams. 2356 struct hops : __sockopt_crtp<hops> 2357 { 2358 using __sockopt_crtp::__sockopt_crtp; 2359 2360 template<typename _Protocol> 2361 int 2362 level(const _Protocol& __p) const noexcept 2363 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2364 2365 template<typename _Protocol> 2366 int 2367 name(const _Protocol& __p) const noexcept 2368 { 2369 return __p.family() == AF_INET6 2370 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL; 2371 } 2372 }; 2373 2374 /// Set whether datagrams are delivered back to the local application. 2375 struct enable_loopback : __sockopt_crtp<enable_loopback> 2376 { 2377 using __sockopt_crtp::__sockopt_crtp; 2378 2379 template<typename _Protocol> 2380 int 2381 level(const _Protocol& __p) const noexcept 2382 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; } 2383 2384 template<typename _Protocol> 2385 int 2386 name(const _Protocol& __p) const noexcept 2387 { 2388 return __p.family() == AF_INET6 2389 ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP; 2390 } 2391 }; 2392 2393 } // namespace multicast 2394 2395 /// @} 2396 2397} // namespace ip 2398} // namespace v1 2399} // namespace net 2400} // namespace experimental 2401 2402 template<> 2403 struct is_error_condition_enum<experimental::net::v1::ip::resolver_errc> 2404 : public true_type {}; 2405 2406 // hash support 2407 template<typename _Tp> struct hash; 2408 template<> 2409 struct hash<experimental::net::v1::ip::address> 2410 : __hash_base<size_t, experimental::net::v1::ip::address> 2411 { 2412 size_t 2413 operator()(const argument_type& __a) const 2414 { 2415 if (__a.is_v4()) 2416 return _Hash_impl::hash(__a.to_v4()); 2417 else 2418 return _Hash_impl::hash(__a.to_v6()); 2419 } 2420 }; 2421 2422 template<> 2423 struct hash<experimental::net::v1::ip::address_v4> 2424 : __hash_base<size_t, experimental::net::v1::ip::address_v4> 2425 { 2426 size_t 2427 operator()(const argument_type& __a) const 2428 { return _Hash_impl::hash(__a.to_bytes()); } 2429 }; 2430 2431 template<> struct hash<experimental::net::v1::ip::address_v6> 2432 : __hash_base<size_t, experimental::net::v1::ip::address_v6> 2433 { 2434 size_t 2435 operator()(const argument_type& __a) const 2436 { return _Hash_impl::hash(__a.to_bytes()); } 2437 }; 2438 2439_GLIBCXX_END_NAMESPACE_VERSION 2440} // namespace std 2441 2442#endif // C++14 2443 2444#endif // _GLIBCXX_EXPERIMENTAL_INTERNET 2445