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