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