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