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