Add missing return
[official-gcc.git] / libstdc++-v3 / include / experimental / socket
blobe92a4374db906d4bba5d3b41b3a35508845c2946
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 # include <sys/socket.h>
46 # include <sys/ioctl.h>
47 # include <sys/fcntl.h>
48 # include <sys/uio.h>
49 # include <poll.h>
50 #endif
52 namespace std _GLIBCXX_VISIBILITY(default)
54 namespace experimental
56 namespace net
58 inline namespace v1
60 _GLIBCXX_BEGIN_NAMESPACE_VERSION
62   /**
63    * @ingroup networking
64    * @{
65    */
67   enum class socket_errc {  // TODO decide values
68     already_open = 3,
69     not_found = 4
70   };
72   const error_category& socket_category() noexcept
73   {
74     struct __cat : error_category
75     {
76       const char* name() const noexcept { return "socket"; }
78       std::string message(int __e) const
79       {
80         if (__e == (int)socket_errc::already_open)
81           return "already open";
82         else if (__e == (int)socket_errc::not_found)
83           return "endpoint not found";
84         return "socket error";
85       }
87       virtual void __message(int) { } // TODO dual ABI XXX
88     };
89     static __cat __c;
90     return __c;
91   }
93   inline error_code
94   make_error_code(socket_errc __e) noexcept
95   { return error_code(static_cast<int>(__e), socket_category()); }
97   inline error_condition
98   make_error_condition(socket_errc __e) noexcept
99   { return error_condition(static_cast<int>(__e), socket_category()); }
101   template<typename _Tp, typename = __void_t<>>
102     struct __is_endpoint_impl : false_type
103     { };
105   // Check Endpoint requirements.
106   template<typename _Tp>
107     auto
108     __endpoint_reqs(const _Tp* __a = 0)
109     -> enable_if_t<__and_<
110       is_default_constructible<_Tp>,
111       __is_value_constructible<_Tp>,
112       is_same<decltype(__a->__protocol()), typename _Tp::protocol_type>
113       >::value,
114     __void_t< typename _Tp::protocol_type::endpoint >>;
116   template<typename _Tp>
117     struct __is_endpoint_impl<_Tp, decltype(__endpoint_reqs<_Tp>())>
118     : true_type
119     { };
121   template<typename _Tp>
122     struct __is_endpoint : __is_endpoint_impl<_Tp>
123     { };
125   // TODO Endpoint reqs for extensible implementations
126   // TODO _Protocol reqs
127   // TODO AcceptableProtocol reqs
128   // TODO GettableSocket reqs
129   // TODO SettableSocket reqs
130   // TODO BooleanSocketOption reqs
131   // TODO IntegerSocketOption reqs
132   // TODO _IoControlCommand reqs
133   // TODO _ConnectCondition reqs
135   /** @brief Sockets
136    * @{
137    */
139   class socket_base
140   {
141   public:
142     struct broadcast : __sockopt_crtp<broadcast, bool>
143     {
144       using __sockopt_crtp::__sockopt_crtp;
146       static const int _S_level = SOL_SOCKET;
147       static const int _S_name = SO_BROADCAST;
148     };
150     struct debug : __sockopt_crtp<debug, bool>
151     {
152       using __sockopt_crtp::__sockopt_crtp;
154       static const int _S_level = SOL_SOCKET;
155       static const int _S_name = SO_DEBUG;
156     };
158     struct do_not_route : __sockopt_crtp<do_not_route, bool>
159     {
160       using __sockopt_crtp::__sockopt_crtp;
162       static const int _S_level = SOL_SOCKET;
163       static const int _S_name = SO_DONTROUTE;
164     };
166     struct keep_alive : __sockopt_crtp<keep_alive, bool>
167     {
168       using __sockopt_crtp::__sockopt_crtp;
170       static const int _S_level = SOL_SOCKET;
171       static const int _S_name = SO_KEEPALIVE;
172     };
174     struct linger : __sockopt_crtp<linger, ::linger>
175     {
176       using __sockopt_crtp::__sockopt_crtp;
178       linger() noexcept = default;
180       linger(bool __e, chrono::seconds __t) noexcept
181       {
182         enabled(__e);
183         timeout(__t);
184       }
186       bool
187       enabled() const noexcept
188       { return _M_value.l_onoff != 0; }
190       void
191       enabled(bool __e) noexcept
192       { _M_value.l_onoff = int(__e); }
194       chrono::seconds
195       timeout() const noexcept
196       { return chrono::seconds(_M_value.l_linger); }
198       void
199       timeout(chrono::seconds __t) noexcept
200       { _M_value.l_linger = __t.count(); }
202       static const int _S_level = SOL_SOCKET;
203       static const int _S_name = SO_LINGER;
204     };
206     struct out_of_band_inline : __sockopt_crtp<out_of_band_inline, bool>
207     {
208       using __sockopt_crtp::__sockopt_crtp;
210       static const int _S_level = SOL_SOCKET;
211       static const int _S_name = SO_OOBINLINE;
212     };
214     struct receive_buffer_size : __sockopt_crtp<receive_buffer_size>
215     {
216       using __sockopt_crtp::__sockopt_crtp;
218       static const int _S_level = SOL_SOCKET;
219       static const int _S_name = SO_RCVBUF;
220     };
222     struct receive_low_watermark : __sockopt_crtp<receive_low_watermark>
223     {
224       using __sockopt_crtp::__sockopt_crtp;
226       static const int _S_level = SOL_SOCKET;
227       static const int _S_name = SO_RCVLOWAT;
228     };
230     struct reuse_address : __sockopt_crtp<reuse_address, bool>
231     {
232       using __sockopt_crtp::__sockopt_crtp;
234       static const int _S_level = SOL_SOCKET;
235       static const int _S_name = SO_REUSEADDR;
236     };
238     struct send_buffer_size : __sockopt_crtp<send_buffer_size>
239     {
240       using __sockopt_crtp::__sockopt_crtp;
242       static const int _S_level = SOL_SOCKET;
243       static const int _S_name = SO_SNDBUF;
244     };
246     struct send_low_watermark : __sockopt_crtp<send_low_watermark>
247     {
248       using __sockopt_crtp::__sockopt_crtp;
250       static const int _S_level = SOL_SOCKET;
251       static const int _S_name = SO_SNDLOWAT;
252     };
254     enum shutdown_type : int
255     {
256       __shutdown_receive        = SHUT_RD,
257       __shutdown_send           = SHUT_WR,
258       __shutdown_both           = SHUT_RDWR
259     };
260     static constexpr shutdown_type shutdown_receive     = __shutdown_receive;
261     static constexpr shutdown_type shutdown_send        = __shutdown_send;
262     static constexpr shutdown_type shutdown_both        = __shutdown_both;
264     enum wait_type : int
265     {
266       __wait_read               = POLLIN,
267       __wait_write              = POLLOUT,
268       __wait_error              = POLLERR
269     };
270     static constexpr wait_type wait_read                = __wait_read;
271     static constexpr wait_type wait_write               = __wait_write;
272     static constexpr wait_type wait_error               = __wait_error;
274     enum message_flags : int
275     {
276       __message_peek            = MSG_PEEK,
277       __message_oob             = MSG_OOB,
278       __message_dontroute       = MSG_DONTROUTE
279     };
280     static constexpr message_flags message_peek         = __message_peek;
281     static constexpr message_flags message_out_of_band  = __message_oob;
282     static constexpr message_flags message_do_not_route = __message_dontroute;
284     static const int max_listen_connections = SOMAXCONN;
286   protected:
287     socket_base() = default;
288     ~socket_base() = default;
290     struct __msg_hdr : ::msghdr
291     {
292 #ifdef IOV_MAX
293       using __iovec_array = array<::iovec, IOV_MAX>;
294 #elif _GLIBCXX_HAVE_UNISTD_H
295       struct __iovec_array
296       {
297         __iovec_array() : _M_ptr(new ::iovec[size()]) { }
299         ::iovec& operator[](size_t __n) noexcept { return _M_ptr[__n]; }
301         ::iovec* data() noexcept { return _M_ptr.get(); }
303         static size_t size()
304         {
305           static const size_t __iov_max = ::sysconf(_SC_IOV_MAX);
306           return __iov_max;
307         }
309       private:
310         unique_ptr<::iovec[]> _M_ptr;
311       };
312 #else
313       using __iovec_array = array<::iovec, 16>;
314 #endif
316       __iovec_array _M_iov;
318       template<typename _BufferSequence>
319         explicit
320         __msg_hdr(const _BufferSequence& __buffers)
321         : msghdr()
322         {
323           auto __buf = net::buffer_sequence_begin(__buffers);
324           const auto __bufend = net::buffer_sequence_end(__buffers);
325           size_t __len = 0;
326           while (__buf != __bufend && __len != _M_iov.size())
327             {
328               _M_iov[__len].iov_base = (void*)__buf->data();
329               _M_iov[__len].iov_len = __buf->size();
330               ++__buf;
331               ++__len;
332             }
333           this->msg_iovlen = __len;
334           this->msg_iov = _M_iov.data();
335         }
337       template<typename _BufferSequence, typename _Endpoint>
338         __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep)
339         : __msg_hdr(__buffers)
340         {
341           this->msg_name = __ep.data();
342           this->msg_namelen = __ep.size();
343         }
344     };
345   };
347   constexpr socket_base::message_flags
348   operator&(socket_base::message_flags __f1, socket_base::message_flags __f2)
349   { return socket_base::message_flags( int(__f1) & int(__f2) ); }
351   constexpr socket_base::message_flags
352   operator|(socket_base::message_flags __f1, socket_base::message_flags __f2)
353   { return socket_base::message_flags( int(__f1) | int(__f2) ); }
355   constexpr socket_base::message_flags
356   operator^(socket_base::message_flags __f1, socket_base::message_flags __f2)
357   { return socket_base::message_flags( int(__f1) ^ int(__f2) ); }
359   constexpr socket_base::message_flags
360   operator~(socket_base::message_flags __f)
361   { return socket_base::message_flags( ~int(__f) ); }
363   inline socket_base::message_flags&
364   operator&=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
365   { return __f1 = (__f1 & __f2); }
367   inline socket_base::message_flags&
368   operator|=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
369   { return __f1 = (__f1 | __f2); }
371   inline socket_base::message_flags&
372   operator^=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
373   { return __f1 = (__f1 ^ __f2); }
375 #if _GLIBCXX_HAVE_UNISTD_H
377   class __socket_impl
378   {
379   protected:
381     using executor_type = io_context::executor_type;
382     using native_handle_type = int;
384     explicit
385     __socket_impl(io_context& __ctx) : _M_ctx(std::addressof(__ctx)) { }
387     __socket_impl(__socket_impl&& __rhs)
388     : _M_ctx(__rhs._M_ctx),
389       _M_sockfd(std::exchange(__rhs._M_sockfd, -1)),
390       _M_bits(std::exchange(__rhs._M_bits, {}))
391     { }
393     __socket_impl&
394     operator=(__socket_impl&& __rhs)
395     {
396       _M_ctx = __rhs._M_ctx;
397       _M_sockfd = std::exchange(__rhs._M_sockfd, -1);
398       _M_bits = std::exchange(__rhs._M_bits, {});
399       return *this;
400     }
402     ~__socket_impl() = default;
404     __socket_impl(const __socket_impl&) = delete;
405     __socket_impl& operator=(const __socket_impl&) = delete;
407     executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
409     native_handle_type native_handle() noexcept { return _M_sockfd; }
411     bool is_open() const noexcept { return _M_sockfd != -1; }
413     void
414     close(error_code& __ec)
415     {
416       if (is_open())
417         {
418           cancel(__ec);
419           if (!__ec)
420             {
421               if (::close(_M_sockfd) == -1)
422                 __ec.assign(errno, generic_category());
423               else
424                 {
425                   get_executor().context()._M_remove_fd(_M_sockfd);
426                   _M_sockfd = -1;
427                 }
428             }
429         }
430     }
432     void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); }
434     void
435     non_blocking(bool __mode, error_code&)
436     { _M_bits.non_blocking = __mode; }
438     bool non_blocking() const { return _M_bits.non_blocking; }
440     void
441     native_non_blocking(bool __mode, error_code& __ec)
442     {
443       int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
444       if (__flags >= 0)
445         {
446           if (__mode)
447             __flags |= O_NONBLOCK;
448           else
449             __flags &= ~O_NONBLOCK;
450           __flags = ::fcntl(_M_sockfd, F_SETFL, __flags);
451         }
452       if (__flags == -1)
453         __ec.assign(errno, generic_category());
454       else
455         {
456           __ec.clear();
457           _M_bits.native_non_blocking = __mode;
458         }
459     }
461     bool
462     native_non_blocking() const
463     {
464       if (_M_bits.native_non_blocking == -1)
465         {
466           const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
467           if (__flags == -1)
468             return 0;
469           _M_bits.native_non_blocking = __flags & O_NONBLOCK;
470         }
471       return _M_bits.native_non_blocking;
472     }
474     io_context* _M_ctx;
475     int         _M_sockfd{-1};
476     struct {
477       unsigned          non_blocking : 1;
478       mutable signed    native_non_blocking : 2;
479       unsigned          enable_connection_aborted : 1;
480     } _M_bits{};
481   };
483   template<typename _Protocol>
484     class __basic_socket_impl : public __socket_impl
485     {
486       using __base = __socket_impl;
488     protected:
489       using protocol_type = _Protocol;
490       using endpoint_type = typename protocol_type::endpoint;
492       explicit
493       __basic_socket_impl(io_context& __ctx) : __base(__ctx) { }
495       __basic_socket_impl(__basic_socket_impl&&) = default;
497       template<typename _OtherProtocol>
498         __basic_socket_impl(__basic_socket_impl<_OtherProtocol>&& __rhs)
499         : __base(std::move(__rhs)), _M_protocol(std::move(__rhs._M_protocol))
500         { }
502       __basic_socket_impl&
503       operator=(__basic_socket_impl&& __rhs)
504       {
505         if (this == std::addressof(__rhs))
506           return *this;
507         _M_close();
508         __base::operator=(std::move(__rhs));
509         return *this;
510       }
512       ~__basic_socket_impl() { _M_close(); }
514       __basic_socket_impl(const __basic_socket_impl&) = delete;
515       __basic_socket_impl& operator=(const __basic_socket_impl&) = delete;
517       void
518       open(const protocol_type& __protocol, error_code& __ec)
519       {
520         if (is_open())
521           __ec = socket_errc::already_open;
522         else
523           {
524             _M_protocol = __protocol;
525             _M_sockfd = ::socket(__protocol.family(), __protocol.type(),
526                                  __protocol.protocol());
527             if (is_open())
528               {
529                 get_executor().context()._M_add_fd(_M_sockfd);
530               __ec.clear();
531               }
532             else
533               __ec.assign(errno, std::generic_category());
534           }
535       }
537       void
538       assign(const protocol_type& __protocol,
539              const native_handle_type& __native_socket,
540              error_code& __ec)
541       {
542         if (is_open())
543           __ec = socket_errc::already_open;
544         else
545           {
546             _M_protocol = __protocol;
547             _M_bits.native_non_blocking = -1;
548             _M_sockfd = __native_socket;
549             if (is_open())
550               {
551                 get_executor().context()._M_add_fd(_M_sockfd);
552                 __ec.clear();
553               }
554             else
555               __ec.assign(errno, std::generic_category());
556           }
557       }
559       template<typename _SettableSocketOption>
560         void
561         set_option(const _SettableSocketOption& __option, error_code& __ec)
562         {
563           int __result = ::setsockopt(_M_sockfd, __option.level(_M_protocol),
564                                       __option.name(_M_protocol),
565                                       __option.data(_M_protocol),
566                                       __option.size(_M_protocol));
567           if (__result == -1)
568             __ec.assign(errno, generic_category());
569           else
570             __ec.clear();
571         }
573       template<typename _GettableSocketOption>
574         void
575         get_option(_GettableSocketOption& __option, error_code& __ec) const
576         {
577           int __result = ::getsockopt(_M_sockfd, __option.level(_M_protocol),
578                                       __option.name(_M_protocol),
579                                       __option.data(_M_protocol),
580                                       __option.size(_M_protocol));
581           if (__result == -1)
582             __ec.assign(errno, generic_category());
583           else
584             __ec.clear();
585         }
587       template<typename _IoControlCommand>
588         void
589         io_control(_IoControlCommand& __command, error_code& __ec)
590         {
591           int __result = ::ioctl(_M_sockfd, __command.name(_M_protocol),
592                                  __command.data(_M_protocol));
593           if (__result == -1)
594             __ec.assign(errno, generic_category());
595           else
596             __ec.clear();
597         }
599       endpoint_type
600       local_endpoint(error_code& __ec) const
601       {
602         endpoint_type __endpoint;
603         socklen_t __endpoint_len = __endpoint.capacity();
604         if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(),
605                           &__endpoint_len) == -1)
606           {
607             __ec.assign(errno, generic_category());
608             return endpoint_type{};
609           }
610         __ec.clear();
611         __endpoint.resize(__endpoint_len);
612         return __endpoint;
613       }
615       void
616       bind(const endpoint_type& __endpoint, error_code& __ec)
617       {
618         if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size())
619             == -1)
620           __ec.assign(errno, generic_category());
621         else
622           __ec.clear();
623       }
625       _Protocol _M_protocol{ endpoint_type{}.protocol() };
627     private:
628       void
629       _M_close()
630       {
631         if (is_open())
632           {
633             error_code __ec;
634             cancel(__ec);
635             set_option(socket_base::linger{false, chrono::seconds{}}, __ec);
636             ::close(_M_sockfd);
637           }
638       }
639     };
641   template<typename _Protocol>
642     class basic_socket
643     : public socket_base, private __basic_socket_impl<_Protocol>
644     {
645       using __base = __basic_socket_impl<_Protocol>;
647     public:
648       // types:
650       typedef io_context::executor_type executor_type;
651       typedef int native_handle_type;
652       typedef _Protocol protocol_type;
653       typedef typename protocol_type::endpoint endpoint_type;
655       // basic_socket operations:
657       executor_type get_executor() noexcept { return __base::get_executor(); }
659       native_handle_type
660       native_handle() noexcept { return __base::native_handle(); }
662       void
663       open(const protocol_type& __protocol = protocol_type())
664       { open(__protocol, __throw_on_error{"basic_socket::open"}); }
666       void
667       open(const protocol_type& __protocol, error_code& __ec)
668       { __base::open(__protocol, __ec); }
670       void
671       assign(const protocol_type& __protocol,
672              const native_handle_type& __native_socket)
673       {
674         assign(__protocol, __native_socket,
675                __throw_on_error{"basic_socket::assign"});
676       }
678       void
679       assign(const protocol_type& __protocol,
680              const native_handle_type& __native_socket,
681              error_code& __ec)
682       { __base::assign(__protocol, __native_socket, __ec); }
684       bool is_open() const noexcept { return __base::is_open(); }
686       void close() { close(__throw_on_error{"basic_socket::close"}); }
688       void close(error_code& __ec) { __base::close(); }
690       void cancel() { cancel(__throw_on_error{"basic_socket::cancel"}); }
692       void cancel(error_code& __ec) { __base::cancel(__ec); }
694       template<typename _SettableSocketOption>
695         void
696         set_option(const _SettableSocketOption& __option)
697         { set_option(__option, __throw_on_error{"basic_socket::set_option"}); }
699       template<typename _SettableSocketOption>
700         void
701         set_option(const _SettableSocketOption& __option, error_code& __ec)
702         { __base::set_option(__option, __ec); }
704       template<typename _GettableSocketOption>
705         void
706         get_option(_GettableSocketOption& __option) const
707         { get_option(__option, __throw_on_error{"basic_socket::get_option"}); }
709       template<typename _GettableSocketOption>
710         void
711         get_option(_GettableSocketOption& __option, error_code& __ec) const
712         { __base::get_option(__option, __ec); }
714       template<typename _IoControlCommand>
715         void
716         io_control(_IoControlCommand& __command)
717         {
718           io_control(__command, __throw_on_error{"basic_socket::io_control"});
719         }
721       template<typename _IoControlCommand>
722         void
723         io_control(_IoControlCommand& __command, error_code& __ec)
724         { __base::io_control(__command, __ec); }
726       void
727       non_blocking(bool __mode)
728       { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); }
730       void
731       non_blocking(bool __mode, error_code& __ec)
732       { __base::non_blocking(__mode, __ec); }
734       bool non_blocking() const { return __base::non_blocking(); }
736       void
737       native_non_blocking(bool __mode)
738       {
739         native_non_blocking(__mode, __throw_on_error{
740             "basic_socket::native_non_blocking"});
741       }
743       void
744       native_non_blocking(bool __mode, error_code& __ec)
745       { __base::native_non_blocking(__mode, __ec); }
747       bool
748       native_non_blocking() const
749       { return __base::native_non_blocking(); }
751       bool at_mark() const
752       { return at_mark(__throw_on_error{"basic_socket::at_mark"}); }
754       bool
755       at_mark(error_code& __ec) const
756       {
757         const int __result = ::sockatmark(native_handle());
758         if (__result == -1)
759           {
760             __ec.assign(errno, generic_category());
761             return false;
762           }
763         __ec.clear();
764         return (bool)__result;
765       }
767       size_t
768       available() const
769       { return available(__throw_on_error{"basic_socket::available"}); }
771       size_t
772       available(error_code& __ec) const
773       {
774         if (!is_open())
775           {
776             __ec = std::make_error_code(errc::bad_file_descriptor);
777             return 0;
778           }
779 #ifdef FIONREAD
780         int __avail = 0;
781         if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1)
782           {
783             __ec.assign(errno, generic_category());
784             return 0;
785           }
786         __ec.clear();
787         return __avail;
788 #else
789         return 0;
790 #endif
791       }
793       void
794       bind(const endpoint_type& __endpoint)
795       { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); }
797       void
798       bind(const endpoint_type& __endpoint, error_code& __ec)
799       { __base::bind(__endpoint, __ec); }
801       void shutdown(shutdown_type __what)
802       { return shutdown(__what, __throw_on_error{"basic_socket::shutdown"}); }
804       void
805       shutdown(shutdown_type __what, error_code& __ec)
806       {
807         if (::shutdown(native_handle(), static_cast<int>(__what)) == -1)
808           __ec.assign(errno, generic_category());
809         else
810           __ec.clear();
811       }
813       endpoint_type
814       local_endpoint() const
815       {
816         return local_endpoint(
817             __throw_on_error{"basic_socket::local_endpoint"});
818       }
820       endpoint_type
821       local_endpoint(error_code& __ec) const
822       { return __base::local_endpoint(__ec); }
824       endpoint_type
825       remote_endpoint() const
826       {
827         return remote_endpoint(
828             __throw_on_error{"basic_socket::remote_endpoint"});
829       }
831       endpoint_type
832       remote_endpoint(error_code& __ec) const
833       {
834         endpoint_type __endpoint;
835         socklen_t __endpoint_len = __endpoint.capacity();
836         if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(),
837                           &__endpoint_len)
838             == -1)
839           {
840             __ec.assign(errno, generic_category());
841             return endpoint_type{};
842           }
843         __ec.clear();
844         __endpoint.resize(__endpoint_len);
845         return __endpoint;
846       }
848       void
849       connect(const endpoint_type& __endpoint)
850       {
851         return connect(__endpoint, __throw_on_error{"basic_socket::connect"});
852       }
854       void
855       connect(const endpoint_type& __endpoint, error_code& __ec)
856       {
857         if (!is_open())
858           {
859             open(__endpoint.protocol(), __ec);
860             if (__ec)
861               return;
862           }
863         if (::connect(native_handle(), (const sockaddr*)__endpoint.data(),
864                       __endpoint.size()) == -1)
865           __ec.assign(errno, generic_category());
866         else
867           __ec.clear();
868       }
870       template<typename _CompletionToken>
871         __deduced_t<_CompletionToken, void(error_code)>
872         async_connect(const endpoint_type& __endpoint,
873                       _CompletionToken&& __token)
874         {
875           async_completion<_CompletionToken, void(error_code)> __init{__token};
877           if (!is_open())
878             {
879               error_code __ec;
880               open(__endpoint.protocol(), __ec);
881               if (__ec)
882                 {
883                   auto __ex = net::get_associated_executor(
884                       __init.completion_handler, get_executor());
885                   auto __a = get_associated_allocator(
886                       __init.completion_handler, std::allocator<void>());
887                   __ex.post(
888                       [__h=std::move(__init.completion_handler), __ec]
889                       () mutable
890                       { __h(__ec); }, __a);
891                   return __init.result.get();
892                 }
893             }
895           get_executor().context().async_wait( native_handle(),
896               socket_base::wait_read,
897               [__h = std::move(__init.completion_handler),
898                __ep = std::move(__endpoint),
899                __fd = native_handle()]
900                (error_code __ec) mutable {
901                   if (!__ec && ::connect(__fd, (const sockaddr*)__ep.data(),
902                                          __ep.size()) == -1)
903                     __ec.assign(errno, generic_category());
904                   __h(__ec);
905               });
906           return __init.result.get();
907         }
909       void
910       wait(wait_type __w)
911       { return wait(__w, __throw_on_error{"basic_socket::wait"}); }
913       void
914       wait(wait_type __w, error_code& __ec)
915       {
916         ::pollfd __fd;
917         __fd.fd = native_handle();
918         __fd.events = static_cast<int>(__w);
919         int __res = ::poll(&__fd, 1, -1);
920         if (__res == -1)
921           __ec.assign(errno, generic_category());
922         else
923           __ec.clear();
924       }
926       template<typename _CompletionToken>
927         __deduced_t<_CompletionToken, void(error_code)>
928         async_wait(wait_type __w, _CompletionToken&& __token)
929         {
930           async_completion<_CompletionToken, void(error_code)> __init{__token};
931           get_executor().context().async_wait( native_handle(),
932               static_cast<int>(__w),
933               [__h = std::move(__init.completion_handler)]
934               (error_code __ec) mutable {
935                   __h(__ec);
936               });
937           return __init.result.get();
938         }
940     protected:
941       // construct / copy / destroy:
943       using __base::__base;
945       explicit
946       basic_socket(io_context& __ctx) : __base(__ctx) { }
948       basic_socket(io_context& __ctx, const protocol_type& __protocol)
949       : __base(__ctx)
950       { open(__protocol); }
952       basic_socket(io_context& __ctx, const endpoint_type& __endpoint)
953       : basic_socket(std::addressof(__ctx), __endpoint.protocol())
954       { bind(__endpoint); }
956       basic_socket(io_context& __ctx, const protocol_type& __protocol,
957                    const native_handle_type& __native_socket)
958       : __base(__ctx)
959       { assign(__protocol, __native_socket); }
961       basic_socket(const basic_socket&) = delete;
963       basic_socket(basic_socket&& __rhs) = default;
965       template<typename _OtherProtocol, typename _Requires
966                = _Require<is_convertible<_OtherProtocol, _Protocol>>>
967         basic_socket(basic_socket<_OtherProtocol>&& __rhs)
968         : __base(std::move(__rhs)) { }
970       ~basic_socket() = default;
972       basic_socket& operator=(const basic_socket&) = delete;
974       basic_socket& operator=(basic_socket&& __rhs) = default;
976       template<typename _OtherProtocol>
977         enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
978                     basic_socket&>
979         operator=(basic_socket<_OtherProtocol>&& __rhs)
980         { return *this = basic_socket{std::move(__rhs)}; }
981     };
983   template<typename _Protocol>
984     class basic_datagram_socket : public basic_socket<_Protocol>
985     {
986       using __base = basic_socket<_Protocol>;
988     public:
989       // types:
991       typedef int native_handle_type;
992       typedef _Protocol protocol_type;
993       typedef typename protocol_type::endpoint endpoint_type;
995       // construct / copy / destroy:
997       explicit
998       basic_datagram_socket(io_context& __ctx) : __base(__ctx) { }
1000       basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol)
1001       : __base(__ctx, __protocol) { }
1003       basic_datagram_socket(io_context& __ctx, const endpoint_type& __endpoint)
1004       : __base(__ctx, __endpoint) { }
1006       basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol,
1007                             const native_handle_type& __native_socket)
1008       : __base(__ctx, __protocol, __native_socket) { }
1010       basic_datagram_socket(const basic_datagram_socket&) = delete;
1012       basic_datagram_socket(basic_datagram_socket&& __rhs) = default;
1014       template<typename _OtherProtocol, typename _Requires
1015                = _Require<is_convertible<_OtherProtocol, _Protocol>>>
1016         basic_datagram_socket(basic_datagram_socket<_OtherProtocol>&& __rhs)
1017         : __base(std::move(__rhs)) { }
1019       ~basic_datagram_socket() = default;
1021       basic_datagram_socket& operator=(const basic_datagram_socket&) = delete;
1023       basic_datagram_socket& operator=(basic_datagram_socket&& __rhs) = default;
1025       template<typename _OtherProtocol>
1026         enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
1027                     basic_datagram_socket&>
1028         operator=(basic_datagram_socket<_OtherProtocol>&& __rhs)
1029         {
1030           __base::operator=(std::move(__rhs));
1031           return *this;
1032         }
1034       // basic_datagram_socket operations:
1036       template<typename _MutableBufferSequence>
1037         size_t
1038         receive(const _MutableBufferSequence& __buffers)
1039         {
1040           return receive(__buffers, socket_base::message_flags(),
1041                          __throw_on_error{"basic_datagram_socket::receive"});
1042         }
1044       template<typename _MutableBufferSequence>
1045         size_t
1046         receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1047         { return receive(__buffers, socket_base::message_flags(), __ec); }
1049       template<typename _MutableBufferSequence>
1050         size_t
1051         receive(const _MutableBufferSequence& __buffers,
1052                        socket_base::message_flags __flags)
1053         {
1054           return receive(__buffers, __flags,
1055                          __throw_on_error{"basic_datagram_socket::receive"});
1056         }
1058       template<typename _MutableBufferSequence>
1059         size_t
1060         receive(const _MutableBufferSequence& __buffers,
1061                 socket_base::message_flags __flags, error_code& __ec)
1062         {
1063           socket_base::__msg_hdr __msg(__buffers);
1064           ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1065                                        static_cast<int>(__flags));
1066           if (__result == -1)
1067             {
1068               __ec.assign(errno, generic_category());
1069               return 0;
1070             }
1071           __ec.clear();
1072           return __result;
1073         }
1075       template<typename _MutableBufferSequence, typename _CompletionToken>
1076         __deduced_t<_CompletionToken, void(error_code, size_t)>
1077         async_receive(const _MutableBufferSequence& __buffers,
1078                       _CompletionToken&& __token)
1079         {
1080           return async_receive(__buffers, socket_base::message_flags(),
1081                                std::forward<_CompletionToken>(__token));
1082         }
1084       template<typename _MutableBufferSequence, typename _CompletionToken>
1085         __deduced_t<_CompletionToken, void(error_code, size_t)>
1086         async_receive(const _MutableBufferSequence& __buffers,
1087                       socket_base::message_flags __flags,
1088                       _CompletionToken&& __token)
1089         {
1090           async_completion<_CompletionToken, void(error_code, size_t)>
1091             __init{__token};
1093           this->get_executor().context().async_wait(this->native_handle(),
1094               socket_base::wait_read,
1095               [__h = std::move(__init.completion_handler),
1096                &__buffers, __flags = static_cast<int>(__flags),
1097                __fd = this->native_handle()]
1098               (error_code __ec) mutable {
1099                   if (__ec)
1100                     {
1101                       __h(__ec);
1102                       return;
1103                     }
1104                   socket_base::__msg_hdr __msg(__buffers);
1105                   ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1106                   if (__result == -1)
1107                     {
1108                       __ec.assign(errno, generic_category());
1109                       __result = 0;
1110                     }
1111                   else
1112                     __ec.clear();
1113                   __h(__ec, __result);
1114               });
1115           return __init.result.get();
1116         }
1118       template<typename _MutableBufferSequence>
1119         size_t
1120         receive_from(const _MutableBufferSequence& __buffers,
1121                      endpoint_type& __sender)
1122         {
1123           return receive_from(__buffers, __sender,
1124                               socket_base::message_flags(),
1125                               __throw_on_error{
1126                                   "basic_datagram_socket::receive_from"});
1127         }
1129       template<typename _MutableBufferSequence>
1130         size_t
1131         receive_from(const _MutableBufferSequence& __buffers,
1132                      endpoint_type& __sender, error_code& __ec)
1133         {
1134           return receive_from(__buffers, __sender,
1135                               socket_base::message_flags(), __ec);
1136         }
1138       template<typename _MutableBufferSequence>
1139         size_t
1140         receive_from(const _MutableBufferSequence& __buffers,
1141                      endpoint_type& __sender,
1142                      socket_base::message_flags __flags)
1143         {
1144           return receive_from(__buffers, __sender, __flags,
1145                               __throw_on_error{
1146                                   "basic_datagram_socket::receive_from"});
1147         }
1149       template<typename _MutableBufferSequence>
1150         size_t
1151         receive_from(const _MutableBufferSequence& __buffers,
1152                      endpoint_type& __sender,
1153                      socket_base::message_flags __flags,
1154                      error_code& __ec)
1155         {
1156           socket_base::__msg_hdr __msg(__buffers, __sender);
1157           ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1158                                        static_cast<int>(__flags));
1159           if (__result == -1)
1160             {
1161               __ec.assign(errno, generic_category());
1162               return 0;
1163             }
1164           __ec.clear();
1165           __sender.resize(__msg.msg_namelen);
1166           return __result;
1167         }
1169       template<typename _MutableBufferSequence, typename _CompletionToken>
1170         __deduced_t<_CompletionToken, void(error_code, size_t)>
1171         async_receive_from(const _MutableBufferSequence& __buffers,
1172                            endpoint_type& __sender,
1173                            _CompletionToken&& __token)
1174         {
1175           return async_receive_from(__buffers, __sender,
1176                                     socket_base::message_flags(),
1177                                     std::forward<_CompletionToken>(__token));
1178         }
1180       template<typename _MutableBufferSequence, typename _CompletionToken>
1181         __deduced_t<_CompletionToken, void(error_code, size_t)>
1182         async_receive_from(const _MutableBufferSequence& __buffers,
1183                            endpoint_type& __sender,
1184                            socket_base::message_flags __flags,
1185                            _CompletionToken&& __token)
1186         {
1187           async_completion<_CompletionToken, void(error_code, size_t)>
1188             __init{__token};
1190           this->get_executor().context().async_wait( this->native_handle(),
1191               socket_base::wait_read,
1192               [__h = std::move(__init.completion_handler),
1193                &__buffers, __flags = static_cast<int>(__flags),
1194                __sender = std::move(__sender),
1195                __fd = this->native_handle()]
1196               (error_code __ec) mutable {
1197                   if (__ec)
1198                     {
1199                       __h(__ec);
1200                       return;
1201                     }
1202                   socket_base::__msg_hdr __msg(__buffers, __sender);
1203                   ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1204                   if (__result == -1)
1205                     {
1206                       __ec.assign(errno, generic_category());
1207                       __result = 0;
1208                     }
1209                   else
1210                     {
1211                       __ec.clear();
1212                       __sender.resize(__msg.msg_namelen);
1213                     }
1214                   __h(__ec, __result);
1215               });
1216           return __init.result.get();
1217         }
1219       template<typename _ConstBufferSequence>
1220         size_t
1221         send(const _ConstBufferSequence& __buffers)
1222         {
1223           return send(__buffers, socket_base::message_flags(),
1224                       __throw_on_error{"basic_datagram_socket::send"});
1225         }
1227       template<typename _ConstBufferSequence>
1228         size_t
1229         send(const _ConstBufferSequence& __buffers, error_code& __ec)
1230         { return send(__buffers, socket_base::message_flags(), __ec); }
1232       template<typename _ConstBufferSequence>
1233         size_t
1234         send(const _ConstBufferSequence& __buffers,
1235              socket_base::message_flags __flags)
1236         {
1237           return send(__buffers, __flags,
1238                       __throw_on_error{"basic_datagram_socket::send"});
1239         }
1241       template<typename _ConstBufferSequence>
1242         size_t
1243         send(const _ConstBufferSequence& __buffers,
1244              socket_base::message_flags __flags, error_code& __ec)
1245         {
1246           socket_base::__msg_hdr __msg(__buffers);
1247           ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1248                                        static_cast<int>(__flags));
1249           if (__result == -1)
1250             {
1251               __ec.assign(errno, generic_category());
1252               return 0;
1253             }
1254           __ec.clear();
1255           return __result;
1256         }
1258       template<typename _ConstBufferSequence, typename _CompletionToken>
1259         __deduced_t<_CompletionToken, void(error_code, size_t)>
1260         async_send(const _ConstBufferSequence& __buffers,
1261                         _CompletionToken&& __token)
1262         {
1263           return async_send(__buffers, socket_base::message_flags(),
1264                             std::forward<_CompletionToken>(__token));
1265         }
1267       template<typename _ConstBufferSequence, typename _CompletionToken>
1268         __deduced_t<_CompletionToken, void(error_code, size_t)>
1269         async_send(const _ConstBufferSequence& __buffers,
1270                    socket_base::message_flags __flags,
1271                    _CompletionToken&& __token)
1272         {
1273           async_completion<_CompletionToken, void(error_code, size_t)>
1274             __init{__token};
1276           this->get_executor().context().async_wait( this->native_handle(),
1277               socket_base::wait_write,
1278               [__h = std::move(__init.completion_handler),
1279                &__buffers, __flags = static_cast<int>(__flags),
1280                __fd = this->native_handle()]
1281               (error_code __ec) mutable {
1282                   if (__ec)
1283                     {
1284                       __h(__ec);
1285                       return;
1286                     }
1287                   socket_base::__msg_hdr __msg(__buffers);
1288                   ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1289                   if (__result == -1)
1290                     {
1291                       __ec.assign(errno, generic_category());
1292                       __result = 0;
1293                     }
1294                   else
1295                     __ec.clear();
1296                   __h(__ec, __result);
1297               });
1298           return __init.result.get();
1299         }
1301       template<typename _ConstBufferSequence>
1302         size_t
1303         send_to(const _ConstBufferSequence& __buffers,
1304                 const endpoint_type& __recipient)
1305         {
1306           return send_to(__buffers, __recipient,
1307                          socket_base::message_flags(),
1308                          __throw_on_error{"basic_datagram_socket::send_to"});
1309         }
1311       template<typename _ConstBufferSequence>
1312         size_t
1313         send_to(const _ConstBufferSequence& __buffers,
1314                 const endpoint_type& __recipient, error_code& __ec)
1315         {
1316           return send_to(__buffers, __recipient,
1317                          socket_base::message_flags(), __ec);
1318         }
1320       template<typename _ConstBufferSequence>
1321         size_t
1322         send_to(const _ConstBufferSequence& __buffers,
1323                 const endpoint_type& __recipient,
1324                 socket_base::message_flags __flags)
1325         {
1326           return send_to(__buffers, __recipient, __flags,
1327                          __throw_on_error{"basic_datagram_socket::send_to"});
1328         }
1330       template<typename _ConstBufferSequence>
1331         size_t
1332         send_to(const _ConstBufferSequence& __buffers,
1333                 const endpoint_type& __recipient,
1334                 socket_base::message_flags __flags, error_code& __ec)
1335         {
1336           socket_base::__msg_hdr __msg(__buffers, __recipient);
1337           ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1338                                        static_cast<int>(__flags));
1339           if (__result == -1)
1340             {
1341               __ec.assign(errno, generic_category());
1342               return 0;
1343             }
1344           __ec.clear();
1345           __recipient.resize(__msg.msg_namelen);
1346           return __result;
1347         }
1349       template<typename _ConstBufferSequence, typename _CompletionToken>
1350         __deduced_t<_CompletionToken, void(error_code, size_t)>
1351         async_send_to(const _ConstBufferSequence& __buffers,
1352                       const endpoint_type& __recipient,
1353                       _CompletionToken&& __token)
1354         {
1355           return async_send_to(__buffers, __recipient,
1356                                socket_base::message_flags(),
1357                                std::forward<_CompletionToken>(__token));
1358         }
1360       template<typename _ConstBufferSequence, typename _CompletionToken>
1361         __deduced_t<_CompletionToken, void(error_code, size_t)>
1362         async_send_to(const _ConstBufferSequence& __buffers,
1363                       const endpoint_type& __recipient,
1364                       socket_base::message_flags __flags,
1365                       _CompletionToken&& __token)
1366         {
1367           async_completion<_CompletionToken, void(error_code, size_t)>
1368             __init{__token};
1370           this->get_executor().context().async_wait( this->native_handle(),
1371               socket_base::wait_write,
1372               [__h = std::move(__init.completion_handler),
1373                &__buffers, __flags = static_cast<int>(__flags),
1374                __recipient = std::move(__recipient),
1375                __fd = this->native_handle()]
1376               (error_code __ec) mutable {
1377                   if (__ec)
1378                     {
1379                       __h(__ec);
1380                       return;
1381                     }
1382                   socket_base::__msg_hdr __msg(__buffers, __recipient);
1383                   ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1384                   if (__result == -1)
1385                     {
1386                       __ec.assign(errno, generic_category());
1387                       __result = 0;
1388                     }
1389                   else
1390                     {
1391                       __ec.clear();
1392                       __recipient.resize(__msg.msg_namelen);
1393                     }
1394                   __h(__ec, __result);
1395               });
1396           return __init.result.get();
1397         }
1398     };
1400   template<typename _Protocol>
1401     class basic_stream_socket : public basic_socket<_Protocol>
1402     {
1403       using __base = basic_socket<_Protocol>;
1405     public:
1406       // types:
1408       typedef int native_handle_type;
1409       typedef _Protocol protocol_type;
1410       typedef typename protocol_type::endpoint endpoint_type;
1412       // construct / copy / destroy:
1414       explicit
1415       basic_stream_socket(io_context& __ctx) : __base(__ctx) { }
1417       basic_stream_socket(io_context& __ctx, const protocol_type& __protocol)
1418       : __base(__ctx, __protocol) { }
1420       basic_stream_socket(io_context& __ctx, const endpoint_type& __endpoint)
1421       : __base(__ctx, __endpoint) { }
1423       basic_stream_socket(io_context& __ctx, const protocol_type& __protocol,
1424                           const native_handle_type& __native_socket)
1425       : __base(__ctx, __protocol, __native_socket) { }
1427       basic_stream_socket(const basic_stream_socket&) = delete;
1429       basic_stream_socket(basic_stream_socket&& __rhs) = default;
1431       template<typename _OtherProtocol, typename _Requires
1432                = _Require<is_convertible<_OtherProtocol, _Protocol>>>
1433         basic_stream_socket(basic_stream_socket<_OtherProtocol>&& __rhs)
1434         : __base(std::move(__rhs)) { }
1436       ~basic_stream_socket() = default;
1438       basic_stream_socket& operator=(const basic_stream_socket&) = delete;
1440       basic_stream_socket& operator=(basic_stream_socket&& __rhs) = default;
1442       template<class _OtherProtocol>
1443         enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
1444                     basic_stream_socket&>
1445         operator=(basic_stream_socket<_OtherProtocol>&& __rhs)
1446         {
1447           __base::operator=(std::move(__rhs));
1448           return *this;
1449         }
1451       // basic_stream_socket operations:
1453       template<class _MutableBufferSequence>
1454         size_t
1455         receive(const _MutableBufferSequence& __buffers)
1456         {
1457           return receive(__buffers, socket_base::message_flags(),
1458                          __throw_on_error{"basic_stream_socket::receive"});
1459         }
1461       template<class _MutableBufferSequence>
1462         size_t
1463         receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1464         { return receive(__buffers, socket_base::message_flags(), __ec); }
1466       template<class _MutableBufferSequence>
1467         size_t
1468         receive(const _MutableBufferSequence& __buffers,
1469                 socket_base::message_flags __flags)
1470         {
1471           return receive(__buffers, __flags,
1472                          __throw_on_error{"basic_stream_socket::receive"});
1473         }
1475       template<class _MutableBufferSequence>
1476         size_t
1477         receive(const _MutableBufferSequence& __buffers,
1478                 socket_base::message_flags __flags, error_code& __ec)
1479         {
1480           if (__buffer_empty(__buffers))
1481             {
1482               __ec.clear();
1483               return 0;
1484             }
1486           socket_base::__msg_hdr __msg(__buffers);
1487           ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1488                                        static_cast<int>(__flags));
1489           if (__result >= 0)
1490             {
1491               __ec.clear();
1492               return __result;
1493             }
1494           __ec.assign(errno, generic_category());
1495           return 0;
1496         }
1498       template<class _MutableBufferSequence, class _CompletionToken>
1499         __deduced_t<_CompletionToken, void(error_code, size_t)>
1500         async_receive(const _MutableBufferSequence& __buffers,
1501                       _CompletionToken&& __token)
1502         {
1503           return async_receive(__buffers, socket_base::message_flags(),
1504                                std::forward<_CompletionToken>(__token));
1505         }
1507       template<class _MutableBufferSequence, class _CompletionToken>
1508         __deduced_t<_CompletionToken, void(error_code, size_t)>
1509         async_receive(const _MutableBufferSequence& __buffers,
1510                       socket_base::message_flags __flags,
1511                       _CompletionToken&& __token)
1512         {
1513           async_completion<_CompletionToken, void(error_code, size_t)>
1514             __init{__token};
1516           if (__buffer_empty(__buffers))
1517             {
1518               auto __ex = net::get_associated_executor(
1519                   __init.completion_handler, this->get_executor());
1520               auto __a = get_associated_allocator(
1521                   __init.completion_handler, std::allocator<void>());
1522               __ex.post(
1523                   [__h=std::move(__init.completion_handler)] () mutable
1524                   { __h(error_code{}, 0); }, __a);
1525               return __init.result.get();
1526             }
1528           this->get_executor().context().async_wait(this->native_handle(),
1529               socket_base::wait_read,
1530               [__h = std::move(__init.completion_handler),
1531                &__buffers, __flags = static_cast<int>(__flags),
1532                __fd = this->native_handle()]
1533               (error_code __ec) mutable {
1534                   if (__ec)
1535                     {
1536                       __h(__ec);
1537                       return;
1538                     }
1539                   socket_base::__msg_hdr __msg(__buffers);
1540                   ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1541                   if (__result == -1)
1542                     {
1543                       __ec.assign(errno, generic_category());
1544                       __result = 0;
1545                     }
1546                   else
1547                     __ec.clear();
1548                   __h(__ec, __result);
1549               });
1550           return __init.result.get();
1551         }
1553       template<class _ConstBufferSequence>
1554         size_t
1555         send(const _ConstBufferSequence& __buffers)
1556         {
1557           return send(__buffers, socket_base::message_flags(),
1558                       __throw_on_error{"basic_stream_socket::send"});
1559         }
1561       template<class _ConstBufferSequence>
1562         size_t
1563         send(const _ConstBufferSequence& __buffers, error_code& __ec)
1564         { return send(__buffers, socket_base::message_flags(), __ec); }
1566       template<class _ConstBufferSequence>
1567         size_t
1568         send(const _ConstBufferSequence& __buffers,
1569              socket_base::message_flags __flags)
1570         {
1571           return send(__buffers, socket_base::message_flags(),
1572                       __throw_on_error{"basic_stream_socket::send"});
1573         }
1575       template<class _ConstBufferSequence>
1576         size_t
1577         send(const _ConstBufferSequence& __buffers,
1578              socket_base::message_flags __flags, error_code& __ec)
1579         {
1580           if (__buffer_empty(__buffers))
1581             {
1582               __ec.clear();
1583               return 0;
1584             }
1586           socket_base::__msg_hdr __msg(__buffers);
1587           ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1588                                        static_cast<int>(__flags));
1589           if (__result >= 0)
1590             {
1591               __ec.clear();
1592               return __result;
1593             }
1594           __ec.assign(errno, generic_category());
1595           return 0;
1596         }
1598       template<class _ConstBufferSequence, class _CompletionToken>
1599         __deduced_t<_CompletionToken, void(error_code, size_t)>
1600         async_send(const _ConstBufferSequence& __buffers,
1601                    _CompletionToken&& __token)
1602         {
1603           return async_send(__buffers, socket_base::message_flags(),
1604                             std::forward<_CompletionToken>(__token));
1605         }
1607       template<class _ConstBufferSequence, class _CompletionToken>
1608         __deduced_t<_CompletionToken, void(error_code, size_t)>
1609         async_send(const _ConstBufferSequence& __buffers,
1610                    socket_base::message_flags __flags,
1611                    _CompletionToken&& __token)
1612         {
1613           async_completion<_CompletionToken, void(error_code, size_t)>
1614             __init{__token};
1616           if (__buffer_empty(__buffers))
1617             {
1618               auto __ex = net::get_associated_executor(
1619                   __init.completion_handler, this->get_executor());
1620               auto __a = get_associated_allocator(
1621                   __init.completion_handler, std::allocator<void>());
1622               __ex.post(
1623                   [__h=std::move(__init.completion_handler)] () mutable
1624                   { __h(error_code{}, 0); }, __a);
1625               return __init.result.get();
1626             }
1628           this->get_executor().context().async_wait(this->native_handle(),
1629               socket_base::wait_write,
1630               [__h = std::move(__init.completion_handler),
1631                &__buffers, __flags = static_cast<int>(__flags),
1632                __fd = this->native_handle()]
1633               (error_code __ec) mutable {
1634                   if (__ec)
1635                     {
1636                       __h(__ec);
1637                       return;
1638                     }
1639                   socket_base::__msg_hdr __msg(__buffers);
1640                   ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1641                   if (__result == -1)
1642                     {
1643                       __ec.assign(errno, generic_category());
1644                       __result = 0;
1645                     }
1646                   else
1647                     __ec.clear();
1648                   __h(__ec, __result);
1649               });
1650           return __init.result.get();
1651         }
1653       template<class _MutableBufferSequence>
1654         size_t
1655         read_some(const _MutableBufferSequence& __buffers)
1656         {
1657           return receive(__buffers,
1658                          __throw_on_error{"basic_stream_socket::read_some"});
1659         }
1661       template<class _MutableBufferSequence>
1662         size_t
1663         read_some(const _MutableBufferSequence& __buffers, error_code& __ec)
1664         { return receive(__buffers, __ec); }
1666       template<class _MutableBufferSequence, class _CompletionToken>
1667         __deduced_t<_CompletionToken, void(error_code, size_t)>
1668         async_read_some(const _MutableBufferSequence& __buffers,
1669                         _CompletionToken&& __token)
1670         {
1671           return async_receive(__buffers,
1672                                std::forward<_CompletionToken>(__token));
1673         }
1675       template<class _ConstBufferSequence>
1676         size_t
1677         write_some(const _ConstBufferSequence& __buffers)
1678         {
1679           return send(__buffers,
1680                       __throw_on_error{"basic_stream_socket:write_some"});
1681         }
1683       template<class _ConstBufferSequence>
1684         size_t
1685         write_some(const _ConstBufferSequence& __buffers, error_code& __ec)
1686         {  return send(__buffers, __ec); }
1688       template<class _ConstBufferSequence, class _CompletionToken>
1689         __deduced_t<_CompletionToken, void(error_code, size_t)>
1690         async_write_some(const _ConstBufferSequence& __buffers,
1691                               _CompletionToken&& __token)
1692         {
1693           return async_send(__buffers,
1694                             std::forward<_CompletionToken>(__token));
1695         }
1696     };
1698   template<typename _AcceptableProtocol>
1699     class basic_socket_acceptor
1700     : public socket_base, private __basic_socket_impl<_AcceptableProtocol>
1701     {
1702       using __base = __basic_socket_impl<_AcceptableProtocol>;
1704     public:
1705       // types:
1707       typedef io_context::executor_type executor_type;
1708       typedef int native_handle_type;
1709       typedef _AcceptableProtocol protocol_type;
1710       typedef typename protocol_type::endpoint endpoint_type;
1711       typedef typename protocol_type::socket socket_type;
1713       // construct / copy / destroy:
1715       explicit
1716       basic_socket_acceptor(io_context& __ctx)
1717       : __base(__ctx), _M_protocol(endpoint_type{}.protocol()) { }
1719       basic_socket_acceptor(io_context& __ctx,
1720                             const protocol_type& __protocol)
1721       : __base(__ctx), _M_protocol(__protocol)
1722       { open(__protocol); }
1724       basic_socket_acceptor(io_context& __ctx, const endpoint_type& __endpoint,
1725                             bool __reuse_addr = true)
1726       : basic_socket_acceptor(__ctx, __endpoint.protocol())
1727       {
1728         if (__reuse_addr)
1729           set_option(reuse_address(true));
1730         bind(__endpoint);
1731         listen();
1732       }
1734       basic_socket_acceptor(io_context& __ctx, const protocol_type& __protocol,
1735                             const native_handle_type& __native_acceptor)
1736       : basic_socket_acceptor(__ctx, __protocol)
1737       { assign(__protocol, __native_acceptor); }
1739       basic_socket_acceptor(const basic_socket_acceptor&) = delete;
1741       basic_socket_acceptor(basic_socket_acceptor&&) = default;
1743       template<typename _OtherProtocol, typename _Requires
1744                = _Require<is_convertible<_OtherProtocol, protocol_type>>>
1745         basic_socket_acceptor(basic_socket_acceptor<_OtherProtocol>&& __rhs)
1746         : __base(std::move(__rhs)) { }
1748       ~basic_socket_acceptor() = default;
1750       basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete;
1752       basic_socket_acceptor& operator=(basic_socket_acceptor&&) = default;
1754       template<class _OtherProtocol>
1755         enable_if_t<is_convertible<_OtherProtocol, protocol_type>::value,
1756                     basic_socket_acceptor&>
1757         operator=(basic_socket_acceptor<_OtherProtocol>&& __rhs)
1758         {
1759           __base::operator=(std::move(__rhs));
1760           return *this;
1761         }
1763       // basic_socket_acceptor operations:
1765       executor_type get_executor() noexcept { return __base::get_executor(); }
1767       native_handle_type
1768       native_handle() noexcept { return __base::native_handle(); }
1770       void
1771       open(const protocol_type& __protocol = protocol_type())
1772       { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); }
1774       void
1775       open(const protocol_type& __protocol, error_code& __ec)
1776       { __base::open(__protocol, __ec); }
1778       void
1779       assign(const protocol_type& __protocol,
1780              const native_handle_type& __native_acceptor)
1781       {
1782         assign(__protocol, __native_acceptor,
1783                __throw_on_error{"basic_socket_acceptor::assign"});
1784       }
1786       void
1787       assign(const protocol_type& __protocol,
1788              const native_handle_type& __native_acceptor,
1789              error_code& __ec)
1790       { __base::assign(__protocol, __native_acceptor, __ec); }
1792       bool
1793       is_open() const noexcept { return __base::is_open(); }
1795       void
1796       close() { close(__throw_on_error{"basic_socket_acceptor::close"}); }
1798       void
1799       close(error_code& __ec) { __base::_close(__ec); }
1801       void
1802       cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); }
1804       void
1805       cancel(error_code& __ec) { __base::cancel(__ec); }
1807       template<typename _SettableSocketOption>
1808         void
1809         set_option(const _SettableSocketOption& __option)
1810         {
1811           set_option(__option,
1812                      __throw_on_error{"basic_socket_acceptor::set_option"});
1813         }
1815       template<typename _SettableSocketOption>
1816         void
1817         set_option(const _SettableSocketOption& __option, error_code& __ec)
1818         { __base::set_option(__option, __ec); }
1820       template<typename _GettableSocketOption>
1821         void
1822         get_option(_GettableSocketOption& __option) const
1823         {
1824           get_option(__option,
1825                      __throw_on_error{"basic_socket_acceptor::get_option"});
1826         }
1828       template<typename _GettableSocketOption>
1829         void
1830         get_option(_GettableSocketOption& __option, error_code& __ec) const
1831         { __base::get_option(__option, __ec); }
1833       template<typename _IoControlCommand>
1834         void
1835         io_control(_IoControlCommand& __command)
1836         {
1837           io_control(__command,
1838                      __throw_on_error{"basic_socket_acceptor::io_control"});
1839         }
1841       template<typename _IoControlCommand>
1842         void
1843         io_control(_IoControlCommand& __command, error_code& __ec)
1844         { __base::io_control(__command, __ec); }
1846       void
1847       non_blocking(bool __mode)
1848       {
1849         non_blocking(__mode,
1850                      __throw_on_error{"basic_socket_acceptor::non_blocking"});
1851       }
1853       void
1854       non_blocking(bool __mode, error_code& __ec)
1855       { __base::non_blocking(__mode, __ec); }
1857       bool non_blocking() const { return __base::non_blocking(); }
1859       void
1860       native_non_blocking(bool __mode)
1861       {
1862         native_non_blocking(__mode, __throw_on_error{
1863             "basic_socket_acceptor::native_non_blocking"});
1864       }
1866       void
1867       native_non_blocking(bool __mode, error_code& __ec)
1868       { __base::native_non_blocking(__mode, __ec); }
1870       bool
1871       native_non_blocking() const
1872       { return __base::native_non_blocking(); }
1874       void
1875       bind(const endpoint_type& __endpoint)
1876       {
1877         return bind(__endpoint,
1878                     __throw_on_error{"basic_socket_acceptor::bind"});
1879       }
1881       void
1882       bind(const endpoint_type& __endpoint, error_code& __ec)
1883       { __base::bind(__endpoint, __ec); }
1885       void
1886       listen(int __backlog = max_listen_connections)
1887       {
1888         return listen(__backlog,
1889                       __throw_on_error{"basic_socket_acceptor::listen"});
1890       }
1892       void listen(int __backlog, error_code& __ec)
1893       {
1894         if (::listen(native_handle(), __backlog) == -1)
1895           __ec.assign(errno, generic_category());
1896         else
1897           __ec.clear();
1898       }
1900       endpoint_type
1901       local_endpoint() const
1902       {
1903         return local_endpoint(
1904             __throw_on_error{"basic_socket_acceptor::local_endpoint"});
1905       }
1907       endpoint_type
1908       local_endpoint(error_code& __ec) const
1909       { return __base::local_endpoint(__ec); }
1911       void
1912       enable_connection_aborted(bool __mode)
1913       { __base::_M_bits.enable_connection_aborted = __mode; }
1915       bool
1916       enable_connection_aborted() const
1917       { return __base::_M_bits.enable_connection_aborted; }
1919       socket_type
1920       accept()
1921       { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); }
1923       socket_type
1924       accept(error_code& __ec)
1925       { return accept(get_executor().context(), __ec); }
1927       socket_type accept(io_context& __ctx)
1928       {
1929         return accept(__ctx,
1930                       __throw_on_error{"basic_socket_acceptor::accept"});
1931       }
1933       socket_type
1934       accept(io_context& __ctx, error_code& __ec)
1935       {
1936         do
1937           {
1938             int __h = ::accept(native_handle(), nullptr, 0);
1939             if (__h != -1)
1940               {
1941                 __ec.clear();
1942                 return socket_type{__ctx, _M_protocol, __h};
1943               }
1944           } while (errno == ECONNABORTED && enable_connection_aborted());
1945         __ec.assign(errno, generic_category());
1946         return socket_type{__ctx};
1947       }
1949       template<class _CompletionToken>
1950         __deduced_t<_CompletionToken, void(error_code, socket_type)>
1951         async_accept(_CompletionToken&& __token)
1952         {
1953           return async_accept(get_executor().context(),
1954                               std::forward<_CompletionToken>(__token));
1955         }
1957       template<class _CompletionToken>
1958         __deduced_t<_CompletionToken, void(error_code, socket_type)>
1959         async_accept(io_context& __ctx, _CompletionToken&& __token)
1960         {
1961           async_completion<_CompletionToken, void(error_code, socket_type)>
1962             __init{__token};
1964           __ctx.get_executor().context().async_wait(native_handle(),
1965               socket_base::wait_read,
1966               [__h = std::move(__init.completion_handler),
1967                __connabort = enable_connection_aborted(),
1968                __fd = native_handle(),
1969                __protocol = _M_protocol,
1970                &__ctx
1971               ]
1972               (error_code __ec) mutable {
1973                   if (__ec)
1974                     {
1975                       __h(__ec, socket_type(__ctx));
1976                       return;
1977                     }
1978                   do
1979                     {
1980                       int __newfd = ::accept(__fd, nullptr, 0);
1981                       if (__newfd != -1)
1982                         {
1983                           __ec.clear();
1984                           __h(__ec, socket_type{__ctx, __protocol, __newfd});
1985                           return;
1986                         }
1987                     } while (errno == ECONNABORTED && __connabort);
1988                   __ec.assign(errno, generic_category());
1989                   __h(__ec, socket_type(__ctx));
1990               });
1991           return __init.result.get();
1992         }
1994       socket_type
1995       accept(endpoint_type& __endpoint)
1996       {
1997         return accept(get_executor().context(), __endpoint,
1998                       __throw_on_error{"basic_socket_acceptor::accept"});
1999       }
2001       socket_type
2002       accept(endpoint_type& __endpoint, error_code& __ec)
2003       { return accept(get_executor().context(), __endpoint, __ec); }
2005       socket_type
2006       accept(io_context& __ctx, endpoint_type& __endpoint)
2007       {
2008         return accept(__ctx, __endpoint,
2009                       __throw_on_error{"basic_socket_acceptor::accept"});
2010       }
2012       socket_type
2013       accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec)
2014       {
2015         do
2016           {
2017             socklen_t __len = __endpoint.capacity();
2018             int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(),
2019                                &__len);
2020             if (__h != -1)
2021               {
2022                 __endpoint.resize(__len);
2023                 return socket_type{__ctx, _M_protocol, __h};
2024               }
2025           } while (errno == ECONNABORTED && enable_connection_aborted());
2026         __ec.assign(errno, generic_category());
2027         return socket_type{__ctx};
2028       }
2030       template<class _CompletionToken>
2031         __deduced_t<_CompletionToken, void(error_code, socket_type)>
2032         async_accept(endpoint_type& __endpoint,
2033                              _CompletionToken&& __token)
2034         {
2035           return async_accept(get_executor().context(), __endpoint,
2036                               std::forward<_CompletionToken>(__token));
2037         }
2039       template<class _CompletionToken>
2040         __deduced_t<_CompletionToken, void(error_code, socket_type)>
2041         async_accept(io_context& __ctx, endpoint_type& __endpoint,
2042                              _CompletionToken&& __token)
2043         {
2044           async_completion<_CompletionToken, void(error_code, socket_type)>
2045             __init{__token};
2047           __ctx.get_executor().context().async_wait(native_handle(),
2048               socket_base::wait_read,
2049               [__h = std::move(__init.completion_handler),
2050               __ep = std::move(__endpoint),
2051                __connabort = enable_connection_aborted(),
2052                __fd = native_handle(),
2053                &__ctx
2054               ]
2055               (error_code __ec) mutable {
2056                   if (__ec)
2057                     {
2058                       __h(__ec, socket_type(__ctx));
2059                       return;
2060                     }
2061                   do
2062                     {
2063                       socklen_t __len = __ep.capacity();
2064                       int __newfd = ::accept(__fd, __ep.data, &__len);
2065                       if (__newfd != -1)
2066                         {
2067                           __ep.resize(__len);
2068                           auto __protocol = __ep.protocol();
2069                           __ec.clear();
2070                           __h(__ec, socket_type{__ctx, __protocol, __newfd});
2071                           return;
2072                         }
2073                     } while (errno == ECONNABORTED && __connabort);
2074                   __ec.assign(errno, generic_category());
2075                   __h(__ec, socket_type(__ctx));
2076               });
2077           return __init.result.get();
2078         }
2080       void
2081       wait(wait_type __w)
2082       { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); }
2084       void
2085       wait(wait_type __w, error_code& __ec)
2086       {
2087         ::pollfd __fds;
2088         __fds.fd = native_handle();
2089         __fds.events = __w; // __w | POLLIN;
2090         if (::poll(&__fds, 1, -1) == -1)
2091           __ec.assign(errno, generic_category());
2092         else
2093           __ec.clear();
2094       }
2096       template<class _CompletionToken>
2097         __deduced_t<_CompletionToken, void(error_code)>
2098         async_wait(wait_type __w, _CompletionToken&& __token)
2099         {
2100           async_completion<_CompletionToken, void(error_code)> __init{__token};
2101           get_executor().context().async_wait( native_handle(),
2102               static_cast<int>(__w),
2103               [__h = std::move(__init.completion_handler)]
2104               (error_code __ec) mutable {
2105                   __h(__ec);
2106               });
2107           return __init.result.get();
2108         }
2110     private:
2111       protocol_type _M_protocol;
2112     };
2114   // @}
2116   /** @brief Socket streams
2117    * @{
2118    */
2120   template<typename _Protocol, typename _Clock, typename _WaitTraits>
2121     class basic_socket_streambuf : public basic_streambuf<char>
2122     {
2123     public:
2124       // types:
2126       typedef _Protocol protocol_type;
2127       typedef typename protocol_type::endpoint endpoint_type;
2128       typedef _Clock clock_type;
2129       typedef typename clock_type::time_point time_point;
2130       typedef typename clock_type::duration duration;
2131       typedef _WaitTraits wait_traits_type;
2133       // construct / copy / destroy:
2135       basic_socket_streambuf() : _M_socket(_S_ctx()) { }
2137       explicit
2138       basic_socket_streambuf(basic_stream_socket<protocol_type> __s)
2139       : _M_socket(std::move(__s)) { }
2141       basic_socket_streambuf(const basic_socket_streambuf&) = delete;
2143       basic_socket_streambuf(basic_socket_streambuf&& __rhs); // TODO
2146       virtual ~basic_socket_streambuf(); // TODO
2148       basic_socket_streambuf& operator=(const basic_socket_streambuf&) = delete;
2150       basic_socket_streambuf& operator=(basic_socket_streambuf&& __rhs); // TODO
2152       // members:
2154       basic_socket_streambuf* connect(const endpoint_type& __e); // TODO
2156       template<typename... _Args>
2157         basic_socket_streambuf* connect(_Args&&... ); // TODO
2159       basic_socket_streambuf* close(); // TODO
2161       basic_socket<protocol_type>& socket() { return _M_socket; }
2162       error_code error() const { return _M_ec; }
2164       time_point expiry() const { return _M_expiry; }
2166       void
2167       expires_at(const time_point& __t)
2168       { _M_expiry = __t; }
2170       void
2171       expires_after(const duration& __d)
2172       { expires_at(clock_type::now() + __d); }
2174     protected:
2175       // overridden virtual functions: // TODO
2176       virtual int_type underflow() override;
2177       virtual int_type pbackfail(int_type __c = traits_type::eof()) override;
2178       virtual int_type overflow(int_type __c = traits_type::eof()) override;
2179       virtual int sync() override;
2180       virtual streambuf* setbuf(char_type* __s, streamsize __n) override;
2182     private:
2183       static io_context&
2184       _S_ctx()
2185       {
2186         static io_context __ctx;
2187         return __ctx;
2188       }
2190       basic_stream_socket<protocol_type> _M_socket;
2191       error_code _M_ec;
2192       time_point _M_expiry{ time_point::max() };
2193     };
2195   template<typename _Protocol, class _Clock, typename _WaitTraits>
2196     class basic_socket_iostream : public basic_iostream<char>
2197     {
2198       using __streambuf_type
2199         = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>;
2201     public:
2202       // types:
2204       typedef _Protocol protocol_type;
2205       typedef typename protocol_type::endpoint endpoint_type;
2206       typedef _Clock clock_type;
2207       typedef typename clock_type::time_point time_point;
2208       typedef typename clock_type::duration duration;
2209       typedef _WaitTraits wait_traits_type;
2211       // construct / copy / destroy:
2213       // TODO base-from-member ?
2214       basic_socket_iostream() : basic_iostream(nullptr), _M_sb()
2215       {
2216         this->init(std::addressof(_M_sb));
2217         this->setf(std::ios::unitbuf);
2218       }
2220       explicit
2221       basic_socket_iostream(basic_stream_socket<protocol_type> __s)
2222       : basic_iostream(nullptr), _M_sb(std::move(__s))
2223       {
2224         this->init(std::addressof(_M_sb));
2225         this->setf(std::ios::unitbuf);
2226       }
2228       basic_socket_iostream(const basic_socket_iostream&) = delete;
2230       basic_socket_iostream(basic_socket_iostream&& __rhs)
2231       : basic_iostream(nullptr), _M_sb(std::move(__rhs._M_sb))
2232         // XXX ???     ^^^^^^^
2233       {
2234         // XXX ??? this->init(std::addressof(_M_sb));
2235         this->set_rbduf(std::addressof(_M_sb));
2236       }
2238       template<typename... _Args>
2239         explicit
2240         basic_socket_iostream(_Args&&... __args)
2241         : basic_iostream(nullptr), _M_sb()
2242         {
2243           this->init(std::addressof(_M_sb));
2244           this->setf(std::ios::unitbuf);
2245           connect(forward<_Args>(__args)...);
2246         }
2248       basic_socket_iostream& operator=(const basic_socket_iostream&) = delete;
2250       basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO
2252       // members:
2254       template<typename... _Args>
2255         void
2256         connect(_Args&&... __args)
2257         {
2258           if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr)
2259             this->setstate(failbit);
2260         }
2262       void
2263       close()
2264       {
2265         if (rdbuf()->close() == nullptr)
2266           this->setstate(failbit);
2267       }
2269       basic_socket_streambuf<protocol_type, clock_type, wait_traits_type>*
2270       rdbuf() const
2271       { return const_cast<__streambuf_type*>(std::addressof(_M_sb)); }
2273       basic_socket<protocol_type>& socket() { return rdbuf()->socket(); }
2274       error_code error() const { return rdbuf()->error(); }
2276       time_point expiry() const { return rdbuf()->expiry(); }
2277       void expires_at(const time_point& __t) { rdbuf()->expires_at(__t); }
2278       void expires_after(const duration& __d) { rdbuf()->expires_after(__d); }
2280     private:
2281       __streambuf_type _M_sb;
2282     };
2284   // @}
2286   /** @brief synchronous connect operations
2287    * @{
2288    */
2290   template<typename _Protocol, typename _EndpointSequence,
2291            typename _ConnectCondition>
2292     inline typename _Protocol::endpoint
2293     connect(basic_socket<_Protocol>& __s,
2294             const _EndpointSequence& __endpoints,
2295             _ConnectCondition __c, error_code& __ec)
2296     {
2297       __ec.clear();
2298       bool __found = false;
2299       for (auto& __ep : __endpoints)
2300         {
2301           if (__c(__ec, __ep))
2302             {
2303               __found = true;
2304               __s.close(__ec);
2305               if (!__ec)
2306                 __s.open(__ep.protocol(), __ec);
2307               if (!__ec)
2308                 __s.connect(__ep, __ec);
2309               if (!__ec)
2310                 return __ep;
2311             }
2312         }
2313       if (!__found)
2314         __ec = socket_errc::not_found;
2315       return typename _Protocol::endpoint{};
2316     }
2318   template<typename _Protocol, typename _InputIterator,
2319            typename _ConnectCondition>
2320     inline _InputIterator
2321     connect(basic_socket<_Protocol>& __s,
2322             _InputIterator __first, _InputIterator __last,
2323             _ConnectCondition __c, error_code& __ec)
2324     {
2325       __ec.clear();
2326       bool __found = false;
2327       for (auto __i = __first; __i != __last; ++__i)
2328         {
2329           if (__c(__ec, *__i))
2330             {
2331               __found = true;
2332               __s.close(__ec);
2333               if (!__ec)
2334                 __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec);
2335               if (!__ec)
2336                 __s.connect(*__i, __ec);
2337               if (!__ec)
2338                 return __i;
2339             }
2340         }
2341       if (!__found)
2342         __ec = socket_errc::not_found;
2343       return __last;
2344     }
2346   template<typename _Protocol, typename _EndpointSequence,
2347            typename _ConnectCondition>
2348     inline typename _Protocol::endpoint
2349     connect(basic_socket<_Protocol>& __s,
2350             const _EndpointSequence& __endpoints,
2351             _ConnectCondition __c)
2352     {
2353       return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"});
2354     }
2356   template<typename _Protocol, typename _InputIterator,
2357            typename _ConnectCondition>
2358     inline _InputIterator
2359     connect(basic_socket<_Protocol>& __s,
2360             _InputIterator __first, _InputIterator __last,
2361             _ConnectCondition __c)
2362     {
2363       return net::connect(__s, __first, __last, __c,
2364                           __throw_on_error{"connect"});
2365     }
2367   template<typename _Protocol, typename _EndpointSequence>
2368     inline typename _Protocol::endpoint
2369     connect(basic_socket<_Protocol>& __s,
2370             const _EndpointSequence& __endpoints)
2371     {
2372       return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2373                           __throw_on_error{"connect"});
2374     }
2376   template<typename _Protocol, typename _EndpointSequence>
2377     inline typename _Protocol::endpoint
2378     connect(basic_socket<_Protocol>& __s,
2379             const _EndpointSequence& __endpoints,
2380             error_code& __ec)
2381     {
2382       return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2383                           __ec);
2384     }
2386   template<typename _Protocol, typename _InputIterator>
2387     inline _InputIterator
2388     connect(basic_socket<_Protocol>& __s,
2389             _InputIterator __first, _InputIterator __last)
2390     {
2391       return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2392                           __throw_on_error{"connect"});
2393     }
2395   template<typename _Protocol, typename _InputIterator>
2396     inline _InputIterator
2397     connect(basic_socket<_Protocol>& __s,
2398             _InputIterator __first, _InputIterator __last,
2399             error_code& __ec)
2400     {
2401       return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2402                           __ec);
2403     }
2405   // @}
2407   /** @brief asynchronous connect operations
2408    * @{
2409    */
2411   template<typename _Protocol, typename _EndpointSequence,
2412            typename _ConnectCondition, typename _CompletionToken>
2413     inline
2414     __deduced_t<_CompletionToken,
2415                 void(error_code, typename _Protocol::endpoint)>
2416     async_connect(basic_socket<_Protocol>& __s,
2417                   const _EndpointSequence& __endpoints,
2418                   _ConnectCondition __c, _CompletionToken&& __token); // TODO
2420   template<typename _Protocol, typename _EndpointSequence,
2421            typename _CompletionToken>
2422     inline
2423     __deduced_t<_CompletionToken,
2424                 void(error_code, typename _Protocol::endpoint)>
2425     async_connect(basic_socket<_Protocol>& __s,
2426                   const _EndpointSequence& __endpoints,
2427                   _CompletionToken&& __token)
2428     {
2429       return net::async_connect(__s, __endpoints,
2430                                 [](auto, auto){ return true; },
2431                                 forward<_CompletionToken>(__token));
2432     }
2434   template<typename _Protocol, typename _InputIterator,
2435            typename _ConnectCondition, typename _CompletionToken>
2436     inline
2437     __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
2438     async_connect(basic_socket<_Protocol>& __s,
2439                   _InputIterator __first, _InputIterator __last,
2440                   _ConnectCondition __c, _CompletionToken&& __token); // TODO
2442   template<typename _Protocol, typename _InputIterator,
2443            typename _CompletionToken>
2444     inline
2445     __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
2446     async_connect(basic_socket<_Protocol>& __s,
2447                   _InputIterator __first, _InputIterator __last,
2448                   _CompletionToken&& __token)
2449     {
2450       return net::async_connect(__s, __first, __last,
2451                                 [](auto, auto){ return true; },
2452                                 forward<_CompletionToken>(__token));
2453     }
2455   // @}
2457 #endif  // _GLIBCXX_HAVE_UNISTD_H
2459   // @}
2461 _GLIBCXX_END_NAMESPACE_VERSION
2462 } // namespace v1
2463 } // namespace net
2464 } // namespace experimental
2466   template<>
2467     struct is_error_code_enum<experimental::net::v1::socket_errc>
2468     : public true_type {};
2470 } // namespace std
2472 #endif // C++14
2474 #endif // _GLIBCXX_EXPERIMENTAL_SOCKET