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