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