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