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