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