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