1 // <experimental/socket> -*- C++ -*-
3 // Copyright (C) 2015-2018 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.
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>
42 #include <bits/unique_ptr.h>
43 #if _GLIBCXX_HAVE_UNISTD_H
45 # include <sys/socket.h>
46 # include <sys/ioctl.h>
47 # include <sys/fcntl.h>
52 namespace std _GLIBCXX_VISIBILITY(default)
54 namespace experimental
60 _GLIBCXX_BEGIN_NAMESPACE_VERSION
67 enum class socket_errc { // TODO decide values
72 const error_category& socket_category() noexcept
74 struct __cat : error_category
76 const char* name() const noexcept { return "socket"; }
78 std::string message(int __e) const
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";
87 virtual void __message(int) { } // TODO dual ABI XXX
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
105 // Check Endpoint requirements.
106 template<typename _Tp>
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>
114 __void_t< typename _Tp::protocol_type::endpoint >>;
116 template<typename _Tp>
117 struct __is_endpoint_impl<_Tp, decltype(__endpoint_reqs<_Tp>())>
121 template<typename _Tp>
122 struct __is_endpoint : __is_endpoint_impl<_Tp>
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
142 struct broadcast : __sockopt_crtp<broadcast, bool>
144 using __sockopt_crtp::__sockopt_crtp;
146 static const int _S_level = SOL_SOCKET;
147 static const int _S_name = SO_BROADCAST;
150 struct debug : __sockopt_crtp<debug, bool>
152 using __sockopt_crtp::__sockopt_crtp;
154 static const int _S_level = SOL_SOCKET;
155 static const int _S_name = SO_DEBUG;
158 struct do_not_route : __sockopt_crtp<do_not_route, bool>
160 using __sockopt_crtp::__sockopt_crtp;
162 static const int _S_level = SOL_SOCKET;
163 static const int _S_name = SO_DONTROUTE;
166 struct keep_alive : __sockopt_crtp<keep_alive, bool>
168 using __sockopt_crtp::__sockopt_crtp;
170 static const int _S_level = SOL_SOCKET;
171 static const int _S_name = SO_KEEPALIVE;
174 struct linger : __sockopt_crtp<linger, ::linger>
176 using __sockopt_crtp::__sockopt_crtp;
178 linger() noexcept = default;
180 linger(bool __e, chrono::seconds __t) noexcept
187 enabled() const noexcept
188 { return _M_value.l_onoff != 0; }
191 enabled(bool __e) noexcept
192 { _M_value.l_onoff = int(__e); }
195 timeout() const noexcept
196 { return chrono::seconds(_M_value.l_linger); }
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;
206 struct out_of_band_inline : __sockopt_crtp<out_of_band_inline, bool>
208 using __sockopt_crtp::__sockopt_crtp;
210 static const int _S_level = SOL_SOCKET;
211 static const int _S_name = SO_OOBINLINE;
214 struct receive_buffer_size : __sockopt_crtp<receive_buffer_size>
216 using __sockopt_crtp::__sockopt_crtp;
218 static const int _S_level = SOL_SOCKET;
219 static const int _S_name = SO_RCVBUF;
222 struct receive_low_watermark : __sockopt_crtp<receive_low_watermark>
224 using __sockopt_crtp::__sockopt_crtp;
226 static const int _S_level = SOL_SOCKET;
227 static const int _S_name = SO_RCVLOWAT;
230 struct reuse_address : __sockopt_crtp<reuse_address, bool>
232 using __sockopt_crtp::__sockopt_crtp;
234 static const int _S_level = SOL_SOCKET;
235 static const int _S_name = SO_REUSEADDR;
238 struct send_buffer_size : __sockopt_crtp<send_buffer_size>
240 using __sockopt_crtp::__sockopt_crtp;
242 static const int _S_level = SOL_SOCKET;
243 static const int _S_name = SO_SNDBUF;
246 struct send_low_watermark : __sockopt_crtp<send_low_watermark>
248 using __sockopt_crtp::__sockopt_crtp;
250 static const int _S_level = SOL_SOCKET;
251 static const int _S_name = SO_SNDLOWAT;
254 enum shutdown_type : int
256 __shutdown_receive = SHUT_RD,
257 __shutdown_send = SHUT_WR,
258 __shutdown_both = SHUT_RDWR
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;
266 __wait_read = POLLIN,
267 __wait_write = POLLOUT,
268 __wait_error = POLLERR
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
276 __message_peek = MSG_PEEK,
277 __message_oob = MSG_OOB,
278 __message_dontroute = MSG_DONTROUTE
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;
287 socket_base() = default;
288 ~socket_base() = default;
290 struct __msg_hdr : ::msghdr
293 using __iovec_array = array<::iovec, IOV_MAX>;
294 #elif _GLIBCXX_HAVE_UNISTD_H
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(); }
305 static const size_t __iov_max = ::sysconf(_SC_IOV_MAX);
310 unique_ptr<::iovec[]> _M_ptr;
313 using __iovec_array = array<::iovec, 16>;
316 __iovec_array _M_iov;
318 template<typename _BufferSequence>
320 __msg_hdr(const _BufferSequence& __buffers)
323 auto __buf = net::buffer_sequence_begin(__buffers);
324 const auto __bufend = net::buffer_sequence_end(__buffers);
326 while (__buf != __bufend && __len != _M_iov.size())
328 _M_iov[__len].iov_base = (void*)__buf->data();
329 _M_iov[__len].iov_len = __buf->size();
333 this->msg_iovlen = __len;
334 this->msg_iov = _M_iov.data();
337 template<typename _BufferSequence, typename _Endpoint>
338 __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep)
339 : __msg_hdr(__buffers)
341 this->msg_name = __ep.data();
342 this->msg_namelen = __ep.size();
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
381 using executor_type = io_context::executor_type;
382 using native_handle_type = int;
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, {}))
394 operator=(__socket_impl&& __rhs)
396 _M_ctx = __rhs._M_ctx;
397 _M_sockfd = std::exchange(__rhs._M_sockfd, -1);
398 _M_bits = std::exchange(__rhs._M_bits, {});
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; }
414 close(error_code& __ec)
421 if (::close(_M_sockfd) == -1)
422 __ec.assign(errno, generic_category());
425 get_executor().context()._M_remove_fd(_M_sockfd);
432 void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); }
435 non_blocking(bool __mode, error_code&)
436 { _M_bits.non_blocking = __mode; }
438 bool non_blocking() const { return _M_bits.non_blocking; }
441 native_non_blocking(bool __mode, error_code& __ec)
443 int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
447 __flags |= O_NONBLOCK;
449 __flags &= ~O_NONBLOCK;
450 __flags = ::fcntl(_M_sockfd, F_SETFL, __flags);
453 __ec.assign(errno, generic_category());
457 _M_bits.native_non_blocking = __mode;
462 native_non_blocking() const
464 if (_M_bits.native_non_blocking == -1)
466 const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
469 _M_bits.native_non_blocking = __flags & O_NONBLOCK;
471 return _M_bits.native_non_blocking;
477 unsigned non_blocking : 1;
478 mutable signed native_non_blocking : 2;
479 unsigned enable_connection_aborted : 1;
483 template<typename _Protocol>
484 class __basic_socket_impl : public __socket_impl
486 using __base = __socket_impl;
489 using protocol_type = _Protocol;
490 using endpoint_type = typename protocol_type::endpoint;
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))
503 operator=(__basic_socket_impl&& __rhs)
505 if (this == std::addressof(__rhs))
508 __base::operator=(std::move(__rhs));
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;
518 open(const protocol_type& __protocol, error_code& __ec)
521 __ec = socket_errc::already_open;
524 _M_protocol = __protocol;
525 _M_sockfd = ::socket(__protocol.family(), __protocol.type(),
526 __protocol.protocol());
529 get_executor().context()._M_add_fd(_M_sockfd);
533 __ec.assign(errno, std::generic_category());
538 assign(const protocol_type& __protocol,
539 const native_handle_type& __native_socket,
543 __ec = socket_errc::already_open;
546 _M_protocol = __protocol;
547 _M_bits.native_non_blocking = -1;
548 _M_sockfd = __native_socket;
551 get_executor().context()._M_add_fd(_M_sockfd);
555 __ec.assign(errno, std::generic_category());
559 template<typename _SettableSocketOption>
561 set_option(const _SettableSocketOption& __option, error_code& __ec)
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));
568 __ec.assign(errno, generic_category());
573 template<typename _GettableSocketOption>
575 get_option(_GettableSocketOption& __option, error_code& __ec) const
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));
582 __ec.assign(errno, generic_category());
587 template<typename _IoControlCommand>
589 io_control(_IoControlCommand& __command, error_code& __ec)
591 int __result = ::ioctl(_M_sockfd, __command.name(_M_protocol),
592 __command.data(_M_protocol));
594 __ec.assign(errno, generic_category());
600 local_endpoint(error_code& __ec) const
602 endpoint_type __endpoint;
603 socklen_t __endpoint_len = __endpoint.capacity();
604 if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(),
605 &__endpoint_len) == -1)
607 __ec.assign(errno, generic_category());
608 return endpoint_type{};
611 __endpoint.resize(__endpoint_len);
616 bind(const endpoint_type& __endpoint, error_code& __ec)
618 if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size())
620 __ec.assign(errno, generic_category());
625 _Protocol _M_protocol{ endpoint_type{}.protocol() };
635 set_option(socket_base::linger{false, chrono::seconds{}}, __ec);
641 template<typename _Protocol>
643 : public socket_base, private __basic_socket_impl<_Protocol>
645 using __base = __basic_socket_impl<_Protocol>;
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(); }
660 native_handle() noexcept { return __base::native_handle(); }
663 open(const protocol_type& __protocol = protocol_type())
664 { open(__protocol, __throw_on_error{"basic_socket::open"}); }
667 open(const protocol_type& __protocol, error_code& __ec)
668 { __base::open(__protocol, __ec); }
671 assign(const protocol_type& __protocol,
672 const native_handle_type& __native_socket)
674 assign(__protocol, __native_socket,
675 __throw_on_error{"basic_socket::assign"});
679 assign(const protocol_type& __protocol,
680 const native_handle_type& __native_socket,
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>
696 set_option(const _SettableSocketOption& __option)
697 { set_option(__option, __throw_on_error{"basic_socket::set_option"}); }
699 template<typename _SettableSocketOption>
701 set_option(const _SettableSocketOption& __option, error_code& __ec)
702 { __base::set_option(__option, __ec); }
704 template<typename _GettableSocketOption>
706 get_option(_GettableSocketOption& __option) const
707 { get_option(__option, __throw_on_error{"basic_socket::get_option"}); }
709 template<typename _GettableSocketOption>
711 get_option(_GettableSocketOption& __option, error_code& __ec) const
712 { __base::get_option(__option, __ec); }
714 template<typename _IoControlCommand>
716 io_control(_IoControlCommand& __command)
718 io_control(__command, __throw_on_error{"basic_socket::io_control"});
721 template<typename _IoControlCommand>
723 io_control(_IoControlCommand& __command, error_code& __ec)
724 { __base::io_control(__command, __ec); }
727 non_blocking(bool __mode)
728 { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); }
731 non_blocking(bool __mode, error_code& __ec)
732 { __base::non_blocking(__mode, __ec); }
734 bool non_blocking() const { return __base::non_blocking(); }
737 native_non_blocking(bool __mode)
739 native_non_blocking(__mode, __throw_on_error{
740 "basic_socket::native_non_blocking"});
744 native_non_blocking(bool __mode, error_code& __ec)
745 { __base::native_non_blocking(__mode, __ec); }
748 native_non_blocking() const
749 { return __base::native_non_blocking(); }
752 { return at_mark(__throw_on_error{"basic_socket::at_mark"}); }
755 at_mark(error_code& __ec) const
757 const int __result = ::sockatmark(native_handle());
760 __ec.assign(errno, generic_category());
764 return (bool)__result;
769 { return available(__throw_on_error{"basic_socket::available"}); }
772 available(error_code& __ec) const
776 __ec = std::make_error_code(errc::bad_file_descriptor);
781 if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1)
783 __ec.assign(errno, generic_category());
794 bind(const endpoint_type& __endpoint)
795 { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); }
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"}); }
805 shutdown(shutdown_type __what, error_code& __ec)
807 if (::shutdown(native_handle(), static_cast<int>(__what)) == -1)
808 __ec.assign(errno, generic_category());
814 local_endpoint() const
816 return local_endpoint(
817 __throw_on_error{"basic_socket::local_endpoint"});
821 local_endpoint(error_code& __ec) const
822 { return __base::local_endpoint(__ec); }
825 remote_endpoint() const
827 return remote_endpoint(
828 __throw_on_error{"basic_socket::remote_endpoint"});
832 remote_endpoint(error_code& __ec) const
834 endpoint_type __endpoint;
835 socklen_t __endpoint_len = __endpoint.capacity();
836 if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(),
840 __ec.assign(errno, generic_category());
841 return endpoint_type{};
844 __endpoint.resize(__endpoint_len);
849 connect(const endpoint_type& __endpoint)
851 return connect(__endpoint, __throw_on_error{"basic_socket::connect"});
855 connect(const endpoint_type& __endpoint, error_code& __ec)
859 open(__endpoint.protocol(), __ec);
863 if (::connect(native_handle(), (const sockaddr*)__endpoint.data(),
864 __endpoint.size()) == -1)
865 __ec.assign(errno, generic_category());
870 template<typename _CompletionToken>
871 __deduced_t<_CompletionToken, void(error_code)>
872 async_connect(const endpoint_type& __endpoint,
873 _CompletionToken&& __token)
875 async_completion<_CompletionToken, void(error_code)> __init{__token};
880 open(__endpoint.protocol(), __ec);
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>());
888 [__h=std::move(__init.completion_handler), __ec]
890 { __h(__ec); }, __a);
891 return __init.result.get();
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(),
903 __ec.assign(errno, generic_category());
906 return __init.result.get();
911 { return wait(__w, __throw_on_error{"basic_socket::wait"}); }
914 wait(wait_type __w, error_code& __ec)
917 __fd.fd = native_handle();
918 __fd.events = static_cast<int>(__w);
919 int __res = ::poll(&__fd, 1, -1);
921 __ec.assign(errno, generic_category());
926 template<typename _CompletionToken>
927 __deduced_t<_CompletionToken, void(error_code)>
928 async_wait(wait_type __w, _CompletionToken&& __token)
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 {
937 return __init.result.get();
941 // construct / copy / destroy:
943 using __base::__base;
946 basic_socket(io_context& __ctx) : __base(__ctx) { }
948 basic_socket(io_context& __ctx, const protocol_type& __protocol)
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)
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,
979 operator=(basic_socket<_OtherProtocol>&& __rhs)
980 { return *this = basic_socket{std::move(__rhs)}; }
983 template<typename _Protocol>
984 class basic_datagram_socket : public basic_socket<_Protocol>
986 using __base = basic_socket<_Protocol>;
991 typedef int native_handle_type;
992 typedef _Protocol protocol_type;
993 typedef typename protocol_type::endpoint endpoint_type;
995 // construct / copy / destroy:
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)
1030 __base::operator=(std::move(__rhs));
1034 // basic_datagram_socket operations:
1036 template<typename _MutableBufferSequence>
1038 receive(const _MutableBufferSequence& __buffers)
1040 return receive(__buffers, socket_base::message_flags(),
1041 __throw_on_error{"basic_datagram_socket::receive"});
1044 template<typename _MutableBufferSequence>
1046 receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1047 { return receive(__buffers, socket_base::message_flags(), __ec); }
1049 template<typename _MutableBufferSequence>
1051 receive(const _MutableBufferSequence& __buffers,
1052 socket_base::message_flags __flags)
1054 return receive(__buffers, __flags,
1055 __throw_on_error{"basic_datagram_socket::receive"});
1058 template<typename _MutableBufferSequence>
1060 receive(const _MutableBufferSequence& __buffers,
1061 socket_base::message_flags __flags, error_code& __ec)
1063 socket_base::__msg_hdr __msg(__buffers);
1064 ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1065 static_cast<int>(__flags));
1068 __ec.assign(errno, generic_category());
1075 template<typename _MutableBufferSequence, typename _CompletionToken>
1076 __deduced_t<_CompletionToken, void(error_code, size_t)>
1077 async_receive(const _MutableBufferSequence& __buffers,
1078 _CompletionToken&& __token)
1080 return async_receive(__buffers, socket_base::message_flags(),
1081 std::forward<_CompletionToken>(__token));
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)
1090 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1104 socket_base::__msg_hdr __msg(__buffers);
1105 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1108 __ec.assign(errno, generic_category());
1113 __h(__ec, __result);
1115 return __init.result.get();
1118 template<typename _MutableBufferSequence>
1120 receive_from(const _MutableBufferSequence& __buffers,
1121 endpoint_type& __sender)
1123 return receive_from(__buffers, __sender,
1124 socket_base::message_flags(),
1126 "basic_datagram_socket::receive_from"});
1129 template<typename _MutableBufferSequence>
1131 receive_from(const _MutableBufferSequence& __buffers,
1132 endpoint_type& __sender, error_code& __ec)
1134 return receive_from(__buffers, __sender,
1135 socket_base::message_flags(), __ec);
1138 template<typename _MutableBufferSequence>
1140 receive_from(const _MutableBufferSequence& __buffers,
1141 endpoint_type& __sender,
1142 socket_base::message_flags __flags)
1144 return receive_from(__buffers, __sender, __flags,
1146 "basic_datagram_socket::receive_from"});
1149 template<typename _MutableBufferSequence>
1151 receive_from(const _MutableBufferSequence& __buffers,
1152 endpoint_type& __sender,
1153 socket_base::message_flags __flags,
1156 socket_base::__msg_hdr __msg(__buffers, __sender);
1157 ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1158 static_cast<int>(__flags));
1161 __ec.assign(errno, generic_category());
1165 __sender.resize(__msg.msg_namelen);
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)
1175 return async_receive_from(__buffers, __sender,
1176 socket_base::message_flags(),
1177 std::forward<_CompletionToken>(__token));
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)
1187 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1202 socket_base::__msg_hdr __msg(__buffers, __sender);
1203 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1206 __ec.assign(errno, generic_category());
1212 __sender.resize(__msg.msg_namelen);
1214 __h(__ec, __result);
1216 return __init.result.get();
1219 template<typename _ConstBufferSequence>
1221 send(const _ConstBufferSequence& __buffers)
1223 return send(__buffers, socket_base::message_flags(),
1224 __throw_on_error{"basic_datagram_socket::send"});
1227 template<typename _ConstBufferSequence>
1229 send(const _ConstBufferSequence& __buffers, error_code& __ec)
1230 { return send(__buffers, socket_base::message_flags(), __ec); }
1232 template<typename _ConstBufferSequence>
1234 send(const _ConstBufferSequence& __buffers,
1235 socket_base::message_flags __flags)
1237 return send(__buffers, __flags,
1238 __throw_on_error{"basic_datagram_socket::send"});
1241 template<typename _ConstBufferSequence>
1243 send(const _ConstBufferSequence& __buffers,
1244 socket_base::message_flags __flags, error_code& __ec)
1246 socket_base::__msg_hdr __msg(__buffers);
1247 ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1248 static_cast<int>(__flags));
1251 __ec.assign(errno, generic_category());
1258 template<typename _ConstBufferSequence, typename _CompletionToken>
1259 __deduced_t<_CompletionToken, void(error_code, size_t)>
1260 async_send(const _ConstBufferSequence& __buffers,
1261 _CompletionToken&& __token)
1263 return async_send(__buffers, socket_base::message_flags(),
1264 std::forward<_CompletionToken>(__token));
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)
1273 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1287 socket_base::__msg_hdr __msg(__buffers);
1288 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1291 __ec.assign(errno, generic_category());
1296 __h(__ec, __result);
1298 return __init.result.get();
1301 template<typename _ConstBufferSequence>
1303 send_to(const _ConstBufferSequence& __buffers,
1304 const endpoint_type& __recipient)
1306 return send_to(__buffers, __recipient,
1307 socket_base::message_flags(),
1308 __throw_on_error{"basic_datagram_socket::send_to"});
1311 template<typename _ConstBufferSequence>
1313 send_to(const _ConstBufferSequence& __buffers,
1314 const endpoint_type& __recipient, error_code& __ec)
1316 return send_to(__buffers, __recipient,
1317 socket_base::message_flags(), __ec);
1320 template<typename _ConstBufferSequence>
1322 send_to(const _ConstBufferSequence& __buffers,
1323 const endpoint_type& __recipient,
1324 socket_base::message_flags __flags)
1326 return send_to(__buffers, __recipient, __flags,
1327 __throw_on_error{"basic_datagram_socket::send_to"});
1330 template<typename _ConstBufferSequence>
1332 send_to(const _ConstBufferSequence& __buffers,
1333 const endpoint_type& __recipient,
1334 socket_base::message_flags __flags, error_code& __ec)
1336 socket_base::__msg_hdr __msg(__buffers, __recipient);
1337 ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1338 static_cast<int>(__flags));
1341 __ec.assign(errno, generic_category());
1345 __recipient.resize(__msg.msg_namelen);
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)
1355 return async_send_to(__buffers, __recipient,
1356 socket_base::message_flags(),
1357 std::forward<_CompletionToken>(__token));
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)
1367 async_completion<_CompletionToken, void(error_code, size_t)>
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 {
1382 socket_base::__msg_hdr __msg(__buffers, __recipient);
1383 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1386 __ec.assign(errno, generic_category());
1392 __recipient.resize(__msg.msg_namelen);
1394 __h(__ec, __result);
1396 return __init.result.get();
1400 template<typename _Protocol>
1401 class basic_stream_socket : public basic_socket<_Protocol>
1403 using __base = basic_socket<_Protocol>;
1408 typedef int native_handle_type;
1409 typedef _Protocol protocol_type;
1410 typedef typename protocol_type::endpoint endpoint_type;
1412 // construct / copy / destroy:
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)
1447 __base::operator=(std::move(__rhs));
1451 // basic_stream_socket operations:
1453 template<class _MutableBufferSequence>
1455 receive(const _MutableBufferSequence& __buffers)
1457 return receive(__buffers, socket_base::message_flags(),
1458 __throw_on_error{"basic_stream_socket::receive"});
1461 template<class _MutableBufferSequence>
1463 receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1464 { return receive(__buffers, socket_base::message_flags(), __ec); }
1466 template<class _MutableBufferSequence>
1468 receive(const _MutableBufferSequence& __buffers,
1469 socket_base::message_flags __flags)
1471 return receive(__buffers, __flags,
1472 __throw_on_error{"basic_stream_socket::receive"});
1475 template<class _MutableBufferSequence>
1477 receive(const _MutableBufferSequence& __buffers,
1478 socket_base::message_flags __flags, error_code& __ec)
1480 if (__buffer_empty(__buffers))
1486 socket_base::__msg_hdr __msg(__buffers);
1487 ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1488 static_cast<int>(__flags));
1494 __ec.assign(errno, generic_category());
1498 template<class _MutableBufferSequence, class _CompletionToken>
1499 __deduced_t<_CompletionToken, void(error_code, size_t)>
1500 async_receive(const _MutableBufferSequence& __buffers,
1501 _CompletionToken&& __token)
1503 return async_receive(__buffers, socket_base::message_flags(),
1504 std::forward<_CompletionToken>(__token));
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)
1513 async_completion<_CompletionToken, void(error_code, size_t)>
1516 if (__buffer_empty(__buffers))
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>());
1523 [__h=std::move(__init.completion_handler)] () mutable
1524 { __h(error_code{}, 0); }, __a);
1525 return __init.result.get();
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 {
1539 socket_base::__msg_hdr __msg(__buffers);
1540 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1543 __ec.assign(errno, generic_category());
1548 __h(__ec, __result);
1550 return __init.result.get();
1553 template<class _ConstBufferSequence>
1555 send(const _ConstBufferSequence& __buffers)
1557 return send(__buffers, socket_base::message_flags(),
1558 __throw_on_error{"basic_stream_socket::send"});
1561 template<class _ConstBufferSequence>
1563 send(const _ConstBufferSequence& __buffers, error_code& __ec)
1564 { return send(__buffers, socket_base::message_flags(), __ec); }
1566 template<class _ConstBufferSequence>
1568 send(const _ConstBufferSequence& __buffers,
1569 socket_base::message_flags __flags)
1571 return send(__buffers, socket_base::message_flags(),
1572 __throw_on_error{"basic_stream_socket::send"});
1575 template<class _ConstBufferSequence>
1577 send(const _ConstBufferSequence& __buffers,
1578 socket_base::message_flags __flags, error_code& __ec)
1580 if (__buffer_empty(__buffers))
1586 socket_base::__msg_hdr __msg(__buffers);
1587 ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1588 static_cast<int>(__flags));
1594 __ec.assign(errno, generic_category());
1598 template<class _ConstBufferSequence, class _CompletionToken>
1599 __deduced_t<_CompletionToken, void(error_code, size_t)>
1600 async_send(const _ConstBufferSequence& __buffers,
1601 _CompletionToken&& __token)
1603 return async_send(__buffers, socket_base::message_flags(),
1604 std::forward<_CompletionToken>(__token));
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)
1613 async_completion<_CompletionToken, void(error_code, size_t)>
1616 if (__buffer_empty(__buffers))
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>());
1623 [__h=std::move(__init.completion_handler)] () mutable
1624 { __h(error_code{}, 0); }, __a);
1625 return __init.result.get();
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 {
1639 socket_base::__msg_hdr __msg(__buffers);
1640 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1643 __ec.assign(errno, generic_category());
1648 __h(__ec, __result);
1650 return __init.result.get();
1653 template<class _MutableBufferSequence>
1655 read_some(const _MutableBufferSequence& __buffers)
1657 return receive(__buffers,
1658 __throw_on_error{"basic_stream_socket::read_some"});
1661 template<class _MutableBufferSequence>
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)
1671 return async_receive(__buffers,
1672 std::forward<_CompletionToken>(__token));
1675 template<class _ConstBufferSequence>
1677 write_some(const _ConstBufferSequence& __buffers)
1679 return send(__buffers,
1680 __throw_on_error{"basic_stream_socket:write_some"});
1683 template<class _ConstBufferSequence>
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)
1693 return async_send(__buffers,
1694 std::forward<_CompletionToken>(__token));
1698 template<typename _AcceptableProtocol>
1699 class basic_socket_acceptor
1700 : public socket_base, private __basic_socket_impl<_AcceptableProtocol>
1702 using __base = __basic_socket_impl<_AcceptableProtocol>;
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:
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())
1729 set_option(reuse_address(true));
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)
1759 __base::operator=(std::move(__rhs));
1763 // basic_socket_acceptor operations:
1765 executor_type get_executor() noexcept { return __base::get_executor(); }
1768 native_handle() noexcept { return __base::native_handle(); }
1771 open(const protocol_type& __protocol = protocol_type())
1772 { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); }
1775 open(const protocol_type& __protocol, error_code& __ec)
1776 { __base::open(__protocol, __ec); }
1779 assign(const protocol_type& __protocol,
1780 const native_handle_type& __native_acceptor)
1782 assign(__protocol, __native_acceptor,
1783 __throw_on_error{"basic_socket_acceptor::assign"});
1787 assign(const protocol_type& __protocol,
1788 const native_handle_type& __native_acceptor,
1790 { __base::assign(__protocol, __native_acceptor, __ec); }
1793 is_open() const noexcept { return __base::is_open(); }
1796 close() { close(__throw_on_error{"basic_socket_acceptor::close"}); }
1799 close(error_code& __ec) { __base::_close(__ec); }
1802 cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); }
1805 cancel(error_code& __ec) { __base::cancel(__ec); }
1807 template<typename _SettableSocketOption>
1809 set_option(const _SettableSocketOption& __option)
1811 set_option(__option,
1812 __throw_on_error{"basic_socket_acceptor::set_option"});
1815 template<typename _SettableSocketOption>
1817 set_option(const _SettableSocketOption& __option, error_code& __ec)
1818 { __base::set_option(__option, __ec); }
1820 template<typename _GettableSocketOption>
1822 get_option(_GettableSocketOption& __option) const
1824 get_option(__option,
1825 __throw_on_error{"basic_socket_acceptor::get_option"});
1828 template<typename _GettableSocketOption>
1830 get_option(_GettableSocketOption& __option, error_code& __ec) const
1831 { __base::get_option(__option, __ec); }
1833 template<typename _IoControlCommand>
1835 io_control(_IoControlCommand& __command)
1837 io_control(__command,
1838 __throw_on_error{"basic_socket_acceptor::io_control"});
1841 template<typename _IoControlCommand>
1843 io_control(_IoControlCommand& __command, error_code& __ec)
1844 { __base::io_control(__command, __ec); }
1847 non_blocking(bool __mode)
1849 non_blocking(__mode,
1850 __throw_on_error{"basic_socket_acceptor::non_blocking"});
1854 non_blocking(bool __mode, error_code& __ec)
1855 { __base::non_blocking(__mode, __ec); }
1857 bool non_blocking() const { return __base::non_blocking(); }
1860 native_non_blocking(bool __mode)
1862 native_non_blocking(__mode, __throw_on_error{
1863 "basic_socket_acceptor::native_non_blocking"});
1867 native_non_blocking(bool __mode, error_code& __ec)
1868 { __base::native_non_blocking(__mode, __ec); }
1871 native_non_blocking() const
1872 { return __base::native_non_blocking(); }
1875 bind(const endpoint_type& __endpoint)
1877 return bind(__endpoint,
1878 __throw_on_error{"basic_socket_acceptor::bind"});
1882 bind(const endpoint_type& __endpoint, error_code& __ec)
1883 { __base::bind(__endpoint, __ec); }
1886 listen(int __backlog = max_listen_connections)
1888 return listen(__backlog,
1889 __throw_on_error{"basic_socket_acceptor::listen"});
1892 void listen(int __backlog, error_code& __ec)
1894 if (::listen(native_handle(), __backlog) == -1)
1895 __ec.assign(errno, generic_category());
1901 local_endpoint() const
1903 return local_endpoint(
1904 __throw_on_error{"basic_socket_acceptor::local_endpoint"});
1908 local_endpoint(error_code& __ec) const
1909 { return __base::local_endpoint(__ec); }
1912 enable_connection_aborted(bool __mode)
1913 { __base::_M_bits.enable_connection_aborted = __mode; }
1916 enable_connection_aborted() const
1917 { return __base::_M_bits.enable_connection_aborted; }
1921 { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); }
1924 accept(error_code& __ec)
1925 { return accept(get_executor().context(), __ec); }
1927 socket_type accept(io_context& __ctx)
1929 return accept(__ctx,
1930 __throw_on_error{"basic_socket_acceptor::accept"});
1934 accept(io_context& __ctx, error_code& __ec)
1938 int __h = ::accept(native_handle(), nullptr, 0);
1942 return socket_type{__ctx, _M_protocol, __h};
1944 } while (errno == ECONNABORTED && enable_connection_aborted());
1945 __ec.assign(errno, generic_category());
1946 return socket_type{__ctx};
1949 template<class _CompletionToken>
1950 __deduced_t<_CompletionToken, void(error_code, socket_type)>
1951 async_accept(_CompletionToken&& __token)
1953 return async_accept(get_executor().context(),
1954 std::forward<_CompletionToken>(__token));
1957 template<class _CompletionToken>
1958 __deduced_t<_CompletionToken, void(error_code, socket_type)>
1959 async_accept(io_context& __ctx, _CompletionToken&& __token)
1961 async_completion<_CompletionToken, void(error_code, socket_type)>
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,
1972 (error_code __ec) mutable {
1975 __h(__ec, socket_type(__ctx));
1980 int __newfd = ::accept(__fd, nullptr, 0);
1984 __h(__ec, socket_type{__ctx, __protocol, __newfd});
1987 } while (errno == ECONNABORTED && __connabort);
1988 __ec.assign(errno, generic_category());
1989 __h(__ec, socket_type(__ctx));
1991 return __init.result.get();
1995 accept(endpoint_type& __endpoint)
1997 return accept(get_executor().context(), __endpoint,
1998 __throw_on_error{"basic_socket_acceptor::accept"});
2002 accept(endpoint_type& __endpoint, error_code& __ec)
2003 { return accept(get_executor().context(), __endpoint, __ec); }
2006 accept(io_context& __ctx, endpoint_type& __endpoint)
2008 return accept(__ctx, __endpoint,
2009 __throw_on_error{"basic_socket_acceptor::accept"});
2013 accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec)
2017 socklen_t __len = __endpoint.capacity();
2018 int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(),
2022 __endpoint.resize(__len);
2023 return socket_type{__ctx, _M_protocol, __h};
2025 } while (errno == ECONNABORTED && enable_connection_aborted());
2026 __ec.assign(errno, generic_category());
2027 return socket_type{__ctx};
2030 template<class _CompletionToken>
2031 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2032 async_accept(endpoint_type& __endpoint,
2033 _CompletionToken&& __token)
2035 return async_accept(get_executor().context(), __endpoint,
2036 std::forward<_CompletionToken>(__token));
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)
2044 async_completion<_CompletionToken, void(error_code, socket_type)>
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(),
2055 (error_code __ec) mutable {
2058 __h(__ec, socket_type(__ctx));
2063 socklen_t __len = __ep.capacity();
2064 int __newfd = ::accept(__fd, __ep.data, &__len);
2068 auto __protocol = __ep.protocol();
2070 __h(__ec, socket_type{__ctx, __protocol, __newfd});
2073 } while (errno == ECONNABORTED && __connabort);
2074 __ec.assign(errno, generic_category());
2075 __h(__ec, socket_type(__ctx));
2077 return __init.result.get();
2082 { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); }
2085 wait(wait_type __w, error_code& __ec)
2088 __fds.fd = native_handle();
2089 __fds.events = __w; // __w | POLLIN;
2090 if (::poll(&__fds, 1, -1) == -1)
2091 __ec.assign(errno, generic_category());
2096 template<class _CompletionToken>
2097 __deduced_t<_CompletionToken, void(error_code)>
2098 async_wait(wait_type __w, _CompletionToken&& __token)
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 {
2107 return __init.result.get();
2111 protocol_type _M_protocol;
2116 /** @brief Socket streams
2120 template<typename _Protocol, typename _Clock, typename _WaitTraits>
2121 class basic_socket_streambuf : public basic_streambuf<char>
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()) { }
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
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; }
2167 expires_at(const time_point& __t)
2168 { _M_expiry = __t; }
2171 expires_after(const duration& __d)
2172 { expires_at(clock_type::now() + __d); }
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;
2186 static io_context __ctx;
2190 basic_stream_socket<protocol_type> _M_socket;
2192 time_point _M_expiry{ time_point::max() };
2195 template<typename _Protocol, class _Clock, typename _WaitTraits>
2196 class basic_socket_iostream : public basic_iostream<char>
2198 using __streambuf_type
2199 = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>;
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()
2216 this->init(std::addressof(_M_sb));
2217 this->setf(std::ios::unitbuf);
2221 basic_socket_iostream(basic_stream_socket<protocol_type> __s)
2222 : basic_iostream(nullptr), _M_sb(std::move(__s))
2224 this->init(std::addressof(_M_sb));
2225 this->setf(std::ios::unitbuf);
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))
2234 // XXX ??? this->init(std::addressof(_M_sb));
2235 this->set_rbduf(std::addressof(_M_sb));
2238 template<typename... _Args>
2240 basic_socket_iostream(_Args&&... __args)
2241 : basic_iostream(nullptr), _M_sb()
2243 this->init(std::addressof(_M_sb));
2244 this->setf(std::ios::unitbuf);
2245 connect(forward<_Args>(__args)...);
2248 basic_socket_iostream& operator=(const basic_socket_iostream&) = delete;
2250 basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO
2254 template<typename... _Args>
2256 connect(_Args&&... __args)
2258 if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr)
2259 this->setstate(failbit);
2265 if (rdbuf()->close() == nullptr)
2266 this->setstate(failbit);
2269 basic_socket_streambuf<protocol_type, clock_type, wait_traits_type>*
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); }
2281 __streambuf_type _M_sb;
2286 /** @brief synchronous connect operations
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)
2298 bool __found = false;
2299 for (auto& __ep : __endpoints)
2301 if (__c(__ec, __ep))
2306 __s.open(__ep.protocol(), __ec);
2308 __s.connect(__ep, __ec);
2314 __ec = socket_errc::not_found;
2315 return typename _Protocol::endpoint{};
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)
2326 bool __found = false;
2327 for (auto __i = __first; __i != __last; ++__i)
2329 if (__c(__ec, *__i))
2334 __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec);
2336 __s.connect(*__i, __ec);
2342 __ec = socket_errc::not_found;
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)
2353 return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"});
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)
2363 return net::connect(__s, __first, __last, __c,
2364 __throw_on_error{"connect"});
2367 template<typename _Protocol, typename _EndpointSequence>
2368 inline typename _Protocol::endpoint
2369 connect(basic_socket<_Protocol>& __s,
2370 const _EndpointSequence& __endpoints)
2372 return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2373 __throw_on_error{"connect"});
2376 template<typename _Protocol, typename _EndpointSequence>
2377 inline typename _Protocol::endpoint
2378 connect(basic_socket<_Protocol>& __s,
2379 const _EndpointSequence& __endpoints,
2382 return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2386 template<typename _Protocol, typename _InputIterator>
2387 inline _InputIterator
2388 connect(basic_socket<_Protocol>& __s,
2389 _InputIterator __first, _InputIterator __last)
2391 return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2392 __throw_on_error{"connect"});
2395 template<typename _Protocol, typename _InputIterator>
2396 inline _InputIterator
2397 connect(basic_socket<_Protocol>& __s,
2398 _InputIterator __first, _InputIterator __last,
2401 return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2407 /** @brief asynchronous connect operations
2411 template<typename _Protocol, typename _EndpointSequence,
2412 typename _ConnectCondition, typename _CompletionToken>
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>
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)
2429 return net::async_connect(__s, __endpoints,
2430 [](auto, auto){ return true; },
2431 forward<_CompletionToken>(__token));
2434 template<typename _Protocol, typename _InputIterator,
2435 typename _ConnectCondition, typename _CompletionToken>
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>
2445 __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
2446 async_connect(basic_socket<_Protocol>& __s,
2447 _InputIterator __first, _InputIterator __last,
2448 _CompletionToken&& __token)
2450 return net::async_connect(__s, __first, __last,
2451 [](auto, auto){ return true; },
2452 forward<_CompletionToken>(__token));
2457 #endif // _GLIBCXX_HAVE_UNISTD_H
2461 _GLIBCXX_END_NAMESPACE_VERSION
2464 } // namespace experimental
2467 struct is_error_code_enum<experimental::net::v1::socket_errc>
2468 : public true_type {};
2474 #endif // _GLIBCXX_EXPERIMENTAL_SOCKET