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