Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/11/experimental/socket
$ cat -n /usr/include/c++/11/experimental/socket 1 //
-*- C++ -*- 2 3 // Copyright (C) 2015-2021 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 //
. 24 25 /** @file experimental/socket 26 * This is a TS C++ Library header. 27 * @ingroup networking-ts 28 */ 29 30 #ifndef _GLIBCXX_EXPERIMENTAL_SOCKET 31 #define _GLIBCXX_EXPERIMENTAL_SOCKET 32 33 #pragma GCC system_header 34 35 #if __cplusplus >= 201402L 36 37 #include
38 #include
39 #include
40 #include
41 #include
42 #include
43 #include
44 #if _GLIBCXX_HAVE_UNISTD_H 45 # include
46 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 47 # include
// socket etc 48 # endif 49 # ifdef _GLIBCXX_HAVE_SYS_IOCTL_H 50 # include
// ioctl 51 # endif 52 # ifdef _GLIBCXX_HAVE_SYS_UIO_H 53 # include
// iovec 54 # endif 55 # ifdef _GLIBCXX_HAVE_POLL_H 56 # include
// poll, pollfd, POLLIN, POLLOUT, POLLERR 57 # endif 58 # ifdef _GLIBCXX_HAVE_FCNTL_H 59 # include
// fcntl, F_GETFL, F_SETFL 60 # endif 61 #endif 62 63 namespace std _GLIBCXX_VISIBILITY(default) 64 { 65 _GLIBCXX_BEGIN_NAMESPACE_VERSION 66 namespace experimental 67 { 68 namespace net 69 { 70 inline namespace v1 71 { 72 73 /** @addtogroup networking-ts 74 * @{ 75 */ 76 77 enum class socket_errc { // TODO decide values 78 already_open = 3, 79 not_found = 4 80 }; 81 82 } // namespace v1 83 } // namespace net 84 } // namespace experimental 85 86 template<> 87 struct is_error_code_enum
88 : public true_type {}; 89 90 namespace experimental 91 { 92 namespace net 93 { 94 inline namespace v1 95 { 96 const error_category& socket_category() noexcept 97 { 98 struct __cat : error_category 99 { 100 const char* name() const noexcept { return "socket"; } 101 102 std::string message(int __e) const 103 { 104 if (__e == (int)socket_errc::already_open) 105 return "already open"; 106 else if (__e == (int)socket_errc::not_found) 107 return "endpoint not found"; 108 return "socket error"; 109 } 110 111 virtual void __message(int) { } // TODO dual ABI XXX 112 }; 113 static __cat __c; 114 return __c; 115 } 116 117 inline error_code 118 make_error_code(socket_errc __e) noexcept 119 { return error_code(static_cast
(__e), socket_category()); } 120 121 inline error_condition 122 make_error_condition(socket_errc __e) noexcept 123 { return error_condition(static_cast
(__e), socket_category()); } 124 125 126 // TODO GettableSocket reqs 127 // TODO SettableSocket reqs 128 // TODO BooleanSocketOption reqs 129 // TODO IntegerSocketOption reqs 130 // TODO IoControlCommand reqs 131 // TODO ConnectCondition reqs 132 133 /** @brief Sockets 134 * @{ 135 */ 136 137 class socket_base 138 { 139 public: 140 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 141 class broadcast : public __sockopt_crtp
142 { 143 public: 144 using __sockopt_crtp::__sockopt_crtp; 145 using __sockopt_crtp::operator=; 146 147 private: 148 friend __sockopt_crtp
; 149 static const int _S_level = SOL_SOCKET; 150 static const int _S_name = SO_BROADCAST; 151 }; 152 153 class debug : public __sockopt_crtp
154 { 155 public: 156 friend __sockopt_crtp
; 157 using __sockopt_crtp::__sockopt_crtp; 158 using __sockopt_crtp::operator=; 159 160 private: 161 static const int _S_level = SOL_SOCKET; 162 static const int _S_name = SO_DEBUG; 163 }; 164 165 class do_not_route : public __sockopt_crtp
166 { 167 public: 168 using __sockopt_crtp::__sockopt_crtp; 169 using __sockopt_crtp::operator=; 170 171 private: 172 friend __sockopt_crtp
; 173 static const int _S_level = SOL_SOCKET; 174 static const int _S_name = SO_DONTROUTE; 175 }; 176 177 class keep_alive : public __sockopt_crtp
178 { 179 public: 180 using __sockopt_crtp::__sockopt_crtp; 181 using __sockopt_crtp::operator=; 182 183 private: 184 friend __sockopt_crtp
; 185 static const int _S_level = SOL_SOCKET; 186 static const int _S_name = SO_KEEPALIVE; 187 }; 188 189 class linger : public __sockopt_crtp
190 { 191 public: 192 using __sockopt_crtp::__sockopt_crtp; 193 using __sockopt_crtp::operator=; 194 195 linger() noexcept = default; 196 197 linger(bool __e, chrono::seconds __t) noexcept 198 { 199 enabled(__e); 200 timeout(__t); 201 } 202 203 bool 204 enabled() const noexcept 205 { return _M_value.l_onoff != 0; } 206 207 void 208 enabled(bool __e) noexcept 209 { _M_value.l_onoff = int(__e); } 210 211 chrono::seconds 212 timeout() const noexcept 213 { return chrono::seconds(_M_value.l_linger); } 214 215 void 216 timeout(chrono::seconds __t) noexcept 217 { _M_value.l_linger = __t.count(); } 218 219 private: 220 friend __sockopt_crtp
; 221 static const int _S_level = SOL_SOCKET; 222 static const int _S_name = SO_LINGER; 223 }; 224 225 class out_of_band_inline : public __sockopt_crtp
226 { 227 public: 228 using __sockopt_crtp::__sockopt_crtp; 229 using __sockopt_crtp::operator=; 230 231 private: 232 friend __sockopt_crtp
; 233 static const int _S_level = SOL_SOCKET; 234 static const int _S_name = SO_OOBINLINE; 235 }; 236 237 class receive_buffer_size : public __sockopt_crtp
238 { 239 public: 240 using __sockopt_crtp::__sockopt_crtp; 241 using __sockopt_crtp::operator=; 242 243 private: 244 friend __sockopt_crtp
; 245 static const int _S_level = SOL_SOCKET; 246 static const int _S_name = SO_RCVBUF; 247 }; 248 249 class receive_low_watermark : public __sockopt_crtp
250 { 251 public: 252 using __sockopt_crtp::__sockopt_crtp; 253 using __sockopt_crtp::operator=; 254 255 private: 256 friend __sockopt_crtp
; 257 static const int _S_level = SOL_SOCKET; 258 static const int _S_name = SO_RCVLOWAT; 259 }; 260 261 class reuse_address : public __sockopt_crtp
262 { 263 public: 264 using __sockopt_crtp::__sockopt_crtp; 265 using __sockopt_crtp::operator=; 266 267 private: 268 friend __sockopt_crtp
; 269 static const int _S_level = SOL_SOCKET; 270 static const int _S_name = SO_REUSEADDR; 271 }; 272 273 class send_buffer_size : public __sockopt_crtp
274 { 275 public: 276 using __sockopt_crtp::__sockopt_crtp; 277 using __sockopt_crtp::operator=; 278 279 private: 280 friend __sockopt_crtp
; 281 static const int _S_level = SOL_SOCKET; 282 static const int _S_name = SO_SNDBUF; 283 }; 284 285 class send_low_watermark : public __sockopt_crtp
286 { 287 public: 288 using __sockopt_crtp::__sockopt_crtp; 289 using __sockopt_crtp::operator=; 290 291 private: 292 friend __sockopt_crtp
; 293 static const int _S_level = SOL_SOCKET; 294 static const int _S_name = SO_SNDLOWAT; 295 }; 296 #endif // HAVE_SYS_SOCKET_H 297 298 enum shutdown_type : int { }; 299 #if defined SHUT_RD && defined SHUT_WR && defined SHUT_RDWR 300 static constexpr shutdown_type shutdown_receive = (shutdown_type)SHUT_RD; 301 static constexpr shutdown_type shutdown_send = (shutdown_type)SHUT_WR; 302 static constexpr shutdown_type shutdown_both = (shutdown_type)SHUT_RDWR; 303 #endif 304 305 enum wait_type : int { }; 306 #ifdef _GLIBCXX_HAVE_POLL_H 307 static constexpr wait_type wait_read = (wait_type)POLLIN; 308 static constexpr wait_type wait_write = (wait_type)POLLOUT; 309 static constexpr wait_type wait_error = (wait_type)POLLERR; 310 #else 311 static constexpr wait_type wait_read = (wait_type)1; 312 static constexpr wait_type wait_write = (wait_type)2; 313 static constexpr wait_type wait_error = (wait_type)4; 314 #endif 315 316 enum message_flags : int { }; 317 #if defined MSG_PEEK && defined MSG_OOB && defined MSG_DONTROUTE 318 static constexpr message_flags message_peek 319 = (message_flags)MSG_PEEK; 320 static constexpr message_flags message_out_of_band 321 = (message_flags)MSG_OOB; 322 static constexpr message_flags message_do_not_route 323 = (message_flags)MSG_DONTROUTE; 324 #endif 325 326 #ifdef SOMAXCONN 327 static constexpr int max_listen_connections = SOMAXCONN; 328 #else 329 static constexpr int max_listen_connections = 4; 330 #endif 331 332 // message_flags bitmask operations are defined as hidden friends. 333 334 friend constexpr message_flags 335 operator&(message_flags __f1, message_flags __f2) noexcept 336 { return message_flags( int(__f1) & int(__f2) ); } 337 338 friend constexpr message_flags 339 operator|(message_flags __f1, message_flags __f2) noexcept 340 { return message_flags( int(__f1) | int(__f2) ); } 341 342 friend constexpr message_flags 343 operator^(message_flags __f1, message_flags __f2) noexcept 344 { return message_flags( int(__f1) ^ int(__f2) ); } 345 346 friend constexpr message_flags 347 operator~(message_flags __f) noexcept 348 { return message_flags( ~int(__f) ); } 349 350 friend constexpr message_flags& 351 operator&=(message_flags& __f1, message_flags __f2) noexcept 352 { return __f1 = (__f1 & __f2); } 353 354 friend constexpr message_flags& 355 operator|=(message_flags& __f1, message_flags __f2) noexcept 356 { return __f1 = (__f1 | __f2); } 357 358 friend constexpr message_flags& 359 operator^=(message_flags& __f1, message_flags __f2) noexcept 360 { return __f1 = (__f1 ^ __f2); } 361 362 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 363 protected: 364 struct __msg_hdr : ::msghdr 365 { 366 #ifdef IOV_MAX 367 using __iovec_array = array<::iovec, IOV_MAX>; 368 #elif _GLIBCXX_HAVE_UNISTD_H 369 struct __iovec_array 370 { 371 __iovec_array() : _M_ptr(new ::iovec[size()]) { } 372 373 ::iovec& operator[](size_t __n) noexcept { return _M_ptr[__n]; } 374 375 ::iovec* data() noexcept { return _M_ptr.get(); } 376 377 static size_t size() 378 { 379 static const size_t __iov_max = ::sysconf(_SC_IOV_MAX); 380 return __iov_max; 381 } 382 383 private: 384 unique_ptr<::iovec[]> _M_ptr; 385 }; 386 #else 387 using __iovec_array = array<::iovec, 16>; 388 #endif 389 390 __iovec_array _M_iov; 391 392 template
393 explicit 394 __msg_hdr(const _BufferSequence& __buffers) 395 : msghdr() 396 { 397 auto __buf = net::buffer_sequence_begin(__buffers); 398 const auto __bufend = net::buffer_sequence_end(__buffers); 399 size_t __len = 0; 400 while (__buf != __bufend && __len != _M_iov.size()) 401 { 402 _M_iov[__len].iov_base = (void*)__buf->data(); 403 _M_iov[__len].iov_len = __buf->size(); 404 ++__buf; 405 ++__len; 406 } 407 this->msg_iovlen = __len; 408 this->msg_iov = _M_iov.data(); 409 } 410 411 template
412 __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep) 413 : __msg_hdr(__buffers) 414 { 415 this->msg_name = __ep.data(); 416 this->msg_namelen = __ep.size(); 417 } 418 }; 419 #endif 420 421 protected: 422 socket_base() = default; 423 ~socket_base() = default; 424 }; 425 426 // TODO define socket_base static constants in .so for C++14 mode 427 428 #if _GLIBCXX_HAVE_UNISTD_H 429 430 class __socket_impl 431 { 432 protected: 433 434 using executor_type = io_context::executor_type; 435 using native_handle_type = int; 436 437 explicit 438 __socket_impl(io_context& __ctx) : _M_ctx(std::addressof(__ctx)) { } 439 440 __socket_impl(__socket_impl&& __rhs) 441 : _M_ctx(__rhs._M_ctx), 442 _M_sockfd(std::exchange(__rhs._M_sockfd, -1)), 443 _M_bits(std::exchange(__rhs._M_bits, {})) 444 { } 445 446 __socket_impl& 447 operator=(__socket_impl&& __rhs) 448 { 449 _M_ctx = __rhs._M_ctx; 450 _M_sockfd = std::exchange(__rhs._M_sockfd, -1); 451 _M_bits = std::exchange(__rhs._M_bits, {}); 452 return *this; 453 } 454 455 ~__socket_impl() = default; 456 457 __socket_impl(const __socket_impl&) = delete; 458 __socket_impl& operator=(const __socket_impl&) = delete; 459 460 executor_type get_executor() noexcept { return _M_ctx->get_executor(); } 461 462 native_handle_type native_handle() noexcept { return _M_sockfd; } 463 464 bool is_open() const noexcept { return _M_sockfd != -1; } 465 466 void 467 close(error_code& __ec) 468 { 469 if (is_open()) 470 { 471 cancel(__ec); 472 if (!__ec) 473 { 474 if (::close(_M_sockfd) == -1) 475 __ec.assign(errno, generic_category()); 476 else 477 { 478 get_executor().context()._M_remove_fd(_M_sockfd); 479 _M_sockfd = -1; 480 } 481 } 482 } 483 } 484 485 void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); } 486 487 void 488 non_blocking(bool __mode, error_code&) 489 { _M_bits.non_blocking = __mode; } 490 491 bool non_blocking() const { return _M_bits.non_blocking; } 492 493 void 494 native_non_blocking(bool __mode, error_code& __ec) 495 { 496 #if defined _GLIBCXX_HAVE_FCNTL_H && defined _GLIBCXX_HAVE_DECL_O_NONBLOCK 497 int __flags = ::fcntl(_M_sockfd, F_GETFL, 0); 498 if (__flags >= 0) 499 { 500 if (__mode) 501 __flags |= O_NONBLOCK; 502 else 503 __flags &= ~O_NONBLOCK; 504 __flags = ::fcntl(_M_sockfd, F_SETFL, __flags); 505 } 506 if (__flags == -1) 507 __ec.assign(errno, generic_category()); 508 else 509 { 510 __ec.clear(); 511 _M_bits.native_non_blocking = __mode; 512 } 513 #else 514 __ec = std::make_error_code(std::errc::not_supported); 515 #endif 516 } 517 518 bool 519 native_non_blocking() const 520 { 521 #if defined _GLIBCXX_HAVE_FCNTL_H && defined _GLIBCXX_HAVE_DECL_O_NONBLOCK 522 if (_M_bits.native_non_blocking == -1) 523 { 524 const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0); 525 if (__flags == -1) 526 return 0; 527 _M_bits.native_non_blocking = __flags & O_NONBLOCK; 528 } 529 return _M_bits.native_non_blocking; 530 #else 531 return false; 532 #endif 533 } 534 535 io_context* _M_ctx; 536 int _M_sockfd{-1}; 537 struct { 538 unsigned non_blocking : 1; 539 mutable signed native_non_blocking : 2; 540 unsigned enable_connection_aborted : 1; 541 } _M_bits{}; 542 }; 543 544 template
545 class __basic_socket_impl : public __socket_impl 546 { 547 using __base = __socket_impl; 548 549 protected: 550 using protocol_type = _Protocol; 551 using endpoint_type = typename protocol_type::endpoint; 552 553 explicit 554 __basic_socket_impl(io_context& __ctx) : __base(__ctx) { } 555 556 __basic_socket_impl(__basic_socket_impl&&) = default; 557 558 template
559 __basic_socket_impl(__basic_socket_impl<_OtherProtocol>&& __rhs) 560 : __base(std::move(__rhs)), _M_protocol(std::move(__rhs._M_protocol)) 561 { } 562 563 __basic_socket_impl& 564 operator=(__basic_socket_impl&& __rhs) 565 { 566 if (this == std::addressof(__rhs)) 567 return *this; 568 _M_close(); 569 __base::operator=(std::move(__rhs)); 570 return *this; 571 } 572 573 ~__basic_socket_impl() { _M_close(); } 574 575 __basic_socket_impl(const __basic_socket_impl&) = delete; 576 __basic_socket_impl& operator=(const __basic_socket_impl&) = delete; 577 578 void 579 open(const protocol_type& __protocol, error_code& __ec) 580 { 581 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 582 if (is_open()) 583 __ec = socket_errc::already_open; 584 else 585 { 586 _M_protocol = __protocol; 587 _M_sockfd = ::socket(__protocol.family(), __protocol.type(), 588 __protocol.protocol()); 589 if (is_open()) 590 { 591 get_executor().context()._M_add_fd(_M_sockfd); 592 __ec.clear(); 593 } 594 else 595 __ec.assign(errno, std::generic_category()); 596 } 597 #else 598 __ec = std::make_error_code(errc::operation_not_supported); 599 #endif 600 } 601 602 void 603 assign(const protocol_type& __protocol, 604 const native_handle_type& __native_socket, 605 error_code& __ec) 606 { 607 if (is_open()) 608 __ec = socket_errc::already_open; 609 else 610 { 611 _M_protocol = __protocol; 612 _M_bits.native_non_blocking = -1; 613 _M_sockfd = __native_socket; 614 if (is_open()) 615 { 616 get_executor().context()._M_add_fd(_M_sockfd); 617 __ec.clear(); 618 } 619 else 620 __ec.assign(errno, std::generic_category()); 621 } 622 } 623 624 native_handle_type release(error_code& __ec) 625 { 626 __glibcxx_assert(is_open()); 627 cancel(__ec); 628 return std::exchange(_M_sockfd, -1); 629 } 630 631 template
632 void 633 set_option(const _SettableSocketOption& __option, error_code& __ec) 634 { 635 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 636 int __result = ::setsockopt(_M_sockfd, __option.level(_M_protocol), 637 __option.name(_M_protocol), 638 __option.data(_M_protocol), 639 __option.size(_M_protocol)); 640 if (__result == -1) 641 __ec.assign(errno, generic_category()); 642 else 643 __ec.clear(); 644 #else 645 __ec = std::make_error_code(std::errc::not_supported); 646 #endif 647 } 648 649 template
650 void 651 get_option(_GettableSocketOption& __option, error_code& __ec) const 652 { 653 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 654 int __result = ::getsockopt(_M_sockfd, __option.level(_M_protocol), 655 __option.name(_M_protocol), 656 __option.data(_M_protocol), 657 __option.size(_M_protocol)); 658 if (__result == -1) 659 __ec.assign(errno, generic_category()); 660 else 661 __ec.clear(); 662 #else 663 __ec = std::make_error_code(std::errc::not_supported); 664 #endif 665 } 666 667 template
668 void 669 io_control(_IoControlCommand& __command, error_code& __ec) 670 { 671 #ifdef _GLIBCXX_HAVE_SYS_IOCTL_H 672 int __result = ::ioctl(_M_sockfd, __command.name(), 673 __command.data()); 674 if (__result == -1) 675 __ec.assign(errno, generic_category()); 676 else 677 __ec.clear(); 678 #else 679 __ec = std::make_error_code(std::errc::not_supported); 680 #endif 681 } 682 683 endpoint_type 684 local_endpoint(error_code& __ec) const 685 { 686 endpoint_type __endpoint; 687 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 688 socklen_t __endpoint_len = __endpoint.capacity(); 689 if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(), 690 &__endpoint_len) == -1) 691 { 692 __ec.assign(errno, generic_category()); 693 return endpoint_type{}; 694 } 695 __ec.clear(); 696 __endpoint.resize(__endpoint_len); 697 #else 698 __ec = std::make_error_code(errc::operation_not_supported); 699 #endif 700 return __endpoint; 701 } 702 703 void 704 bind(const endpoint_type& __endpoint, error_code& __ec) 705 { 706 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 707 if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size()) 708 == -1) 709 __ec.assign(errno, generic_category()); 710 else 711 __ec.clear(); 712 #else 713 __ec = std::make_error_code(errc::operation_not_supported); 714 #endif 715 } 716 717 _Protocol _M_protocol{ endpoint_type{}.protocol() }; 718 719 private: 720 void 721 _M_close() 722 { 723 if (is_open()) 724 { 725 error_code __ec; 726 cancel(__ec); 727 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 728 set_option(socket_base::linger{false, chrono::seconds{}}, __ec); 729 #endif 730 ::close(_M_sockfd); 731 } 732 } 733 }; 734 735 template
736 class basic_socket 737 : public socket_base, private __basic_socket_impl<_Protocol> 738 { 739 using __base = __basic_socket_impl<_Protocol>; 740 741 public: 742 // types: 743 744 using executor_type = io_context::executor_type; 745 using native_handle_type = int; 746 using protocol_type = _Protocol; 747 using endpoint_type = typename protocol_type::endpoint; 748 749 static_assert(__detail::__protocol
, 750 "protocol_type meets the Protocol requirements"); 751 752 // basic_socket operations: 753 754 executor_type get_executor() noexcept { return __base::get_executor(); } 755 756 native_handle_type 757 native_handle() noexcept { return __base::native_handle(); } 758 759 void 760 open(const protocol_type& __protocol = protocol_type()) 761 { open(__protocol, __throw_on_error{"basic_socket::open"}); } 762 763 void 764 open(const protocol_type& __protocol, error_code& __ec) 765 { __base::open(__protocol, __ec); } 766 767 void 768 assign(const protocol_type& __protocol, 769 const native_handle_type& __native_socket) 770 { 771 assign(__protocol, __native_socket, 772 __throw_on_error{"basic_socket::assign"}); 773 } 774 775 void 776 assign(const protocol_type& __protocol, 777 const native_handle_type& __native_socket, 778 error_code& __ec) 779 { __base::assign(__protocol, __native_socket, __ec); } 780 781 native_handle_type release() 782 { return release(__throw_on_error{"basic_socket::release"}); } 783 784 native_handle_type release(error_code& __ec) 785 { return __base::release(__ec); } 786 787 _GLIBCXX_NODISCARD bool 788 is_open() const noexcept { return __base::is_open(); } 789 790 void close() { close(__throw_on_error{"basic_socket::close"}); } 791 792 void close(error_code& __ec) { __base::close(__ec); } 793 794 void cancel() { cancel(__throw_on_error{"basic_socket::cancel"}); } 795 796 void cancel(error_code& __ec) { __base::cancel(__ec); } 797 798 template
799 void 800 set_option(const _SettableSocketOption& __option) 801 { set_option(__option, __throw_on_error{"basic_socket::set_option"}); } 802 803 template
804 void 805 set_option(const _SettableSocketOption& __option, error_code& __ec) 806 { __base::set_option(__option, __ec); } 807 808 template
809 void 810 get_option(_GettableSocketOption& __option) const 811 { get_option(__option, __throw_on_error{"basic_socket::get_option"}); } 812 813 template
814 void 815 get_option(_GettableSocketOption& __option, error_code& __ec) const 816 { __base::get_option(__option, __ec); } 817 818 template
819 void 820 io_control(_IoControlCommand& __command) 821 { 822 io_control(__command, __throw_on_error{"basic_socket::io_control"}); 823 } 824 825 template
826 void 827 io_control(_IoControlCommand& __command, error_code& __ec) 828 { __base::io_control(__command, __ec); } 829 830 void 831 non_blocking(bool __mode) 832 { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); } 833 834 void 835 non_blocking(bool __mode, error_code& __ec) 836 { __base::non_blocking(__mode, __ec); } 837 838 bool non_blocking() const { return __base::non_blocking(); } 839 840 void 841 native_non_blocking(bool __mode) 842 { 843 native_non_blocking(__mode, __throw_on_error{ 844 "basic_socket::native_non_blocking"}); 845 } 846 847 void 848 native_non_blocking(bool __mode, error_code& __ec) 849 { __base::native_non_blocking(__mode, __ec); } 850 851 bool 852 native_non_blocking() const 853 { return __base::native_non_blocking(); } 854 855 bool at_mark() const 856 { return at_mark(__throw_on_error{"basic_socket::at_mark"}); } 857 858 bool 859 at_mark(error_code& __ec) const 860 { 861 #ifdef _GLIBCXX_HAVE_SOCKATMARK 862 const int __result = ::sockatmark(native_handle()); 863 if (__result == -1) 864 { 865 __ec.assign(errno, generic_category()); 866 return false; 867 } 868 __ec.clear(); 869 return (bool)__result; 870 #else 871 __ec = std::make_error_code(errc::operation_not_supported); 872 return false; 873 #endif 874 } 875 876 size_t 877 available() const 878 { return available(__throw_on_error{"basic_socket::available"}); } 879 880 size_t 881 available(error_code& __ec) const 882 { 883 if (!is_open()) 884 { 885 __ec = std::make_error_code(errc::bad_file_descriptor); 886 return 0; 887 } 888 #if defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined FIONREAD 889 int __avail = 0; 890 if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1) 891 { 892 __ec.assign(errno, generic_category()); 893 return 0; 894 } 895 __ec.clear(); 896 return __avail; 897 #else 898 return 0; 899 #endif 900 } 901 902 void 903 bind(const endpoint_type& __endpoint) 904 { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); } 905 906 void 907 bind(const endpoint_type& __endpoint, error_code& __ec) 908 { __base::bind(__endpoint, __ec); } 909 910 void shutdown(shutdown_type __what) 911 { return shutdown(__what, __throw_on_error{"basic_socket::shutdown"}); } 912 913 void 914 shutdown(shutdown_type __what, error_code& __ec) 915 { 916 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 917 if (::shutdown(native_handle(), static_cast
(__what)) == -1) 918 __ec.assign(errno, generic_category()); 919 else 920 __ec.clear(); 921 #else 922 __ec = std::make_error_code(errc::operation_not_supported); 923 #endif 924 } 925 926 endpoint_type 927 local_endpoint() const 928 { 929 return local_endpoint( 930 __throw_on_error{"basic_socket::local_endpoint"}); 931 } 932 933 endpoint_type 934 local_endpoint(error_code& __ec) const 935 { return __base::local_endpoint(__ec); } 936 937 endpoint_type 938 remote_endpoint() const 939 { 940 return remote_endpoint( 941 __throw_on_error{"basic_socket::remote_endpoint"}); 942 } 943 944 endpoint_type 945 remote_endpoint(error_code& __ec) const 946 { 947 endpoint_type __endpoint; 948 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 949 socklen_t __endpoint_len = __endpoint.capacity(); 950 if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(), 951 &__endpoint_len) 952 == -1) 953 { 954 __ec.assign(errno, generic_category()); 955 return endpoint_type{}; 956 } 957 __ec.clear(); 958 __endpoint.resize(__endpoint_len); 959 #else 960 __ec = std::make_error_code(errc::operation_not_supported); 961 #endif 962 return __endpoint; 963 } 964 965 void 966 connect(const endpoint_type& __endpoint) 967 { 968 return connect(__endpoint, __throw_on_error{"basic_socket::connect"}); 969 } 970 971 void 972 connect(const endpoint_type& __endpoint, error_code& __ec) 973 { 974 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 975 if (!is_open()) 976 { 977 open(__endpoint.protocol(), __ec); 978 if (__ec) 979 return; 980 } 981 if (::connect(native_handle(), (const sockaddr*)__endpoint.data(), 982 __endpoint.size()) == -1) 983 __ec.assign(errno, generic_category()); 984 else 985 __ec.clear(); 986 #else 987 __ec = std::make_error_code(errc::operation_not_supported); 988 #endif 989 } 990 991 template
992 __deduced_t<_CompletionToken, void(error_code)> 993 async_connect(const endpoint_type& __endpoint, 994 _CompletionToken&& __token) 995 { 996 async_completion<_CompletionToken, void(error_code)> __init{__token}; 997 998 if (!is_open()) 999 { 1000 error_code __ec; 1001 open(__endpoint.protocol(), __ec); 1002 if (__ec) 1003 { 1004 auto __ex = net::get_associated_executor( 1005 __init.completion_handler, get_executor()); 1006 auto __a = get_associated_allocator( 1007 __init.completion_handler, std::allocator
()); 1008 __ex.post( 1009 [__h = std::move(__init.completion_handler), __ec] 1010 () mutable 1011 { __h(__ec); }, __a); 1012 return __init.result.get(); 1013 } 1014 } 1015 1016 get_executor().context().async_wait( native_handle(), 1017 (int) socket_base::wait_read, 1018 [__h = std::move(__init.completion_handler), 1019 __ep = std::move(__endpoint), 1020 __fd = native_handle()] 1021 (error_code __ec) mutable { 1022 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1023 if (!__ec && ::connect(__fd, (const sockaddr*)__ep.data(), 1024 __ep.size()) == -1) 1025 __ec.assign(errno, generic_category()); 1026 #else 1027 __ec = std::make_error_code(errc::operation_not_supported); 1028 #endif 1029 __h(__ec); 1030 }); 1031 return __init.result.get(); 1032 } 1033 1034 void 1035 wait(wait_type __w) 1036 { return wait(__w, __throw_on_error{"basic_socket::wait"}); } 1037 1038 void 1039 wait(wait_type __w, error_code& __ec) 1040 { 1041 #ifdef _GLIBCXX_HAVE_POLL_H 1042 ::pollfd __fd; 1043 __fd.fd = native_handle(); 1044 __fd.events = static_cast
(__w); 1045 int __res = ::poll(&__fd, 1, -1); 1046 if (__res == -1) 1047 __ec.assign(errno, generic_category()); 1048 else 1049 __ec.clear(); 1050 #else 1051 __ec = std::make_error_code(errc::operation_not_supported); 1052 #endif 1053 } 1054 1055 template
1056 __deduced_t<_CompletionToken, void(error_code)> 1057 async_wait(wait_type __w, _CompletionToken&& __token) 1058 { 1059 async_completion<_CompletionToken, void(error_code)> __init{__token}; 1060 get_executor().context().async_wait( native_handle(), 1061 static_cast
(__w), 1062 [__h = std::move(__init.completion_handler)] 1063 (error_code __ec) mutable { 1064 __h(__ec); 1065 }); 1066 return __init.result.get(); 1067 } 1068 1069 protected: 1070 // construct / copy / destroy: 1071 1072 using __base::__base; 1073 1074 explicit 1075 basic_socket(io_context& __ctx) : __base(__ctx) { } 1076 1077 basic_socket(io_context& __ctx, const protocol_type& __protocol) 1078 : __base(__ctx) 1079 { open(__protocol); } 1080 1081 basic_socket(io_context& __ctx, const endpoint_type& __endpoint) 1082 : basic_socket(__ctx, __endpoint.protocol()) 1083 { bind(__endpoint); } 1084 1085 basic_socket(io_context& __ctx, const protocol_type& __protocol, 1086 const native_handle_type& __native_socket) 1087 : __base(__ctx) 1088 { assign(__protocol, __native_socket); } 1089 1090 basic_socket(const basic_socket&) = delete; 1091 1092 basic_socket(basic_socket&& __rhs) = default; 1093 1094 template
>> 1096 basic_socket(basic_socket<_OtherProtocol>&& __rhs) 1097 : __base(std::move(__rhs)) { } 1098 1099 ~basic_socket() = default; 1100 1101 basic_socket& operator=(const basic_socket&) = delete; 1102 1103 basic_socket& operator=(basic_socket&& __rhs) = default; 1104 1105 template
1106 enable_if_t
::value, 1107 basic_socket&> 1108 operator=(basic_socket<_OtherProtocol>&& __rhs) 1109 { return *this = basic_socket{std::move(__rhs)}; } 1110 }; 1111 1112 template
1113 class basic_datagram_socket : public basic_socket<_Protocol> 1114 { 1115 using __base = basic_socket<_Protocol>; 1116 1117 public: 1118 // types: 1119 1120 using native_handle_type = int; 1121 using protocol_type = _Protocol; 1122 using endpoint_type = typename protocol_type::endpoint; 1123 1124 // construct / copy / destroy: 1125 1126 explicit 1127 basic_datagram_socket(io_context& __ctx) : __base(__ctx) { } 1128 1129 basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol) 1130 : __base(__ctx, __protocol) { } 1131 1132 basic_datagram_socket(io_context& __ctx, const endpoint_type& __endpoint) 1133 : __base(__ctx, __endpoint) { } 1134 1135 basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol, 1136 const native_handle_type& __native_socket) 1137 : __base(__ctx, __protocol, __native_socket) { } 1138 1139 basic_datagram_socket(const basic_datagram_socket&) = delete; 1140 1141 basic_datagram_socket(basic_datagram_socket&& __rhs) = default; 1142 1143 template
>> 1145 basic_datagram_socket(basic_datagram_socket<_OtherProtocol>&& __rhs) 1146 : __base(std::move(__rhs)) { } 1147 1148 ~basic_datagram_socket() = default; 1149 1150 basic_datagram_socket& operator=(const basic_datagram_socket&) = delete; 1151 1152 basic_datagram_socket& operator=(basic_datagram_socket&& __rhs) = default; 1153 1154 template
1155 enable_if_t
::value, 1156 basic_datagram_socket&> 1157 operator=(basic_datagram_socket<_OtherProtocol>&& __rhs) 1158 { 1159 __base::operator=(std::move(__rhs)); 1160 return *this; 1161 } 1162 1163 // basic_datagram_socket operations: 1164 1165 template
1166 size_t 1167 receive(const _MutableBufferSequence& __buffers) 1168 { 1169 return receive(__buffers, socket_base::message_flags(), 1170 __throw_on_error{"basic_datagram_socket::receive"}); 1171 } 1172 1173 template
1174 size_t 1175 receive(const _MutableBufferSequence& __buffers, error_code& __ec) 1176 { return receive(__buffers, socket_base::message_flags(), __ec); } 1177 1178 template
1179 size_t 1180 receive(const _MutableBufferSequence& __buffers, 1181 socket_base::message_flags __flags) 1182 { 1183 return receive(__buffers, __flags, 1184 __throw_on_error{"basic_datagram_socket::receive"}); 1185 } 1186 1187 template
1188 size_t 1189 receive(const _MutableBufferSequence& __buffers, 1190 socket_base::message_flags __flags, error_code& __ec) 1191 { 1192 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1193 socket_base::__msg_hdr __msg(__buffers); 1194 ssize_t __result = ::recvmsg(this->native_handle(), &__msg, 1195 static_cast
(__flags)); 1196 if (__result == -1) 1197 { 1198 __ec.assign(errno, generic_category()); 1199 return 0; 1200 } 1201 __ec.clear(); 1202 return __result; 1203 #else 1204 __ec = std::make_error_code(errc::operation_not_supported); 1205 return 0; 1206 #endif 1207 } 1208 1209 template
1210 __deduced_t<_CompletionToken, void(error_code, size_t)> 1211 async_receive(const _MutableBufferSequence& __buffers, 1212 _CompletionToken&& __token) 1213 { 1214 return async_receive(__buffers, socket_base::message_flags(), 1215 std::forward<_CompletionToken>(__token)); 1216 } 1217 1218 template
1219 __deduced_t<_CompletionToken, void(error_code, size_t)> 1220 async_receive(const _MutableBufferSequence& __buffers, 1221 socket_base::message_flags __flags, 1222 _CompletionToken&& __token) 1223 { 1224 async_completion<_CompletionToken, void(error_code, size_t)> 1225 __init{__token}; 1226 1227 this->get_executor().context().async_wait(this->native_handle(), 1228 (int) socket_base::wait_read, 1229 [__h = std::move(__init.completion_handler), 1230 &__buffers, __flags = static_cast
(__flags), 1231 __fd = this->native_handle()] 1232 (error_code __ec) mutable { 1233 if (__ec) 1234 { 1235 __h(__ec); 1236 return; 1237 } 1238 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1239 socket_base::__msg_hdr __msg(__buffers); 1240 ssize_t __result = ::recvmsg(__fd, &__msg, __flags); 1241 if (__result == -1) 1242 { 1243 __ec.assign(errno, generic_category()); 1244 __result = 0; 1245 } 1246 else 1247 __ec.clear(); 1248 __h(__ec, __result); 1249 #else 1250 __h(std::make_error_code(errc::operation_not_supported), 0); 1251 #endif 1252 }); 1253 return __init.result.get(); 1254 } 1255 1256 template
1257 size_t 1258 receive_from(const _MutableBufferSequence& __buffers, 1259 endpoint_type& __sender) 1260 { 1261 return receive_from(__buffers, __sender, 1262 socket_base::message_flags(), 1263 __throw_on_error{ 1264 "basic_datagram_socket::receive_from"}); 1265 } 1266 1267 template
1268 size_t 1269 receive_from(const _MutableBufferSequence& __buffers, 1270 endpoint_type& __sender, error_code& __ec) 1271 { 1272 return receive_from(__buffers, __sender, 1273 socket_base::message_flags(), __ec); 1274 } 1275 1276 template
1277 size_t 1278 receive_from(const _MutableBufferSequence& __buffers, 1279 endpoint_type& __sender, 1280 socket_base::message_flags __flags) 1281 { 1282 return receive_from(__buffers, __sender, __flags, 1283 __throw_on_error{ 1284 "basic_datagram_socket::receive_from"}); 1285 } 1286 1287 template
1288 size_t 1289 receive_from(const _MutableBufferSequence& __buffers, 1290 endpoint_type& __sender, 1291 socket_base::message_flags __flags, 1292 error_code& __ec) 1293 { 1294 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1295 socket_base::__msg_hdr __msg(__buffers, __sender); 1296 ssize_t __result = ::recvmsg(this->native_handle(), &__msg, 1297 static_cast
(__flags)); 1298 if (__result == -1) 1299 { 1300 __ec.assign(errno, generic_category()); 1301 return 0; 1302 } 1303 __ec.clear(); 1304 __sender.resize(__msg.msg_namelen); 1305 return __result; 1306 #else 1307 __ec = std::make_error_code(errc::operation_not_supported); 1308 return 0; 1309 #endif 1310 } 1311 1312 template
1313 __deduced_t<_CompletionToken, void(error_code, size_t)> 1314 async_receive_from(const _MutableBufferSequence& __buffers, 1315 endpoint_type& __sender, 1316 _CompletionToken&& __token) 1317 { 1318 return async_receive_from(__buffers, __sender, 1319 socket_base::message_flags(), 1320 std::forward<_CompletionToken>(__token)); 1321 } 1322 1323 template
1324 __deduced_t<_CompletionToken, void(error_code, size_t)> 1325 async_receive_from(const _MutableBufferSequence& __buffers, 1326 endpoint_type& __sender, 1327 socket_base::message_flags __flags, 1328 _CompletionToken&& __token) 1329 { 1330 async_completion<_CompletionToken, void(error_code, size_t)> 1331 __init{__token}; 1332 1333 this->get_executor().context().async_wait( this->native_handle(), 1334 (int) socket_base::wait_read, 1335 [__h = std::move(__init.completion_handler), 1336 &__buffers, __flags = static_cast
(__flags), 1337 __sender = std::move(__sender), 1338 __fd = this->native_handle()] 1339 (error_code __ec) mutable { 1340 if (__ec) 1341 { 1342 __h(__ec); 1343 return; 1344 } 1345 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1346 socket_base::__msg_hdr __msg(__buffers, __sender); 1347 ssize_t __result = ::recvmsg(__fd, &__msg, __flags); 1348 if (__result == -1) 1349 { 1350 __ec.assign(errno, generic_category()); 1351 __result = 0; 1352 } 1353 else 1354 { 1355 __ec.clear(); 1356 __sender.resize(__msg.msg_namelen); 1357 } 1358 __h(__ec, __result); 1359 #else 1360 __h(std::make_error_code(errc::operation_not_supported), 0); 1361 #endif 1362 }); 1363 return __init.result.get(); 1364 } 1365 1366 template
1367 size_t 1368 send(const _ConstBufferSequence& __buffers) 1369 { 1370 return send(__buffers, socket_base::message_flags(), 1371 __throw_on_error{"basic_datagram_socket::send"}); 1372 } 1373 1374 template
1375 size_t 1376 send(const _ConstBufferSequence& __buffers, error_code& __ec) 1377 { return send(__buffers, socket_base::message_flags(), __ec); } 1378 1379 template
1380 size_t 1381 send(const _ConstBufferSequence& __buffers, 1382 socket_base::message_flags __flags) 1383 { 1384 return send(__buffers, __flags, 1385 __throw_on_error{"basic_datagram_socket::send"}); 1386 } 1387 1388 template
1389 size_t 1390 send(const _ConstBufferSequence& __buffers, 1391 socket_base::message_flags __flags, error_code& __ec) 1392 { 1393 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1394 socket_base::__msg_hdr __msg(__buffers); 1395 ssize_t __result = ::sendmsg(this->native_handle(), &__msg, 1396 static_cast
(__flags)); 1397 if (__result == -1) 1398 { 1399 __ec.assign(errno, generic_category()); 1400 return 0; 1401 } 1402 __ec.clear(); 1403 return __result; 1404 #else 1405 __ec = std::make_error_code(errc::operation_not_supported); 1406 return 0; 1407 #endif 1408 } 1409 1410 template
1411 __deduced_t<_CompletionToken, void(error_code, size_t)> 1412 async_send(const _ConstBufferSequence& __buffers, 1413 _CompletionToken&& __token) 1414 { 1415 return async_send(__buffers, socket_base::message_flags(), 1416 std::forward<_CompletionToken>(__token)); 1417 } 1418 1419 template
1420 __deduced_t<_CompletionToken, void(error_code, size_t)> 1421 async_send(const _ConstBufferSequence& __buffers, 1422 socket_base::message_flags __flags, 1423 _CompletionToken&& __token) 1424 { 1425 async_completion<_CompletionToken, void(error_code, size_t)> 1426 __init{__token}; 1427 1428 this->get_executor().context().async_wait( this->native_handle(), 1429 (int) socket_base::wait_write, 1430 [__h = std::move(__init.completion_handler), 1431 &__buffers, __flags = static_cast
(__flags), 1432 __fd = this->native_handle()] 1433 (error_code __ec) mutable { 1434 if (__ec) 1435 { 1436 __h(__ec); 1437 return; 1438 } 1439 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1440 socket_base::__msg_hdr __msg(__buffers); 1441 ssize_t __result = ::sendmsg(__fd, &__msg, __flags); 1442 if (__result == -1) 1443 { 1444 __ec.assign(errno, generic_category()); 1445 __result = 0; 1446 } 1447 else 1448 __ec.clear(); 1449 __h(__ec, __result); 1450 #else 1451 __h(std::make_error_code(errc::operation_not_supported), 0); 1452 #endif 1453 }); 1454 return __init.result.get(); 1455 } 1456 1457 template
1458 size_t 1459 send_to(const _ConstBufferSequence& __buffers, 1460 const endpoint_type& __recipient) 1461 { 1462 return send_to(__buffers, __recipient, 1463 socket_base::message_flags(), 1464 __throw_on_error{"basic_datagram_socket::send_to"}); 1465 } 1466 1467 template
1468 size_t 1469 send_to(const _ConstBufferSequence& __buffers, 1470 const endpoint_type& __recipient, error_code& __ec) 1471 { 1472 return send_to(__buffers, __recipient, 1473 socket_base::message_flags(), __ec); 1474 } 1475 1476 template
1477 size_t 1478 send_to(const _ConstBufferSequence& __buffers, 1479 const endpoint_type& __recipient, 1480 socket_base::message_flags __flags) 1481 { 1482 return send_to(__buffers, __recipient, __flags, 1483 __throw_on_error{"basic_datagram_socket::send_to"}); 1484 } 1485 1486 template
1487 size_t 1488 send_to(const _ConstBufferSequence& __buffers, 1489 const endpoint_type& __recipient, 1490 socket_base::message_flags __flags, error_code& __ec) 1491 { 1492 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1493 socket_base::__msg_hdr __msg(__buffers, __recipient); 1494 ssize_t __result = ::sendmsg(this->native_handle(), &__msg, 1495 static_cast
(__flags)); 1496 if (__result == -1) 1497 { 1498 __ec.assign(errno, generic_category()); 1499 return 0; 1500 } 1501 __ec.clear(); 1502 __recipient.resize(__msg.msg_namelen); 1503 return __result; 1504 #else 1505 __ec = std::make_error_code(errc::operation_not_supported); 1506 return 0; 1507 #endif 1508 } 1509 1510 template
1511 __deduced_t<_CompletionToken, void(error_code, size_t)> 1512 async_send_to(const _ConstBufferSequence& __buffers, 1513 const endpoint_type& __recipient, 1514 _CompletionToken&& __token) 1515 { 1516 return async_send_to(__buffers, __recipient, 1517 socket_base::message_flags(), 1518 std::forward<_CompletionToken>(__token)); 1519 } 1520 1521 template
1522 __deduced_t<_CompletionToken, void(error_code, size_t)> 1523 async_send_to(const _ConstBufferSequence& __buffers, 1524 const endpoint_type& __recipient, 1525 socket_base::message_flags __flags, 1526 _CompletionToken&& __token) 1527 { 1528 async_completion<_CompletionToken, void(error_code, size_t)> 1529 __init{__token}; 1530 1531 this->get_executor().context().async_wait( this->native_handle(), 1532 (int) socket_base::wait_write, 1533 [__h = std::move(__init.completion_handler), 1534 &__buffers, __flags = static_cast
(__flags), 1535 __recipient = std::move(__recipient), 1536 __fd = this->native_handle()] 1537 (error_code __ec) mutable { 1538 if (__ec) 1539 { 1540 __h(__ec); 1541 return; 1542 } 1543 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1544 socket_base::__msg_hdr __msg(__buffers, __recipient); 1545 ssize_t __result = ::sendmsg(__fd, &__msg, __flags); 1546 if (__result == -1) 1547 { 1548 __ec.assign(errno, generic_category()); 1549 __result = 0; 1550 } 1551 else 1552 { 1553 __ec.clear(); 1554 __recipient.resize(__msg.msg_namelen); 1555 } 1556 __h(__ec, __result); 1557 #else 1558 __h(std::make_error_code(errc::operation_not_supported), 0); 1559 #endif 1560 }); 1561 return __init.result.get(); 1562 } 1563 }; 1564 1565 template
1566 class basic_stream_socket : public basic_socket<_Protocol> 1567 { 1568 using __base = basic_socket<_Protocol>; 1569 1570 public: 1571 // types: 1572 1573 using native_handle_type = int; 1574 using protocol_type = _Protocol; 1575 using endpoint_type = typename protocol_type::endpoint; 1576 1577 // construct / copy / destroy: 1578 1579 explicit 1580 basic_stream_socket(io_context& __ctx) : __base(__ctx) { } 1581 1582 basic_stream_socket(io_context& __ctx, const protocol_type& __protocol) 1583 : __base(__ctx, __protocol) { } 1584 1585 basic_stream_socket(io_context& __ctx, const endpoint_type& __endpoint) 1586 : __base(__ctx, __endpoint) { } 1587 1588 basic_stream_socket(io_context& __ctx, const protocol_type& __protocol, 1589 const native_handle_type& __native_socket) 1590 : __base(__ctx, __protocol, __native_socket) { } 1591 1592 basic_stream_socket(const basic_stream_socket&) = delete; 1593 1594 basic_stream_socket(basic_stream_socket&& __rhs) = default; 1595 1596 template
>> 1598 basic_stream_socket(basic_stream_socket<_OtherProtocol>&& __rhs) 1599 : __base(std::move(__rhs)) { } 1600 1601 ~basic_stream_socket() = default; 1602 1603 basic_stream_socket& operator=(const basic_stream_socket&) = delete; 1604 1605 basic_stream_socket& operator=(basic_stream_socket&& __rhs) = default; 1606 1607 template
1608 enable_if_t
::value, 1609 basic_stream_socket&> 1610 operator=(basic_stream_socket<_OtherProtocol>&& __rhs) 1611 { 1612 __base::operator=(std::move(__rhs)); 1613 return *this; 1614 } 1615 1616 // basic_stream_socket operations: 1617 1618 template
1619 size_t 1620 receive(const _MutableBufferSequence& __buffers) 1621 { 1622 return receive(__buffers, socket_base::message_flags(), 1623 __throw_on_error{"basic_stream_socket::receive"}); 1624 } 1625 1626 template
1627 size_t 1628 receive(const _MutableBufferSequence& __buffers, error_code& __ec) 1629 { return receive(__buffers, socket_base::message_flags(), __ec); } 1630 1631 template
1632 size_t 1633 receive(const _MutableBufferSequence& __buffers, 1634 socket_base::message_flags __flags) 1635 { 1636 return receive(__buffers, __flags, 1637 __throw_on_error{"basic_stream_socket::receive"}); 1638 } 1639 1640 template
1641 size_t 1642 receive(const _MutableBufferSequence& __buffers, 1643 socket_base::message_flags __flags, error_code& __ec) 1644 { 1645 if (__buffer_empty(__buffers)) 1646 { 1647 __ec.clear(); 1648 return 0; 1649 } 1650 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1651 socket_base::__msg_hdr __msg(__buffers); 1652 ssize_t __result = ::recvmsg(this->native_handle(), &__msg, 1653 static_cast
(__flags)); 1654 if (__result >= 0) 1655 { 1656 __ec.clear(); 1657 return __result; 1658 } 1659 __ec.assign(errno, generic_category()); 1660 #else 1661 __ec = std::make_error_code(errc::operation_not_supported); 1662 #endif 1663 return 0; 1664 } 1665 1666 template
1667 __deduced_t<_CompletionToken, void(error_code, size_t)> 1668 async_receive(const _MutableBufferSequence& __buffers, 1669 _CompletionToken&& __token) 1670 { 1671 return async_receive(__buffers, socket_base::message_flags(), 1672 std::forward<_CompletionToken>(__token)); 1673 } 1674 1675 template
1676 __deduced_t<_CompletionToken, void(error_code, size_t)> 1677 async_receive(const _MutableBufferSequence& __buffers, 1678 socket_base::message_flags __flags, 1679 _CompletionToken&& __token) 1680 { 1681 async_completion<_CompletionToken, void(error_code, size_t)> 1682 __init{__token}; 1683 1684 if (__buffer_empty(__buffers)) 1685 { 1686 auto __ex = net::get_associated_executor( 1687 __init.completion_handler, this->get_executor()); 1688 auto __a = get_associated_allocator( 1689 __init.completion_handler, std::allocator
()); 1690 __ex.post( 1691 [__h=std::move(__init.completion_handler)] () mutable 1692 { __h(error_code{}, 0); }, __a); 1693 return __init.result.get(); 1694 } 1695 1696 this->get_executor().context().async_wait(this->native_handle(), 1697 (int) socket_base::wait_read, 1698 [__h = std::move(__init.completion_handler), 1699 &__buffers, __flags = static_cast
(__flags), 1700 __fd = this->native_handle()] 1701 (error_code __ec) mutable { 1702 if (__ec) 1703 { 1704 __h(__ec); 1705 return; 1706 } 1707 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1708 socket_base::__msg_hdr __msg(__buffers); 1709 ssize_t __result = ::recvmsg(__fd, &__msg, __flags); 1710 if (__result == -1) 1711 { 1712 __ec.assign(errno, generic_category()); 1713 __result = 0; 1714 } 1715 else 1716 __ec.clear(); 1717 __h(__ec, __result); 1718 #else 1719 __h(std::make_error_code(errc::operation_not_supported), 0); 1720 #endif 1721 }); 1722 return __init.result.get(); 1723 } 1724 1725 template
1726 size_t 1727 send(const _ConstBufferSequence& __buffers) 1728 { 1729 return send(__buffers, socket_base::message_flags(), 1730 __throw_on_error{"basic_stream_socket::send"}); 1731 } 1732 1733 template
1734 size_t 1735 send(const _ConstBufferSequence& __buffers, error_code& __ec) 1736 { return send(__buffers, socket_base::message_flags(), __ec); } 1737 1738 template
1739 size_t 1740 send(const _ConstBufferSequence& __buffers, 1741 socket_base::message_flags __flags) 1742 { 1743 return send(__buffers, socket_base::message_flags(), 1744 __throw_on_error{"basic_stream_socket::send"}); 1745 } 1746 1747 template
1748 size_t 1749 send(const _ConstBufferSequence& __buffers, 1750 socket_base::message_flags __flags, error_code& __ec) 1751 { 1752 if (__buffer_empty(__buffers)) 1753 { 1754 __ec.clear(); 1755 return 0; 1756 } 1757 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1758 socket_base::__msg_hdr __msg(__buffers); 1759 ssize_t __result = ::sendmsg(this->native_handle(), &__msg, 1760 static_cast
(__flags)); 1761 if (__result >= 0) 1762 { 1763 __ec.clear(); 1764 return __result; 1765 } 1766 __ec.assign(errno, generic_category()); 1767 #else 1768 __ec = std::make_error_code(errc::operation_not_supported); 1769 #endif 1770 return 0; 1771 } 1772 1773 template
1774 __deduced_t<_CompletionToken, void(error_code, size_t)> 1775 async_send(const _ConstBufferSequence& __buffers, 1776 _CompletionToken&& __token) 1777 { 1778 return async_send(__buffers, socket_base::message_flags(), 1779 std::forward<_CompletionToken>(__token)); 1780 } 1781 1782 template
1783 __deduced_t<_CompletionToken, void(error_code, size_t)> 1784 async_send(const _ConstBufferSequence& __buffers, 1785 socket_base::message_flags __flags, 1786 _CompletionToken&& __token) 1787 { 1788 async_completion<_CompletionToken, void(error_code, size_t)> 1789 __init{__token}; 1790 1791 if (__buffer_empty(__buffers)) 1792 { 1793 auto __ex = net::get_associated_executor( 1794 __init.completion_handler, this->get_executor()); 1795 auto __a = get_associated_allocator( 1796 __init.completion_handler, std::allocator
()); 1797 __ex.post( 1798 [__h=std::move(__init.completion_handler)] () mutable 1799 { __h(error_code{}, 0); }, __a); 1800 return __init.result.get(); 1801 } 1802 1803 this->get_executor().context().async_wait(this->native_handle(), 1804 (int) socket_base::wait_write, 1805 [__h = std::move(__init.completion_handler), 1806 &__buffers, __flags = static_cast
(__flags), 1807 __fd = this->native_handle()] 1808 (error_code __ec) mutable { 1809 if (__ec) 1810 { 1811 __h(__ec); 1812 return; 1813 } 1814 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1815 socket_base::__msg_hdr __msg(__buffers); 1816 ssize_t __result = ::sendmsg(__fd, &__msg, __flags); 1817 if (__result == -1) 1818 { 1819 __ec.assign(errno, generic_category()); 1820 __result = 0; 1821 } 1822 else 1823 __ec.clear(); 1824 __h(__ec, __result); 1825 #else 1826 __h(std::make_error_code(errc::operation_not_supported), 0); 1827 #endif 1828 }); 1829 return __init.result.get(); 1830 } 1831 1832 template
1833 size_t 1834 read_some(const _MutableBufferSequence& __buffers) 1835 { 1836 return receive(__buffers, 1837 __throw_on_error{"basic_stream_socket::read_some"}); 1838 } 1839 1840 template
1841 size_t 1842 read_some(const _MutableBufferSequence& __buffers, error_code& __ec) 1843 { return receive(__buffers, __ec); } 1844 1845 template
1846 __deduced_t<_CompletionToken, void(error_code, size_t)> 1847 async_read_some(const _MutableBufferSequence& __buffers, 1848 _CompletionToken&& __token) 1849 { 1850 return async_receive(__buffers, 1851 std::forward<_CompletionToken>(__token)); 1852 } 1853 1854 template
1855 size_t 1856 write_some(const _ConstBufferSequence& __buffers) 1857 { 1858 return send(__buffers, 1859 __throw_on_error{"basic_stream_socket:write_some"}); 1860 } 1861 1862 template
1863 size_t 1864 write_some(const _ConstBufferSequence& __buffers, error_code& __ec) 1865 { return send(__buffers, __ec); } 1866 1867 template
1868 __deduced_t<_CompletionToken, void(error_code, size_t)> 1869 async_write_some(const _ConstBufferSequence& __buffers, 1870 _CompletionToken&& __token) 1871 { 1872 return async_send(__buffers, 1873 std::forward<_CompletionToken>(__token)); 1874 } 1875 }; 1876 1877 template
1878 class basic_socket_acceptor 1879 : public socket_base, private __basic_socket_impl<_AcceptableProtocol> 1880 { 1881 using __base = __basic_socket_impl<_AcceptableProtocol>; 1882 1883 public: 1884 // types: 1885 1886 using executor_type = io_context::executor_type; 1887 using native_handle_type = int; 1888 using protocol_type = _AcceptableProtocol; 1889 using endpoint_type = typename protocol_type::endpoint; 1890 using socket_type = typename protocol_type::socket; 1891 1892 static_assert(__detail::__acceptable_protocol
, 1893 "protocol_type meets the AcceptableProtocol requirements"); 1894 1895 // construct / copy / destroy: 1896 1897 explicit 1898 basic_socket_acceptor(io_context& __ctx) 1899 : __base(__ctx), _M_protocol(endpoint_type{}.protocol()) { } 1900 1901 basic_socket_acceptor(io_context& __ctx, 1902 const protocol_type& __protocol) 1903 : __base(__ctx), _M_protocol(__protocol) 1904 { open(__protocol); } 1905 1906 basic_socket_acceptor(io_context& __ctx, const endpoint_type& __endpoint, 1907 [[__maybe_unused__]] bool __reuse_addr = true) 1908 : basic_socket_acceptor(__ctx, __endpoint.protocol()) 1909 { 1910 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1911 if (__reuse_addr) 1912 set_option(reuse_address(true)); 1913 #endif 1914 bind(__endpoint); 1915 listen(); 1916 } 1917 1918 basic_socket_acceptor(io_context& __ctx, const protocol_type& __protocol, 1919 const native_handle_type& __native_acceptor) 1920 : basic_socket_acceptor(__ctx, __protocol) 1921 { assign(__protocol, __native_acceptor); } 1922 1923 basic_socket_acceptor(const basic_socket_acceptor&) = delete; 1924 1925 basic_socket_acceptor(basic_socket_acceptor&&) = default; 1926 1927 template
>> 1929 basic_socket_acceptor(basic_socket_acceptor<_OtherProtocol>&& __rhs) 1930 : __base(std::move(__rhs)) { } 1931 1932 ~basic_socket_acceptor() = default; 1933 1934 basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete; 1935 1936 basic_socket_acceptor& operator=(basic_socket_acceptor&&) = default; 1937 1938 template
1939 enable_if_t
::value, 1940 basic_socket_acceptor&> 1941 operator=(basic_socket_acceptor<_OtherProtocol>&& __rhs) 1942 { 1943 __base::operator=(std::move(__rhs)); 1944 return *this; 1945 } 1946 1947 // basic_socket_acceptor operations: 1948 1949 executor_type get_executor() noexcept { return __base::get_executor(); } 1950 1951 native_handle_type 1952 native_handle() noexcept { return __base::native_handle(); } 1953 1954 void 1955 open(const protocol_type& __protocol = protocol_type()) 1956 { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); } 1957 1958 void 1959 open(const protocol_type& __protocol, error_code& __ec) 1960 { __base::open(__protocol, __ec); } 1961 1962 void 1963 assign(const protocol_type& __protocol, 1964 const native_handle_type& __native_acceptor) 1965 { 1966 assign(__protocol, __native_acceptor, 1967 __throw_on_error{"basic_socket_acceptor::assign"}); 1968 } 1969 1970 void 1971 assign(const protocol_type& __protocol, 1972 const native_handle_type& __native_acceptor, 1973 error_code& __ec) 1974 { __base::assign(__protocol, __native_acceptor, __ec); } 1975 1976 native_handle_type release() 1977 { return release(__throw_on_error{"basic_socket_acceptor::release"}); } 1978 1979 native_handle_type release(error_code& __ec) 1980 { return __base::release(__ec); } 1981 1982 _GLIBCXX_NODISCARD bool 1983 is_open() const noexcept { return __base::is_open(); } 1984 1985 void 1986 close() { close(__throw_on_error{"basic_socket_acceptor::close"}); } 1987 1988 void 1989 close(error_code& __ec) { __base::_close(__ec); } 1990 1991 void 1992 cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); } 1993 1994 void 1995 cancel(error_code& __ec) { __base::cancel(__ec); } 1996 1997 template
1998 void 1999 set_option(const _SettableSocketOption& __option) 2000 { 2001 set_option(__option, 2002 __throw_on_error{"basic_socket_acceptor::set_option"}); 2003 } 2004 2005 template
2006 void 2007 set_option(const _SettableSocketOption& __option, error_code& __ec) 2008 { __base::set_option(__option, __ec); } 2009 2010 template
2011 void 2012 get_option(_GettableSocketOption& __option) const 2013 { 2014 get_option(__option, 2015 __throw_on_error{"basic_socket_acceptor::get_option"}); 2016 } 2017 2018 template
2019 void 2020 get_option(_GettableSocketOption& __option, error_code& __ec) const 2021 { __base::get_option(__option, __ec); } 2022 2023 template
2024 void 2025 io_control(_IoControlCommand& __command) 2026 { 2027 io_control(__command, 2028 __throw_on_error{"basic_socket_acceptor::io_control"}); 2029 } 2030 2031 template
2032 void 2033 io_control(_IoControlCommand& __command, error_code& __ec) 2034 { __base::io_control(__command, __ec); } 2035 2036 void 2037 non_blocking(bool __mode) 2038 { 2039 non_blocking(__mode, 2040 __throw_on_error{"basic_socket_acceptor::non_blocking"}); 2041 } 2042 2043 void 2044 non_blocking(bool __mode, error_code& __ec) 2045 { __base::non_blocking(__mode, __ec); } 2046 2047 bool non_blocking() const { return __base::non_blocking(); } 2048 2049 void 2050 native_non_blocking(bool __mode) 2051 { 2052 native_non_blocking(__mode, __throw_on_error{ 2053 "basic_socket_acceptor::native_non_blocking"}); 2054 } 2055 2056 void 2057 native_non_blocking(bool __mode, error_code& __ec) 2058 { __base::native_non_blocking(__mode, __ec); } 2059 2060 bool 2061 native_non_blocking() const 2062 { return __base::native_non_blocking(); } 2063 2064 void 2065 bind(const endpoint_type& __endpoint) 2066 { 2067 return bind(__endpoint, 2068 __throw_on_error{"basic_socket_acceptor::bind"}); 2069 } 2070 2071 void 2072 bind(const endpoint_type& __endpoint, error_code& __ec) 2073 { __base::bind(__endpoint, __ec); } 2074 2075 void 2076 listen(int __backlog = max_listen_connections) 2077 { 2078 return listen(__backlog, 2079 __throw_on_error{"basic_socket_acceptor::listen"}); 2080 } 2081 2082 void 2083 listen(int __backlog, error_code& __ec) 2084 { 2085 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2086 if (::listen(native_handle(), __backlog) == -1) 2087 __ec.assign(errno, generic_category()); 2088 else 2089 __ec.clear(); 2090 #else 2091 __ec = std::make_error_code(errc::operation_not_supported); 2092 #endif 2093 } 2094 2095 endpoint_type 2096 local_endpoint() const 2097 { 2098 return local_endpoint( 2099 __throw_on_error{"basic_socket_acceptor::local_endpoint"}); 2100 } 2101 2102 endpoint_type 2103 local_endpoint(error_code& __ec) const 2104 { return __base::local_endpoint(__ec); } 2105 2106 void 2107 enable_connection_aborted(bool __mode) 2108 { __base::_M_bits.enable_connection_aborted = __mode; } 2109 2110 bool 2111 enable_connection_aborted() const 2112 { return __base::_M_bits.enable_connection_aborted; } 2113 2114 socket_type 2115 accept() 2116 { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); } 2117 2118 socket_type 2119 accept(error_code& __ec) 2120 { return accept(get_executor().context(), __ec); } 2121 2122 socket_type accept(io_context& __ctx) 2123 { 2124 return accept(__ctx, 2125 __throw_on_error{"basic_socket_acceptor::accept"}); 2126 } 2127 2128 socket_type 2129 accept(io_context& __ctx, error_code& __ec) 2130 { 2131 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2132 do 2133 { 2134 int __h = ::accept(native_handle(), nullptr, 0); 2135 if (__h != -1) 2136 { 2137 __ec.clear(); 2138 return socket_type{__ctx, _M_protocol, __h}; 2139 } 2140 } while (errno == ECONNABORTED && enable_connection_aborted()); 2141 __ec.assign(errno, generic_category()); 2142 #else 2143 __ec = std::make_error_code(errc::operation_not_supported); 2144 #endif 2145 return socket_type{__ctx}; 2146 } 2147 2148 template
2149 __deduced_t<_CompletionToken, void(error_code, socket_type)> 2150 async_accept(_CompletionToken&& __token) 2151 { 2152 return async_accept(get_executor().context(), 2153 std::forward<_CompletionToken>(__token)); 2154 } 2155 2156 template
2157 __deduced_t<_CompletionToken, void(error_code, socket_type)> 2158 async_accept(io_context& __ctx, _CompletionToken&& __token) 2159 { 2160 async_completion<_CompletionToken, void(error_code, socket_type)> 2161 __init{__token}; 2162 2163 __ctx.async_wait(native_handle(), 2164 (int) socket_base::wait_read, 2165 [__h = std::move(__init.completion_handler), 2166 __connabort = enable_connection_aborted(), 2167 __fd = native_handle(), 2168 __protocol = _M_protocol, 2169 &__ctx 2170 ] 2171 (error_code __ec) mutable { 2172 if (__ec) 2173 { 2174 __h(__ec, socket_type(__ctx)); 2175 return; 2176 } 2177 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2178 do 2179 { 2180 int __newfd = ::accept(__fd, nullptr, 0); 2181 if (__newfd != -1) 2182 { 2183 __ec.clear(); 2184 __h(__ec, socket_type{__ctx, __protocol, __newfd}); 2185 return; 2186 } 2187 } while (errno == ECONNABORTED && __connabort); 2188 __ec.assign(errno, generic_category()); 2189 __h(__ec, socket_type(__ctx)); 2190 #else 2191 __h(std::make_error_code(errc::operation_not_supported), 0); 2192 #endif 2193 }); 2194 return __init.result.get(); 2195 } 2196 2197 socket_type 2198 accept(endpoint_type& __endpoint) 2199 { 2200 return accept(get_executor().context(), __endpoint, 2201 __throw_on_error{"basic_socket_acceptor::accept"}); 2202 } 2203 2204 socket_type 2205 accept(endpoint_type& __endpoint, error_code& __ec) 2206 { return accept(get_executor().context(), __endpoint, __ec); } 2207 2208 socket_type 2209 accept(io_context& __ctx, endpoint_type& __endpoint) 2210 { 2211 return accept(__ctx, __endpoint, 2212 __throw_on_error{"basic_socket_acceptor::accept"}); 2213 } 2214 2215 socket_type 2216 accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec) 2217 { 2218 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2219 do 2220 { 2221 socklen_t __len = __endpoint.capacity(); 2222 int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(), 2223 &__len); 2224 if (__h != -1) 2225 { 2226 __endpoint.resize(__len); 2227 return socket_type{__ctx, _M_protocol, __h}; 2228 } 2229 } while (errno == ECONNABORTED && enable_connection_aborted()); 2230 __ec.assign(errno, generic_category()); 2231 #else 2232 __ec = std::make_error_code(errc::operation_not_supported); 2233 #endif 2234 return socket_type{__ctx}; 2235 } 2236 2237 template
2238 __deduced_t<_CompletionToken, void(error_code, socket_type)> 2239 async_accept(endpoint_type& __endpoint, 2240 _CompletionToken&& __token) 2241 { 2242 return async_accept(get_executor().context(), __endpoint, 2243 std::forward<_CompletionToken>(__token)); 2244 } 2245 2246 template
2247 __deduced_t<_CompletionToken, void(error_code, socket_type)> 2248 async_accept(io_context& __ctx, endpoint_type& __endpoint, 2249 _CompletionToken&& __token) 2250 { 2251 async_completion<_CompletionToken, void(error_code, socket_type)> 2252 __init{__token}; 2253 2254 __ctx.async_wait(native_handle(), 2255 (int) socket_base::wait_read, 2256 [__h = std::move(__init.completion_handler), 2257 __ep = std::move(__endpoint), 2258 __connabort = enable_connection_aborted(), 2259 __fd = native_handle(), 2260 &__ctx 2261 ] 2262 (error_code __ec) mutable { 2263 if (__ec) 2264 { 2265 __h(__ec, socket_type(__ctx)); 2266 return; 2267 } 2268 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2269 do 2270 { 2271 socklen_t __len = __ep.capacity(); 2272 int __newfd = ::accept(__fd, __ep.data, &__len); 2273 if (__newfd != -1) 2274 { 2275 __ep.resize(__len); 2276 auto __protocol = __ep.protocol(); 2277 __ec.clear(); 2278 __h(__ec, socket_type{__ctx, __protocol, __newfd}); 2279 return; 2280 } 2281 } while (errno == ECONNABORTED && __connabort); 2282 __ec.assign(errno, generic_category()); 2283 #else 2284 __ec = std::make_error_code(errc::operation_not_supported); 2285 #endif 2286 __h(__ec, socket_type(__ctx)); 2287 }); 2288 return __init.result.get(); 2289 } 2290 2291 void 2292 wait(wait_type __w) 2293 { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); } 2294 2295 void 2296 wait(wait_type __w, error_code& __ec) 2297 { 2298 #ifdef _GLIBCXX_HAVE_POLL_H 2299 ::pollfd __fds; 2300 __fds.fd = native_handle(); 2301 __fds.events = __w; // __w | POLLIN; 2302 if (::poll(&__fds, 1, -1) == -1) 2303 __ec.assign(errno, generic_category()); 2304 else 2305 __ec.clear(); 2306 #else 2307 __ec = std::make_error_code(errc::operation_not_supported); 2308 #endif 2309 } 2310 2311 template
2312 __deduced_t<_CompletionToken, void(error_code)> 2313 async_wait(wait_type __w, _CompletionToken&& __token) 2314 { 2315 async_completion<_CompletionToken, void(error_code)> __init{__token}; 2316 get_executor().context().async_wait( native_handle(), 2317 static_cast
(__w), 2318 [__h = std::move(__init.completion_handler)] 2319 (error_code __ec) mutable { 2320 __h(__ec); 2321 }); 2322 return __init.result.get(); 2323 } 2324 2325 private: 2326 protocol_type _M_protocol; 2327 }; 2328 2329 /// @} 2330 2331 /** @brief Socket streams 2332 * @{ 2333 */ 2334 2335 template
2336 class basic_socket_streambuf : public basic_streambuf
2337 { 2338 public: 2339 // types: 2340 2341 using protocol_type = _Protocol; 2342 using endpoint_type = typename protocol_type::endpoint; 2343 using clock_type = _Clock; 2344 using time_point = typename clock_type::time_point; 2345 using duration = typename clock_type::duration; 2346 using wait_traits_type = _WaitTraits; 2347 2348 // construct / copy / destroy: 2349 2350 basic_socket_streambuf() : _M_socket(_S_ctx()) { } 2351 2352 explicit 2353 basic_socket_streambuf(basic_stream_socket
__s) 2354 : _M_socket(std::move(__s)) { } 2355 2356 basic_socket_streambuf(const basic_socket_streambuf&) = delete; 2357 2358 basic_socket_streambuf(basic_socket_streambuf&& __rhs); // TODO 2359 2360 2361 virtual ~basic_socket_streambuf(); // TODO 2362 2363 basic_socket_streambuf& operator=(const basic_socket_streambuf&) = delete; 2364 2365 basic_socket_streambuf& operator=(basic_socket_streambuf&& __rhs); // TODO 2366 2367 // members: 2368 2369 basic_socket_streambuf* connect(const endpoint_type& __e); // TODO 2370 2371 template
2372 basic_socket_streambuf* connect(_Args&&... ); // TODO 2373 2374 basic_socket_streambuf* close(); // TODO 2375 2376 basic_socket
& socket() { return _M_socket; } 2377 2378 error_code error() const noexcept { return _M_ec; } 2379 2380 time_point expiry() const { return _M_expiry; } 2381 2382 void 2383 expires_at(const time_point& __t) 2384 { _M_expiry = __t; } 2385 2386 void 2387 expires_after(const duration& __d) 2388 { expires_at(clock_type::now() + __d); } 2389 2390 protected: 2391 // overridden virtual functions: // TODO 2392 virtual int_type underflow() override; 2393 virtual int_type pbackfail(int_type __c = traits_type::eof()) override; 2394 virtual int_type overflow(int_type __c = traits_type::eof()) override; 2395 virtual int sync() override; 2396 virtual streambuf* setbuf(char_type* __s, streamsize __n) override; 2397 2398 private: 2399 static io_context& 2400 _S_ctx() 2401 { 2402 static io_context __ctx; 2403 return __ctx; 2404 } 2405 2406 basic_stream_socket
_M_socket; 2407 error_code _M_ec; 2408 time_point _M_expiry{ time_point::max() }; 2409 }; 2410 2411 template
2412 class basic_socket_iostream : public basic_iostream
2413 { 2414 using __streambuf_type 2415 = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>; 2416 2417 public: 2418 // types: 2419 2420 using protocol_type = _Protocol; 2421 using endpoint_type = typename protocol_type::endpoint; 2422 using clock_type = _Clock; 2423 using time_point = typename clock_type::time_point; 2424 using duration = typename clock_type::duration; 2425 using wait_traits_type = _WaitTraits; 2426 2427 // construct / copy / destroy: 2428 2429 // TODO base-from-member ? 2430 basic_socket_iostream() : basic_iostream(nullptr), _M_sb() 2431 { 2432 this->init(std::addressof(_M_sb)); 2433 this->setf(std::ios::unitbuf); 2434 } 2435 2436 explicit 2437 basic_socket_iostream(basic_stream_socket
__s) 2438 : basic_iostream(nullptr), _M_sb(std::move(__s)) 2439 { 2440 this->init(std::addressof(_M_sb)); 2441 this->setf(std::ios::unitbuf); 2442 } 2443 2444 basic_socket_iostream(const basic_socket_iostream&) = delete; 2445 2446 basic_socket_iostream(basic_socket_iostream&& __rhs) 2447 : basic_iostream(nullptr), _M_sb(std::move(__rhs._M_sb)) 2448 // XXX ??? ^^^^^^^ 2449 { 2450 // XXX ??? this->init(std::addressof(_M_sb)); 2451 this->set_rbduf(std::addressof(_M_sb)); 2452 } 2453 2454 template
2455 explicit 2456 basic_socket_iostream(_Args&&... __args) 2457 : basic_iostream(nullptr), _M_sb() 2458 { 2459 this->init(std::addressof(_M_sb)); 2460 this->setf(std::ios::unitbuf); 2461 connect(forward<_Args>(__args)...); 2462 } 2463 2464 basic_socket_iostream& operator=(const basic_socket_iostream&) = delete; 2465 2466 basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO 2467 2468 // members: 2469 2470 template
2471 void 2472 connect(_Args&&... __args) 2473 { 2474 if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr) 2475 this->setstate(failbit); 2476 } 2477 2478 void 2479 close() 2480 { 2481 if (rdbuf()->close() == nullptr) 2482 this->setstate(failbit); 2483 } 2484 2485 basic_socket_streambuf
* 2486 rdbuf() const 2487 { return const_cast<__streambuf_type*>(std::addressof(_M_sb)); } 2488 2489 basic_socket
& socket() { return rdbuf()->socket(); } 2490 error_code error() const noexcept { return rdbuf()->error(); } 2491 2492 time_point expiry() const { return rdbuf()->expiry(); } 2493 void expires_at(const time_point& __t) { rdbuf()->expires_at(__t); } 2494 void expires_after(const duration& __d) { rdbuf()->expires_after(__d); } 2495 2496 private: 2497 __streambuf_type _M_sb; 2498 }; 2499 2500 /// @} 2501 2502 /** @brief synchronous connect operations 2503 * @{ 2504 */ 2505 2506 template
2508 inline typename _Protocol::endpoint 2509 connect(basic_socket<_Protocol>& __s, 2510 const _EndpointSequence& __endpoints, 2511 _ConnectCondition __c, error_code& __ec) 2512 { 2513 __ec.clear(); 2514 bool __found = false; 2515 for (auto& __ep : __endpoints) 2516 { 2517 if (__c(__ec, __ep)) 2518 { 2519 __found = true; 2520 __s.close(__ec); 2521 if (!__ec) 2522 __s.open(__ep.protocol(), __ec); 2523 if (!__ec) 2524 __s.connect(__ep, __ec); 2525 if (!__ec) 2526 return __ep; 2527 } 2528 } 2529 if (!__found) 2530 __ec = socket_errc::not_found; 2531 return typename _Protocol::endpoint{}; 2532 } 2533 2534 template
2536 inline _InputIterator 2537 connect(basic_socket<_Protocol>& __s, 2538 _InputIterator __first, _InputIterator __last, 2539 _ConnectCondition __c, error_code& __ec) 2540 { 2541 __ec.clear(); 2542 bool __found = false; 2543 for (auto __i = __first; __i != __last; ++__i) 2544 { 2545 if (__c(__ec, *__i)) 2546 { 2547 __found = true; 2548 __s.close(__ec); 2549 if (!__ec) 2550 __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec); 2551 if (!__ec) 2552 __s.connect(*__i, __ec); 2553 if (!__ec) 2554 return __i; 2555 } 2556 } 2557 if (!__found) 2558 __ec = socket_errc::not_found; 2559 return __last; 2560 } 2561 2562 template
2564 inline typename _Protocol::endpoint 2565 connect(basic_socket<_Protocol>& __s, 2566 const _EndpointSequence& __endpoints, 2567 _ConnectCondition __c) 2568 { 2569 return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"}); 2570 } 2571 2572 template
2574 inline _InputIterator 2575 connect(basic_socket<_Protocol>& __s, 2576 _InputIterator __first, _InputIterator __last, 2577 _ConnectCondition __c) 2578 { 2579 return net::connect(__s, __first, __last, __c, 2580 __throw_on_error{"connect"}); 2581 } 2582 2583 template
2584 inline typename _Protocol::endpoint 2585 connect(basic_socket<_Protocol>& __s, 2586 const _EndpointSequence& __endpoints) 2587 { 2588 return net::connect(__s, __endpoints, [](auto, auto){ return true; }, 2589 __throw_on_error{"connect"}); 2590 } 2591 2592 template
2593 inline typename _Protocol::endpoint 2594 connect(basic_socket<_Protocol>& __s, 2595 const _EndpointSequence& __endpoints, 2596 error_code& __ec) 2597 { 2598 return net::connect(__s, __endpoints, [](auto, auto){ return true; }, 2599 __ec); 2600 } 2601 2602 template
2603 inline _InputIterator 2604 connect(basic_socket<_Protocol>& __s, 2605 _InputIterator __first, _InputIterator __last) 2606 { 2607 return net::connect(__s, __first, __last, [](auto, auto){ return true; }, 2608 __throw_on_error{"connect"}); 2609 } 2610 2611 template
2612 inline _InputIterator 2613 connect(basic_socket<_Protocol>& __s, 2614 _InputIterator __first, _InputIterator __last, 2615 error_code& __ec) 2616 { 2617 return net::connect(__s, __first, __last, [](auto, auto){ return true; }, 2618 __ec); 2619 } 2620 2621 /// @} 2622 2623 /** @brief asynchronous connect operations 2624 * @{ 2625 */ 2626 2627 template
2629 inline 2630 __deduced_t<_CompletionToken, 2631 void(error_code, typename _Protocol::endpoint)> 2632 async_connect(basic_socket<_Protocol>& __s, 2633 const _EndpointSequence& __endpoints, 2634 _ConnectCondition __c, _CompletionToken&& __token); // TODO 2635 2636 template
2638 inline 2639 __deduced_t<_CompletionToken, 2640 void(error_code, typename _Protocol::endpoint)> 2641 async_connect(basic_socket<_Protocol>& __s, 2642 const _EndpointSequence& __endpoints, 2643 _CompletionToken&& __token) 2644 { 2645 return net::async_connect(__s, __endpoints, 2646 [](auto, auto){ return true; }, 2647 forward<_CompletionToken>(__token)); 2648 } 2649 2650 template
2652 inline 2653 __deduced_t<_CompletionToken, void(error_code, _InputIterator)> 2654 async_connect(basic_socket<_Protocol>& __s, 2655 _InputIterator __first, _InputIterator __last, 2656 _ConnectCondition __c, _CompletionToken&& __token); // TODO 2657 2658 template
2660 inline 2661 __deduced_t<_CompletionToken, void(error_code, _InputIterator)> 2662 async_connect(basic_socket<_Protocol>& __s, 2663 _InputIterator __first, _InputIterator __last, 2664 _CompletionToken&& __token) 2665 { 2666 return net::async_connect(__s, __first, __last, 2667 [](auto, auto){ return true; }, 2668 forward<_CompletionToken>(__token)); 2669 } 2670 2671 /// @} 2672 2673 #endif // _GLIBCXX_HAVE_UNISTD_H 2674 2675 /// @} 2676 2677 } // namespace v1 2678 } // namespace net 2679 } // namespace experimental 2680 2681 _GLIBCXX_END_NAMESPACE_VERSION 2682 } // namespace std 2683 2684 #endif // C++14 2685 2686 #endif // _GLIBCXX_EXPERIMENTAL_SOCKET
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™