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