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