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