1627f7eb2Smrg// <experimental/socket> -*- C++ -*- 2627f7eb2Smrg 3*4c3eb207Smrg// Copyright (C) 2015-2020 Free Software Foundation, Inc. 4627f7eb2Smrg// 5627f7eb2Smrg// This file is part of the GNU ISO C++ Library. This library is free 6627f7eb2Smrg// software; you can redistribute it and/or modify it under the 7627f7eb2Smrg// terms of the GNU General Public License as published by the 8627f7eb2Smrg// Free Software Foundation; either version 3, or (at your option) 9627f7eb2Smrg// any later version. 10627f7eb2Smrg 11627f7eb2Smrg// This library is distributed in the hope that it will be useful, 12627f7eb2Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 13627f7eb2Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14627f7eb2Smrg// GNU General Public License for more details. 15627f7eb2Smrg 16627f7eb2Smrg// Under Section 7 of GPL version 3, you are granted additional 17627f7eb2Smrg// permissions described in the GCC Runtime Library Exception, version 18627f7eb2Smrg// 3.1, as published by the Free Software Foundation. 19627f7eb2Smrg 20627f7eb2Smrg// You should have received a copy of the GNU General Public License and 21627f7eb2Smrg// a copy of the GCC Runtime Library Exception along with this program; 22627f7eb2Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23627f7eb2Smrg// <http://www.gnu.org/licenses/>. 24627f7eb2Smrg 25627f7eb2Smrg/** @file experimental/socket 26627f7eb2Smrg * This is a TS C++ Library header. 27*4c3eb207Smrg * @ingroup networking-ts 28627f7eb2Smrg */ 29627f7eb2Smrg 30627f7eb2Smrg#ifndef _GLIBCXX_EXPERIMENTAL_SOCKET 31627f7eb2Smrg#define _GLIBCXX_EXPERIMENTAL_SOCKET 32627f7eb2Smrg 33627f7eb2Smrg#pragma GCC system_header 34627f7eb2Smrg 35627f7eb2Smrg#if __cplusplus >= 201402L 36627f7eb2Smrg 37627f7eb2Smrg#include <experimental/netfwd> 38627f7eb2Smrg#include <experimental/buffer> 39627f7eb2Smrg#include <experimental/io_context> 40627f7eb2Smrg#include <experimental/bits/net.h> 41627f7eb2Smrg#include <streambuf> 42627f7eb2Smrg#include <istream> 43627f7eb2Smrg#include <bits/unique_ptr.h> 44627f7eb2Smrg#if _GLIBCXX_HAVE_UNISTD_H 45627f7eb2Smrg# include <unistd.h> 46627f7eb2Smrg# ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 47627f7eb2Smrg# include <sys/socket.h> // socket etc 48627f7eb2Smrg# endif 49627f7eb2Smrg# ifdef _GLIBCXX_HAVE_SYS_IOCTL_H 50627f7eb2Smrg# include <sys/ioctl.h> // ioctl 51627f7eb2Smrg# endif 52627f7eb2Smrg# ifdef _GLIBCXX_HAVE_SYS_UIO_H 53627f7eb2Smrg# include <sys/uio.h> // iovec 54627f7eb2Smrg# endif 55627f7eb2Smrg# ifdef _GLIBCXX_HAVE_POLL_H 56627f7eb2Smrg# include <poll.h> // poll, pollfd, POLLIN, POLLOUT, POLLERR 57627f7eb2Smrg# endif 58627f7eb2Smrg# ifdef _GLIBCXX_HAVE_FCNTL_H 59627f7eb2Smrg# include <fcntl.h> // fcntl, F_GETFL, F_SETFL 60627f7eb2Smrg# endif 61627f7eb2Smrg#endif 62627f7eb2Smrg 63627f7eb2Smrgnamespace std _GLIBCXX_VISIBILITY(default) 64627f7eb2Smrg{ 65627f7eb2Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 66627f7eb2Smrgnamespace experimental 67627f7eb2Smrg{ 68627f7eb2Smrgnamespace net 69627f7eb2Smrg{ 70627f7eb2Smrginline namespace v1 71627f7eb2Smrg{ 72627f7eb2Smrg 73*4c3eb207Smrg /** @addtogroup networking-ts 74627f7eb2Smrg * @{ 75627f7eb2Smrg */ 76627f7eb2Smrg 77627f7eb2Smrg enum class socket_errc { // TODO decide values 78627f7eb2Smrg already_open = 3, 79627f7eb2Smrg not_found = 4 80627f7eb2Smrg }; 81627f7eb2Smrg 82*4c3eb207Smrg} // namespace v1 83*4c3eb207Smrg} // namespace net 84*4c3eb207Smrg} // namespace experimental 85*4c3eb207Smrg 86*4c3eb207Smrg template<> 87*4c3eb207Smrg struct is_error_code_enum<experimental::net::v1::socket_errc> 88*4c3eb207Smrg : public true_type {}; 89*4c3eb207Smrg 90*4c3eb207Smrgnamespace experimental 91*4c3eb207Smrg{ 92*4c3eb207Smrgnamespace net 93*4c3eb207Smrg{ 94*4c3eb207Smrginline namespace v1 95*4c3eb207Smrg{ 96627f7eb2Smrg const error_category& socket_category() noexcept 97627f7eb2Smrg { 98627f7eb2Smrg struct __cat : error_category 99627f7eb2Smrg { 100627f7eb2Smrg const char* name() const noexcept { return "socket"; } 101627f7eb2Smrg 102627f7eb2Smrg std::string message(int __e) const 103627f7eb2Smrg { 104627f7eb2Smrg if (__e == (int)socket_errc::already_open) 105627f7eb2Smrg return "already open"; 106627f7eb2Smrg else if (__e == (int)socket_errc::not_found) 107627f7eb2Smrg return "endpoint not found"; 108627f7eb2Smrg return "socket error"; 109627f7eb2Smrg } 110627f7eb2Smrg 111627f7eb2Smrg virtual void __message(int) { } // TODO dual ABI XXX 112627f7eb2Smrg }; 113627f7eb2Smrg static __cat __c; 114627f7eb2Smrg return __c; 115627f7eb2Smrg } 116627f7eb2Smrg 117627f7eb2Smrg inline error_code 118627f7eb2Smrg make_error_code(socket_errc __e) noexcept 119627f7eb2Smrg { return error_code(static_cast<int>(__e), socket_category()); } 120627f7eb2Smrg 121627f7eb2Smrg inline error_condition 122627f7eb2Smrg make_error_condition(socket_errc __e) noexcept 123627f7eb2Smrg { return error_condition(static_cast<int>(__e), socket_category()); } 124627f7eb2Smrg 125627f7eb2Smrg template<typename _Tp, typename = __void_t<>> 126627f7eb2Smrg struct __is_endpoint_impl : false_type 127627f7eb2Smrg { }; 128627f7eb2Smrg 129627f7eb2Smrg // Check Endpoint requirements. 130627f7eb2Smrg template<typename _Tp> 131627f7eb2Smrg auto 132627f7eb2Smrg __endpoint_reqs(const _Tp* __a = 0) 133627f7eb2Smrg -> enable_if_t<__and_< 134627f7eb2Smrg is_default_constructible<_Tp>, 135627f7eb2Smrg __is_value_constructible<_Tp>, 136627f7eb2Smrg is_same<decltype(__a->__protocol()), typename _Tp::protocol_type> 137627f7eb2Smrg >::value, 138627f7eb2Smrg __void_t< typename _Tp::protocol_type::endpoint >>; 139627f7eb2Smrg 140627f7eb2Smrg template<typename _Tp> 141627f7eb2Smrg struct __is_endpoint_impl<_Tp, decltype(__endpoint_reqs<_Tp>())> 142627f7eb2Smrg : true_type 143627f7eb2Smrg { }; 144627f7eb2Smrg 145627f7eb2Smrg template<typename _Tp> 146627f7eb2Smrg struct __is_endpoint : __is_endpoint_impl<_Tp> 147627f7eb2Smrg { }; 148627f7eb2Smrg 149627f7eb2Smrg // TODO Endpoint reqs for extensible implementations 150627f7eb2Smrg // TODO _Protocol reqs 151627f7eb2Smrg // TODO AcceptableProtocol reqs 152627f7eb2Smrg // TODO GettableSocket reqs 153627f7eb2Smrg // TODO SettableSocket reqs 154627f7eb2Smrg // TODO BooleanSocketOption reqs 155627f7eb2Smrg // TODO IntegerSocketOption reqs 156*4c3eb207Smrg // TODO IoControlCommand reqs 157*4c3eb207Smrg // TODO ConnectCondition reqs 158627f7eb2Smrg 159627f7eb2Smrg /** @brief Sockets 160627f7eb2Smrg * @{ 161627f7eb2Smrg */ 162627f7eb2Smrg 163627f7eb2Smrg class socket_base 164627f7eb2Smrg { 165627f7eb2Smrg public: 166627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 167627f7eb2Smrg struct broadcast : __sockopt_crtp<broadcast, bool> 168627f7eb2Smrg { 169627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 170627f7eb2Smrg 171627f7eb2Smrg static const int _S_level = SOL_SOCKET; 172627f7eb2Smrg static const int _S_name = SO_BROADCAST; 173627f7eb2Smrg }; 174627f7eb2Smrg 175627f7eb2Smrg struct debug : __sockopt_crtp<debug, bool> 176627f7eb2Smrg { 177627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 178627f7eb2Smrg 179627f7eb2Smrg static const int _S_level = SOL_SOCKET; 180627f7eb2Smrg static const int _S_name = SO_DEBUG; 181627f7eb2Smrg }; 182627f7eb2Smrg 183627f7eb2Smrg struct do_not_route : __sockopt_crtp<do_not_route, bool> 184627f7eb2Smrg { 185627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 186627f7eb2Smrg 187627f7eb2Smrg static const int _S_level = SOL_SOCKET; 188627f7eb2Smrg static const int _S_name = SO_DONTROUTE; 189627f7eb2Smrg }; 190627f7eb2Smrg 191627f7eb2Smrg struct keep_alive : __sockopt_crtp<keep_alive, bool> 192627f7eb2Smrg { 193627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 194627f7eb2Smrg 195627f7eb2Smrg static const int _S_level = SOL_SOCKET; 196627f7eb2Smrg static const int _S_name = SO_KEEPALIVE; 197627f7eb2Smrg }; 198627f7eb2Smrg 199627f7eb2Smrg struct linger : __sockopt_crtp<linger, ::linger> 200627f7eb2Smrg { 201627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 202627f7eb2Smrg 203627f7eb2Smrg linger() noexcept = default; 204627f7eb2Smrg 205627f7eb2Smrg linger(bool __e, chrono::seconds __t) noexcept 206627f7eb2Smrg { 207627f7eb2Smrg enabled(__e); 208627f7eb2Smrg timeout(__t); 209627f7eb2Smrg } 210627f7eb2Smrg 211627f7eb2Smrg bool 212627f7eb2Smrg enabled() const noexcept 213627f7eb2Smrg { return _M_value.l_onoff != 0; } 214627f7eb2Smrg 215627f7eb2Smrg void 216627f7eb2Smrg enabled(bool __e) noexcept 217627f7eb2Smrg { _M_value.l_onoff = int(__e); } 218627f7eb2Smrg 219627f7eb2Smrg chrono::seconds 220627f7eb2Smrg timeout() const noexcept 221627f7eb2Smrg { return chrono::seconds(_M_value.l_linger); } 222627f7eb2Smrg 223627f7eb2Smrg void 224627f7eb2Smrg timeout(chrono::seconds __t) noexcept 225627f7eb2Smrg { _M_value.l_linger = __t.count(); } 226627f7eb2Smrg 227627f7eb2Smrg static const int _S_level = SOL_SOCKET; 228627f7eb2Smrg static const int _S_name = SO_LINGER; 229627f7eb2Smrg }; 230627f7eb2Smrg 231627f7eb2Smrg struct out_of_band_inline : __sockopt_crtp<out_of_band_inline, bool> 232627f7eb2Smrg { 233627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 234627f7eb2Smrg 235627f7eb2Smrg static const int _S_level = SOL_SOCKET; 236627f7eb2Smrg static const int _S_name = SO_OOBINLINE; 237627f7eb2Smrg }; 238627f7eb2Smrg 239627f7eb2Smrg struct receive_buffer_size : __sockopt_crtp<receive_buffer_size> 240627f7eb2Smrg { 241627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 242627f7eb2Smrg 243627f7eb2Smrg static const int _S_level = SOL_SOCKET; 244627f7eb2Smrg static const int _S_name = SO_RCVBUF; 245627f7eb2Smrg }; 246627f7eb2Smrg 247627f7eb2Smrg struct receive_low_watermark : __sockopt_crtp<receive_low_watermark> 248627f7eb2Smrg { 249627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 250627f7eb2Smrg 251627f7eb2Smrg static const int _S_level = SOL_SOCKET; 252627f7eb2Smrg static const int _S_name = SO_RCVLOWAT; 253627f7eb2Smrg }; 254627f7eb2Smrg 255627f7eb2Smrg struct reuse_address : __sockopt_crtp<reuse_address, bool> 256627f7eb2Smrg { 257627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 258627f7eb2Smrg 259627f7eb2Smrg static const int _S_level = SOL_SOCKET; 260627f7eb2Smrg static const int _S_name = SO_REUSEADDR; 261627f7eb2Smrg }; 262627f7eb2Smrg 263627f7eb2Smrg struct send_buffer_size : __sockopt_crtp<send_buffer_size> 264627f7eb2Smrg { 265627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 266627f7eb2Smrg 267627f7eb2Smrg static const int _S_level = SOL_SOCKET; 268627f7eb2Smrg static const int _S_name = SO_SNDBUF; 269627f7eb2Smrg }; 270627f7eb2Smrg 271627f7eb2Smrg struct send_low_watermark : __sockopt_crtp<send_low_watermark> 272627f7eb2Smrg { 273627f7eb2Smrg using __sockopt_crtp::__sockopt_crtp; 274627f7eb2Smrg 275627f7eb2Smrg static const int _S_level = SOL_SOCKET; 276627f7eb2Smrg static const int _S_name = SO_SNDLOWAT; 277627f7eb2Smrg }; 278627f7eb2Smrg 279627f7eb2Smrg enum shutdown_type : int 280627f7eb2Smrg { 281627f7eb2Smrg __shutdown_receive = SHUT_RD, 282627f7eb2Smrg __shutdown_send = SHUT_WR, 283627f7eb2Smrg __shutdown_both = SHUT_RDWR 284627f7eb2Smrg }; 285627f7eb2Smrg static constexpr shutdown_type shutdown_receive = __shutdown_receive; 286627f7eb2Smrg static constexpr shutdown_type shutdown_send = __shutdown_send; 287627f7eb2Smrg static constexpr shutdown_type shutdown_both = __shutdown_both; 288627f7eb2Smrg 289627f7eb2Smrg#ifdef _GLIBCXX_HAVE_POLL_H 290627f7eb2Smrg enum wait_type : int 291627f7eb2Smrg { 292627f7eb2Smrg __wait_read = POLLIN, 293627f7eb2Smrg __wait_write = POLLOUT, 294627f7eb2Smrg __wait_error = POLLERR 295627f7eb2Smrg }; 296627f7eb2Smrg static constexpr wait_type wait_read = __wait_read; 297627f7eb2Smrg static constexpr wait_type wait_write = __wait_write; 298627f7eb2Smrg static constexpr wait_type wait_error = __wait_error; 299627f7eb2Smrg#endif 300627f7eb2Smrg 301627f7eb2Smrg enum message_flags : int 302627f7eb2Smrg { 303627f7eb2Smrg __message_peek = MSG_PEEK, 304627f7eb2Smrg __message_oob = MSG_OOB, 305627f7eb2Smrg __message_dontroute = MSG_DONTROUTE 306627f7eb2Smrg }; 307627f7eb2Smrg static constexpr message_flags message_peek = __message_peek; 308627f7eb2Smrg static constexpr message_flags message_out_of_band = __message_oob; 309627f7eb2Smrg static constexpr message_flags message_do_not_route = __message_dontroute; 310627f7eb2Smrg 311627f7eb2Smrg static const int max_listen_connections = SOMAXCONN; 312627f7eb2Smrg#endif 313627f7eb2Smrg 314627f7eb2Smrg protected: 315627f7eb2Smrg socket_base() = default; 316627f7eb2Smrg ~socket_base() = default; 317627f7eb2Smrg 318627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 319627f7eb2Smrg struct __msg_hdr : ::msghdr 320627f7eb2Smrg { 321627f7eb2Smrg#ifdef IOV_MAX 322627f7eb2Smrg using __iovec_array = array<::iovec, IOV_MAX>; 323627f7eb2Smrg#elif _GLIBCXX_HAVE_UNISTD_H 324627f7eb2Smrg struct __iovec_array 325627f7eb2Smrg { 326627f7eb2Smrg __iovec_array() : _M_ptr(new ::iovec[size()]) { } 327627f7eb2Smrg 328627f7eb2Smrg ::iovec& operator[](size_t __n) noexcept { return _M_ptr[__n]; } 329627f7eb2Smrg 330627f7eb2Smrg ::iovec* data() noexcept { return _M_ptr.get(); } 331627f7eb2Smrg 332627f7eb2Smrg static size_t size() 333627f7eb2Smrg { 334627f7eb2Smrg static const size_t __iov_max = ::sysconf(_SC_IOV_MAX); 335627f7eb2Smrg return __iov_max; 336627f7eb2Smrg } 337627f7eb2Smrg 338627f7eb2Smrg private: 339627f7eb2Smrg unique_ptr<::iovec[]> _M_ptr; 340627f7eb2Smrg }; 341627f7eb2Smrg#else 342627f7eb2Smrg using __iovec_array = array<::iovec, 16>; 343627f7eb2Smrg#endif 344627f7eb2Smrg 345627f7eb2Smrg __iovec_array _M_iov; 346627f7eb2Smrg 347627f7eb2Smrg template<typename _BufferSequence> 348627f7eb2Smrg explicit 349627f7eb2Smrg __msg_hdr(const _BufferSequence& __buffers) 350627f7eb2Smrg : msghdr() 351627f7eb2Smrg { 352627f7eb2Smrg auto __buf = net::buffer_sequence_begin(__buffers); 353627f7eb2Smrg const auto __bufend = net::buffer_sequence_end(__buffers); 354627f7eb2Smrg size_t __len = 0; 355627f7eb2Smrg while (__buf != __bufend && __len != _M_iov.size()) 356627f7eb2Smrg { 357627f7eb2Smrg _M_iov[__len].iov_base = (void*)__buf->data(); 358627f7eb2Smrg _M_iov[__len].iov_len = __buf->size(); 359627f7eb2Smrg ++__buf; 360627f7eb2Smrg ++__len; 361627f7eb2Smrg } 362627f7eb2Smrg this->msg_iovlen = __len; 363627f7eb2Smrg this->msg_iov = _M_iov.data(); 364627f7eb2Smrg } 365627f7eb2Smrg 366627f7eb2Smrg template<typename _BufferSequence, typename _Endpoint> 367627f7eb2Smrg __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep) 368627f7eb2Smrg : __msg_hdr(__buffers) 369627f7eb2Smrg { 370627f7eb2Smrg this->msg_name = __ep.data(); 371627f7eb2Smrg this->msg_namelen = __ep.size(); 372627f7eb2Smrg } 373627f7eb2Smrg }; 374627f7eb2Smrg#endif 375627f7eb2Smrg }; 376627f7eb2Smrg 377627f7eb2Smrg constexpr socket_base::message_flags 378627f7eb2Smrg operator&(socket_base::message_flags __f1, socket_base::message_flags __f2) 379627f7eb2Smrg { return socket_base::message_flags( int(__f1) & int(__f2) ); } 380627f7eb2Smrg 381627f7eb2Smrg constexpr socket_base::message_flags 382627f7eb2Smrg operator|(socket_base::message_flags __f1, socket_base::message_flags __f2) 383627f7eb2Smrg { return socket_base::message_flags( int(__f1) | int(__f2) ); } 384627f7eb2Smrg 385627f7eb2Smrg constexpr socket_base::message_flags 386627f7eb2Smrg operator^(socket_base::message_flags __f1, socket_base::message_flags __f2) 387627f7eb2Smrg { return socket_base::message_flags( int(__f1) ^ int(__f2) ); } 388627f7eb2Smrg 389627f7eb2Smrg constexpr socket_base::message_flags 390627f7eb2Smrg operator~(socket_base::message_flags __f) 391627f7eb2Smrg { return socket_base::message_flags( ~int(__f) ); } 392627f7eb2Smrg 393627f7eb2Smrg inline socket_base::message_flags& 394627f7eb2Smrg operator&=(socket_base::message_flags& __f1, socket_base::message_flags __f2) 395627f7eb2Smrg { return __f1 = (__f1 & __f2); } 396627f7eb2Smrg 397627f7eb2Smrg inline socket_base::message_flags& 398627f7eb2Smrg operator|=(socket_base::message_flags& __f1, socket_base::message_flags __f2) 399627f7eb2Smrg { return __f1 = (__f1 | __f2); } 400627f7eb2Smrg 401627f7eb2Smrg inline socket_base::message_flags& 402627f7eb2Smrg operator^=(socket_base::message_flags& __f1, socket_base::message_flags __f2) 403627f7eb2Smrg { return __f1 = (__f1 ^ __f2); } 404627f7eb2Smrg 405627f7eb2Smrg#if _GLIBCXX_HAVE_UNISTD_H 406627f7eb2Smrg 407627f7eb2Smrg class __socket_impl 408627f7eb2Smrg { 409627f7eb2Smrg protected: 410627f7eb2Smrg 411627f7eb2Smrg using executor_type = io_context::executor_type; 412627f7eb2Smrg using native_handle_type = int; 413627f7eb2Smrg 414627f7eb2Smrg explicit 415627f7eb2Smrg __socket_impl(io_context& __ctx) : _M_ctx(std::addressof(__ctx)) { } 416627f7eb2Smrg 417627f7eb2Smrg __socket_impl(__socket_impl&& __rhs) 418627f7eb2Smrg : _M_ctx(__rhs._M_ctx), 419627f7eb2Smrg _M_sockfd(std::exchange(__rhs._M_sockfd, -1)), 420627f7eb2Smrg _M_bits(std::exchange(__rhs._M_bits, {})) 421627f7eb2Smrg { } 422627f7eb2Smrg 423627f7eb2Smrg __socket_impl& 424627f7eb2Smrg operator=(__socket_impl&& __rhs) 425627f7eb2Smrg { 426627f7eb2Smrg _M_ctx = __rhs._M_ctx; 427627f7eb2Smrg _M_sockfd = std::exchange(__rhs._M_sockfd, -1); 428627f7eb2Smrg _M_bits = std::exchange(__rhs._M_bits, {}); 429627f7eb2Smrg return *this; 430627f7eb2Smrg } 431627f7eb2Smrg 432627f7eb2Smrg ~__socket_impl() = default; 433627f7eb2Smrg 434627f7eb2Smrg __socket_impl(const __socket_impl&) = delete; 435627f7eb2Smrg __socket_impl& operator=(const __socket_impl&) = delete; 436627f7eb2Smrg 437627f7eb2Smrg executor_type get_executor() noexcept { return _M_ctx->get_executor(); } 438627f7eb2Smrg 439627f7eb2Smrg native_handle_type native_handle() noexcept { return _M_sockfd; } 440627f7eb2Smrg 441627f7eb2Smrg bool is_open() const noexcept { return _M_sockfd != -1; } 442627f7eb2Smrg 443627f7eb2Smrg void 444627f7eb2Smrg close(error_code& __ec) 445627f7eb2Smrg { 446627f7eb2Smrg if (is_open()) 447627f7eb2Smrg { 448627f7eb2Smrg cancel(__ec); 449627f7eb2Smrg if (!__ec) 450627f7eb2Smrg { 451627f7eb2Smrg if (::close(_M_sockfd) == -1) 452627f7eb2Smrg __ec.assign(errno, generic_category()); 453627f7eb2Smrg else 454627f7eb2Smrg { 455627f7eb2Smrg get_executor().context()._M_remove_fd(_M_sockfd); 456627f7eb2Smrg _M_sockfd = -1; 457627f7eb2Smrg } 458627f7eb2Smrg } 459627f7eb2Smrg } 460627f7eb2Smrg } 461627f7eb2Smrg 462627f7eb2Smrg void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); } 463627f7eb2Smrg 464627f7eb2Smrg void 465627f7eb2Smrg non_blocking(bool __mode, error_code&) 466627f7eb2Smrg { _M_bits.non_blocking = __mode; } 467627f7eb2Smrg 468627f7eb2Smrg bool non_blocking() const { return _M_bits.non_blocking; } 469627f7eb2Smrg 470627f7eb2Smrg void 471627f7eb2Smrg native_non_blocking(bool __mode, error_code& __ec) 472627f7eb2Smrg { 473627f7eb2Smrg#ifdef _GLIBCXX_HAVE_FCNTL_H 474627f7eb2Smrg int __flags = ::fcntl(_M_sockfd, F_GETFL, 0); 475627f7eb2Smrg if (__flags >= 0) 476627f7eb2Smrg { 477627f7eb2Smrg if (__mode) 478627f7eb2Smrg __flags |= O_NONBLOCK; 479627f7eb2Smrg else 480627f7eb2Smrg __flags &= ~O_NONBLOCK; 481627f7eb2Smrg __flags = ::fcntl(_M_sockfd, F_SETFL, __flags); 482627f7eb2Smrg } 483627f7eb2Smrg if (__flags == -1) 484627f7eb2Smrg __ec.assign(errno, generic_category()); 485627f7eb2Smrg else 486627f7eb2Smrg { 487627f7eb2Smrg __ec.clear(); 488627f7eb2Smrg _M_bits.native_non_blocking = __mode; 489627f7eb2Smrg } 490627f7eb2Smrg#else 491627f7eb2Smrg __ec = std::make_error_code(std::errc::not_supported); 492627f7eb2Smrg#endif 493627f7eb2Smrg } 494627f7eb2Smrg 495627f7eb2Smrg bool 496627f7eb2Smrg native_non_blocking() const 497627f7eb2Smrg { 498627f7eb2Smrg#ifdef _GLIBCXX_HAVE_FCNTL_H 499627f7eb2Smrg if (_M_bits.native_non_blocking == -1) 500627f7eb2Smrg { 501627f7eb2Smrg const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0); 502627f7eb2Smrg if (__flags == -1) 503627f7eb2Smrg return 0; 504627f7eb2Smrg _M_bits.native_non_blocking = __flags & O_NONBLOCK; 505627f7eb2Smrg } 506627f7eb2Smrg return _M_bits.native_non_blocking; 507627f7eb2Smrg#else 508627f7eb2Smrg return false; 509627f7eb2Smrg#endif 510627f7eb2Smrg } 511627f7eb2Smrg 512627f7eb2Smrg io_context* _M_ctx; 513627f7eb2Smrg int _M_sockfd{-1}; 514627f7eb2Smrg struct { 515627f7eb2Smrg unsigned non_blocking : 1; 516627f7eb2Smrg mutable signed native_non_blocking : 2; 517627f7eb2Smrg unsigned enable_connection_aborted : 1; 518627f7eb2Smrg } _M_bits{}; 519627f7eb2Smrg }; 520627f7eb2Smrg 521627f7eb2Smrg template<typename _Protocol> 522627f7eb2Smrg class __basic_socket_impl : public __socket_impl 523627f7eb2Smrg { 524627f7eb2Smrg using __base = __socket_impl; 525627f7eb2Smrg 526627f7eb2Smrg protected: 527627f7eb2Smrg using protocol_type = _Protocol; 528627f7eb2Smrg using endpoint_type = typename protocol_type::endpoint; 529627f7eb2Smrg 530627f7eb2Smrg explicit 531627f7eb2Smrg __basic_socket_impl(io_context& __ctx) : __base(__ctx) { } 532627f7eb2Smrg 533627f7eb2Smrg __basic_socket_impl(__basic_socket_impl&&) = default; 534627f7eb2Smrg 535627f7eb2Smrg template<typename _OtherProtocol> 536627f7eb2Smrg __basic_socket_impl(__basic_socket_impl<_OtherProtocol>&& __rhs) 537627f7eb2Smrg : __base(std::move(__rhs)), _M_protocol(std::move(__rhs._M_protocol)) 538627f7eb2Smrg { } 539627f7eb2Smrg 540627f7eb2Smrg __basic_socket_impl& 541627f7eb2Smrg operator=(__basic_socket_impl&& __rhs) 542627f7eb2Smrg { 543627f7eb2Smrg if (this == std::addressof(__rhs)) 544627f7eb2Smrg return *this; 545627f7eb2Smrg _M_close(); 546627f7eb2Smrg __base::operator=(std::move(__rhs)); 547627f7eb2Smrg return *this; 548627f7eb2Smrg } 549627f7eb2Smrg 550627f7eb2Smrg ~__basic_socket_impl() { _M_close(); } 551627f7eb2Smrg 552627f7eb2Smrg __basic_socket_impl(const __basic_socket_impl&) = delete; 553627f7eb2Smrg __basic_socket_impl& operator=(const __basic_socket_impl&) = delete; 554627f7eb2Smrg 555627f7eb2Smrg void 556627f7eb2Smrg open(const protocol_type& __protocol, error_code& __ec) 557627f7eb2Smrg { 558627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 559627f7eb2Smrg if (is_open()) 560627f7eb2Smrg __ec = socket_errc::already_open; 561627f7eb2Smrg else 562627f7eb2Smrg { 563627f7eb2Smrg _M_protocol = __protocol; 564627f7eb2Smrg _M_sockfd = ::socket(__protocol.family(), __protocol.type(), 565627f7eb2Smrg __protocol.protocol()); 566627f7eb2Smrg if (is_open()) 567627f7eb2Smrg { 568627f7eb2Smrg get_executor().context()._M_add_fd(_M_sockfd); 569627f7eb2Smrg __ec.clear(); 570627f7eb2Smrg } 571627f7eb2Smrg else 572627f7eb2Smrg __ec.assign(errno, std::generic_category()); 573627f7eb2Smrg } 574627f7eb2Smrg#else 575627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 576627f7eb2Smrg#endif 577627f7eb2Smrg } 578627f7eb2Smrg 579627f7eb2Smrg void 580627f7eb2Smrg assign(const protocol_type& __protocol, 581627f7eb2Smrg const native_handle_type& __native_socket, 582627f7eb2Smrg error_code& __ec) 583627f7eb2Smrg { 584627f7eb2Smrg if (is_open()) 585627f7eb2Smrg __ec = socket_errc::already_open; 586627f7eb2Smrg else 587627f7eb2Smrg { 588627f7eb2Smrg _M_protocol = __protocol; 589627f7eb2Smrg _M_bits.native_non_blocking = -1; 590627f7eb2Smrg _M_sockfd = __native_socket; 591627f7eb2Smrg if (is_open()) 592627f7eb2Smrg { 593627f7eb2Smrg get_executor().context()._M_add_fd(_M_sockfd); 594627f7eb2Smrg __ec.clear(); 595627f7eb2Smrg } 596627f7eb2Smrg else 597627f7eb2Smrg __ec.assign(errno, std::generic_category()); 598627f7eb2Smrg } 599627f7eb2Smrg } 600627f7eb2Smrg 601*4c3eb207Smrg native_handle_type release(error_code& __ec) 602*4c3eb207Smrg { 603*4c3eb207Smrg __glibcxx_assert(is_open()); 604*4c3eb207Smrg cancel(__ec); 605*4c3eb207Smrg return std::exchange(_M_sockfd, -1); 606*4c3eb207Smrg } 607*4c3eb207Smrg 608627f7eb2Smrg template<typename _SettableSocketOption> 609627f7eb2Smrg void 610627f7eb2Smrg set_option(const _SettableSocketOption& __option, error_code& __ec) 611627f7eb2Smrg { 612627f7eb2Smrg int __result = ::setsockopt(_M_sockfd, __option.level(_M_protocol), 613627f7eb2Smrg __option.name(_M_protocol), 614627f7eb2Smrg __option.data(_M_protocol), 615627f7eb2Smrg __option.size(_M_protocol)); 616627f7eb2Smrg if (__result == -1) 617627f7eb2Smrg __ec.assign(errno, generic_category()); 618627f7eb2Smrg else 619627f7eb2Smrg __ec.clear(); 620627f7eb2Smrg } 621627f7eb2Smrg 622627f7eb2Smrg template<typename _GettableSocketOption> 623627f7eb2Smrg void 624627f7eb2Smrg get_option(_GettableSocketOption& __option, error_code& __ec) const 625627f7eb2Smrg { 626627f7eb2Smrg int __result = ::getsockopt(_M_sockfd, __option.level(_M_protocol), 627627f7eb2Smrg __option.name(_M_protocol), 628627f7eb2Smrg __option.data(_M_protocol), 629627f7eb2Smrg __option.size(_M_protocol)); 630627f7eb2Smrg if (__result == -1) 631627f7eb2Smrg __ec.assign(errno, generic_category()); 632627f7eb2Smrg else 633627f7eb2Smrg __ec.clear(); 634627f7eb2Smrg } 635627f7eb2Smrg 636627f7eb2Smrg template<typename _IoControlCommand> 637627f7eb2Smrg void 638627f7eb2Smrg io_control(_IoControlCommand& __command, error_code& __ec) 639627f7eb2Smrg { 640627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_IOCTL_H 641627f7eb2Smrg int __result = ::ioctl(_M_sockfd, __command.name(), 642627f7eb2Smrg __command.data()); 643627f7eb2Smrg if (__result == -1) 644627f7eb2Smrg __ec.assign(errno, generic_category()); 645627f7eb2Smrg else 646627f7eb2Smrg __ec.clear(); 647627f7eb2Smrg#else 648627f7eb2Smrg __ec = std::make_error_code(std::errc::not_supported); 649627f7eb2Smrg#endif 650627f7eb2Smrg } 651627f7eb2Smrg 652627f7eb2Smrg endpoint_type 653627f7eb2Smrg local_endpoint(error_code& __ec) const 654627f7eb2Smrg { 655627f7eb2Smrg endpoint_type __endpoint; 656627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 657627f7eb2Smrg socklen_t __endpoint_len = __endpoint.capacity(); 658627f7eb2Smrg if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(), 659627f7eb2Smrg &__endpoint_len) == -1) 660627f7eb2Smrg { 661627f7eb2Smrg __ec.assign(errno, generic_category()); 662627f7eb2Smrg return endpoint_type{}; 663627f7eb2Smrg } 664627f7eb2Smrg __ec.clear(); 665627f7eb2Smrg __endpoint.resize(__endpoint_len); 666627f7eb2Smrg#else 667627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 668627f7eb2Smrg#endif 669627f7eb2Smrg return __endpoint; 670627f7eb2Smrg } 671627f7eb2Smrg 672627f7eb2Smrg void 673627f7eb2Smrg bind(const endpoint_type& __endpoint, error_code& __ec) 674627f7eb2Smrg { 675627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 676627f7eb2Smrg if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size()) 677627f7eb2Smrg == -1) 678627f7eb2Smrg __ec.assign(errno, generic_category()); 679627f7eb2Smrg else 680627f7eb2Smrg __ec.clear(); 681627f7eb2Smrg#else 682627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 683627f7eb2Smrg#endif 684627f7eb2Smrg } 685627f7eb2Smrg 686627f7eb2Smrg _Protocol _M_protocol{ endpoint_type{}.protocol() }; 687627f7eb2Smrg 688627f7eb2Smrg private: 689627f7eb2Smrg void 690627f7eb2Smrg _M_close() 691627f7eb2Smrg { 692627f7eb2Smrg if (is_open()) 693627f7eb2Smrg { 694627f7eb2Smrg error_code __ec; 695627f7eb2Smrg cancel(__ec); 696627f7eb2Smrg set_option(socket_base::linger{false, chrono::seconds{}}, __ec); 697627f7eb2Smrg ::close(_M_sockfd); 698627f7eb2Smrg } 699627f7eb2Smrg } 700627f7eb2Smrg }; 701627f7eb2Smrg 702627f7eb2Smrg template<typename _Protocol> 703627f7eb2Smrg class basic_socket 704627f7eb2Smrg : public socket_base, private __basic_socket_impl<_Protocol> 705627f7eb2Smrg { 706627f7eb2Smrg using __base = __basic_socket_impl<_Protocol>; 707627f7eb2Smrg 708627f7eb2Smrg public: 709627f7eb2Smrg // types: 710627f7eb2Smrg 711627f7eb2Smrg typedef io_context::executor_type executor_type; 712627f7eb2Smrg typedef int native_handle_type; 713627f7eb2Smrg typedef _Protocol protocol_type; 714627f7eb2Smrg typedef typename protocol_type::endpoint endpoint_type; 715627f7eb2Smrg 716627f7eb2Smrg // basic_socket operations: 717627f7eb2Smrg 718627f7eb2Smrg executor_type get_executor() noexcept { return __base::get_executor(); } 719627f7eb2Smrg 720627f7eb2Smrg native_handle_type 721627f7eb2Smrg native_handle() noexcept { return __base::native_handle(); } 722627f7eb2Smrg 723627f7eb2Smrg void 724627f7eb2Smrg open(const protocol_type& __protocol = protocol_type()) 725627f7eb2Smrg { open(__protocol, __throw_on_error{"basic_socket::open"}); } 726627f7eb2Smrg 727627f7eb2Smrg void 728627f7eb2Smrg open(const protocol_type& __protocol, error_code& __ec) 729627f7eb2Smrg { __base::open(__protocol, __ec); } 730627f7eb2Smrg 731627f7eb2Smrg void 732627f7eb2Smrg assign(const protocol_type& __protocol, 733627f7eb2Smrg const native_handle_type& __native_socket) 734627f7eb2Smrg { 735627f7eb2Smrg assign(__protocol, __native_socket, 736627f7eb2Smrg __throw_on_error{"basic_socket::assign"}); 737627f7eb2Smrg } 738627f7eb2Smrg 739627f7eb2Smrg void 740627f7eb2Smrg assign(const protocol_type& __protocol, 741627f7eb2Smrg const native_handle_type& __native_socket, 742627f7eb2Smrg error_code& __ec) 743627f7eb2Smrg { __base::assign(__protocol, __native_socket, __ec); } 744627f7eb2Smrg 745*4c3eb207Smrg native_handle_type release() 746*4c3eb207Smrg { return release(__throw_on_error{"basic_socket::release"}); } 747*4c3eb207Smrg 748*4c3eb207Smrg native_handle_type release(error_code& __ec) 749*4c3eb207Smrg { return __base::release(__ec); } 750*4c3eb207Smrg 751*4c3eb207Smrg _GLIBCXX_NODISCARD bool 752*4c3eb207Smrg is_open() const noexcept { return __base::is_open(); } 753627f7eb2Smrg 754627f7eb2Smrg void close() { close(__throw_on_error{"basic_socket::close"}); } 755627f7eb2Smrg 756*4c3eb207Smrg void close(error_code& __ec) { __base::close(__ec); } 757627f7eb2Smrg 758627f7eb2Smrg void cancel() { cancel(__throw_on_error{"basic_socket::cancel"}); } 759627f7eb2Smrg 760627f7eb2Smrg void cancel(error_code& __ec) { __base::cancel(__ec); } 761627f7eb2Smrg 762627f7eb2Smrg template<typename _SettableSocketOption> 763627f7eb2Smrg void 764627f7eb2Smrg set_option(const _SettableSocketOption& __option) 765627f7eb2Smrg { set_option(__option, __throw_on_error{"basic_socket::set_option"}); } 766627f7eb2Smrg 767627f7eb2Smrg template<typename _SettableSocketOption> 768627f7eb2Smrg void 769627f7eb2Smrg set_option(const _SettableSocketOption& __option, error_code& __ec) 770627f7eb2Smrg { __base::set_option(__option, __ec); } 771627f7eb2Smrg 772627f7eb2Smrg template<typename _GettableSocketOption> 773627f7eb2Smrg void 774627f7eb2Smrg get_option(_GettableSocketOption& __option) const 775627f7eb2Smrg { get_option(__option, __throw_on_error{"basic_socket::get_option"}); } 776627f7eb2Smrg 777627f7eb2Smrg template<typename _GettableSocketOption> 778627f7eb2Smrg void 779627f7eb2Smrg get_option(_GettableSocketOption& __option, error_code& __ec) const 780627f7eb2Smrg { __base::get_option(__option, __ec); } 781627f7eb2Smrg 782627f7eb2Smrg template<typename _IoControlCommand> 783627f7eb2Smrg void 784627f7eb2Smrg io_control(_IoControlCommand& __command) 785627f7eb2Smrg { 786627f7eb2Smrg io_control(__command, __throw_on_error{"basic_socket::io_control"}); 787627f7eb2Smrg } 788627f7eb2Smrg 789627f7eb2Smrg template<typename _IoControlCommand> 790627f7eb2Smrg void 791627f7eb2Smrg io_control(_IoControlCommand& __command, error_code& __ec) 792627f7eb2Smrg { __base::io_control(__command, __ec); } 793627f7eb2Smrg 794627f7eb2Smrg void 795627f7eb2Smrg non_blocking(bool __mode) 796627f7eb2Smrg { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); } 797627f7eb2Smrg 798627f7eb2Smrg void 799627f7eb2Smrg non_blocking(bool __mode, error_code& __ec) 800627f7eb2Smrg { __base::non_blocking(__mode, __ec); } 801627f7eb2Smrg 802627f7eb2Smrg bool non_blocking() const { return __base::non_blocking(); } 803627f7eb2Smrg 804627f7eb2Smrg void 805627f7eb2Smrg native_non_blocking(bool __mode) 806627f7eb2Smrg { 807627f7eb2Smrg native_non_blocking(__mode, __throw_on_error{ 808627f7eb2Smrg "basic_socket::native_non_blocking"}); 809627f7eb2Smrg } 810627f7eb2Smrg 811627f7eb2Smrg void 812627f7eb2Smrg native_non_blocking(bool __mode, error_code& __ec) 813627f7eb2Smrg { __base::native_non_blocking(__mode, __ec); } 814627f7eb2Smrg 815627f7eb2Smrg bool 816627f7eb2Smrg native_non_blocking() const 817627f7eb2Smrg { return __base::native_non_blocking(); } 818627f7eb2Smrg 819627f7eb2Smrg bool at_mark() const 820627f7eb2Smrg { return at_mark(__throw_on_error{"basic_socket::at_mark"}); } 821627f7eb2Smrg 822627f7eb2Smrg bool 823627f7eb2Smrg at_mark(error_code& __ec) const 824627f7eb2Smrg { 825627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SOCKATMARK 826627f7eb2Smrg const int __result = ::sockatmark(native_handle()); 827627f7eb2Smrg if (__result == -1) 828627f7eb2Smrg { 829627f7eb2Smrg __ec.assign(errno, generic_category()); 830627f7eb2Smrg return false; 831627f7eb2Smrg } 832627f7eb2Smrg __ec.clear(); 833627f7eb2Smrg return (bool)__result; 834627f7eb2Smrg#else 835627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 836627f7eb2Smrg return false; 837627f7eb2Smrg#endif 838627f7eb2Smrg } 839627f7eb2Smrg 840627f7eb2Smrg size_t 841627f7eb2Smrg available() const 842627f7eb2Smrg { return available(__throw_on_error{"basic_socket::available"}); } 843627f7eb2Smrg 844627f7eb2Smrg size_t 845627f7eb2Smrg available(error_code& __ec) const 846627f7eb2Smrg { 847627f7eb2Smrg if (!is_open()) 848627f7eb2Smrg { 849627f7eb2Smrg __ec = std::make_error_code(errc::bad_file_descriptor); 850627f7eb2Smrg return 0; 851627f7eb2Smrg } 852627f7eb2Smrg#if defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined FIONREAD 853627f7eb2Smrg int __avail = 0; 854627f7eb2Smrg if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1) 855627f7eb2Smrg { 856627f7eb2Smrg __ec.assign(errno, generic_category()); 857627f7eb2Smrg return 0; 858627f7eb2Smrg } 859627f7eb2Smrg __ec.clear(); 860627f7eb2Smrg return __avail; 861627f7eb2Smrg#else 862627f7eb2Smrg return 0; 863627f7eb2Smrg#endif 864627f7eb2Smrg } 865627f7eb2Smrg 866627f7eb2Smrg void 867627f7eb2Smrg bind(const endpoint_type& __endpoint) 868627f7eb2Smrg { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); } 869627f7eb2Smrg 870627f7eb2Smrg void 871627f7eb2Smrg bind(const endpoint_type& __endpoint, error_code& __ec) 872627f7eb2Smrg { __base::bind(__endpoint, __ec); } 873627f7eb2Smrg 874627f7eb2Smrg void shutdown(shutdown_type __what) 875627f7eb2Smrg { return shutdown(__what, __throw_on_error{"basic_socket::shutdown"}); } 876627f7eb2Smrg 877627f7eb2Smrg void 878627f7eb2Smrg shutdown(shutdown_type __what, error_code& __ec) 879627f7eb2Smrg { 880627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 881627f7eb2Smrg if (::shutdown(native_handle(), static_cast<int>(__what)) == -1) 882627f7eb2Smrg __ec.assign(errno, generic_category()); 883627f7eb2Smrg else 884627f7eb2Smrg __ec.clear(); 885627f7eb2Smrg#else 886627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 887627f7eb2Smrg#endif 888627f7eb2Smrg } 889627f7eb2Smrg 890627f7eb2Smrg endpoint_type 891627f7eb2Smrg local_endpoint() const 892627f7eb2Smrg { 893627f7eb2Smrg return local_endpoint( 894627f7eb2Smrg __throw_on_error{"basic_socket::local_endpoint"}); 895627f7eb2Smrg } 896627f7eb2Smrg 897627f7eb2Smrg endpoint_type 898627f7eb2Smrg local_endpoint(error_code& __ec) const 899627f7eb2Smrg { return __base::local_endpoint(__ec); } 900627f7eb2Smrg 901627f7eb2Smrg endpoint_type 902627f7eb2Smrg remote_endpoint() const 903627f7eb2Smrg { 904627f7eb2Smrg return remote_endpoint( 905627f7eb2Smrg __throw_on_error{"basic_socket::remote_endpoint"}); 906627f7eb2Smrg } 907627f7eb2Smrg 908627f7eb2Smrg endpoint_type 909627f7eb2Smrg remote_endpoint(error_code& __ec) const 910627f7eb2Smrg { 911627f7eb2Smrg endpoint_type __endpoint; 912627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 913627f7eb2Smrg socklen_t __endpoint_len = __endpoint.capacity(); 914627f7eb2Smrg if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(), 915627f7eb2Smrg &__endpoint_len) 916627f7eb2Smrg == -1) 917627f7eb2Smrg { 918627f7eb2Smrg __ec.assign(errno, generic_category()); 919627f7eb2Smrg return endpoint_type{}; 920627f7eb2Smrg } 921627f7eb2Smrg __ec.clear(); 922627f7eb2Smrg __endpoint.resize(__endpoint_len); 923627f7eb2Smrg#else 924627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 925627f7eb2Smrg#endif 926627f7eb2Smrg return __endpoint; 927627f7eb2Smrg } 928627f7eb2Smrg 929627f7eb2Smrg void 930627f7eb2Smrg connect(const endpoint_type& __endpoint) 931627f7eb2Smrg { 932627f7eb2Smrg return connect(__endpoint, __throw_on_error{"basic_socket::connect"}); 933627f7eb2Smrg } 934627f7eb2Smrg 935627f7eb2Smrg void 936627f7eb2Smrg connect(const endpoint_type& __endpoint, error_code& __ec) 937627f7eb2Smrg { 938*4c3eb207Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 939627f7eb2Smrg if (!is_open()) 940627f7eb2Smrg { 941627f7eb2Smrg open(__endpoint.protocol(), __ec); 942627f7eb2Smrg if (__ec) 943627f7eb2Smrg return; 944627f7eb2Smrg } 945627f7eb2Smrg if (::connect(native_handle(), (const sockaddr*)__endpoint.data(), 946627f7eb2Smrg __endpoint.size()) == -1) 947627f7eb2Smrg __ec.assign(errno, generic_category()); 948627f7eb2Smrg else 949627f7eb2Smrg __ec.clear(); 950627f7eb2Smrg#else 951627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 952627f7eb2Smrg#endif 953627f7eb2Smrg } 954627f7eb2Smrg 955627f7eb2Smrg template<typename _CompletionToken> 956627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code)> 957627f7eb2Smrg async_connect(const endpoint_type& __endpoint, 958627f7eb2Smrg _CompletionToken&& __token) 959627f7eb2Smrg { 960627f7eb2Smrg async_completion<_CompletionToken, void(error_code)> __init{__token}; 961627f7eb2Smrg 962627f7eb2Smrg if (!is_open()) 963627f7eb2Smrg { 964627f7eb2Smrg error_code __ec; 965627f7eb2Smrg open(__endpoint.protocol(), __ec); 966627f7eb2Smrg if (__ec) 967627f7eb2Smrg { 968627f7eb2Smrg auto __ex = net::get_associated_executor( 969627f7eb2Smrg __init.completion_handler, get_executor()); 970627f7eb2Smrg auto __a = get_associated_allocator( 971627f7eb2Smrg __init.completion_handler, std::allocator<void>()); 972627f7eb2Smrg __ex.post( 973627f7eb2Smrg [__h = std::move(__init.completion_handler), __ec] 974627f7eb2Smrg () mutable 975627f7eb2Smrg { __h(__ec); }, __a); 976627f7eb2Smrg return __init.result.get(); 977627f7eb2Smrg } 978627f7eb2Smrg } 979627f7eb2Smrg 980627f7eb2Smrg get_executor().context().async_wait( native_handle(), 981627f7eb2Smrg socket_base::wait_read, 982627f7eb2Smrg [__h = std::move(__init.completion_handler), 983627f7eb2Smrg __ep = std::move(__endpoint), 984627f7eb2Smrg __fd = native_handle()] 985627f7eb2Smrg (error_code __ec) mutable { 986627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 987627f7eb2Smrg if (!__ec && ::connect(__fd, (const sockaddr*)__ep.data(), 988627f7eb2Smrg __ep.size()) == -1) 989627f7eb2Smrg __ec.assign(errno, generic_category()); 990627f7eb2Smrg#else 991627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 992627f7eb2Smrg#endif 993627f7eb2Smrg __h(__ec); 994627f7eb2Smrg }); 995627f7eb2Smrg return __init.result.get(); 996627f7eb2Smrg } 997627f7eb2Smrg 998627f7eb2Smrg void 999627f7eb2Smrg wait(wait_type __w) 1000627f7eb2Smrg { return wait(__w, __throw_on_error{"basic_socket::wait"}); } 1001627f7eb2Smrg 1002627f7eb2Smrg void 1003627f7eb2Smrg wait(wait_type __w, error_code& __ec) 1004627f7eb2Smrg { 1005627f7eb2Smrg#ifdef _GLIBCXX_HAVE_POLL_H 1006627f7eb2Smrg ::pollfd __fd; 1007627f7eb2Smrg __fd.fd = native_handle(); 1008627f7eb2Smrg __fd.events = static_cast<int>(__w); 1009627f7eb2Smrg int __res = ::poll(&__fd, 1, -1); 1010627f7eb2Smrg if (__res == -1) 1011627f7eb2Smrg __ec.assign(errno, generic_category()); 1012627f7eb2Smrg else 1013627f7eb2Smrg __ec.clear(); 1014627f7eb2Smrg#else 1015627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1016627f7eb2Smrg#endif 1017627f7eb2Smrg } 1018627f7eb2Smrg 1019627f7eb2Smrg template<typename _CompletionToken> 1020627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code)> 1021627f7eb2Smrg async_wait(wait_type __w, _CompletionToken&& __token) 1022627f7eb2Smrg { 1023627f7eb2Smrg async_completion<_CompletionToken, void(error_code)> __init{__token}; 1024627f7eb2Smrg get_executor().context().async_wait( native_handle(), 1025627f7eb2Smrg static_cast<int>(__w), 1026627f7eb2Smrg [__h = std::move(__init.completion_handler)] 1027627f7eb2Smrg (error_code __ec) mutable { 1028627f7eb2Smrg __h(__ec); 1029627f7eb2Smrg }); 1030627f7eb2Smrg return __init.result.get(); 1031627f7eb2Smrg } 1032627f7eb2Smrg 1033627f7eb2Smrg protected: 1034627f7eb2Smrg // construct / copy / destroy: 1035627f7eb2Smrg 1036627f7eb2Smrg using __base::__base; 1037627f7eb2Smrg 1038627f7eb2Smrg explicit 1039627f7eb2Smrg basic_socket(io_context& __ctx) : __base(__ctx) { } 1040627f7eb2Smrg 1041627f7eb2Smrg basic_socket(io_context& __ctx, const protocol_type& __protocol) 1042627f7eb2Smrg : __base(__ctx) 1043627f7eb2Smrg { open(__protocol); } 1044627f7eb2Smrg 1045627f7eb2Smrg basic_socket(io_context& __ctx, const endpoint_type& __endpoint) 1046*4c3eb207Smrg : basic_socket(__ctx, __endpoint.protocol()) 1047627f7eb2Smrg { bind(__endpoint); } 1048627f7eb2Smrg 1049627f7eb2Smrg basic_socket(io_context& __ctx, const protocol_type& __protocol, 1050627f7eb2Smrg const native_handle_type& __native_socket) 1051627f7eb2Smrg : __base(__ctx) 1052627f7eb2Smrg { assign(__protocol, __native_socket); } 1053627f7eb2Smrg 1054627f7eb2Smrg basic_socket(const basic_socket&) = delete; 1055627f7eb2Smrg 1056627f7eb2Smrg basic_socket(basic_socket&& __rhs) = default; 1057627f7eb2Smrg 1058627f7eb2Smrg template<typename _OtherProtocol, typename _Requires 1059627f7eb2Smrg = _Require<is_convertible<_OtherProtocol, _Protocol>>> 1060627f7eb2Smrg basic_socket(basic_socket<_OtherProtocol>&& __rhs) 1061627f7eb2Smrg : __base(std::move(__rhs)) { } 1062627f7eb2Smrg 1063627f7eb2Smrg ~basic_socket() = default; 1064627f7eb2Smrg 1065627f7eb2Smrg basic_socket& operator=(const basic_socket&) = delete; 1066627f7eb2Smrg 1067627f7eb2Smrg basic_socket& operator=(basic_socket&& __rhs) = default; 1068627f7eb2Smrg 1069627f7eb2Smrg template<typename _OtherProtocol> 1070627f7eb2Smrg enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value, 1071627f7eb2Smrg basic_socket&> 1072627f7eb2Smrg operator=(basic_socket<_OtherProtocol>&& __rhs) 1073627f7eb2Smrg { return *this = basic_socket{std::move(__rhs)}; } 1074627f7eb2Smrg }; 1075627f7eb2Smrg 1076627f7eb2Smrg template<typename _Protocol> 1077627f7eb2Smrg class basic_datagram_socket : public basic_socket<_Protocol> 1078627f7eb2Smrg { 1079627f7eb2Smrg using __base = basic_socket<_Protocol>; 1080627f7eb2Smrg 1081627f7eb2Smrg public: 1082627f7eb2Smrg // types: 1083627f7eb2Smrg 1084627f7eb2Smrg typedef int native_handle_type; 1085627f7eb2Smrg typedef _Protocol protocol_type; 1086627f7eb2Smrg typedef typename protocol_type::endpoint endpoint_type; 1087627f7eb2Smrg 1088627f7eb2Smrg // construct / copy / destroy: 1089627f7eb2Smrg 1090627f7eb2Smrg explicit 1091627f7eb2Smrg basic_datagram_socket(io_context& __ctx) : __base(__ctx) { } 1092627f7eb2Smrg 1093627f7eb2Smrg basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol) 1094627f7eb2Smrg : __base(__ctx, __protocol) { } 1095627f7eb2Smrg 1096627f7eb2Smrg basic_datagram_socket(io_context& __ctx, const endpoint_type& __endpoint) 1097627f7eb2Smrg : __base(__ctx, __endpoint) { } 1098627f7eb2Smrg 1099627f7eb2Smrg basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol, 1100627f7eb2Smrg const native_handle_type& __native_socket) 1101627f7eb2Smrg : __base(__ctx, __protocol, __native_socket) { } 1102627f7eb2Smrg 1103627f7eb2Smrg basic_datagram_socket(const basic_datagram_socket&) = delete; 1104627f7eb2Smrg 1105627f7eb2Smrg basic_datagram_socket(basic_datagram_socket&& __rhs) = default; 1106627f7eb2Smrg 1107627f7eb2Smrg template<typename _OtherProtocol, typename _Requires 1108627f7eb2Smrg = _Require<is_convertible<_OtherProtocol, _Protocol>>> 1109627f7eb2Smrg basic_datagram_socket(basic_datagram_socket<_OtherProtocol>&& __rhs) 1110627f7eb2Smrg : __base(std::move(__rhs)) { } 1111627f7eb2Smrg 1112627f7eb2Smrg ~basic_datagram_socket() = default; 1113627f7eb2Smrg 1114627f7eb2Smrg basic_datagram_socket& operator=(const basic_datagram_socket&) = delete; 1115627f7eb2Smrg 1116627f7eb2Smrg basic_datagram_socket& operator=(basic_datagram_socket&& __rhs) = default; 1117627f7eb2Smrg 1118627f7eb2Smrg template<typename _OtherProtocol> 1119627f7eb2Smrg enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value, 1120627f7eb2Smrg basic_datagram_socket&> 1121627f7eb2Smrg operator=(basic_datagram_socket<_OtherProtocol>&& __rhs) 1122627f7eb2Smrg { 1123627f7eb2Smrg __base::operator=(std::move(__rhs)); 1124627f7eb2Smrg return *this; 1125627f7eb2Smrg } 1126627f7eb2Smrg 1127627f7eb2Smrg // basic_datagram_socket operations: 1128627f7eb2Smrg 1129627f7eb2Smrg template<typename _MutableBufferSequence> 1130627f7eb2Smrg size_t 1131627f7eb2Smrg receive(const _MutableBufferSequence& __buffers) 1132627f7eb2Smrg { 1133627f7eb2Smrg return receive(__buffers, socket_base::message_flags(), 1134627f7eb2Smrg __throw_on_error{"basic_datagram_socket::receive"}); 1135627f7eb2Smrg } 1136627f7eb2Smrg 1137627f7eb2Smrg template<typename _MutableBufferSequence> 1138627f7eb2Smrg size_t 1139627f7eb2Smrg receive(const _MutableBufferSequence& __buffers, error_code& __ec) 1140627f7eb2Smrg { return receive(__buffers, socket_base::message_flags(), __ec); } 1141627f7eb2Smrg 1142627f7eb2Smrg template<typename _MutableBufferSequence> 1143627f7eb2Smrg size_t 1144627f7eb2Smrg receive(const _MutableBufferSequence& __buffers, 1145627f7eb2Smrg socket_base::message_flags __flags) 1146627f7eb2Smrg { 1147627f7eb2Smrg return receive(__buffers, __flags, 1148627f7eb2Smrg __throw_on_error{"basic_datagram_socket::receive"}); 1149627f7eb2Smrg } 1150627f7eb2Smrg 1151627f7eb2Smrg template<typename _MutableBufferSequence> 1152627f7eb2Smrg size_t 1153627f7eb2Smrg receive(const _MutableBufferSequence& __buffers, 1154627f7eb2Smrg socket_base::message_flags __flags, error_code& __ec) 1155627f7eb2Smrg { 1156627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1157627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1158627f7eb2Smrg ssize_t __result = ::recvmsg(this->native_handle(), &__msg, 1159627f7eb2Smrg static_cast<int>(__flags)); 1160627f7eb2Smrg if (__result == -1) 1161627f7eb2Smrg { 1162627f7eb2Smrg __ec.assign(errno, generic_category()); 1163627f7eb2Smrg return 0; 1164627f7eb2Smrg } 1165627f7eb2Smrg __ec.clear(); 1166627f7eb2Smrg return __result; 1167627f7eb2Smrg#else 1168627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1169627f7eb2Smrg return 0; 1170627f7eb2Smrg#endif 1171627f7eb2Smrg } 1172627f7eb2Smrg 1173627f7eb2Smrg template<typename _MutableBufferSequence, typename _CompletionToken> 1174627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1175627f7eb2Smrg async_receive(const _MutableBufferSequence& __buffers, 1176627f7eb2Smrg _CompletionToken&& __token) 1177627f7eb2Smrg { 1178627f7eb2Smrg return async_receive(__buffers, socket_base::message_flags(), 1179627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1180627f7eb2Smrg } 1181627f7eb2Smrg 1182627f7eb2Smrg template<typename _MutableBufferSequence, typename _CompletionToken> 1183627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1184627f7eb2Smrg async_receive(const _MutableBufferSequence& __buffers, 1185627f7eb2Smrg socket_base::message_flags __flags, 1186627f7eb2Smrg _CompletionToken&& __token) 1187627f7eb2Smrg { 1188627f7eb2Smrg async_completion<_CompletionToken, void(error_code, size_t)> 1189627f7eb2Smrg __init{__token}; 1190627f7eb2Smrg 1191627f7eb2Smrg this->get_executor().context().async_wait(this->native_handle(), 1192627f7eb2Smrg socket_base::wait_read, 1193627f7eb2Smrg [__h = std::move(__init.completion_handler), 1194627f7eb2Smrg &__buffers, __flags = static_cast<int>(__flags), 1195627f7eb2Smrg __fd = this->native_handle()] 1196627f7eb2Smrg (error_code __ec) mutable { 1197627f7eb2Smrg if (__ec) 1198627f7eb2Smrg { 1199627f7eb2Smrg __h(__ec); 1200627f7eb2Smrg return; 1201627f7eb2Smrg } 1202627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1203627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1204627f7eb2Smrg ssize_t __result = ::recvmsg(__fd, &__msg, __flags); 1205627f7eb2Smrg if (__result == -1) 1206627f7eb2Smrg { 1207627f7eb2Smrg __ec.assign(errno, generic_category()); 1208627f7eb2Smrg __result = 0; 1209627f7eb2Smrg } 1210627f7eb2Smrg else 1211627f7eb2Smrg __ec.clear(); 1212627f7eb2Smrg __h(__ec, __result); 1213627f7eb2Smrg#else 1214627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 1215627f7eb2Smrg#endif 1216627f7eb2Smrg }); 1217627f7eb2Smrg return __init.result.get(); 1218627f7eb2Smrg } 1219627f7eb2Smrg 1220627f7eb2Smrg template<typename _MutableBufferSequence> 1221627f7eb2Smrg size_t 1222627f7eb2Smrg receive_from(const _MutableBufferSequence& __buffers, 1223627f7eb2Smrg endpoint_type& __sender) 1224627f7eb2Smrg { 1225627f7eb2Smrg return receive_from(__buffers, __sender, 1226627f7eb2Smrg socket_base::message_flags(), 1227627f7eb2Smrg __throw_on_error{ 1228627f7eb2Smrg "basic_datagram_socket::receive_from"}); 1229627f7eb2Smrg } 1230627f7eb2Smrg 1231627f7eb2Smrg template<typename _MutableBufferSequence> 1232627f7eb2Smrg size_t 1233627f7eb2Smrg receive_from(const _MutableBufferSequence& __buffers, 1234627f7eb2Smrg endpoint_type& __sender, error_code& __ec) 1235627f7eb2Smrg { 1236627f7eb2Smrg return receive_from(__buffers, __sender, 1237627f7eb2Smrg socket_base::message_flags(), __ec); 1238627f7eb2Smrg } 1239627f7eb2Smrg 1240627f7eb2Smrg template<typename _MutableBufferSequence> 1241627f7eb2Smrg size_t 1242627f7eb2Smrg receive_from(const _MutableBufferSequence& __buffers, 1243627f7eb2Smrg endpoint_type& __sender, 1244627f7eb2Smrg socket_base::message_flags __flags) 1245627f7eb2Smrg { 1246627f7eb2Smrg return receive_from(__buffers, __sender, __flags, 1247627f7eb2Smrg __throw_on_error{ 1248627f7eb2Smrg "basic_datagram_socket::receive_from"}); 1249627f7eb2Smrg } 1250627f7eb2Smrg 1251627f7eb2Smrg template<typename _MutableBufferSequence> 1252627f7eb2Smrg size_t 1253627f7eb2Smrg receive_from(const _MutableBufferSequence& __buffers, 1254627f7eb2Smrg endpoint_type& __sender, 1255627f7eb2Smrg socket_base::message_flags __flags, 1256627f7eb2Smrg error_code& __ec) 1257627f7eb2Smrg { 1258627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1259627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers, __sender); 1260627f7eb2Smrg ssize_t __result = ::recvmsg(this->native_handle(), &__msg, 1261627f7eb2Smrg static_cast<int>(__flags)); 1262627f7eb2Smrg if (__result == -1) 1263627f7eb2Smrg { 1264627f7eb2Smrg __ec.assign(errno, generic_category()); 1265627f7eb2Smrg return 0; 1266627f7eb2Smrg } 1267627f7eb2Smrg __ec.clear(); 1268627f7eb2Smrg __sender.resize(__msg.msg_namelen); 1269627f7eb2Smrg return __result; 1270627f7eb2Smrg#else 1271627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1272627f7eb2Smrg return 0; 1273627f7eb2Smrg#endif 1274627f7eb2Smrg } 1275627f7eb2Smrg 1276627f7eb2Smrg template<typename _MutableBufferSequence, typename _CompletionToken> 1277627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1278627f7eb2Smrg async_receive_from(const _MutableBufferSequence& __buffers, 1279627f7eb2Smrg endpoint_type& __sender, 1280627f7eb2Smrg _CompletionToken&& __token) 1281627f7eb2Smrg { 1282627f7eb2Smrg return async_receive_from(__buffers, __sender, 1283627f7eb2Smrg socket_base::message_flags(), 1284627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1285627f7eb2Smrg } 1286627f7eb2Smrg 1287627f7eb2Smrg template<typename _MutableBufferSequence, typename _CompletionToken> 1288627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1289627f7eb2Smrg async_receive_from(const _MutableBufferSequence& __buffers, 1290627f7eb2Smrg endpoint_type& __sender, 1291627f7eb2Smrg socket_base::message_flags __flags, 1292627f7eb2Smrg _CompletionToken&& __token) 1293627f7eb2Smrg { 1294627f7eb2Smrg async_completion<_CompletionToken, void(error_code, size_t)> 1295627f7eb2Smrg __init{__token}; 1296627f7eb2Smrg 1297627f7eb2Smrg this->get_executor().context().async_wait( this->native_handle(), 1298627f7eb2Smrg socket_base::wait_read, 1299627f7eb2Smrg [__h = std::move(__init.completion_handler), 1300627f7eb2Smrg &__buffers, __flags = static_cast<int>(__flags), 1301627f7eb2Smrg __sender = std::move(__sender), 1302627f7eb2Smrg __fd = this->native_handle()] 1303627f7eb2Smrg (error_code __ec) mutable { 1304627f7eb2Smrg if (__ec) 1305627f7eb2Smrg { 1306627f7eb2Smrg __h(__ec); 1307627f7eb2Smrg return; 1308627f7eb2Smrg } 1309627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1310627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers, __sender); 1311627f7eb2Smrg ssize_t __result = ::recvmsg(__fd, &__msg, __flags); 1312627f7eb2Smrg if (__result == -1) 1313627f7eb2Smrg { 1314627f7eb2Smrg __ec.assign(errno, generic_category()); 1315627f7eb2Smrg __result = 0; 1316627f7eb2Smrg } 1317627f7eb2Smrg else 1318627f7eb2Smrg { 1319627f7eb2Smrg __ec.clear(); 1320627f7eb2Smrg __sender.resize(__msg.msg_namelen); 1321627f7eb2Smrg } 1322627f7eb2Smrg __h(__ec, __result); 1323627f7eb2Smrg#else 1324627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 1325627f7eb2Smrg#endif 1326627f7eb2Smrg }); 1327627f7eb2Smrg return __init.result.get(); 1328627f7eb2Smrg } 1329627f7eb2Smrg 1330627f7eb2Smrg template<typename _ConstBufferSequence> 1331627f7eb2Smrg size_t 1332627f7eb2Smrg send(const _ConstBufferSequence& __buffers) 1333627f7eb2Smrg { 1334627f7eb2Smrg return send(__buffers, socket_base::message_flags(), 1335627f7eb2Smrg __throw_on_error{"basic_datagram_socket::send"}); 1336627f7eb2Smrg } 1337627f7eb2Smrg 1338627f7eb2Smrg template<typename _ConstBufferSequence> 1339627f7eb2Smrg size_t 1340627f7eb2Smrg send(const _ConstBufferSequence& __buffers, error_code& __ec) 1341627f7eb2Smrg { return send(__buffers, socket_base::message_flags(), __ec); } 1342627f7eb2Smrg 1343627f7eb2Smrg template<typename _ConstBufferSequence> 1344627f7eb2Smrg size_t 1345627f7eb2Smrg send(const _ConstBufferSequence& __buffers, 1346627f7eb2Smrg socket_base::message_flags __flags) 1347627f7eb2Smrg { 1348627f7eb2Smrg return send(__buffers, __flags, 1349627f7eb2Smrg __throw_on_error{"basic_datagram_socket::send"}); 1350627f7eb2Smrg } 1351627f7eb2Smrg 1352627f7eb2Smrg template<typename _ConstBufferSequence> 1353627f7eb2Smrg size_t 1354627f7eb2Smrg send(const _ConstBufferSequence& __buffers, 1355627f7eb2Smrg socket_base::message_flags __flags, error_code& __ec) 1356627f7eb2Smrg { 1357627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1358627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1359627f7eb2Smrg ssize_t __result = ::sendmsg(this->native_handle(), &__msg, 1360627f7eb2Smrg static_cast<int>(__flags)); 1361627f7eb2Smrg if (__result == -1) 1362627f7eb2Smrg { 1363627f7eb2Smrg __ec.assign(errno, generic_category()); 1364627f7eb2Smrg return 0; 1365627f7eb2Smrg } 1366627f7eb2Smrg __ec.clear(); 1367627f7eb2Smrg return __result; 1368627f7eb2Smrg#else 1369627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1370627f7eb2Smrg return 0; 1371627f7eb2Smrg#endif 1372627f7eb2Smrg } 1373627f7eb2Smrg 1374627f7eb2Smrg template<typename _ConstBufferSequence, typename _CompletionToken> 1375627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1376627f7eb2Smrg async_send(const _ConstBufferSequence& __buffers, 1377627f7eb2Smrg _CompletionToken&& __token) 1378627f7eb2Smrg { 1379627f7eb2Smrg return async_send(__buffers, socket_base::message_flags(), 1380627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1381627f7eb2Smrg } 1382627f7eb2Smrg 1383627f7eb2Smrg template<typename _ConstBufferSequence, typename _CompletionToken> 1384627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1385627f7eb2Smrg async_send(const _ConstBufferSequence& __buffers, 1386627f7eb2Smrg socket_base::message_flags __flags, 1387627f7eb2Smrg _CompletionToken&& __token) 1388627f7eb2Smrg { 1389627f7eb2Smrg async_completion<_CompletionToken, void(error_code, size_t)> 1390627f7eb2Smrg __init{__token}; 1391627f7eb2Smrg 1392627f7eb2Smrg this->get_executor().context().async_wait( this->native_handle(), 1393627f7eb2Smrg socket_base::wait_write, 1394627f7eb2Smrg [__h = std::move(__init.completion_handler), 1395627f7eb2Smrg &__buffers, __flags = static_cast<int>(__flags), 1396627f7eb2Smrg __fd = this->native_handle()] 1397627f7eb2Smrg (error_code __ec) mutable { 1398627f7eb2Smrg if (__ec) 1399627f7eb2Smrg { 1400627f7eb2Smrg __h(__ec); 1401627f7eb2Smrg return; 1402627f7eb2Smrg } 1403627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1404627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1405627f7eb2Smrg ssize_t __result = ::sendmsg(__fd, &__msg, __flags); 1406627f7eb2Smrg if (__result == -1) 1407627f7eb2Smrg { 1408627f7eb2Smrg __ec.assign(errno, generic_category()); 1409627f7eb2Smrg __result = 0; 1410627f7eb2Smrg } 1411627f7eb2Smrg else 1412627f7eb2Smrg __ec.clear(); 1413627f7eb2Smrg __h(__ec, __result); 1414627f7eb2Smrg#else 1415627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 1416627f7eb2Smrg#endif 1417627f7eb2Smrg }); 1418627f7eb2Smrg return __init.result.get(); 1419627f7eb2Smrg } 1420627f7eb2Smrg 1421627f7eb2Smrg template<typename _ConstBufferSequence> 1422627f7eb2Smrg size_t 1423627f7eb2Smrg send_to(const _ConstBufferSequence& __buffers, 1424627f7eb2Smrg const endpoint_type& __recipient) 1425627f7eb2Smrg { 1426627f7eb2Smrg return send_to(__buffers, __recipient, 1427627f7eb2Smrg socket_base::message_flags(), 1428627f7eb2Smrg __throw_on_error{"basic_datagram_socket::send_to"}); 1429627f7eb2Smrg } 1430627f7eb2Smrg 1431627f7eb2Smrg template<typename _ConstBufferSequence> 1432627f7eb2Smrg size_t 1433627f7eb2Smrg send_to(const _ConstBufferSequence& __buffers, 1434627f7eb2Smrg const endpoint_type& __recipient, error_code& __ec) 1435627f7eb2Smrg { 1436627f7eb2Smrg return send_to(__buffers, __recipient, 1437627f7eb2Smrg socket_base::message_flags(), __ec); 1438627f7eb2Smrg } 1439627f7eb2Smrg 1440627f7eb2Smrg template<typename _ConstBufferSequence> 1441627f7eb2Smrg size_t 1442627f7eb2Smrg send_to(const _ConstBufferSequence& __buffers, 1443627f7eb2Smrg const endpoint_type& __recipient, 1444627f7eb2Smrg socket_base::message_flags __flags) 1445627f7eb2Smrg { 1446627f7eb2Smrg return send_to(__buffers, __recipient, __flags, 1447627f7eb2Smrg __throw_on_error{"basic_datagram_socket::send_to"}); 1448627f7eb2Smrg } 1449627f7eb2Smrg 1450627f7eb2Smrg template<typename _ConstBufferSequence> 1451627f7eb2Smrg size_t 1452627f7eb2Smrg send_to(const _ConstBufferSequence& __buffers, 1453627f7eb2Smrg const endpoint_type& __recipient, 1454627f7eb2Smrg socket_base::message_flags __flags, error_code& __ec) 1455627f7eb2Smrg { 1456627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1457627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers, __recipient); 1458627f7eb2Smrg ssize_t __result = ::sendmsg(this->native_handle(), &__msg, 1459627f7eb2Smrg static_cast<int>(__flags)); 1460627f7eb2Smrg if (__result == -1) 1461627f7eb2Smrg { 1462627f7eb2Smrg __ec.assign(errno, generic_category()); 1463627f7eb2Smrg return 0; 1464627f7eb2Smrg } 1465627f7eb2Smrg __ec.clear(); 1466627f7eb2Smrg __recipient.resize(__msg.msg_namelen); 1467627f7eb2Smrg return __result; 1468627f7eb2Smrg#else 1469627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1470627f7eb2Smrg return 0; 1471627f7eb2Smrg#endif 1472627f7eb2Smrg } 1473627f7eb2Smrg 1474627f7eb2Smrg template<typename _ConstBufferSequence, typename _CompletionToken> 1475627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1476627f7eb2Smrg async_send_to(const _ConstBufferSequence& __buffers, 1477627f7eb2Smrg const endpoint_type& __recipient, 1478627f7eb2Smrg _CompletionToken&& __token) 1479627f7eb2Smrg { 1480627f7eb2Smrg return async_send_to(__buffers, __recipient, 1481627f7eb2Smrg socket_base::message_flags(), 1482627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1483627f7eb2Smrg } 1484627f7eb2Smrg 1485627f7eb2Smrg template<typename _ConstBufferSequence, typename _CompletionToken> 1486627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1487627f7eb2Smrg async_send_to(const _ConstBufferSequence& __buffers, 1488627f7eb2Smrg const endpoint_type& __recipient, 1489627f7eb2Smrg socket_base::message_flags __flags, 1490627f7eb2Smrg _CompletionToken&& __token) 1491627f7eb2Smrg { 1492627f7eb2Smrg async_completion<_CompletionToken, void(error_code, size_t)> 1493627f7eb2Smrg __init{__token}; 1494627f7eb2Smrg 1495627f7eb2Smrg this->get_executor().context().async_wait( this->native_handle(), 1496627f7eb2Smrg socket_base::wait_write, 1497627f7eb2Smrg [__h = std::move(__init.completion_handler), 1498627f7eb2Smrg &__buffers, __flags = static_cast<int>(__flags), 1499627f7eb2Smrg __recipient = std::move(__recipient), 1500627f7eb2Smrg __fd = this->native_handle()] 1501627f7eb2Smrg (error_code __ec) mutable { 1502627f7eb2Smrg if (__ec) 1503627f7eb2Smrg { 1504627f7eb2Smrg __h(__ec); 1505627f7eb2Smrg return; 1506627f7eb2Smrg } 1507627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1508627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers, __recipient); 1509627f7eb2Smrg ssize_t __result = ::sendmsg(__fd, &__msg, __flags); 1510627f7eb2Smrg if (__result == -1) 1511627f7eb2Smrg { 1512627f7eb2Smrg __ec.assign(errno, generic_category()); 1513627f7eb2Smrg __result = 0; 1514627f7eb2Smrg } 1515627f7eb2Smrg else 1516627f7eb2Smrg { 1517627f7eb2Smrg __ec.clear(); 1518627f7eb2Smrg __recipient.resize(__msg.msg_namelen); 1519627f7eb2Smrg } 1520627f7eb2Smrg __h(__ec, __result); 1521627f7eb2Smrg#else 1522627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 1523627f7eb2Smrg#endif 1524627f7eb2Smrg }); 1525627f7eb2Smrg return __init.result.get(); 1526627f7eb2Smrg } 1527627f7eb2Smrg }; 1528627f7eb2Smrg 1529627f7eb2Smrg template<typename _Protocol> 1530627f7eb2Smrg class basic_stream_socket : public basic_socket<_Protocol> 1531627f7eb2Smrg { 1532627f7eb2Smrg using __base = basic_socket<_Protocol>; 1533627f7eb2Smrg 1534627f7eb2Smrg public: 1535627f7eb2Smrg // types: 1536627f7eb2Smrg 1537627f7eb2Smrg typedef int native_handle_type; 1538627f7eb2Smrg typedef _Protocol protocol_type; 1539627f7eb2Smrg typedef typename protocol_type::endpoint endpoint_type; 1540627f7eb2Smrg 1541627f7eb2Smrg // construct / copy / destroy: 1542627f7eb2Smrg 1543627f7eb2Smrg explicit 1544627f7eb2Smrg basic_stream_socket(io_context& __ctx) : __base(__ctx) { } 1545627f7eb2Smrg 1546627f7eb2Smrg basic_stream_socket(io_context& __ctx, const protocol_type& __protocol) 1547627f7eb2Smrg : __base(__ctx, __protocol) { } 1548627f7eb2Smrg 1549627f7eb2Smrg basic_stream_socket(io_context& __ctx, const endpoint_type& __endpoint) 1550627f7eb2Smrg : __base(__ctx, __endpoint) { } 1551627f7eb2Smrg 1552627f7eb2Smrg basic_stream_socket(io_context& __ctx, const protocol_type& __protocol, 1553627f7eb2Smrg const native_handle_type& __native_socket) 1554627f7eb2Smrg : __base(__ctx, __protocol, __native_socket) { } 1555627f7eb2Smrg 1556627f7eb2Smrg basic_stream_socket(const basic_stream_socket&) = delete; 1557627f7eb2Smrg 1558627f7eb2Smrg basic_stream_socket(basic_stream_socket&& __rhs) = default; 1559627f7eb2Smrg 1560627f7eb2Smrg template<typename _OtherProtocol, typename _Requires 1561627f7eb2Smrg = _Require<is_convertible<_OtherProtocol, _Protocol>>> 1562627f7eb2Smrg basic_stream_socket(basic_stream_socket<_OtherProtocol>&& __rhs) 1563627f7eb2Smrg : __base(std::move(__rhs)) { } 1564627f7eb2Smrg 1565627f7eb2Smrg ~basic_stream_socket() = default; 1566627f7eb2Smrg 1567627f7eb2Smrg basic_stream_socket& operator=(const basic_stream_socket&) = delete; 1568627f7eb2Smrg 1569627f7eb2Smrg basic_stream_socket& operator=(basic_stream_socket&& __rhs) = default; 1570627f7eb2Smrg 1571627f7eb2Smrg template<class _OtherProtocol> 1572627f7eb2Smrg enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value, 1573627f7eb2Smrg basic_stream_socket&> 1574627f7eb2Smrg operator=(basic_stream_socket<_OtherProtocol>&& __rhs) 1575627f7eb2Smrg { 1576627f7eb2Smrg __base::operator=(std::move(__rhs)); 1577627f7eb2Smrg return *this; 1578627f7eb2Smrg } 1579627f7eb2Smrg 1580627f7eb2Smrg // basic_stream_socket operations: 1581627f7eb2Smrg 1582627f7eb2Smrg template<class _MutableBufferSequence> 1583627f7eb2Smrg size_t 1584627f7eb2Smrg receive(const _MutableBufferSequence& __buffers) 1585627f7eb2Smrg { 1586627f7eb2Smrg return receive(__buffers, socket_base::message_flags(), 1587627f7eb2Smrg __throw_on_error{"basic_stream_socket::receive"}); 1588627f7eb2Smrg } 1589627f7eb2Smrg 1590627f7eb2Smrg template<class _MutableBufferSequence> 1591627f7eb2Smrg size_t 1592627f7eb2Smrg receive(const _MutableBufferSequence& __buffers, error_code& __ec) 1593627f7eb2Smrg { return receive(__buffers, socket_base::message_flags(), __ec); } 1594627f7eb2Smrg 1595627f7eb2Smrg template<class _MutableBufferSequence> 1596627f7eb2Smrg size_t 1597627f7eb2Smrg receive(const _MutableBufferSequence& __buffers, 1598627f7eb2Smrg socket_base::message_flags __flags) 1599627f7eb2Smrg { 1600627f7eb2Smrg return receive(__buffers, __flags, 1601627f7eb2Smrg __throw_on_error{"basic_stream_socket::receive"}); 1602627f7eb2Smrg } 1603627f7eb2Smrg 1604627f7eb2Smrg template<class _MutableBufferSequence> 1605627f7eb2Smrg size_t 1606627f7eb2Smrg receive(const _MutableBufferSequence& __buffers, 1607627f7eb2Smrg socket_base::message_flags __flags, error_code& __ec) 1608627f7eb2Smrg { 1609627f7eb2Smrg if (__buffer_empty(__buffers)) 1610627f7eb2Smrg { 1611627f7eb2Smrg __ec.clear(); 1612627f7eb2Smrg return 0; 1613627f7eb2Smrg } 1614627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1615627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1616627f7eb2Smrg ssize_t __result = ::recvmsg(this->native_handle(), &__msg, 1617627f7eb2Smrg static_cast<int>(__flags)); 1618627f7eb2Smrg if (__result >= 0) 1619627f7eb2Smrg { 1620627f7eb2Smrg __ec.clear(); 1621627f7eb2Smrg return __result; 1622627f7eb2Smrg } 1623627f7eb2Smrg __ec.assign(errno, generic_category()); 1624627f7eb2Smrg#else 1625627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1626627f7eb2Smrg#endif 1627627f7eb2Smrg return 0; 1628627f7eb2Smrg } 1629627f7eb2Smrg 1630627f7eb2Smrg template<class _MutableBufferSequence, class _CompletionToken> 1631627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1632627f7eb2Smrg async_receive(const _MutableBufferSequence& __buffers, 1633627f7eb2Smrg _CompletionToken&& __token) 1634627f7eb2Smrg { 1635627f7eb2Smrg return async_receive(__buffers, socket_base::message_flags(), 1636627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1637627f7eb2Smrg } 1638627f7eb2Smrg 1639627f7eb2Smrg template<class _MutableBufferSequence, class _CompletionToken> 1640627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1641627f7eb2Smrg async_receive(const _MutableBufferSequence& __buffers, 1642627f7eb2Smrg socket_base::message_flags __flags, 1643627f7eb2Smrg _CompletionToken&& __token) 1644627f7eb2Smrg { 1645627f7eb2Smrg async_completion<_CompletionToken, void(error_code, size_t)> 1646627f7eb2Smrg __init{__token}; 1647627f7eb2Smrg 1648627f7eb2Smrg if (__buffer_empty(__buffers)) 1649627f7eb2Smrg { 1650627f7eb2Smrg auto __ex = net::get_associated_executor( 1651627f7eb2Smrg __init.completion_handler, this->get_executor()); 1652627f7eb2Smrg auto __a = get_associated_allocator( 1653627f7eb2Smrg __init.completion_handler, std::allocator<void>()); 1654627f7eb2Smrg __ex.post( 1655627f7eb2Smrg [__h=std::move(__init.completion_handler)] () mutable 1656627f7eb2Smrg { __h(error_code{}, 0); }, __a); 1657627f7eb2Smrg return __init.result.get(); 1658627f7eb2Smrg } 1659627f7eb2Smrg 1660627f7eb2Smrg this->get_executor().context().async_wait(this->native_handle(), 1661627f7eb2Smrg socket_base::wait_read, 1662627f7eb2Smrg [__h = std::move(__init.completion_handler), 1663627f7eb2Smrg &__buffers, __flags = static_cast<int>(__flags), 1664627f7eb2Smrg __fd = this->native_handle()] 1665627f7eb2Smrg (error_code __ec) mutable { 1666627f7eb2Smrg if (__ec) 1667627f7eb2Smrg { 1668627f7eb2Smrg __h(__ec); 1669627f7eb2Smrg return; 1670627f7eb2Smrg } 1671627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1672627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1673627f7eb2Smrg ssize_t __result = ::recvmsg(__fd, &__msg, __flags); 1674627f7eb2Smrg if (__result == -1) 1675627f7eb2Smrg { 1676627f7eb2Smrg __ec.assign(errno, generic_category()); 1677627f7eb2Smrg __result = 0; 1678627f7eb2Smrg } 1679627f7eb2Smrg else 1680627f7eb2Smrg __ec.clear(); 1681627f7eb2Smrg __h(__ec, __result); 1682627f7eb2Smrg#else 1683627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 1684627f7eb2Smrg#endif 1685627f7eb2Smrg }); 1686627f7eb2Smrg return __init.result.get(); 1687627f7eb2Smrg } 1688627f7eb2Smrg 1689627f7eb2Smrg template<class _ConstBufferSequence> 1690627f7eb2Smrg size_t 1691627f7eb2Smrg send(const _ConstBufferSequence& __buffers) 1692627f7eb2Smrg { 1693627f7eb2Smrg return send(__buffers, socket_base::message_flags(), 1694627f7eb2Smrg __throw_on_error{"basic_stream_socket::send"}); 1695627f7eb2Smrg } 1696627f7eb2Smrg 1697627f7eb2Smrg template<class _ConstBufferSequence> 1698627f7eb2Smrg size_t 1699627f7eb2Smrg send(const _ConstBufferSequence& __buffers, error_code& __ec) 1700627f7eb2Smrg { return send(__buffers, socket_base::message_flags(), __ec); } 1701627f7eb2Smrg 1702627f7eb2Smrg template<class _ConstBufferSequence> 1703627f7eb2Smrg size_t 1704627f7eb2Smrg send(const _ConstBufferSequence& __buffers, 1705627f7eb2Smrg socket_base::message_flags __flags) 1706627f7eb2Smrg { 1707627f7eb2Smrg return send(__buffers, socket_base::message_flags(), 1708627f7eb2Smrg __throw_on_error{"basic_stream_socket::send"}); 1709627f7eb2Smrg } 1710627f7eb2Smrg 1711627f7eb2Smrg template<class _ConstBufferSequence> 1712627f7eb2Smrg size_t 1713627f7eb2Smrg send(const _ConstBufferSequence& __buffers, 1714627f7eb2Smrg socket_base::message_flags __flags, error_code& __ec) 1715627f7eb2Smrg { 1716627f7eb2Smrg if (__buffer_empty(__buffers)) 1717627f7eb2Smrg { 1718627f7eb2Smrg __ec.clear(); 1719627f7eb2Smrg return 0; 1720627f7eb2Smrg } 1721627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1722627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1723627f7eb2Smrg ssize_t __result = ::sendmsg(this->native_handle(), &__msg, 1724627f7eb2Smrg static_cast<int>(__flags)); 1725627f7eb2Smrg if (__result >= 0) 1726627f7eb2Smrg { 1727627f7eb2Smrg __ec.clear(); 1728627f7eb2Smrg return __result; 1729627f7eb2Smrg } 1730627f7eb2Smrg __ec.assign(errno, generic_category()); 1731627f7eb2Smrg#else 1732627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 1733627f7eb2Smrg#endif 1734627f7eb2Smrg return 0; 1735627f7eb2Smrg } 1736627f7eb2Smrg 1737627f7eb2Smrg template<class _ConstBufferSequence, class _CompletionToken> 1738627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1739627f7eb2Smrg async_send(const _ConstBufferSequence& __buffers, 1740627f7eb2Smrg _CompletionToken&& __token) 1741627f7eb2Smrg { 1742627f7eb2Smrg return async_send(__buffers, socket_base::message_flags(), 1743627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1744627f7eb2Smrg } 1745627f7eb2Smrg 1746627f7eb2Smrg template<class _ConstBufferSequence, class _CompletionToken> 1747627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1748627f7eb2Smrg async_send(const _ConstBufferSequence& __buffers, 1749627f7eb2Smrg socket_base::message_flags __flags, 1750627f7eb2Smrg _CompletionToken&& __token) 1751627f7eb2Smrg { 1752627f7eb2Smrg async_completion<_CompletionToken, void(error_code, size_t)> 1753627f7eb2Smrg __init{__token}; 1754627f7eb2Smrg 1755627f7eb2Smrg if (__buffer_empty(__buffers)) 1756627f7eb2Smrg { 1757627f7eb2Smrg auto __ex = net::get_associated_executor( 1758627f7eb2Smrg __init.completion_handler, this->get_executor()); 1759627f7eb2Smrg auto __a = get_associated_allocator( 1760627f7eb2Smrg __init.completion_handler, std::allocator<void>()); 1761627f7eb2Smrg __ex.post( 1762627f7eb2Smrg [__h=std::move(__init.completion_handler)] () mutable 1763627f7eb2Smrg { __h(error_code{}, 0); }, __a); 1764627f7eb2Smrg return __init.result.get(); 1765627f7eb2Smrg } 1766627f7eb2Smrg 1767627f7eb2Smrg this->get_executor().context().async_wait(this->native_handle(), 1768627f7eb2Smrg socket_base::wait_write, 1769627f7eb2Smrg [__h = std::move(__init.completion_handler), 1770627f7eb2Smrg &__buffers, __flags = static_cast<int>(__flags), 1771627f7eb2Smrg __fd = this->native_handle()] 1772627f7eb2Smrg (error_code __ec) mutable { 1773627f7eb2Smrg if (__ec) 1774627f7eb2Smrg { 1775627f7eb2Smrg __h(__ec); 1776627f7eb2Smrg return; 1777627f7eb2Smrg } 1778627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 1779627f7eb2Smrg socket_base::__msg_hdr __msg(__buffers); 1780627f7eb2Smrg ssize_t __result = ::sendmsg(__fd, &__msg, __flags); 1781627f7eb2Smrg if (__result == -1) 1782627f7eb2Smrg { 1783627f7eb2Smrg __ec.assign(errno, generic_category()); 1784627f7eb2Smrg __result = 0; 1785627f7eb2Smrg } 1786627f7eb2Smrg else 1787627f7eb2Smrg __ec.clear(); 1788627f7eb2Smrg __h(__ec, __result); 1789627f7eb2Smrg#else 1790627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 1791627f7eb2Smrg#endif 1792627f7eb2Smrg }); 1793627f7eb2Smrg return __init.result.get(); 1794627f7eb2Smrg } 1795627f7eb2Smrg 1796627f7eb2Smrg template<class _MutableBufferSequence> 1797627f7eb2Smrg size_t 1798627f7eb2Smrg read_some(const _MutableBufferSequence& __buffers) 1799627f7eb2Smrg { 1800627f7eb2Smrg return receive(__buffers, 1801627f7eb2Smrg __throw_on_error{"basic_stream_socket::read_some"}); 1802627f7eb2Smrg } 1803627f7eb2Smrg 1804627f7eb2Smrg template<class _MutableBufferSequence> 1805627f7eb2Smrg size_t 1806627f7eb2Smrg read_some(const _MutableBufferSequence& __buffers, error_code& __ec) 1807627f7eb2Smrg { return receive(__buffers, __ec); } 1808627f7eb2Smrg 1809627f7eb2Smrg template<class _MutableBufferSequence, class _CompletionToken> 1810627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1811627f7eb2Smrg async_read_some(const _MutableBufferSequence& __buffers, 1812627f7eb2Smrg _CompletionToken&& __token) 1813627f7eb2Smrg { 1814627f7eb2Smrg return async_receive(__buffers, 1815627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1816627f7eb2Smrg } 1817627f7eb2Smrg 1818627f7eb2Smrg template<class _ConstBufferSequence> 1819627f7eb2Smrg size_t 1820627f7eb2Smrg write_some(const _ConstBufferSequence& __buffers) 1821627f7eb2Smrg { 1822627f7eb2Smrg return send(__buffers, 1823627f7eb2Smrg __throw_on_error{"basic_stream_socket:write_some"}); 1824627f7eb2Smrg } 1825627f7eb2Smrg 1826627f7eb2Smrg template<class _ConstBufferSequence> 1827627f7eb2Smrg size_t 1828627f7eb2Smrg write_some(const _ConstBufferSequence& __buffers, error_code& __ec) 1829627f7eb2Smrg { return send(__buffers, __ec); } 1830627f7eb2Smrg 1831627f7eb2Smrg template<class _ConstBufferSequence, class _CompletionToken> 1832627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, size_t)> 1833627f7eb2Smrg async_write_some(const _ConstBufferSequence& __buffers, 1834627f7eb2Smrg _CompletionToken&& __token) 1835627f7eb2Smrg { 1836627f7eb2Smrg return async_send(__buffers, 1837627f7eb2Smrg std::forward<_CompletionToken>(__token)); 1838627f7eb2Smrg } 1839627f7eb2Smrg }; 1840627f7eb2Smrg 1841627f7eb2Smrg template<typename _AcceptableProtocol> 1842627f7eb2Smrg class basic_socket_acceptor 1843627f7eb2Smrg : public socket_base, private __basic_socket_impl<_AcceptableProtocol> 1844627f7eb2Smrg { 1845627f7eb2Smrg using __base = __basic_socket_impl<_AcceptableProtocol>; 1846627f7eb2Smrg 1847627f7eb2Smrg public: 1848627f7eb2Smrg // types: 1849627f7eb2Smrg 1850627f7eb2Smrg typedef io_context::executor_type executor_type; 1851627f7eb2Smrg typedef int native_handle_type; 1852627f7eb2Smrg typedef _AcceptableProtocol protocol_type; 1853627f7eb2Smrg typedef typename protocol_type::endpoint endpoint_type; 1854627f7eb2Smrg typedef typename protocol_type::socket socket_type; 1855627f7eb2Smrg 1856627f7eb2Smrg // construct / copy / destroy: 1857627f7eb2Smrg 1858627f7eb2Smrg explicit 1859627f7eb2Smrg basic_socket_acceptor(io_context& __ctx) 1860627f7eb2Smrg : __base(__ctx), _M_protocol(endpoint_type{}.protocol()) { } 1861627f7eb2Smrg 1862627f7eb2Smrg basic_socket_acceptor(io_context& __ctx, 1863627f7eb2Smrg const protocol_type& __protocol) 1864627f7eb2Smrg : __base(__ctx), _M_protocol(__protocol) 1865627f7eb2Smrg { open(__protocol); } 1866627f7eb2Smrg 1867627f7eb2Smrg basic_socket_acceptor(io_context& __ctx, const endpoint_type& __endpoint, 1868627f7eb2Smrg bool __reuse_addr = true) 1869627f7eb2Smrg : basic_socket_acceptor(__ctx, __endpoint.protocol()) 1870627f7eb2Smrg { 1871627f7eb2Smrg if (__reuse_addr) 1872627f7eb2Smrg set_option(reuse_address(true)); 1873627f7eb2Smrg bind(__endpoint); 1874627f7eb2Smrg listen(); 1875627f7eb2Smrg } 1876627f7eb2Smrg 1877627f7eb2Smrg basic_socket_acceptor(io_context& __ctx, const protocol_type& __protocol, 1878627f7eb2Smrg const native_handle_type& __native_acceptor) 1879627f7eb2Smrg : basic_socket_acceptor(__ctx, __protocol) 1880627f7eb2Smrg { assign(__protocol, __native_acceptor); } 1881627f7eb2Smrg 1882627f7eb2Smrg basic_socket_acceptor(const basic_socket_acceptor&) = delete; 1883627f7eb2Smrg 1884627f7eb2Smrg basic_socket_acceptor(basic_socket_acceptor&&) = default; 1885627f7eb2Smrg 1886627f7eb2Smrg template<typename _OtherProtocol, typename _Requires 1887627f7eb2Smrg = _Require<is_convertible<_OtherProtocol, protocol_type>>> 1888627f7eb2Smrg basic_socket_acceptor(basic_socket_acceptor<_OtherProtocol>&& __rhs) 1889627f7eb2Smrg : __base(std::move(__rhs)) { } 1890627f7eb2Smrg 1891627f7eb2Smrg ~basic_socket_acceptor() = default; 1892627f7eb2Smrg 1893627f7eb2Smrg basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete; 1894627f7eb2Smrg 1895627f7eb2Smrg basic_socket_acceptor& operator=(basic_socket_acceptor&&) = default; 1896627f7eb2Smrg 1897627f7eb2Smrg template<class _OtherProtocol> 1898627f7eb2Smrg enable_if_t<is_convertible<_OtherProtocol, protocol_type>::value, 1899627f7eb2Smrg basic_socket_acceptor&> 1900627f7eb2Smrg operator=(basic_socket_acceptor<_OtherProtocol>&& __rhs) 1901627f7eb2Smrg { 1902627f7eb2Smrg __base::operator=(std::move(__rhs)); 1903627f7eb2Smrg return *this; 1904627f7eb2Smrg } 1905627f7eb2Smrg 1906627f7eb2Smrg // basic_socket_acceptor operations: 1907627f7eb2Smrg 1908627f7eb2Smrg executor_type get_executor() noexcept { return __base::get_executor(); } 1909627f7eb2Smrg 1910627f7eb2Smrg native_handle_type 1911627f7eb2Smrg native_handle() noexcept { return __base::native_handle(); } 1912627f7eb2Smrg 1913627f7eb2Smrg void 1914627f7eb2Smrg open(const protocol_type& __protocol = protocol_type()) 1915627f7eb2Smrg { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); } 1916627f7eb2Smrg 1917627f7eb2Smrg void 1918627f7eb2Smrg open(const protocol_type& __protocol, error_code& __ec) 1919627f7eb2Smrg { __base::open(__protocol, __ec); } 1920627f7eb2Smrg 1921627f7eb2Smrg void 1922627f7eb2Smrg assign(const protocol_type& __protocol, 1923627f7eb2Smrg const native_handle_type& __native_acceptor) 1924627f7eb2Smrg { 1925627f7eb2Smrg assign(__protocol, __native_acceptor, 1926627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::assign"}); 1927627f7eb2Smrg } 1928627f7eb2Smrg 1929627f7eb2Smrg void 1930627f7eb2Smrg assign(const protocol_type& __protocol, 1931627f7eb2Smrg const native_handle_type& __native_acceptor, 1932627f7eb2Smrg error_code& __ec) 1933627f7eb2Smrg { __base::assign(__protocol, __native_acceptor, __ec); } 1934627f7eb2Smrg 1935*4c3eb207Smrg native_handle_type release() 1936*4c3eb207Smrg { return release(__throw_on_error{"basic_socket_acceptor::release"}); } 1937*4c3eb207Smrg 1938*4c3eb207Smrg native_handle_type release(error_code& __ec) 1939*4c3eb207Smrg { return __base::release(__ec); } 1940*4c3eb207Smrg 1941*4c3eb207Smrg _GLIBCXX_NODISCARD bool 1942627f7eb2Smrg is_open() const noexcept { return __base::is_open(); } 1943627f7eb2Smrg 1944627f7eb2Smrg void 1945627f7eb2Smrg close() { close(__throw_on_error{"basic_socket_acceptor::close"}); } 1946627f7eb2Smrg 1947627f7eb2Smrg void 1948627f7eb2Smrg close(error_code& __ec) { __base::_close(__ec); } 1949627f7eb2Smrg 1950627f7eb2Smrg void 1951627f7eb2Smrg cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); } 1952627f7eb2Smrg 1953627f7eb2Smrg void 1954627f7eb2Smrg cancel(error_code& __ec) { __base::cancel(__ec); } 1955627f7eb2Smrg 1956627f7eb2Smrg template<typename _SettableSocketOption> 1957627f7eb2Smrg void 1958627f7eb2Smrg set_option(const _SettableSocketOption& __option) 1959627f7eb2Smrg { 1960627f7eb2Smrg set_option(__option, 1961627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::set_option"}); 1962627f7eb2Smrg } 1963627f7eb2Smrg 1964627f7eb2Smrg template<typename _SettableSocketOption> 1965627f7eb2Smrg void 1966627f7eb2Smrg set_option(const _SettableSocketOption& __option, error_code& __ec) 1967627f7eb2Smrg { __base::set_option(__option, __ec); } 1968627f7eb2Smrg 1969627f7eb2Smrg template<typename _GettableSocketOption> 1970627f7eb2Smrg void 1971627f7eb2Smrg get_option(_GettableSocketOption& __option) const 1972627f7eb2Smrg { 1973627f7eb2Smrg get_option(__option, 1974627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::get_option"}); 1975627f7eb2Smrg } 1976627f7eb2Smrg 1977627f7eb2Smrg template<typename _GettableSocketOption> 1978627f7eb2Smrg void 1979627f7eb2Smrg get_option(_GettableSocketOption& __option, error_code& __ec) const 1980627f7eb2Smrg { __base::get_option(__option, __ec); } 1981627f7eb2Smrg 1982627f7eb2Smrg template<typename _IoControlCommand> 1983627f7eb2Smrg void 1984627f7eb2Smrg io_control(_IoControlCommand& __command) 1985627f7eb2Smrg { 1986627f7eb2Smrg io_control(__command, 1987627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::io_control"}); 1988627f7eb2Smrg } 1989627f7eb2Smrg 1990627f7eb2Smrg template<typename _IoControlCommand> 1991627f7eb2Smrg void 1992627f7eb2Smrg io_control(_IoControlCommand& __command, error_code& __ec) 1993627f7eb2Smrg { __base::io_control(__command, __ec); } 1994627f7eb2Smrg 1995627f7eb2Smrg void 1996627f7eb2Smrg non_blocking(bool __mode) 1997627f7eb2Smrg { 1998627f7eb2Smrg non_blocking(__mode, 1999627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::non_blocking"}); 2000627f7eb2Smrg } 2001627f7eb2Smrg 2002627f7eb2Smrg void 2003627f7eb2Smrg non_blocking(bool __mode, error_code& __ec) 2004627f7eb2Smrg { __base::non_blocking(__mode, __ec); } 2005627f7eb2Smrg 2006627f7eb2Smrg bool non_blocking() const { return __base::non_blocking(); } 2007627f7eb2Smrg 2008627f7eb2Smrg void 2009627f7eb2Smrg native_non_blocking(bool __mode) 2010627f7eb2Smrg { 2011627f7eb2Smrg native_non_blocking(__mode, __throw_on_error{ 2012627f7eb2Smrg "basic_socket_acceptor::native_non_blocking"}); 2013627f7eb2Smrg } 2014627f7eb2Smrg 2015627f7eb2Smrg void 2016627f7eb2Smrg native_non_blocking(bool __mode, error_code& __ec) 2017627f7eb2Smrg { __base::native_non_blocking(__mode, __ec); } 2018627f7eb2Smrg 2019627f7eb2Smrg bool 2020627f7eb2Smrg native_non_blocking() const 2021627f7eb2Smrg { return __base::native_non_blocking(); } 2022627f7eb2Smrg 2023627f7eb2Smrg void 2024627f7eb2Smrg bind(const endpoint_type& __endpoint) 2025627f7eb2Smrg { 2026627f7eb2Smrg return bind(__endpoint, 2027627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::bind"}); 2028627f7eb2Smrg } 2029627f7eb2Smrg 2030627f7eb2Smrg void 2031627f7eb2Smrg bind(const endpoint_type& __endpoint, error_code& __ec) 2032627f7eb2Smrg { __base::bind(__endpoint, __ec); } 2033627f7eb2Smrg 2034627f7eb2Smrg void 2035627f7eb2Smrg listen(int __backlog = max_listen_connections) 2036627f7eb2Smrg { 2037627f7eb2Smrg return listen(__backlog, 2038627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::listen"}); 2039627f7eb2Smrg } 2040627f7eb2Smrg 2041627f7eb2Smrg void 2042627f7eb2Smrg listen(int __backlog, error_code& __ec) 2043627f7eb2Smrg { 2044627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2045627f7eb2Smrg if (::listen(native_handle(), __backlog) == -1) 2046627f7eb2Smrg __ec.assign(errno, generic_category()); 2047627f7eb2Smrg else 2048627f7eb2Smrg __ec.clear(); 2049627f7eb2Smrg#else 2050627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 2051627f7eb2Smrg#endif 2052627f7eb2Smrg } 2053627f7eb2Smrg 2054627f7eb2Smrg endpoint_type 2055627f7eb2Smrg local_endpoint() const 2056627f7eb2Smrg { 2057627f7eb2Smrg return local_endpoint( 2058627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::local_endpoint"}); 2059627f7eb2Smrg } 2060627f7eb2Smrg 2061627f7eb2Smrg endpoint_type 2062627f7eb2Smrg local_endpoint(error_code& __ec) const 2063627f7eb2Smrg { return __base::local_endpoint(__ec); } 2064627f7eb2Smrg 2065627f7eb2Smrg void 2066627f7eb2Smrg enable_connection_aborted(bool __mode) 2067627f7eb2Smrg { __base::_M_bits.enable_connection_aborted = __mode; } 2068627f7eb2Smrg 2069627f7eb2Smrg bool 2070627f7eb2Smrg enable_connection_aborted() const 2071627f7eb2Smrg { return __base::_M_bits.enable_connection_aborted; } 2072627f7eb2Smrg 2073627f7eb2Smrg socket_type 2074627f7eb2Smrg accept() 2075627f7eb2Smrg { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); } 2076627f7eb2Smrg 2077627f7eb2Smrg socket_type 2078627f7eb2Smrg accept(error_code& __ec) 2079627f7eb2Smrg { return accept(get_executor().context(), __ec); } 2080627f7eb2Smrg 2081627f7eb2Smrg socket_type accept(io_context& __ctx) 2082627f7eb2Smrg { 2083627f7eb2Smrg return accept(__ctx, 2084627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::accept"}); 2085627f7eb2Smrg } 2086627f7eb2Smrg 2087627f7eb2Smrg socket_type 2088627f7eb2Smrg accept(io_context& __ctx, error_code& __ec) 2089627f7eb2Smrg { 2090627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2091627f7eb2Smrg do 2092627f7eb2Smrg { 2093627f7eb2Smrg int __h = ::accept(native_handle(), nullptr, 0); 2094627f7eb2Smrg if (__h != -1) 2095627f7eb2Smrg { 2096627f7eb2Smrg __ec.clear(); 2097627f7eb2Smrg return socket_type{__ctx, _M_protocol, __h}; 2098627f7eb2Smrg } 2099627f7eb2Smrg } while (errno == ECONNABORTED && enable_connection_aborted()); 2100627f7eb2Smrg __ec.assign(errno, generic_category()); 2101627f7eb2Smrg#else 2102627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 2103627f7eb2Smrg#endif 2104627f7eb2Smrg return socket_type{__ctx}; 2105627f7eb2Smrg } 2106627f7eb2Smrg 2107627f7eb2Smrg template<class _CompletionToken> 2108627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, socket_type)> 2109627f7eb2Smrg async_accept(_CompletionToken&& __token) 2110627f7eb2Smrg { 2111627f7eb2Smrg return async_accept(get_executor().context(), 2112627f7eb2Smrg std::forward<_CompletionToken>(__token)); 2113627f7eb2Smrg } 2114627f7eb2Smrg 2115627f7eb2Smrg template<class _CompletionToken> 2116627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, socket_type)> 2117627f7eb2Smrg async_accept(io_context& __ctx, _CompletionToken&& __token) 2118627f7eb2Smrg { 2119627f7eb2Smrg async_completion<_CompletionToken, void(error_code, socket_type)> 2120627f7eb2Smrg __init{__token}; 2121627f7eb2Smrg 2122627f7eb2Smrg __ctx.get_executor().context().async_wait(native_handle(), 2123627f7eb2Smrg socket_base::wait_read, 2124627f7eb2Smrg [__h = std::move(__init.completion_handler), 2125627f7eb2Smrg __connabort = enable_connection_aborted(), 2126627f7eb2Smrg __fd = native_handle(), 2127627f7eb2Smrg __protocol = _M_protocol, 2128627f7eb2Smrg &__ctx 2129627f7eb2Smrg ] 2130627f7eb2Smrg (error_code __ec) mutable { 2131627f7eb2Smrg if (__ec) 2132627f7eb2Smrg { 2133627f7eb2Smrg __h(__ec, socket_type(__ctx)); 2134627f7eb2Smrg return; 2135627f7eb2Smrg } 2136627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2137627f7eb2Smrg do 2138627f7eb2Smrg { 2139627f7eb2Smrg int __newfd = ::accept(__fd, nullptr, 0); 2140627f7eb2Smrg if (__newfd != -1) 2141627f7eb2Smrg { 2142627f7eb2Smrg __ec.clear(); 2143627f7eb2Smrg __h(__ec, socket_type{__ctx, __protocol, __newfd}); 2144627f7eb2Smrg return; 2145627f7eb2Smrg } 2146627f7eb2Smrg } while (errno == ECONNABORTED && __connabort); 2147627f7eb2Smrg __ec.assign(errno, generic_category()); 2148627f7eb2Smrg __h(__ec, socket_type(__ctx)); 2149627f7eb2Smrg#else 2150627f7eb2Smrg __h(std::make_error_code(errc::operation_not_supported), 0); 2151627f7eb2Smrg#endif 2152627f7eb2Smrg }); 2153627f7eb2Smrg return __init.result.get(); 2154627f7eb2Smrg } 2155627f7eb2Smrg 2156627f7eb2Smrg socket_type 2157627f7eb2Smrg accept(endpoint_type& __endpoint) 2158627f7eb2Smrg { 2159627f7eb2Smrg return accept(get_executor().context(), __endpoint, 2160627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::accept"}); 2161627f7eb2Smrg } 2162627f7eb2Smrg 2163627f7eb2Smrg socket_type 2164627f7eb2Smrg accept(endpoint_type& __endpoint, error_code& __ec) 2165627f7eb2Smrg { return accept(get_executor().context(), __endpoint, __ec); } 2166627f7eb2Smrg 2167627f7eb2Smrg socket_type 2168627f7eb2Smrg accept(io_context& __ctx, endpoint_type& __endpoint) 2169627f7eb2Smrg { 2170627f7eb2Smrg return accept(__ctx, __endpoint, 2171627f7eb2Smrg __throw_on_error{"basic_socket_acceptor::accept"}); 2172627f7eb2Smrg } 2173627f7eb2Smrg 2174627f7eb2Smrg socket_type 2175627f7eb2Smrg accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec) 2176627f7eb2Smrg { 2177627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2178627f7eb2Smrg do 2179627f7eb2Smrg { 2180627f7eb2Smrg socklen_t __len = __endpoint.capacity(); 2181627f7eb2Smrg int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(), 2182627f7eb2Smrg &__len); 2183627f7eb2Smrg if (__h != -1) 2184627f7eb2Smrg { 2185627f7eb2Smrg __endpoint.resize(__len); 2186627f7eb2Smrg return socket_type{__ctx, _M_protocol, __h}; 2187627f7eb2Smrg } 2188627f7eb2Smrg } while (errno == ECONNABORTED && enable_connection_aborted()); 2189627f7eb2Smrg __ec.assign(errno, generic_category()); 2190627f7eb2Smrg#else 2191627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 2192627f7eb2Smrg#endif 2193627f7eb2Smrg return socket_type{__ctx}; 2194627f7eb2Smrg } 2195627f7eb2Smrg 2196627f7eb2Smrg template<class _CompletionToken> 2197627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, socket_type)> 2198627f7eb2Smrg async_accept(endpoint_type& __endpoint, 2199627f7eb2Smrg _CompletionToken&& __token) 2200627f7eb2Smrg { 2201627f7eb2Smrg return async_accept(get_executor().context(), __endpoint, 2202627f7eb2Smrg std::forward<_CompletionToken>(__token)); 2203627f7eb2Smrg } 2204627f7eb2Smrg 2205627f7eb2Smrg template<class _CompletionToken> 2206627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, socket_type)> 2207627f7eb2Smrg async_accept(io_context& __ctx, endpoint_type& __endpoint, 2208627f7eb2Smrg _CompletionToken&& __token) 2209627f7eb2Smrg { 2210627f7eb2Smrg async_completion<_CompletionToken, void(error_code, socket_type)> 2211627f7eb2Smrg __init{__token}; 2212627f7eb2Smrg 2213627f7eb2Smrg __ctx.get_executor().context().async_wait(native_handle(), 2214627f7eb2Smrg socket_base::wait_read, 2215627f7eb2Smrg [__h = std::move(__init.completion_handler), 2216627f7eb2Smrg __ep = std::move(__endpoint), 2217627f7eb2Smrg __connabort = enable_connection_aborted(), 2218627f7eb2Smrg __fd = native_handle(), 2219627f7eb2Smrg &__ctx 2220627f7eb2Smrg ] 2221627f7eb2Smrg (error_code __ec) mutable { 2222627f7eb2Smrg if (__ec) 2223627f7eb2Smrg { 2224627f7eb2Smrg __h(__ec, socket_type(__ctx)); 2225627f7eb2Smrg return; 2226627f7eb2Smrg } 2227627f7eb2Smrg#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H 2228627f7eb2Smrg do 2229627f7eb2Smrg { 2230627f7eb2Smrg socklen_t __len = __ep.capacity(); 2231627f7eb2Smrg int __newfd = ::accept(__fd, __ep.data, &__len); 2232627f7eb2Smrg if (__newfd != -1) 2233627f7eb2Smrg { 2234627f7eb2Smrg __ep.resize(__len); 2235627f7eb2Smrg auto __protocol = __ep.protocol(); 2236627f7eb2Smrg __ec.clear(); 2237627f7eb2Smrg __h(__ec, socket_type{__ctx, __protocol, __newfd}); 2238627f7eb2Smrg return; 2239627f7eb2Smrg } 2240627f7eb2Smrg } while (errno == ECONNABORTED && __connabort); 2241627f7eb2Smrg __ec.assign(errno, generic_category()); 2242627f7eb2Smrg#else 2243627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 2244627f7eb2Smrg#endif 2245627f7eb2Smrg __h(__ec, socket_type(__ctx)); 2246627f7eb2Smrg }); 2247627f7eb2Smrg return __init.result.get(); 2248627f7eb2Smrg } 2249627f7eb2Smrg 2250627f7eb2Smrg void 2251627f7eb2Smrg wait(wait_type __w) 2252627f7eb2Smrg { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); } 2253627f7eb2Smrg 2254627f7eb2Smrg void 2255627f7eb2Smrg wait(wait_type __w, error_code& __ec) 2256627f7eb2Smrg { 2257627f7eb2Smrg#ifdef _GLIBCXX_HAVE_POLL_H 2258627f7eb2Smrg ::pollfd __fds; 2259627f7eb2Smrg __fds.fd = native_handle(); 2260627f7eb2Smrg __fds.events = __w; // __w | POLLIN; 2261627f7eb2Smrg if (::poll(&__fds, 1, -1) == -1) 2262627f7eb2Smrg __ec.assign(errno, generic_category()); 2263627f7eb2Smrg else 2264627f7eb2Smrg __ec.clear(); 2265627f7eb2Smrg#else 2266627f7eb2Smrg __ec = std::make_error_code(errc::operation_not_supported); 2267627f7eb2Smrg#endif 2268627f7eb2Smrg } 2269627f7eb2Smrg 2270627f7eb2Smrg template<class _CompletionToken> 2271627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code)> 2272627f7eb2Smrg async_wait(wait_type __w, _CompletionToken&& __token) 2273627f7eb2Smrg { 2274627f7eb2Smrg async_completion<_CompletionToken, void(error_code)> __init{__token}; 2275627f7eb2Smrg get_executor().context().async_wait( native_handle(), 2276627f7eb2Smrg static_cast<int>(__w), 2277627f7eb2Smrg [__h = std::move(__init.completion_handler)] 2278627f7eb2Smrg (error_code __ec) mutable { 2279627f7eb2Smrg __h(__ec); 2280627f7eb2Smrg }); 2281627f7eb2Smrg return __init.result.get(); 2282627f7eb2Smrg } 2283627f7eb2Smrg 2284627f7eb2Smrg private: 2285627f7eb2Smrg protocol_type _M_protocol; 2286627f7eb2Smrg }; 2287627f7eb2Smrg 2288*4c3eb207Smrg /// @} 2289627f7eb2Smrg 2290627f7eb2Smrg /** @brief Socket streams 2291627f7eb2Smrg * @{ 2292627f7eb2Smrg */ 2293627f7eb2Smrg 2294627f7eb2Smrg template<typename _Protocol, typename _Clock, typename _WaitTraits> 2295627f7eb2Smrg class basic_socket_streambuf : public basic_streambuf<char> 2296627f7eb2Smrg { 2297627f7eb2Smrg public: 2298627f7eb2Smrg // types: 2299627f7eb2Smrg 2300627f7eb2Smrg typedef _Protocol protocol_type; 2301627f7eb2Smrg typedef typename protocol_type::endpoint endpoint_type; 2302627f7eb2Smrg typedef _Clock clock_type; 2303627f7eb2Smrg typedef typename clock_type::time_point time_point; 2304627f7eb2Smrg typedef typename clock_type::duration duration; 2305627f7eb2Smrg typedef _WaitTraits wait_traits_type; 2306627f7eb2Smrg 2307627f7eb2Smrg // construct / copy / destroy: 2308627f7eb2Smrg 2309627f7eb2Smrg basic_socket_streambuf() : _M_socket(_S_ctx()) { } 2310627f7eb2Smrg 2311627f7eb2Smrg explicit 2312627f7eb2Smrg basic_socket_streambuf(basic_stream_socket<protocol_type> __s) 2313627f7eb2Smrg : _M_socket(std::move(__s)) { } 2314627f7eb2Smrg 2315627f7eb2Smrg basic_socket_streambuf(const basic_socket_streambuf&) = delete; 2316627f7eb2Smrg 2317627f7eb2Smrg basic_socket_streambuf(basic_socket_streambuf&& __rhs); // TODO 2318627f7eb2Smrg 2319627f7eb2Smrg 2320627f7eb2Smrg virtual ~basic_socket_streambuf(); // TODO 2321627f7eb2Smrg 2322627f7eb2Smrg basic_socket_streambuf& operator=(const basic_socket_streambuf&) = delete; 2323627f7eb2Smrg 2324627f7eb2Smrg basic_socket_streambuf& operator=(basic_socket_streambuf&& __rhs); // TODO 2325627f7eb2Smrg 2326627f7eb2Smrg // members: 2327627f7eb2Smrg 2328627f7eb2Smrg basic_socket_streambuf* connect(const endpoint_type& __e); // TODO 2329627f7eb2Smrg 2330627f7eb2Smrg template<typename... _Args> 2331627f7eb2Smrg basic_socket_streambuf* connect(_Args&&... ); // TODO 2332627f7eb2Smrg 2333627f7eb2Smrg basic_socket_streambuf* close(); // TODO 2334627f7eb2Smrg 2335627f7eb2Smrg basic_socket<protocol_type>& socket() { return _M_socket; } 2336*4c3eb207Smrg 2337*4c3eb207Smrg error_code error() const noexcept { return _M_ec; } 2338627f7eb2Smrg 2339627f7eb2Smrg time_point expiry() const { return _M_expiry; } 2340627f7eb2Smrg 2341627f7eb2Smrg void 2342627f7eb2Smrg expires_at(const time_point& __t) 2343627f7eb2Smrg { _M_expiry = __t; } 2344627f7eb2Smrg 2345627f7eb2Smrg void 2346627f7eb2Smrg expires_after(const duration& __d) 2347627f7eb2Smrg { expires_at(clock_type::now() + __d); } 2348627f7eb2Smrg 2349627f7eb2Smrg protected: 2350627f7eb2Smrg // overridden virtual functions: // TODO 2351627f7eb2Smrg virtual int_type underflow() override; 2352627f7eb2Smrg virtual int_type pbackfail(int_type __c = traits_type::eof()) override; 2353627f7eb2Smrg virtual int_type overflow(int_type __c = traits_type::eof()) override; 2354627f7eb2Smrg virtual int sync() override; 2355627f7eb2Smrg virtual streambuf* setbuf(char_type* __s, streamsize __n) override; 2356627f7eb2Smrg 2357627f7eb2Smrg private: 2358627f7eb2Smrg static io_context& 2359627f7eb2Smrg _S_ctx() 2360627f7eb2Smrg { 2361627f7eb2Smrg static io_context __ctx; 2362627f7eb2Smrg return __ctx; 2363627f7eb2Smrg } 2364627f7eb2Smrg 2365627f7eb2Smrg basic_stream_socket<protocol_type> _M_socket; 2366627f7eb2Smrg error_code _M_ec; 2367627f7eb2Smrg time_point _M_expiry{ time_point::max() }; 2368627f7eb2Smrg }; 2369627f7eb2Smrg 2370627f7eb2Smrg template<typename _Protocol, class _Clock, typename _WaitTraits> 2371627f7eb2Smrg class basic_socket_iostream : public basic_iostream<char> 2372627f7eb2Smrg { 2373627f7eb2Smrg using __streambuf_type 2374627f7eb2Smrg = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>; 2375627f7eb2Smrg 2376627f7eb2Smrg public: 2377627f7eb2Smrg // types: 2378627f7eb2Smrg 2379627f7eb2Smrg typedef _Protocol protocol_type; 2380627f7eb2Smrg typedef typename protocol_type::endpoint endpoint_type; 2381627f7eb2Smrg typedef _Clock clock_type; 2382627f7eb2Smrg typedef typename clock_type::time_point time_point; 2383627f7eb2Smrg typedef typename clock_type::duration duration; 2384627f7eb2Smrg typedef _WaitTraits wait_traits_type; 2385627f7eb2Smrg 2386627f7eb2Smrg // construct / copy / destroy: 2387627f7eb2Smrg 2388627f7eb2Smrg // TODO base-from-member ? 2389627f7eb2Smrg basic_socket_iostream() : basic_iostream(nullptr), _M_sb() 2390627f7eb2Smrg { 2391627f7eb2Smrg this->init(std::addressof(_M_sb)); 2392627f7eb2Smrg this->setf(std::ios::unitbuf); 2393627f7eb2Smrg } 2394627f7eb2Smrg 2395627f7eb2Smrg explicit 2396627f7eb2Smrg basic_socket_iostream(basic_stream_socket<protocol_type> __s) 2397627f7eb2Smrg : basic_iostream(nullptr), _M_sb(std::move(__s)) 2398627f7eb2Smrg { 2399627f7eb2Smrg this->init(std::addressof(_M_sb)); 2400627f7eb2Smrg this->setf(std::ios::unitbuf); 2401627f7eb2Smrg } 2402627f7eb2Smrg 2403627f7eb2Smrg basic_socket_iostream(const basic_socket_iostream&) = delete; 2404627f7eb2Smrg 2405627f7eb2Smrg basic_socket_iostream(basic_socket_iostream&& __rhs) 2406627f7eb2Smrg : basic_iostream(nullptr), _M_sb(std::move(__rhs._M_sb)) 2407627f7eb2Smrg // XXX ??? ^^^^^^^ 2408627f7eb2Smrg { 2409627f7eb2Smrg // XXX ??? this->init(std::addressof(_M_sb)); 2410627f7eb2Smrg this->set_rbduf(std::addressof(_M_sb)); 2411627f7eb2Smrg } 2412627f7eb2Smrg 2413627f7eb2Smrg template<typename... _Args> 2414627f7eb2Smrg explicit 2415627f7eb2Smrg basic_socket_iostream(_Args&&... __args) 2416627f7eb2Smrg : basic_iostream(nullptr), _M_sb() 2417627f7eb2Smrg { 2418627f7eb2Smrg this->init(std::addressof(_M_sb)); 2419627f7eb2Smrg this->setf(std::ios::unitbuf); 2420627f7eb2Smrg connect(forward<_Args>(__args)...); 2421627f7eb2Smrg } 2422627f7eb2Smrg 2423627f7eb2Smrg basic_socket_iostream& operator=(const basic_socket_iostream&) = delete; 2424627f7eb2Smrg 2425627f7eb2Smrg basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO 2426627f7eb2Smrg 2427627f7eb2Smrg // members: 2428627f7eb2Smrg 2429627f7eb2Smrg template<typename... _Args> 2430627f7eb2Smrg void 2431627f7eb2Smrg connect(_Args&&... __args) 2432627f7eb2Smrg { 2433627f7eb2Smrg if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr) 2434627f7eb2Smrg this->setstate(failbit); 2435627f7eb2Smrg } 2436627f7eb2Smrg 2437627f7eb2Smrg void 2438627f7eb2Smrg close() 2439627f7eb2Smrg { 2440627f7eb2Smrg if (rdbuf()->close() == nullptr) 2441627f7eb2Smrg this->setstate(failbit); 2442627f7eb2Smrg } 2443627f7eb2Smrg 2444627f7eb2Smrg basic_socket_streambuf<protocol_type, clock_type, wait_traits_type>* 2445627f7eb2Smrg rdbuf() const 2446627f7eb2Smrg { return const_cast<__streambuf_type*>(std::addressof(_M_sb)); } 2447627f7eb2Smrg 2448627f7eb2Smrg basic_socket<protocol_type>& socket() { return rdbuf()->socket(); } 2449*4c3eb207Smrg error_code error() const noexcept { return rdbuf()->error(); } 2450627f7eb2Smrg 2451627f7eb2Smrg time_point expiry() const { return rdbuf()->expiry(); } 2452627f7eb2Smrg void expires_at(const time_point& __t) { rdbuf()->expires_at(__t); } 2453627f7eb2Smrg void expires_after(const duration& __d) { rdbuf()->expires_after(__d); } 2454627f7eb2Smrg 2455627f7eb2Smrg private: 2456627f7eb2Smrg __streambuf_type _M_sb; 2457627f7eb2Smrg }; 2458627f7eb2Smrg 2459*4c3eb207Smrg /// @} 2460627f7eb2Smrg 2461627f7eb2Smrg /** @brief synchronous connect operations 2462627f7eb2Smrg * @{ 2463627f7eb2Smrg */ 2464627f7eb2Smrg 2465627f7eb2Smrg template<typename _Protocol, typename _EndpointSequence, 2466627f7eb2Smrg typename _ConnectCondition> 2467627f7eb2Smrg inline typename _Protocol::endpoint 2468627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2469627f7eb2Smrg const _EndpointSequence& __endpoints, 2470627f7eb2Smrg _ConnectCondition __c, error_code& __ec) 2471627f7eb2Smrg { 2472627f7eb2Smrg __ec.clear(); 2473627f7eb2Smrg bool __found = false; 2474627f7eb2Smrg for (auto& __ep : __endpoints) 2475627f7eb2Smrg { 2476627f7eb2Smrg if (__c(__ec, __ep)) 2477627f7eb2Smrg { 2478627f7eb2Smrg __found = true; 2479627f7eb2Smrg __s.close(__ec); 2480627f7eb2Smrg if (!__ec) 2481627f7eb2Smrg __s.open(__ep.protocol(), __ec); 2482627f7eb2Smrg if (!__ec) 2483627f7eb2Smrg __s.connect(__ep, __ec); 2484627f7eb2Smrg if (!__ec) 2485627f7eb2Smrg return __ep; 2486627f7eb2Smrg } 2487627f7eb2Smrg } 2488627f7eb2Smrg if (!__found) 2489627f7eb2Smrg __ec = socket_errc::not_found; 2490627f7eb2Smrg return typename _Protocol::endpoint{}; 2491627f7eb2Smrg } 2492627f7eb2Smrg 2493627f7eb2Smrg template<typename _Protocol, typename _InputIterator, 2494627f7eb2Smrg typename _ConnectCondition> 2495627f7eb2Smrg inline _InputIterator 2496627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2497627f7eb2Smrg _InputIterator __first, _InputIterator __last, 2498627f7eb2Smrg _ConnectCondition __c, error_code& __ec) 2499627f7eb2Smrg { 2500627f7eb2Smrg __ec.clear(); 2501627f7eb2Smrg bool __found = false; 2502627f7eb2Smrg for (auto __i = __first; __i != __last; ++__i) 2503627f7eb2Smrg { 2504627f7eb2Smrg if (__c(__ec, *__i)) 2505627f7eb2Smrg { 2506627f7eb2Smrg __found = true; 2507627f7eb2Smrg __s.close(__ec); 2508627f7eb2Smrg if (!__ec) 2509627f7eb2Smrg __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec); 2510627f7eb2Smrg if (!__ec) 2511627f7eb2Smrg __s.connect(*__i, __ec); 2512627f7eb2Smrg if (!__ec) 2513627f7eb2Smrg return __i; 2514627f7eb2Smrg } 2515627f7eb2Smrg } 2516627f7eb2Smrg if (!__found) 2517627f7eb2Smrg __ec = socket_errc::not_found; 2518627f7eb2Smrg return __last; 2519627f7eb2Smrg } 2520627f7eb2Smrg 2521627f7eb2Smrg template<typename _Protocol, typename _EndpointSequence, 2522627f7eb2Smrg typename _ConnectCondition> 2523627f7eb2Smrg inline typename _Protocol::endpoint 2524627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2525627f7eb2Smrg const _EndpointSequence& __endpoints, 2526627f7eb2Smrg _ConnectCondition __c) 2527627f7eb2Smrg { 2528627f7eb2Smrg return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"}); 2529627f7eb2Smrg } 2530627f7eb2Smrg 2531627f7eb2Smrg template<typename _Protocol, typename _InputIterator, 2532627f7eb2Smrg typename _ConnectCondition> 2533627f7eb2Smrg inline _InputIterator 2534627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2535627f7eb2Smrg _InputIterator __first, _InputIterator __last, 2536627f7eb2Smrg _ConnectCondition __c) 2537627f7eb2Smrg { 2538627f7eb2Smrg return net::connect(__s, __first, __last, __c, 2539627f7eb2Smrg __throw_on_error{"connect"}); 2540627f7eb2Smrg } 2541627f7eb2Smrg 2542627f7eb2Smrg template<typename _Protocol, typename _EndpointSequence> 2543627f7eb2Smrg inline typename _Protocol::endpoint 2544627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2545627f7eb2Smrg const _EndpointSequence& __endpoints) 2546627f7eb2Smrg { 2547627f7eb2Smrg return net::connect(__s, __endpoints, [](auto, auto){ return true; }, 2548627f7eb2Smrg __throw_on_error{"connect"}); 2549627f7eb2Smrg } 2550627f7eb2Smrg 2551627f7eb2Smrg template<typename _Protocol, typename _EndpointSequence> 2552627f7eb2Smrg inline typename _Protocol::endpoint 2553627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2554627f7eb2Smrg const _EndpointSequence& __endpoints, 2555627f7eb2Smrg error_code& __ec) 2556627f7eb2Smrg { 2557627f7eb2Smrg return net::connect(__s, __endpoints, [](auto, auto){ return true; }, 2558627f7eb2Smrg __ec); 2559627f7eb2Smrg } 2560627f7eb2Smrg 2561627f7eb2Smrg template<typename _Protocol, typename _InputIterator> 2562627f7eb2Smrg inline _InputIterator 2563627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2564627f7eb2Smrg _InputIterator __first, _InputIterator __last) 2565627f7eb2Smrg { 2566627f7eb2Smrg return net::connect(__s, __first, __last, [](auto, auto){ return true; }, 2567627f7eb2Smrg __throw_on_error{"connect"}); 2568627f7eb2Smrg } 2569627f7eb2Smrg 2570627f7eb2Smrg template<typename _Protocol, typename _InputIterator> 2571627f7eb2Smrg inline _InputIterator 2572627f7eb2Smrg connect(basic_socket<_Protocol>& __s, 2573627f7eb2Smrg _InputIterator __first, _InputIterator __last, 2574627f7eb2Smrg error_code& __ec) 2575627f7eb2Smrg { 2576627f7eb2Smrg return net::connect(__s, __first, __last, [](auto, auto){ return true; }, 2577627f7eb2Smrg __ec); 2578627f7eb2Smrg } 2579627f7eb2Smrg 2580*4c3eb207Smrg /// @} 2581627f7eb2Smrg 2582627f7eb2Smrg /** @brief asynchronous connect operations 2583627f7eb2Smrg * @{ 2584627f7eb2Smrg */ 2585627f7eb2Smrg 2586627f7eb2Smrg template<typename _Protocol, typename _EndpointSequence, 2587627f7eb2Smrg typename _ConnectCondition, typename _CompletionToken> 2588627f7eb2Smrg inline 2589627f7eb2Smrg __deduced_t<_CompletionToken, 2590627f7eb2Smrg void(error_code, typename _Protocol::endpoint)> 2591627f7eb2Smrg async_connect(basic_socket<_Protocol>& __s, 2592627f7eb2Smrg const _EndpointSequence& __endpoints, 2593627f7eb2Smrg _ConnectCondition __c, _CompletionToken&& __token); // TODO 2594627f7eb2Smrg 2595627f7eb2Smrg template<typename _Protocol, typename _EndpointSequence, 2596627f7eb2Smrg typename _CompletionToken> 2597627f7eb2Smrg inline 2598627f7eb2Smrg __deduced_t<_CompletionToken, 2599627f7eb2Smrg void(error_code, typename _Protocol::endpoint)> 2600627f7eb2Smrg async_connect(basic_socket<_Protocol>& __s, 2601627f7eb2Smrg const _EndpointSequence& __endpoints, 2602627f7eb2Smrg _CompletionToken&& __token) 2603627f7eb2Smrg { 2604627f7eb2Smrg return net::async_connect(__s, __endpoints, 2605627f7eb2Smrg [](auto, auto){ return true; }, 2606627f7eb2Smrg forward<_CompletionToken>(__token)); 2607627f7eb2Smrg } 2608627f7eb2Smrg 2609627f7eb2Smrg template<typename _Protocol, typename _InputIterator, 2610627f7eb2Smrg typename _ConnectCondition, typename _CompletionToken> 2611627f7eb2Smrg inline 2612627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, _InputIterator)> 2613627f7eb2Smrg async_connect(basic_socket<_Protocol>& __s, 2614627f7eb2Smrg _InputIterator __first, _InputIterator __last, 2615627f7eb2Smrg _ConnectCondition __c, _CompletionToken&& __token); // TODO 2616627f7eb2Smrg 2617627f7eb2Smrg template<typename _Protocol, typename _InputIterator, 2618627f7eb2Smrg typename _CompletionToken> 2619627f7eb2Smrg inline 2620627f7eb2Smrg __deduced_t<_CompletionToken, void(error_code, _InputIterator)> 2621627f7eb2Smrg async_connect(basic_socket<_Protocol>& __s, 2622627f7eb2Smrg _InputIterator __first, _InputIterator __last, 2623627f7eb2Smrg _CompletionToken&& __token) 2624627f7eb2Smrg { 2625627f7eb2Smrg return net::async_connect(__s, __first, __last, 2626627f7eb2Smrg [](auto, auto){ return true; }, 2627627f7eb2Smrg forward<_CompletionToken>(__token)); 2628627f7eb2Smrg } 2629627f7eb2Smrg 2630*4c3eb207Smrg /// @} 2631627f7eb2Smrg 2632627f7eb2Smrg#endif // _GLIBCXX_HAVE_UNISTD_H 2633627f7eb2Smrg 2634*4c3eb207Smrg /// @} 2635627f7eb2Smrg 2636627f7eb2Smrg} // namespace v1 2637627f7eb2Smrg} // namespace net 2638627f7eb2Smrg} // namespace experimental 2639627f7eb2Smrg 2640627f7eb2Smrg_GLIBCXX_END_NAMESPACE_VERSION 2641627f7eb2Smrg} // namespace std 2642627f7eb2Smrg 2643627f7eb2Smrg#endif // C++14 2644627f7eb2Smrg 2645627f7eb2Smrg#endif // _GLIBCXX_EXPERIMENTAL_SOCKET 2646