1 // <experimental/socket> -*- C++ -*-
3 // Copyright (C) 2015-2019 Free Software Foundation, Inc.
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)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file experimental/socket
26 * This is a TS C++ Library header.
27 * @ingroup networking-ts
30 #ifndef _GLIBCXX_EXPERIMENTAL_SOCKET
31 #define _GLIBCXX_EXPERIMENTAL_SOCKET
33 #pragma GCC system_header
35 #if __cplusplus >= 201402L
37 #include <experimental/netfwd>
38 #include <experimental/buffer>
39 #include <experimental/io_context>
40 #include <experimental/bits/net.h>
43 #include <bits/unique_ptr.h>
44 #if _GLIBCXX_HAVE_UNISTD_H
46 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
47 # include <sys/socket.h> // socket etc
49 # ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
50 # include <sys/ioctl.h> // ioctl
52 # ifdef _GLIBCXX_HAVE_SYS_UIO_H
53 # include <sys/uio.h> // iovec
55 # ifdef _GLIBCXX_HAVE_POLL_H
56 # include <poll.h> // poll, pollfd, POLLIN, POLLOUT, POLLERR
58 # ifdef _GLIBCXX_HAVE_FCNTL_H
59 # include <fcntl.h> // fcntl, F_GETFL, F_SETFL
63 namespace std _GLIBCXX_VISIBILITY(default)
65 _GLIBCXX_BEGIN_NAMESPACE_VERSION
66 namespace experimental
73 /** @addtogroup networking-ts
77 enum class socket_errc { // TODO decide values
82 const error_category& socket_category() noexcept
84 struct __cat : error_category
86 const char* name() const noexcept { return "socket"; }
88 std::string message(int __e) const
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";
97 virtual void __message(int) { } // TODO dual ABI XXX
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
115 // Check Endpoint requirements.
116 template<typename _Tp>
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>
124 __void_t< typename _Tp::protocol_type::endpoint >>;
126 template<typename _Tp>
127 struct __is_endpoint_impl<_Tp, decltype(__endpoint_reqs<_Tp>())>
131 template<typename _Tp>
132 struct __is_endpoint : __is_endpoint_impl<_Tp>
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
152 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
153 struct broadcast : __sockopt_crtp<broadcast, bool>
155 using __sockopt_crtp::__sockopt_crtp;
157 static const int _S_level = SOL_SOCKET;
158 static const int _S_name = SO_BROADCAST;
161 struct debug : __sockopt_crtp<debug, bool>
163 using __sockopt_crtp::__sockopt_crtp;
165 static const int _S_level = SOL_SOCKET;
166 static const int _S_name = SO_DEBUG;
169 struct do_not_route : __sockopt_crtp<do_not_route, bool>
171 using __sockopt_crtp::__sockopt_crtp;
173 static const int _S_level = SOL_SOCKET;
174 static const int _S_name = SO_DONTROUTE;
177 struct keep_alive : __sockopt_crtp<keep_alive, bool>
179 using __sockopt_crtp::__sockopt_crtp;
181 static const int _S_level = SOL_SOCKET;
182 static const int _S_name = SO_KEEPALIVE;
185 struct linger : __sockopt_crtp<linger, ::linger>
187 using __sockopt_crtp::__sockopt_crtp;
189 linger() noexcept = default;
191 linger(bool __e, chrono::seconds __t) noexcept
198 enabled() const noexcept
199 { return _M_value.l_onoff != 0; }
202 enabled(bool __e) noexcept
203 { _M_value.l_onoff = int(__e); }
206 timeout() const noexcept
207 { return chrono::seconds(_M_value.l_linger); }
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;
217 struct out_of_band_inline : __sockopt_crtp<out_of_band_inline, bool>
219 using __sockopt_crtp::__sockopt_crtp;
221 static const int _S_level = SOL_SOCKET;
222 static const int _S_name = SO_OOBINLINE;
225 struct receive_buffer_size : __sockopt_crtp<receive_buffer_size>
227 using __sockopt_crtp::__sockopt_crtp;
229 static const int _S_level = SOL_SOCKET;
230 static const int _S_name = SO_RCVBUF;
233 struct receive_low_watermark : __sockopt_crtp<receive_low_watermark>
235 using __sockopt_crtp::__sockopt_crtp;
237 static const int _S_level = SOL_SOCKET;
238 static const int _S_name = SO_RCVLOWAT;
241 struct reuse_address : __sockopt_crtp<reuse_address, bool>
243 using __sockopt_crtp::__sockopt_crtp;
245 static const int _S_level = SOL_SOCKET;
246 static const int _S_name = SO_REUSEADDR;
249 struct send_buffer_size : __sockopt_crtp<send_buffer_size>
251 using __sockopt_crtp::__sockopt_crtp;
253 static const int _S_level = SOL_SOCKET;
254 static const int _S_name = SO_SNDBUF;
257 struct send_low_watermark : __sockopt_crtp<send_low_watermark>
259 using __sockopt_crtp::__sockopt_crtp;
261 static const int _S_level = SOL_SOCKET;
262 static const int _S_name = SO_SNDLOWAT;
265 enum shutdown_type : int
267 __shutdown_receive = SHUT_RD,
268 __shutdown_send = SHUT_WR,
269 __shutdown_both = SHUT_RDWR
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
278 __wait_read = POLLIN,
279 __wait_write = POLLOUT,
280 __wait_error = POLLERR
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;
287 enum message_flags : int
289 __message_peek = MSG_PEEK,
290 __message_oob = MSG_OOB,
291 __message_dontroute = MSG_DONTROUTE
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;
301 socket_base() = default;
302 ~socket_base() = default;
304 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
305 struct __msg_hdr : ::msghdr
308 using __iovec_array = array<::iovec, IOV_MAX>;
309 #elif _GLIBCXX_HAVE_UNISTD_H
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(); }
320 static const size_t __iov_max = ::sysconf(_SC_IOV_MAX);
325 unique_ptr<::iovec[]> _M_ptr;
328 using __iovec_array = array<::iovec, 16>;
331 __iovec_array _M_iov;
333 template<typename _BufferSequence>
335 __msg_hdr(const _BufferSequence& __buffers)
338 auto __buf = net::buffer_sequence_begin(__buffers);
339 const auto __bufend = net::buffer_sequence_end(__buffers);
341 while (__buf != __bufend && __len != _M_iov.size())
343 _M_iov[__len].iov_base = (void*)__buf->data();
344 _M_iov[__len].iov_len = __buf->size();
348 this->msg_iovlen = __len;
349 this->msg_iov = _M_iov.data();
352 template<typename _BufferSequence, typename _Endpoint>
353 __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep)
354 : __msg_hdr(__buffers)
356 this->msg_name = __ep.data();
357 this->msg_namelen = __ep.size();
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
397 using executor_type = io_context::executor_type;
398 using native_handle_type = int;
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, {}))
410 operator=(__socket_impl&& __rhs)
412 _M_ctx = __rhs._M_ctx;
413 _M_sockfd = std::exchange(__rhs._M_sockfd, -1);
414 _M_bits = std::exchange(__rhs._M_bits, {});
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; }
430 close(error_code& __ec)
437 if (::close(_M_sockfd) == -1)
438 __ec.assign(errno, generic_category());
441 get_executor().context()._M_remove_fd(_M_sockfd);
448 void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); }
451 non_blocking(bool __mode, error_code&)
452 { _M_bits.non_blocking = __mode; }
454 bool non_blocking() const { return _M_bits.non_blocking; }
457 native_non_blocking(bool __mode, error_code& __ec)
459 #ifdef _GLIBCXX_HAVE_FCNTL_H
460 int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
464 __flags |= O_NONBLOCK;
466 __flags &= ~O_NONBLOCK;
467 __flags = ::fcntl(_M_sockfd, F_SETFL, __flags);
470 __ec.assign(errno, generic_category());
474 _M_bits.native_non_blocking = __mode;
477 __ec = std::make_error_code(std::errc::not_supported);
482 native_non_blocking() const
484 #ifdef _GLIBCXX_HAVE_FCNTL_H
485 if (_M_bits.native_non_blocking == -1)
487 const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
490 _M_bits.native_non_blocking = __flags & O_NONBLOCK;
492 return _M_bits.native_non_blocking;
501 unsigned non_blocking : 1;
502 mutable signed native_non_blocking : 2;
503 unsigned enable_connection_aborted : 1;
507 template<typename _Protocol>
508 class __basic_socket_impl : public __socket_impl
510 using __base = __socket_impl;
513 using protocol_type = _Protocol;
514 using endpoint_type = typename protocol_type::endpoint;
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))
527 operator=(__basic_socket_impl&& __rhs)
529 if (this == std::addressof(__rhs))
532 __base::operator=(std::move(__rhs));
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;
542 open(const protocol_type& __protocol, error_code& __ec)
544 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
546 __ec = socket_errc::already_open;
549 _M_protocol = __protocol;
550 _M_sockfd = ::socket(__protocol.family(), __protocol.type(),
551 __protocol.protocol());
554 get_executor().context()._M_add_fd(_M_sockfd);
558 __ec.assign(errno, std::generic_category());
561 __ec = std::make_error_code(errc::operation_not_supported);
566 assign(const protocol_type& __protocol,
567 const native_handle_type& __native_socket,
571 __ec = socket_errc::already_open;
574 _M_protocol = __protocol;
575 _M_bits.native_non_blocking = -1;
576 _M_sockfd = __native_socket;
579 get_executor().context()._M_add_fd(_M_sockfd);
583 __ec.assign(errno, std::generic_category());
587 template<typename _SettableSocketOption>
589 set_option(const _SettableSocketOption& __option, error_code& __ec)
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));
596 __ec.assign(errno, generic_category());
601 template<typename _GettableSocketOption>
603 get_option(_GettableSocketOption& __option, error_code& __ec) const
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));
610 __ec.assign(errno, generic_category());
615 template<typename _IoControlCommand>
617 io_control(_IoControlCommand& __command, error_code& __ec)
619 #ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
620 int __result = ::ioctl(_M_sockfd, __command.name(),
623 __ec.assign(errno, generic_category());
627 __ec = std::make_error_code(std::errc::not_supported);
632 local_endpoint(error_code& __ec) const
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)
640 __ec.assign(errno, generic_category());
641 return endpoint_type{};
644 __endpoint.resize(__endpoint_len);
646 __ec = std::make_error_code(errc::operation_not_supported);
652 bind(const endpoint_type& __endpoint, error_code& __ec)
654 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
655 if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size())
657 __ec.assign(errno, generic_category());
661 __ec = std::make_error_code(errc::operation_not_supported);
665 _Protocol _M_protocol{ endpoint_type{}.protocol() };
675 set_option(socket_base::linger{false, chrono::seconds{}}, __ec);
681 template<typename _Protocol>
683 : public socket_base, private __basic_socket_impl<_Protocol>
685 using __base = __basic_socket_impl<_Protocol>;
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(); }
700 native_handle() noexcept { return __base::native_handle(); }
703 open(const protocol_type& __protocol = protocol_type())
704 { open(__protocol, __throw_on_error{"basic_socket::open"}); }
707 open(const protocol_type& __protocol, error_code& __ec)
708 { __base::open(__protocol, __ec); }
711 assign(const protocol_type& __protocol,
712 const native_handle_type& __native_socket)
714 assign(__protocol, __native_socket,
715 __throw_on_error{"basic_socket::assign"});
719 assign(const protocol_type& __protocol,
720 const native_handle_type& __native_socket,
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>
736 set_option(const _SettableSocketOption& __option)
737 { set_option(__option, __throw_on_error{"basic_socket::set_option"}); }
739 template<typename _SettableSocketOption>
741 set_option(const _SettableSocketOption& __option, error_code& __ec)
742 { __base::set_option(__option, __ec); }
744 template<typename _GettableSocketOption>
746 get_option(_GettableSocketOption& __option) const
747 { get_option(__option, __throw_on_error{"basic_socket::get_option"}); }
749 template<typename _GettableSocketOption>
751 get_option(_GettableSocketOption& __option, error_code& __ec) const
752 { __base::get_option(__option, __ec); }
754 template<typename _IoControlCommand>
756 io_control(_IoControlCommand& __command)
758 io_control(__command, __throw_on_error{"basic_socket::io_control"});
761 template<typename _IoControlCommand>
763 io_control(_IoControlCommand& __command, error_code& __ec)
764 { __base::io_control(__command, __ec); }
767 non_blocking(bool __mode)
768 { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); }
771 non_blocking(bool __mode, error_code& __ec)
772 { __base::non_blocking(__mode, __ec); }
774 bool non_blocking() const { return __base::non_blocking(); }
777 native_non_blocking(bool __mode)
779 native_non_blocking(__mode, __throw_on_error{
780 "basic_socket::native_non_blocking"});
784 native_non_blocking(bool __mode, error_code& __ec)
785 { __base::native_non_blocking(__mode, __ec); }
788 native_non_blocking() const
789 { return __base::native_non_blocking(); }
792 { return at_mark(__throw_on_error{"basic_socket::at_mark"}); }
795 at_mark(error_code& __ec) const
797 #ifdef _GLIBCXX_HAVE_SOCKATMARK
798 const int __result = ::sockatmark(native_handle());
801 __ec.assign(errno, generic_category());
805 return (bool)__result;
807 __ec = std::make_error_code(errc::operation_not_supported);
814 { return available(__throw_on_error{"basic_socket::available"}); }
817 available(error_code& __ec) const
821 __ec = std::make_error_code(errc::bad_file_descriptor);
824 #if defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined FIONREAD
826 if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1)
828 __ec.assign(errno, generic_category());
839 bind(const endpoint_type& __endpoint)
840 { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); }
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"}); }
850 shutdown(shutdown_type __what, error_code& __ec)
852 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
853 if (::shutdown(native_handle(), static_cast<int>(__what)) == -1)
854 __ec.assign(errno, generic_category());
858 __ec = std::make_error_code(errc::operation_not_supported);
863 local_endpoint() const
865 return local_endpoint(
866 __throw_on_error{"basic_socket::local_endpoint"});
870 local_endpoint(error_code& __ec) const
871 { return __base::local_endpoint(__ec); }
874 remote_endpoint() const
876 return remote_endpoint(
877 __throw_on_error{"basic_socket::remote_endpoint"});
881 remote_endpoint(error_code& __ec) const
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(),
890 __ec.assign(errno, generic_category());
891 return endpoint_type{};
894 __endpoint.resize(__endpoint_len);
896 __ec = std::make_error_code(errc::operation_not_supported);
902 connect(const endpoint_type& __endpoint)
904 return connect(__endpoint, __throw_on_error{"basic_socket::connect"});
908 connect(const endpoint_type& __endpoint, error_code& __ec)
912 open(__endpoint.protocol(), __ec);
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());
923 __ec = std::make_error_code(errc::operation_not_supported);
927 template<typename _CompletionToken>
928 __deduced_t<_CompletionToken, void(error_code)>
929 async_connect(const endpoint_type& __endpoint,
930 _CompletionToken&& __token)
932 async_completion<_CompletionToken, void(error_code)> __init{__token};
937 open(__endpoint.protocol(), __ec);
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>());
945 [__h=std::move(__init.completion_handler), __ec]
947 { __h(__ec); }, __a);
948 return __init.result.get();
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(),
961 __ec.assign(errno, generic_category());
963 __ec = std::make_error_code(errc::operation_not_supported);
967 return __init.result.get();
972 { return wait(__w, __throw_on_error{"basic_socket::wait"}); }
975 wait(wait_type __w, error_code& __ec)
977 #ifdef _GLIBCXX_HAVE_POLL_H
979 __fd.fd = native_handle();
980 __fd.events = static_cast<int>(__w);
981 int __res = ::poll(&__fd, 1, -1);
983 __ec.assign(errno, generic_category());
987 __ec = std::make_error_code(errc::operation_not_supported);
991 template<typename _CompletionToken>
992 __deduced_t<_CompletionToken, void(error_code)>
993 async_wait(wait_type __w, _CompletionToken&& __token)
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 {
1002 return __init.result.get();
1006 // construct / copy / destroy:
1008 using __base::__base;
1011 basic_socket(io_context& __ctx) : __base(__ctx) { }
1013 basic_socket(io_context& __ctx, const protocol_type& __protocol)
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)
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,
1044 operator=(basic_socket<_OtherProtocol>&& __rhs)
1045 { return *this = basic_socket{std::move(__rhs)}; }
1048 template<typename _Protocol>
1049 class basic_datagram_socket : public basic_socket<_Protocol>
1051 using __base = basic_socket<_Protocol>;
1056 typedef int native_handle_type;
1057 typedef _Protocol protocol_type;
1058 typedef typename protocol_type::endpoint endpoint_type;
1060 // construct / copy / destroy:
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)
1095 __base::operator=(std::move(__rhs));
1099 // basic_datagram_socket operations:
1101 template<typename _MutableBufferSequence>
1103 receive(const _MutableBufferSequence& __buffers)
1105 return receive(__buffers, socket_base::message_flags(),
1106 __throw_on_error{"basic_datagram_socket::receive"});
1109 template<typename _MutableBufferSequence>
1111 receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1112 { return receive(__buffers, socket_base::message_flags(), __ec); }
1114 template<typename _MutableBufferSequence>
1116 receive(const _MutableBufferSequence& __buffers,
1117 socket_base::message_flags __flags)
1119 return receive(__buffers, __flags,
1120 __throw_on_error{"basic_datagram_socket::receive"});
1123 template<typename _MutableBufferSequence>
1125 receive(const _MutableBufferSequence& __buffers,
1126 socket_base::message_flags __flags, error_code& __ec)
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));
1134 __ec.assign(errno, generic_category());
1140 __ec = std::make_error_code(errc::operation_not_supported);
1145 template<typename _MutableBufferSequence, typename _CompletionToken>
1146 __deduced_t<_CompletionToken, void(error_code, size_t)>
1147 async_receive(const _MutableBufferSequence& __buffers,
1148 _CompletionToken&& __token)
1150 return async_receive(__buffers, socket_base::message_flags(),
1151 std::forward<_CompletionToken>(__token));
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)
1160 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1174 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1175 socket_base::__msg_hdr __msg(__buffers);
1176 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1179 __ec.assign(errno, generic_category());
1184 __h(__ec, __result);
1186 __h(std::make_error_code(errc::operation_not_supported), 0);
1189 return __init.result.get();
1192 template<typename _MutableBufferSequence>
1194 receive_from(const _MutableBufferSequence& __buffers,
1195 endpoint_type& __sender)
1197 return receive_from(__buffers, __sender,
1198 socket_base::message_flags(),
1200 "basic_datagram_socket::receive_from"});
1203 template<typename _MutableBufferSequence>
1205 receive_from(const _MutableBufferSequence& __buffers,
1206 endpoint_type& __sender, error_code& __ec)
1208 return receive_from(__buffers, __sender,
1209 socket_base::message_flags(), __ec);
1212 template<typename _MutableBufferSequence>
1214 receive_from(const _MutableBufferSequence& __buffers,
1215 endpoint_type& __sender,
1216 socket_base::message_flags __flags)
1218 return receive_from(__buffers, __sender, __flags,
1220 "basic_datagram_socket::receive_from"});
1223 template<typename _MutableBufferSequence>
1225 receive_from(const _MutableBufferSequence& __buffers,
1226 endpoint_type& __sender,
1227 socket_base::message_flags __flags,
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));
1236 __ec.assign(errno, generic_category());
1240 __sender.resize(__msg.msg_namelen);
1243 __ec = std::make_error_code(errc::operation_not_supported);
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)
1254 return async_receive_from(__buffers, __sender,
1255 socket_base::message_flags(),
1256 std::forward<_CompletionToken>(__token));
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)
1266 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1281 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1282 socket_base::__msg_hdr __msg(__buffers, __sender);
1283 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1286 __ec.assign(errno, generic_category());
1292 __sender.resize(__msg.msg_namelen);
1294 __h(__ec, __result);
1296 __h(std::make_error_code(errc::operation_not_supported), 0);
1299 return __init.result.get();
1302 template<typename _ConstBufferSequence>
1304 send(const _ConstBufferSequence& __buffers)
1306 return send(__buffers, socket_base::message_flags(),
1307 __throw_on_error{"basic_datagram_socket::send"});
1310 template<typename _ConstBufferSequence>
1312 send(const _ConstBufferSequence& __buffers, error_code& __ec)
1313 { return send(__buffers, socket_base::message_flags(), __ec); }
1315 template<typename _ConstBufferSequence>
1317 send(const _ConstBufferSequence& __buffers,
1318 socket_base::message_flags __flags)
1320 return send(__buffers, __flags,
1321 __throw_on_error{"basic_datagram_socket::send"});
1324 template<typename _ConstBufferSequence>
1326 send(const _ConstBufferSequence& __buffers,
1327 socket_base::message_flags __flags, error_code& __ec)
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));
1335 __ec.assign(errno, generic_category());
1341 __ec = std::make_error_code(errc::operation_not_supported);
1346 template<typename _ConstBufferSequence, typename _CompletionToken>
1347 __deduced_t<_CompletionToken, void(error_code, size_t)>
1348 async_send(const _ConstBufferSequence& __buffers,
1349 _CompletionToken&& __token)
1351 return async_send(__buffers, socket_base::message_flags(),
1352 std::forward<_CompletionToken>(__token));
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)
1361 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1375 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1376 socket_base::__msg_hdr __msg(__buffers);
1377 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1380 __ec.assign(errno, generic_category());
1385 __h(__ec, __result);
1387 __h(std::make_error_code(errc::operation_not_supported), 0);
1390 return __init.result.get();
1393 template<typename _ConstBufferSequence>
1395 send_to(const _ConstBufferSequence& __buffers,
1396 const endpoint_type& __recipient)
1398 return send_to(__buffers, __recipient,
1399 socket_base::message_flags(),
1400 __throw_on_error{"basic_datagram_socket::send_to"});
1403 template<typename _ConstBufferSequence>
1405 send_to(const _ConstBufferSequence& __buffers,
1406 const endpoint_type& __recipient, error_code& __ec)
1408 return send_to(__buffers, __recipient,
1409 socket_base::message_flags(), __ec);
1412 template<typename _ConstBufferSequence>
1414 send_to(const _ConstBufferSequence& __buffers,
1415 const endpoint_type& __recipient,
1416 socket_base::message_flags __flags)
1418 return send_to(__buffers, __recipient, __flags,
1419 __throw_on_error{"basic_datagram_socket::send_to"});
1422 template<typename _ConstBufferSequence>
1424 send_to(const _ConstBufferSequence& __buffers,
1425 const endpoint_type& __recipient,
1426 socket_base::message_flags __flags, error_code& __ec)
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));
1434 __ec.assign(errno, generic_category());
1438 __recipient.resize(__msg.msg_namelen);
1441 __ec = std::make_error_code(errc::operation_not_supported);
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)
1452 return async_send_to(__buffers, __recipient,
1453 socket_base::message_flags(),
1454 std::forward<_CompletionToken>(__token));
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)
1464 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1479 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1480 socket_base::__msg_hdr __msg(__buffers, __recipient);
1481 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1484 __ec.assign(errno, generic_category());
1490 __recipient.resize(__msg.msg_namelen);
1492 __h(__ec, __result);
1494 __h(std::make_error_code(errc::operation_not_supported), 0);
1497 return __init.result.get();
1501 template<typename _Protocol>
1502 class basic_stream_socket : public basic_socket<_Protocol>
1504 using __base = basic_socket<_Protocol>;
1509 typedef int native_handle_type;
1510 typedef _Protocol protocol_type;
1511 typedef typename protocol_type::endpoint endpoint_type;
1513 // construct / copy / destroy:
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)
1548 __base::operator=(std::move(__rhs));
1552 // basic_stream_socket operations:
1554 template<class _MutableBufferSequence>
1556 receive(const _MutableBufferSequence& __buffers)
1558 return receive(__buffers, socket_base::message_flags(),
1559 __throw_on_error{"basic_stream_socket::receive"});
1562 template<class _MutableBufferSequence>
1564 receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1565 { return receive(__buffers, socket_base::message_flags(), __ec); }
1567 template<class _MutableBufferSequence>
1569 receive(const _MutableBufferSequence& __buffers,
1570 socket_base::message_flags __flags)
1572 return receive(__buffers, __flags,
1573 __throw_on_error{"basic_stream_socket::receive"});
1576 template<class _MutableBufferSequence>
1578 receive(const _MutableBufferSequence& __buffers,
1579 socket_base::message_flags __flags, error_code& __ec)
1581 if (__buffer_empty(__buffers))
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));
1595 __ec.assign(errno, generic_category());
1597 __ec = std::make_error_code(errc::operation_not_supported);
1602 template<class _MutableBufferSequence, class _CompletionToken>
1603 __deduced_t<_CompletionToken, void(error_code, size_t)>
1604 async_receive(const _MutableBufferSequence& __buffers,
1605 _CompletionToken&& __token)
1607 return async_receive(__buffers, socket_base::message_flags(),
1608 std::forward<_CompletionToken>(__token));
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)
1617 async_completion<_CompletionToken, void(error_code, size_t)>
1620 if (__buffer_empty(__buffers))
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>());
1627 [__h=std::move(__init.completion_handler)] () mutable
1628 { __h(error_code{}, 0); }, __a);
1629 return __init.result.get();
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 {
1643 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1644 socket_base::__msg_hdr __msg(__buffers);
1645 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1648 __ec.assign(errno, generic_category());
1653 __h(__ec, __result);
1655 __h(std::make_error_code(errc::operation_not_supported), 0);
1658 return __init.result.get();
1661 template<class _ConstBufferSequence>
1663 send(const _ConstBufferSequence& __buffers)
1665 return send(__buffers, socket_base::message_flags(),
1666 __throw_on_error{"basic_stream_socket::send"});
1669 template<class _ConstBufferSequence>
1671 send(const _ConstBufferSequence& __buffers, error_code& __ec)
1672 { return send(__buffers, socket_base::message_flags(), __ec); }
1674 template<class _ConstBufferSequence>
1676 send(const _ConstBufferSequence& __buffers,
1677 socket_base::message_flags __flags)
1679 return send(__buffers, socket_base::message_flags(),
1680 __throw_on_error{"basic_stream_socket::send"});
1683 template<class _ConstBufferSequence>
1685 send(const _ConstBufferSequence& __buffers,
1686 socket_base::message_flags __flags, error_code& __ec)
1688 if (__buffer_empty(__buffers))
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));
1702 __ec.assign(errno, generic_category());
1704 __ec = std::make_error_code(errc::operation_not_supported);
1709 template<class _ConstBufferSequence, class _CompletionToken>
1710 __deduced_t<_CompletionToken, void(error_code, size_t)>
1711 async_send(const _ConstBufferSequence& __buffers,
1712 _CompletionToken&& __token)
1714 return async_send(__buffers, socket_base::message_flags(),
1715 std::forward<_CompletionToken>(__token));
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)
1724 async_completion<_CompletionToken, void(error_code, size_t)>
1727 if (__buffer_empty(__buffers))
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>());
1734 [__h=std::move(__init.completion_handler)] () mutable
1735 { __h(error_code{}, 0); }, __a);
1736 return __init.result.get();
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 {
1750 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1751 socket_base::__msg_hdr __msg(__buffers);
1752 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1755 __ec.assign(errno, generic_category());
1760 __h(__ec, __result);
1762 __h(std::make_error_code(errc::operation_not_supported), 0);
1765 return __init.result.get();
1768 template<class _MutableBufferSequence>
1770 read_some(const _MutableBufferSequence& __buffers)
1772 return receive(__buffers,
1773 __throw_on_error{"basic_stream_socket::read_some"});
1776 template<class _MutableBufferSequence>
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)
1786 return async_receive(__buffers,
1787 std::forward<_CompletionToken>(__token));
1790 template<class _ConstBufferSequence>
1792 write_some(const _ConstBufferSequence& __buffers)
1794 return send(__buffers,
1795 __throw_on_error{"basic_stream_socket:write_some"});
1798 template<class _ConstBufferSequence>
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)
1808 return async_send(__buffers,
1809 std::forward<_CompletionToken>(__token));
1813 template<typename _AcceptableProtocol>
1814 class basic_socket_acceptor
1815 : public socket_base, private __basic_socket_impl<_AcceptableProtocol>
1817 using __base = __basic_socket_impl<_AcceptableProtocol>;
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:
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())
1844 set_option(reuse_address(true));
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)
1874 __base::operator=(std::move(__rhs));
1878 // basic_socket_acceptor operations:
1880 executor_type get_executor() noexcept { return __base::get_executor(); }
1883 native_handle() noexcept { return __base::native_handle(); }
1886 open(const protocol_type& __protocol = protocol_type())
1887 { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); }
1890 open(const protocol_type& __protocol, error_code& __ec)
1891 { __base::open(__protocol, __ec); }
1894 assign(const protocol_type& __protocol,
1895 const native_handle_type& __native_acceptor)
1897 assign(__protocol, __native_acceptor,
1898 __throw_on_error{"basic_socket_acceptor::assign"});
1902 assign(const protocol_type& __protocol,
1903 const native_handle_type& __native_acceptor,
1905 { __base::assign(__protocol, __native_acceptor, __ec); }
1908 is_open() const noexcept { return __base::is_open(); }
1911 close() { close(__throw_on_error{"basic_socket_acceptor::close"}); }
1914 close(error_code& __ec) { __base::_close(__ec); }
1917 cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); }
1920 cancel(error_code& __ec) { __base::cancel(__ec); }
1922 template<typename _SettableSocketOption>
1924 set_option(const _SettableSocketOption& __option)
1926 set_option(__option,
1927 __throw_on_error{"basic_socket_acceptor::set_option"});
1930 template<typename _SettableSocketOption>
1932 set_option(const _SettableSocketOption& __option, error_code& __ec)
1933 { __base::set_option(__option, __ec); }
1935 template<typename _GettableSocketOption>
1937 get_option(_GettableSocketOption& __option) const
1939 get_option(__option,
1940 __throw_on_error{"basic_socket_acceptor::get_option"});
1943 template<typename _GettableSocketOption>
1945 get_option(_GettableSocketOption& __option, error_code& __ec) const
1946 { __base::get_option(__option, __ec); }
1948 template<typename _IoControlCommand>
1950 io_control(_IoControlCommand& __command)
1952 io_control(__command,
1953 __throw_on_error{"basic_socket_acceptor::io_control"});
1956 template<typename _IoControlCommand>
1958 io_control(_IoControlCommand& __command, error_code& __ec)
1959 { __base::io_control(__command, __ec); }
1962 non_blocking(bool __mode)
1964 non_blocking(__mode,
1965 __throw_on_error{"basic_socket_acceptor::non_blocking"});
1969 non_blocking(bool __mode, error_code& __ec)
1970 { __base::non_blocking(__mode, __ec); }
1972 bool non_blocking() const { return __base::non_blocking(); }
1975 native_non_blocking(bool __mode)
1977 native_non_blocking(__mode, __throw_on_error{
1978 "basic_socket_acceptor::native_non_blocking"});
1982 native_non_blocking(bool __mode, error_code& __ec)
1983 { __base::native_non_blocking(__mode, __ec); }
1986 native_non_blocking() const
1987 { return __base::native_non_blocking(); }
1990 bind(const endpoint_type& __endpoint)
1992 return bind(__endpoint,
1993 __throw_on_error{"basic_socket_acceptor::bind"});
1997 bind(const endpoint_type& __endpoint, error_code& __ec)
1998 { __base::bind(__endpoint, __ec); }
2001 listen(int __backlog = max_listen_connections)
2003 return listen(__backlog,
2004 __throw_on_error{"basic_socket_acceptor::listen"});
2008 listen(int __backlog, error_code& __ec)
2010 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2011 if (::listen(native_handle(), __backlog) == -1)
2012 __ec.assign(errno, generic_category());
2016 __ec = std::make_error_code(errc::operation_not_supported);
2021 local_endpoint() const
2023 return local_endpoint(
2024 __throw_on_error{"basic_socket_acceptor::local_endpoint"});
2028 local_endpoint(error_code& __ec) const
2029 { return __base::local_endpoint(__ec); }
2032 enable_connection_aborted(bool __mode)
2033 { __base::_M_bits.enable_connection_aborted = __mode; }
2036 enable_connection_aborted() const
2037 { return __base::_M_bits.enable_connection_aborted; }
2041 { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); }
2044 accept(error_code& __ec)
2045 { return accept(get_executor().context(), __ec); }
2047 socket_type accept(io_context& __ctx)
2049 return accept(__ctx,
2050 __throw_on_error{"basic_socket_acceptor::accept"});
2054 accept(io_context& __ctx, error_code& __ec)
2056 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2059 int __h = ::accept(native_handle(), nullptr, 0);
2063 return socket_type{__ctx, _M_protocol, __h};
2065 } while (errno == ECONNABORTED && enable_connection_aborted());
2066 __ec.assign(errno, generic_category());
2068 __ec = std::make_error_code(errc::operation_not_supported);
2070 return socket_type{__ctx};
2073 template<class _CompletionToken>
2074 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2075 async_accept(_CompletionToken&& __token)
2077 return async_accept(get_executor().context(),
2078 std::forward<_CompletionToken>(__token));
2081 template<class _CompletionToken>
2082 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2083 async_accept(io_context& __ctx, _CompletionToken&& __token)
2085 async_completion<_CompletionToken, void(error_code, socket_type)>
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,
2096 (error_code __ec) mutable {
2099 __h(__ec, socket_type(__ctx));
2102 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2105 int __newfd = ::accept(__fd, nullptr, 0);
2109 __h(__ec, socket_type{__ctx, __protocol, __newfd});
2112 } while (errno == ECONNABORTED && __connabort);
2113 __ec.assign(errno, generic_category());
2114 __h(__ec, socket_type(__ctx));
2116 __h(std::make_error_code(errc::operation_not_supported), 0);
2119 return __init.result.get();
2123 accept(endpoint_type& __endpoint)
2125 return accept(get_executor().context(), __endpoint,
2126 __throw_on_error{"basic_socket_acceptor::accept"});
2130 accept(endpoint_type& __endpoint, error_code& __ec)
2131 { return accept(get_executor().context(), __endpoint, __ec); }
2134 accept(io_context& __ctx, endpoint_type& __endpoint)
2136 return accept(__ctx, __endpoint,
2137 __throw_on_error{"basic_socket_acceptor::accept"});
2141 accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec)
2143 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2146 socklen_t __len = __endpoint.capacity();
2147 int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(),
2151 __endpoint.resize(__len);
2152 return socket_type{__ctx, _M_protocol, __h};
2154 } while (errno == ECONNABORTED && enable_connection_aborted());
2155 __ec.assign(errno, generic_category());
2157 __ec = std::make_error_code(errc::operation_not_supported);
2159 return socket_type{__ctx};
2162 template<class _CompletionToken>
2163 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2164 async_accept(endpoint_type& __endpoint,
2165 _CompletionToken&& __token)
2167 return async_accept(get_executor().context(), __endpoint,
2168 std::forward<_CompletionToken>(__token));
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)
2176 async_completion<_CompletionToken, void(error_code, socket_type)>
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(),
2187 (error_code __ec) mutable {
2190 __h(__ec, socket_type(__ctx));
2193 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2196 socklen_t __len = __ep.capacity();
2197 int __newfd = ::accept(__fd, __ep.data, &__len);
2201 auto __protocol = __ep.protocol();
2203 __h(__ec, socket_type{__ctx, __protocol, __newfd});
2206 } while (errno == ECONNABORTED && __connabort);
2207 __ec.assign(errno, generic_category());
2209 __ec = std::make_error_code(errc::operation_not_supported);
2211 __h(__ec, socket_type(__ctx));
2213 return __init.result.get();
2218 { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); }
2221 wait(wait_type __w, error_code& __ec)
2223 #ifdef _GLIBCXX_HAVE_POLL_H
2225 __fds.fd = native_handle();
2226 __fds.events = __w; // __w | POLLIN;
2227 if (::poll(&__fds, 1, -1) == -1)
2228 __ec.assign(errno, generic_category());
2232 __ec = std::make_error_code(errc::operation_not_supported);
2236 template<class _CompletionToken>
2237 __deduced_t<_CompletionToken, void(error_code)>
2238 async_wait(wait_type __w, _CompletionToken&& __token)
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 {
2247 return __init.result.get();
2251 protocol_type _M_protocol;
2256 /** @brief Socket streams
2260 template<typename _Protocol, typename _Clock, typename _WaitTraits>
2261 class basic_socket_streambuf : public basic_streambuf<char>
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()) { }
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
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; }
2307 expires_at(const time_point& __t)
2308 { _M_expiry = __t; }
2311 expires_after(const duration& __d)
2312 { expires_at(clock_type::now() + __d); }
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;
2326 static io_context __ctx;
2330 basic_stream_socket<protocol_type> _M_socket;
2332 time_point _M_expiry{ time_point::max() };
2335 template<typename _Protocol, class _Clock, typename _WaitTraits>
2336 class basic_socket_iostream : public basic_iostream<char>
2338 using __streambuf_type
2339 = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>;
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()
2356 this->init(std::addressof(_M_sb));
2357 this->setf(std::ios::unitbuf);
2361 basic_socket_iostream(basic_stream_socket<protocol_type> __s)
2362 : basic_iostream(nullptr), _M_sb(std::move(__s))
2364 this->init(std::addressof(_M_sb));
2365 this->setf(std::ios::unitbuf);
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))
2374 // XXX ??? this->init(std::addressof(_M_sb));
2375 this->set_rbduf(std::addressof(_M_sb));
2378 template<typename... _Args>
2380 basic_socket_iostream(_Args&&... __args)
2381 : basic_iostream(nullptr), _M_sb()
2383 this->init(std::addressof(_M_sb));
2384 this->setf(std::ios::unitbuf);
2385 connect(forward<_Args>(__args)...);
2388 basic_socket_iostream& operator=(const basic_socket_iostream&) = delete;
2390 basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO
2394 template<typename... _Args>
2396 connect(_Args&&... __args)
2398 if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr)
2399 this->setstate(failbit);
2405 if (rdbuf()->close() == nullptr)
2406 this->setstate(failbit);
2409 basic_socket_streambuf<protocol_type, clock_type, wait_traits_type>*
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); }
2421 __streambuf_type _M_sb;
2426 /** @brief synchronous connect operations
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)
2438 bool __found = false;
2439 for (auto& __ep : __endpoints)
2441 if (__c(__ec, __ep))
2446 __s.open(__ep.protocol(), __ec);
2448 __s.connect(__ep, __ec);
2454 __ec = socket_errc::not_found;
2455 return typename _Protocol::endpoint{};
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)
2466 bool __found = false;
2467 for (auto __i = __first; __i != __last; ++__i)
2469 if (__c(__ec, *__i))
2474 __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec);
2476 __s.connect(*__i, __ec);
2482 __ec = socket_errc::not_found;
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)
2493 return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"});
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)
2503 return net::connect(__s, __first, __last, __c,
2504 __throw_on_error{"connect"});
2507 template<typename _Protocol, typename _EndpointSequence>
2508 inline typename _Protocol::endpoint
2509 connect(basic_socket<_Protocol>& __s,
2510 const _EndpointSequence& __endpoints)
2512 return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2513 __throw_on_error{"connect"});
2516 template<typename _Protocol, typename _EndpointSequence>
2517 inline typename _Protocol::endpoint
2518 connect(basic_socket<_Protocol>& __s,
2519 const _EndpointSequence& __endpoints,
2522 return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2526 template<typename _Protocol, typename _InputIterator>
2527 inline _InputIterator
2528 connect(basic_socket<_Protocol>& __s,
2529 _InputIterator __first, _InputIterator __last)
2531 return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2532 __throw_on_error{"connect"});
2535 template<typename _Protocol, typename _InputIterator>
2536 inline _InputIterator
2537 connect(basic_socket<_Protocol>& __s,
2538 _InputIterator __first, _InputIterator __last,
2541 return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2547 /** @brief asynchronous connect operations
2551 template<typename _Protocol, typename _EndpointSequence,
2552 typename _ConnectCondition, typename _CompletionToken>
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>
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)
2569 return net::async_connect(__s, __endpoints,
2570 [](auto, auto){ return true; },
2571 forward<_CompletionToken>(__token));
2574 template<typename _Protocol, typename _InputIterator,
2575 typename _ConnectCondition, typename _CompletionToken>
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>
2585 __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
2586 async_connect(basic_socket<_Protocol>& __s,
2587 _InputIterator __first, _InputIterator __last,
2588 _CompletionToken&& __token)
2590 return net::async_connect(__s, __first, __last,
2591 [](auto, auto){ return true; },
2592 forward<_CompletionToken>(__token));
2597 #endif // _GLIBCXX_HAVE_UNISTD_H
2603 } // namespace experimental
2606 struct is_error_code_enum<experimental::net::v1::socket_errc>
2607 : public true_type {};
2609 _GLIBCXX_END_NAMESPACE_VERSION
2614 #endif // _GLIBCXX_EXPERIMENTAL_SOCKET