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