1 // <experimental/socket> -*- C++ -*-
3 // Copyright (C) 2015-2024 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 #include <bits/requires_hosted.h> // experimental is currently omitted
37 #if __cplusplus >= 201402L
39 #include <experimental/netfwd>
40 #include <experimental/buffer>
41 #include <experimental/io_context>
42 #include <experimental/bits/net.h>
45 #include <bits/unique_ptr.h>
46 #if _GLIBCXX_HAVE_UNISTD_H
48 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
49 # include <sys/socket.h> // socket etc
51 # ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
52 # include <sys/ioctl.h> // ioctl
54 # ifdef _GLIBCXX_HAVE_SYS_UIO_H
55 # include <sys/uio.h> // iovec
57 # ifdef _GLIBCXX_HAVE_POLL_H
58 # include <poll.h> // poll, pollfd, POLLIN, POLLOUT, POLLERR
60 # ifdef _GLIBCXX_HAVE_FCNTL_H
61 # include <fcntl.h> // fcntl, F_GETFL, F_SETFL
65 namespace std _GLIBCXX_VISIBILITY(default)
67 _GLIBCXX_BEGIN_NAMESPACE_VERSION
68 namespace experimental
75 /** @addtogroup networking-ts
79 enum class socket_errc { // TODO decide values
86 } // namespace experimental
89 struct is_error_code_enum<experimental::net::v1::socket_errc>
90 : public true_type {};
92 namespace experimental
98 const error_category& socket_category() noexcept
100 struct __cat : error_category
102 const char* name() const noexcept { return "socket"; }
104 std::string message(int __e) const
106 if (__e == (int)socket_errc::already_open)
107 return "already open";
108 else if (__e == (int)socket_errc::not_found)
109 return "endpoint not found";
110 return "socket error";
113 virtual void __message(int) { } // TODO dual ABI XXX
120 make_error_code(socket_errc __e) noexcept
121 { return error_code(static_cast<int>(__e), socket_category()); }
123 inline error_condition
124 make_error_condition(socket_errc __e) noexcept
125 { return error_condition(static_cast<int>(__e), socket_category()); }
128 // TODO GettableSocket reqs
129 // TODO SettableSocket reqs
130 // TODO BooleanSocketOption reqs
131 // TODO IntegerSocketOption reqs
132 // TODO IoControlCommand reqs
133 // TODO ConnectCondition reqs
142 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
143 class broadcast : public __sockopt_crtp<broadcast, bool>
146 using __sockopt_crtp::__sockopt_crtp;
147 using __sockopt_crtp::operator=;
150 friend __sockopt_crtp<broadcast, bool>;
151 static const int _S_level = SOL_SOCKET;
152 static const int _S_name = SO_BROADCAST;
155 class debug : public __sockopt_crtp<debug, bool>
158 friend __sockopt_crtp<debug, bool>;
159 using __sockopt_crtp::__sockopt_crtp;
160 using __sockopt_crtp::operator=;
163 static const int _S_level = SOL_SOCKET;
164 static const int _S_name = SO_DEBUG;
167 class do_not_route : public __sockopt_crtp<do_not_route, bool>
170 using __sockopt_crtp::__sockopt_crtp;
171 using __sockopt_crtp::operator=;
174 friend __sockopt_crtp<do_not_route, bool>;
175 static const int _S_level = SOL_SOCKET;
176 static const int _S_name = SO_DONTROUTE;
179 class keep_alive : public __sockopt_crtp<keep_alive, bool>
182 using __sockopt_crtp::__sockopt_crtp;
183 using __sockopt_crtp::operator=;
186 friend __sockopt_crtp<keep_alive, bool>;
187 static const int _S_level = SOL_SOCKET;
188 static const int _S_name = SO_KEEPALIVE;
191 class linger : public __sockopt_crtp<linger, ::linger>
194 using __sockopt_crtp::__sockopt_crtp;
195 using __sockopt_crtp::operator=;
197 linger() noexcept = default;
199 linger(bool __e, chrono::seconds __t) noexcept
206 enabled() const noexcept
207 { return _M_value.l_onoff != 0; }
210 enabled(bool __e) noexcept
211 { _M_value.l_onoff = int(__e); }
214 timeout() const noexcept
215 { return chrono::seconds(_M_value.l_linger); }
218 timeout(chrono::seconds __t) noexcept
219 { _M_value.l_linger = __t.count(); }
222 friend __sockopt_crtp<linger, ::linger>;
223 static const int _S_level = SOL_SOCKET;
224 static const int _S_name = SO_LINGER;
227 class out_of_band_inline : public __sockopt_crtp<out_of_band_inline, bool>
230 using __sockopt_crtp::__sockopt_crtp;
231 using __sockopt_crtp::operator=;
234 friend __sockopt_crtp<out_of_band_inline, bool>;
235 static const int _S_level = SOL_SOCKET;
236 static const int _S_name = SO_OOBINLINE;
239 class receive_buffer_size : public __sockopt_crtp<receive_buffer_size>
242 using __sockopt_crtp::__sockopt_crtp;
243 using __sockopt_crtp::operator=;
246 friend __sockopt_crtp<receive_buffer_size>;
247 static const int _S_level = SOL_SOCKET;
248 static const int _S_name = SO_RCVBUF;
251 class receive_low_watermark : public __sockopt_crtp<receive_low_watermark>
254 using __sockopt_crtp::__sockopt_crtp;
255 using __sockopt_crtp::operator=;
258 friend __sockopt_crtp<receive_low_watermark>;
259 static const int _S_level = SOL_SOCKET;
260 static const int _S_name = SO_RCVLOWAT;
263 class reuse_address : public __sockopt_crtp<reuse_address, bool>
266 using __sockopt_crtp::__sockopt_crtp;
267 using __sockopt_crtp::operator=;
270 friend __sockopt_crtp<reuse_address, bool>;
271 static const int _S_level = SOL_SOCKET;
272 static const int _S_name = SO_REUSEADDR;
275 class send_buffer_size : public __sockopt_crtp<send_buffer_size>
278 using __sockopt_crtp::__sockopt_crtp;
279 using __sockopt_crtp::operator=;
282 friend __sockopt_crtp<send_buffer_size>;
283 static const int _S_level = SOL_SOCKET;
284 static const int _S_name = SO_SNDBUF;
287 class send_low_watermark : public __sockopt_crtp<send_low_watermark>
290 using __sockopt_crtp::__sockopt_crtp;
291 using __sockopt_crtp::operator=;
294 friend __sockopt_crtp<send_low_watermark>;
295 static const int _S_level = SOL_SOCKET;
296 static const int _S_name = SO_SNDLOWAT;
298 #endif // HAVE_SYS_SOCKET_H
300 enum shutdown_type : int { };
301 #if defined SHUT_RD && defined SHUT_WR && defined SHUT_RDWR
302 static constexpr shutdown_type shutdown_receive = (shutdown_type)SHUT_RD;
303 static constexpr shutdown_type shutdown_send = (shutdown_type)SHUT_WR;
304 static constexpr shutdown_type shutdown_both = (shutdown_type)SHUT_RDWR;
307 enum wait_type : int { };
308 #ifdef _GLIBCXX_HAVE_POLL_H
309 static constexpr wait_type wait_read = (wait_type)POLLIN;
310 static constexpr wait_type wait_write = (wait_type)POLLOUT;
311 static constexpr wait_type wait_error = (wait_type)POLLERR;
313 static constexpr wait_type wait_read = (wait_type)1;
314 static constexpr wait_type wait_write = (wait_type)2;
315 static constexpr wait_type wait_error = (wait_type)4;
318 enum message_flags : int { };
319 #if defined MSG_PEEK && defined MSG_OOB && defined MSG_DONTROUTE
320 static constexpr message_flags message_peek
321 = (message_flags)MSG_PEEK;
322 static constexpr message_flags message_out_of_band
323 = (message_flags)MSG_OOB;
324 static constexpr message_flags message_do_not_route
325 = (message_flags)MSG_DONTROUTE;
329 static constexpr int max_listen_connections = SOMAXCONN;
331 static constexpr int max_listen_connections = 4;
334 // message_flags bitmask operations are defined as hidden friends.
336 friend constexpr message_flags
337 operator&(message_flags __f1, message_flags __f2) noexcept
338 { return message_flags( int(__f1) & int(__f2) ); }
340 friend constexpr message_flags
341 operator|(message_flags __f1, message_flags __f2) noexcept
342 { return message_flags( int(__f1) | int(__f2) ); }
344 friend constexpr message_flags
345 operator^(message_flags __f1, message_flags __f2) noexcept
346 { return message_flags( int(__f1) ^ int(__f2) ); }
348 friend constexpr message_flags
349 operator~(message_flags __f) noexcept
350 { return message_flags( ~int(__f) ); }
352 friend constexpr message_flags&
353 operator&=(message_flags& __f1, message_flags __f2) noexcept
354 { return __f1 = (__f1 & __f2); }
356 friend constexpr message_flags&
357 operator|=(message_flags& __f1, message_flags __f2) noexcept
358 { return __f1 = (__f1 | __f2); }
360 friend constexpr message_flags&
361 operator^=(message_flags& __f1, message_flags __f2) noexcept
362 { return __f1 = (__f1 ^ __f2); }
364 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
366 struct __msg_hdr : ::msghdr
369 using __iovec_array = array<::iovec, IOV_MAX>;
370 #elif _GLIBCXX_HAVE_UNISTD_H
373 __iovec_array() : _M_ptr(new ::iovec[size()]) { }
375 ::iovec& operator[](size_t __n) noexcept { return _M_ptr[__n]; }
377 ::iovec* data() noexcept { return _M_ptr.get(); }
381 static const size_t __iov_max = ::sysconf(_SC_IOV_MAX);
386 unique_ptr<::iovec[]> _M_ptr;
389 using __iovec_array = array<::iovec, 16>;
392 __iovec_array _M_iov;
394 template<typename _BufferSequence>
396 __msg_hdr(const _BufferSequence& __buffers)
399 auto __buf = net::buffer_sequence_begin(__buffers);
400 const auto __bufend = net::buffer_sequence_end(__buffers);
402 while (__buf != __bufend && __len != _M_iov.size())
404 _M_iov[__len].iov_base = (void*)__buf->data();
405 _M_iov[__len].iov_len = __buf->size();
409 this->msg_iovlen = __len;
410 this->msg_iov = _M_iov.data();
413 template<typename _BufferSequence, typename _Endpoint>
414 __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep)
415 : __msg_hdr(__buffers)
417 this->msg_name = __ep.data();
418 this->msg_namelen = __ep.size();
424 socket_base() = default;
425 ~socket_base() = default;
428 // TODO define socket_base static constants in .so for C++14 mode
430 #if _GLIBCXX_HAVE_UNISTD_H
436 using executor_type = io_context::executor_type;
437 using native_handle_type = int;
440 __socket_impl(io_context& __ctx) : _M_ctx(std::addressof(__ctx)) { }
442 __socket_impl(__socket_impl&& __rhs)
443 : _M_ctx(__rhs._M_ctx),
444 _M_sockfd(std::__exchange(__rhs._M_sockfd, -1)),
445 _M_bits(std::__exchange(__rhs._M_bits, {}))
449 operator=(__socket_impl&& __rhs)
451 _M_ctx = __rhs._M_ctx;
452 _M_sockfd = std::__exchange(__rhs._M_sockfd, -1);
453 _M_bits = std::__exchange(__rhs._M_bits, {});
457 ~__socket_impl() = default;
459 __socket_impl(const __socket_impl&) = delete;
460 __socket_impl& operator=(const __socket_impl&) = delete;
462 executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
464 native_handle_type native_handle() noexcept { return _M_sockfd; }
466 bool is_open() const noexcept { return _M_sockfd != -1; }
469 close(error_code& __ec)
476 if (::close(_M_sockfd) == -1)
477 __ec.assign(errno, generic_category());
480 get_executor().context()._M_remove_fd(_M_sockfd);
487 void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); }
490 non_blocking(bool __mode, error_code&)
491 { _M_bits.non_blocking = __mode; }
493 bool non_blocking() const { return _M_bits.non_blocking; }
496 native_non_blocking([[maybe_unused]] bool __mode, error_code& __ec)
498 #if defined _GLIBCXX_HAVE_FCNTL_H && defined _GLIBCXX_HAVE_DECL_O_NONBLOCK
499 int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
503 __flags |= O_NONBLOCK;
505 __flags &= ~O_NONBLOCK;
506 __flags = ::fcntl(_M_sockfd, F_SETFL, __flags);
509 __ec.assign(errno, generic_category());
513 _M_bits.native_non_blocking = __mode;
516 __ec = std::make_error_code(std::errc::not_supported);
521 native_non_blocking() const
523 #if defined _GLIBCXX_HAVE_FCNTL_H && defined _GLIBCXX_HAVE_DECL_O_NONBLOCK
524 if (_M_bits.native_non_blocking == -1)
526 const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
529 _M_bits.native_non_blocking = __flags & O_NONBLOCK;
531 return _M_bits.native_non_blocking;
540 unsigned non_blocking : 1;
541 mutable signed native_non_blocking : 2;
542 unsigned enable_connection_aborted : 1;
546 template<typename _Protocol>
547 class __basic_socket_impl : public __socket_impl
549 using __base = __socket_impl;
552 using protocol_type = _Protocol;
553 using endpoint_type = typename protocol_type::endpoint;
556 __basic_socket_impl(io_context& __ctx) : __base(__ctx) { }
558 __basic_socket_impl(__basic_socket_impl&&) = default;
560 template<typename _OtherProtocol>
561 __basic_socket_impl(__basic_socket_impl<_OtherProtocol>&& __rhs)
562 : __base(std::move(__rhs)), _M_protocol(std::move(__rhs._M_protocol))
566 operator=(__basic_socket_impl&& __rhs)
568 if (this == std::addressof(__rhs))
571 __base::operator=(std::move(__rhs));
575 ~__basic_socket_impl() { _M_close(); }
577 __basic_socket_impl(const __basic_socket_impl&) = delete;
578 __basic_socket_impl& operator=(const __basic_socket_impl&) = delete;
581 open(const protocol_type& __protocol, error_code& __ec)
583 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
585 __ec = socket_errc::already_open;
588 _M_protocol = __protocol;
589 _M_sockfd = ::socket(__protocol.family(), __protocol.type(),
590 __protocol.protocol());
593 get_executor().context()._M_add_fd(_M_sockfd);
597 __ec.assign(errno, std::generic_category());
600 __ec = std::make_error_code(errc::operation_not_supported);
605 assign(const protocol_type& __protocol,
606 const native_handle_type& __native_socket,
610 __ec = socket_errc::already_open;
613 _M_protocol = __protocol;
614 _M_bits.native_non_blocking = -1;
615 _M_sockfd = __native_socket;
618 get_executor().context()._M_add_fd(_M_sockfd);
622 __ec.assign(errno, std::generic_category());
626 native_handle_type release(error_code& __ec)
628 __glibcxx_assert(is_open());
630 return std::__exchange(_M_sockfd, -1);
633 template<typename _SettableSocketOption>
635 set_option(const _SettableSocketOption& __option, error_code& __ec)
637 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
638 int __result = ::setsockopt(_M_sockfd, __option.level(_M_protocol),
639 __option.name(_M_protocol),
640 __option.data(_M_protocol),
641 __option.size(_M_protocol));
643 __ec.assign(errno, generic_category());
647 __ec = std::make_error_code(std::errc::not_supported);
651 template<typename _GettableSocketOption>
653 get_option(_GettableSocketOption& __option, error_code& __ec) const
655 # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
656 int __result = ::getsockopt(_M_sockfd, __option.level(_M_protocol),
657 __option.name(_M_protocol),
658 __option.data(_M_protocol),
659 __option.size(_M_protocol));
661 __ec.assign(errno, generic_category());
665 __ec = std::make_error_code(std::errc::not_supported);
669 template<typename _IoControlCommand>
671 io_control(_IoControlCommand& __command, error_code& __ec)
673 #ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
674 int __result = ::ioctl(_M_sockfd, __command.name(),
677 __ec.assign(errno, generic_category());
681 __ec = std::make_error_code(std::errc::not_supported);
686 local_endpoint(error_code& __ec) const
688 endpoint_type __endpoint;
689 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
690 socklen_t __endpoint_len = __endpoint.capacity();
691 if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(),
692 &__endpoint_len) == -1)
694 __ec.assign(errno, generic_category());
695 return endpoint_type{};
698 __endpoint.resize(__endpoint_len);
700 __ec = std::make_error_code(errc::operation_not_supported);
706 bind(const endpoint_type& __endpoint, error_code& __ec)
708 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
709 if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size())
711 __ec.assign(errno, generic_category());
715 __ec = std::make_error_code(errc::operation_not_supported);
719 _Protocol _M_protocol{ endpoint_type{}.protocol() };
729 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
730 set_option(socket_base::linger{false, chrono::seconds{}}, __ec);
737 template<typename _Protocol>
739 : public socket_base, private __basic_socket_impl<_Protocol>
741 using __base = __basic_socket_impl<_Protocol>;
746 using executor_type = io_context::executor_type;
747 using native_handle_type = int;
748 using protocol_type = _Protocol;
749 using endpoint_type = typename protocol_type::endpoint;
751 static_assert(__detail::__protocol<protocol_type>,
752 "protocol_type meets the Protocol requirements");
754 // basic_socket operations:
756 executor_type get_executor() noexcept { return __base::get_executor(); }
759 native_handle() noexcept { return __base::native_handle(); }
762 open(const protocol_type& __protocol = protocol_type())
763 { open(__protocol, __throw_on_error{"basic_socket::open"}); }
766 open(const protocol_type& __protocol, error_code& __ec)
767 { __base::open(__protocol, __ec); }
770 assign(const protocol_type& __protocol,
771 const native_handle_type& __native_socket)
773 assign(__protocol, __native_socket,
774 __throw_on_error{"basic_socket::assign"});
778 assign(const protocol_type& __protocol,
779 const native_handle_type& __native_socket,
781 { __base::assign(__protocol, __native_socket, __ec); }
783 native_handle_type release()
784 { return release(__throw_on_error{"basic_socket::release"}); }
786 native_handle_type release(error_code& __ec)
787 { return __base::release(__ec); }
789 _GLIBCXX_NODISCARD bool
790 is_open() const noexcept { return __base::is_open(); }
792 void close() { close(__throw_on_error{"basic_socket::close"}); }
794 void close(error_code& __ec) { __base::close(__ec); }
796 void cancel() { cancel(__throw_on_error{"basic_socket::cancel"}); }
798 void cancel(error_code& __ec) { __base::cancel(__ec); }
800 template<typename _SettableSocketOption>
802 set_option(const _SettableSocketOption& __option)
803 { set_option(__option, __throw_on_error{"basic_socket::set_option"}); }
805 template<typename _SettableSocketOption>
807 set_option(const _SettableSocketOption& __option, error_code& __ec)
808 { __base::set_option(__option, __ec); }
810 template<typename _GettableSocketOption>
812 get_option(_GettableSocketOption& __option) const
813 { get_option(__option, __throw_on_error{"basic_socket::get_option"}); }
815 template<typename _GettableSocketOption>
817 get_option(_GettableSocketOption& __option, error_code& __ec) const
818 { __base::get_option(__option, __ec); }
820 template<typename _IoControlCommand>
822 io_control(_IoControlCommand& __command)
824 io_control(__command, __throw_on_error{"basic_socket::io_control"});
827 template<typename _IoControlCommand>
829 io_control(_IoControlCommand& __command, error_code& __ec)
830 { __base::io_control(__command, __ec); }
833 non_blocking(bool __mode)
834 { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); }
837 non_blocking(bool __mode, error_code& __ec)
838 { __base::non_blocking(__mode, __ec); }
840 bool non_blocking() const { return __base::non_blocking(); }
843 native_non_blocking(bool __mode)
845 native_non_blocking(__mode, __throw_on_error{
846 "basic_socket::native_non_blocking"});
850 native_non_blocking(bool __mode, error_code& __ec)
851 { __base::native_non_blocking(__mode, __ec); }
854 native_non_blocking() const
855 { return __base::native_non_blocking(); }
858 { return at_mark(__throw_on_error{"basic_socket::at_mark"}); }
861 at_mark(error_code& __ec) const
863 #ifdef _GLIBCXX_HAVE_SOCKATMARK
864 const int __result = ::sockatmark(native_handle());
867 __ec.assign(errno, generic_category());
871 return (bool)__result;
873 __ec = std::make_error_code(errc::operation_not_supported);
880 { return available(__throw_on_error{"basic_socket::available"}); }
883 available(error_code& __ec) const
887 __ec = std::make_error_code(errc::bad_file_descriptor);
890 #if defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined FIONREAD
892 if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1)
894 __ec.assign(errno, generic_category());
905 bind(const endpoint_type& __endpoint)
906 { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); }
909 bind(const endpoint_type& __endpoint, error_code& __ec)
910 { __base::bind(__endpoint, __ec); }
912 void shutdown(shutdown_type __what)
913 { return shutdown(__what, __throw_on_error{"basic_socket::shutdown"}); }
916 shutdown(shutdown_type __what, error_code& __ec)
918 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
919 if (::shutdown(native_handle(), static_cast<int>(__what)) == -1)
920 __ec.assign(errno, generic_category());
924 __ec = std::make_error_code(errc::operation_not_supported);
929 local_endpoint() const
931 return local_endpoint(
932 __throw_on_error{"basic_socket::local_endpoint"});
936 local_endpoint(error_code& __ec) const
937 { return __base::local_endpoint(__ec); }
940 remote_endpoint() const
942 return remote_endpoint(
943 __throw_on_error{"basic_socket::remote_endpoint"});
947 remote_endpoint(error_code& __ec) const
949 endpoint_type __endpoint;
950 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
951 socklen_t __endpoint_len = __endpoint.capacity();
952 if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(),
956 __ec.assign(errno, generic_category());
957 return endpoint_type{};
960 __endpoint.resize(__endpoint_len);
962 __ec = std::make_error_code(errc::operation_not_supported);
968 connect(const endpoint_type& __endpoint)
970 return connect(__endpoint, __throw_on_error{"basic_socket::connect"});
974 connect(const endpoint_type& __endpoint, error_code& __ec)
976 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
979 open(__endpoint.protocol(), __ec);
983 if (::connect(native_handle(), (const sockaddr*)__endpoint.data(),
984 __endpoint.size()) == -1)
985 __ec.assign(errno, generic_category());
989 __ec = std::make_error_code(errc::operation_not_supported);
993 template<typename _CompletionToken>
994 __deduced_t<_CompletionToken, void(error_code)>
995 async_connect(const endpoint_type& __endpoint,
996 _CompletionToken&& __token)
998 async_completion<_CompletionToken, void(error_code)> __init{__token};
1003 open(__endpoint.protocol(), __ec);
1006 auto __ex = net::get_associated_executor(
1007 __init.completion_handler, get_executor());
1008 auto __a = get_associated_allocator(
1009 __init.completion_handler, std::allocator<void>());
1011 [__h = std::move(__init.completion_handler), __ec]
1013 { __h(__ec); }, __a);
1014 return __init.result.get();
1018 get_executor().context().async_wait( native_handle(),
1019 (int) socket_base::wait_read,
1020 [__h = std::move(__init.completion_handler),
1021 __ep = std::move(__endpoint),
1022 __fd = native_handle()]
1023 (error_code __ec) mutable {
1024 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1025 if (!__ec && ::connect(__fd, (const sockaddr*)__ep.data(),
1027 __ec.assign(errno, generic_category());
1029 __ec = std::make_error_code(errc::operation_not_supported);
1033 return __init.result.get();
1038 { return wait(__w, __throw_on_error{"basic_socket::wait"}); }
1041 wait(wait_type __w, error_code& __ec)
1043 #ifdef _GLIBCXX_HAVE_POLL_H
1045 __fd.fd = native_handle();
1046 __fd.events = static_cast<int>(__w);
1047 int __res = ::poll(&__fd, 1, -1);
1049 __ec.assign(errno, generic_category());
1053 __ec = std::make_error_code(errc::operation_not_supported);
1057 template<typename _CompletionToken>
1058 __deduced_t<_CompletionToken, void(error_code)>
1059 async_wait(wait_type __w, _CompletionToken&& __token)
1061 async_completion<_CompletionToken, void(error_code)> __init{__token};
1062 get_executor().context().async_wait( native_handle(),
1063 static_cast<int>(__w),
1064 [__h = std::move(__init.completion_handler)]
1065 (error_code __ec) mutable {
1068 return __init.result.get();
1072 // construct / copy / destroy:
1074 using __base::__base;
1077 basic_socket(io_context& __ctx) : __base(__ctx) { }
1079 basic_socket(io_context& __ctx, const protocol_type& __protocol)
1081 { open(__protocol); }
1083 basic_socket(io_context& __ctx, const endpoint_type& __endpoint)
1084 : basic_socket(__ctx, __endpoint.protocol())
1085 { bind(__endpoint); }
1087 basic_socket(io_context& __ctx, const protocol_type& __protocol,
1088 const native_handle_type& __native_socket)
1090 { assign(__protocol, __native_socket); }
1092 basic_socket(const basic_socket&) = delete;
1094 basic_socket(basic_socket&& __rhs) = default;
1096 template<typename _OtherProtocol, typename _Requires
1097 = _Require<is_convertible<_OtherProtocol, _Protocol>>>
1098 basic_socket(basic_socket<_OtherProtocol>&& __rhs)
1099 : __base(std::move(__rhs)) { }
1101 ~basic_socket() = default;
1103 basic_socket& operator=(const basic_socket&) = delete;
1105 basic_socket& operator=(basic_socket&& __rhs) = default;
1107 template<typename _OtherProtocol>
1108 enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
1110 operator=(basic_socket<_OtherProtocol>&& __rhs)
1111 { return *this = basic_socket{std::move(__rhs)}; }
1114 template<typename _Protocol>
1115 class basic_datagram_socket : public basic_socket<_Protocol>
1117 using __base = basic_socket<_Protocol>;
1122 using native_handle_type = int;
1123 using protocol_type = _Protocol;
1124 using endpoint_type = typename protocol_type::endpoint;
1126 // construct / copy / destroy:
1129 basic_datagram_socket(io_context& __ctx) : __base(__ctx) { }
1131 basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol)
1132 : __base(__ctx, __protocol) { }
1134 basic_datagram_socket(io_context& __ctx, const endpoint_type& __endpoint)
1135 : __base(__ctx, __endpoint) { }
1137 basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol,
1138 const native_handle_type& __native_socket)
1139 : __base(__ctx, __protocol, __native_socket) { }
1141 basic_datagram_socket(const basic_datagram_socket&) = delete;
1143 basic_datagram_socket(basic_datagram_socket&& __rhs) = default;
1145 template<typename _OtherProtocol, typename _Requires
1146 = _Require<is_convertible<_OtherProtocol, _Protocol>>>
1147 basic_datagram_socket(basic_datagram_socket<_OtherProtocol>&& __rhs)
1148 : __base(std::move(__rhs)) { }
1150 ~basic_datagram_socket() = default;
1152 basic_datagram_socket& operator=(const basic_datagram_socket&) = delete;
1154 basic_datagram_socket& operator=(basic_datagram_socket&& __rhs) = default;
1156 template<typename _OtherProtocol>
1157 enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
1158 basic_datagram_socket&>
1159 operator=(basic_datagram_socket<_OtherProtocol>&& __rhs)
1161 __base::operator=(std::move(__rhs));
1165 // basic_datagram_socket operations:
1167 template<typename _MutableBufferSequence>
1169 receive(const _MutableBufferSequence& __buffers)
1171 return receive(__buffers, socket_base::message_flags(),
1172 __throw_on_error{"basic_datagram_socket::receive"});
1175 template<typename _MutableBufferSequence>
1177 receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1178 { return receive(__buffers, socket_base::message_flags(), __ec); }
1180 template<typename _MutableBufferSequence>
1182 receive(const _MutableBufferSequence& __buffers,
1183 socket_base::message_flags __flags)
1185 return receive(__buffers, __flags,
1186 __throw_on_error{"basic_datagram_socket::receive"});
1189 template<typename _MutableBufferSequence>
1191 receive(const _MutableBufferSequence& __buffers,
1192 socket_base::message_flags __flags, error_code& __ec)
1194 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1195 socket_base::__msg_hdr __msg(__buffers);
1196 ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1197 static_cast<int>(__flags));
1200 __ec.assign(errno, generic_category());
1206 __ec = std::make_error_code(errc::operation_not_supported);
1211 template<typename _MutableBufferSequence, typename _CompletionToken>
1212 __deduced_t<_CompletionToken, void(error_code, size_t)>
1213 async_receive(const _MutableBufferSequence& __buffers,
1214 _CompletionToken&& __token)
1216 return async_receive(__buffers, socket_base::message_flags(),
1217 std::forward<_CompletionToken>(__token));
1220 template<typename _MutableBufferSequence, typename _CompletionToken>
1221 __deduced_t<_CompletionToken, void(error_code, size_t)>
1222 async_receive(const _MutableBufferSequence& __buffers,
1223 socket_base::message_flags __flags,
1224 _CompletionToken&& __token)
1226 async_completion<_CompletionToken, void(error_code, size_t)>
1229 this->get_executor().context().async_wait(this->native_handle(),
1230 (int) socket_base::wait_read,
1231 [__h = std::move(__init.completion_handler),
1232 &__buffers, __flags = static_cast<int>(__flags),
1233 __fd = this->native_handle()]
1234 (error_code __ec) mutable {
1240 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1241 socket_base::__msg_hdr __msg(__buffers);
1242 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1245 __ec.assign(errno, generic_category());
1250 __h(__ec, __result);
1252 __h(std::make_error_code(errc::operation_not_supported), 0);
1255 return __init.result.get();
1258 template<typename _MutableBufferSequence>
1260 receive_from(const _MutableBufferSequence& __buffers,
1261 endpoint_type& __sender)
1263 return receive_from(__buffers, __sender,
1264 socket_base::message_flags(),
1266 "basic_datagram_socket::receive_from"});
1269 template<typename _MutableBufferSequence>
1271 receive_from(const _MutableBufferSequence& __buffers,
1272 endpoint_type& __sender, error_code& __ec)
1274 return receive_from(__buffers, __sender,
1275 socket_base::message_flags(), __ec);
1278 template<typename _MutableBufferSequence>
1280 receive_from(const _MutableBufferSequence& __buffers,
1281 endpoint_type& __sender,
1282 socket_base::message_flags __flags)
1284 return receive_from(__buffers, __sender, __flags,
1286 "basic_datagram_socket::receive_from"});
1289 template<typename _MutableBufferSequence>
1291 receive_from(const _MutableBufferSequence& __buffers,
1292 endpoint_type& __sender,
1293 socket_base::message_flags __flags,
1296 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1297 socket_base::__msg_hdr __msg(__buffers, __sender);
1298 ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1299 static_cast<int>(__flags));
1302 __ec.assign(errno, generic_category());
1306 __sender.resize(__msg.msg_namelen);
1309 __ec = std::make_error_code(errc::operation_not_supported);
1314 template<typename _MutableBufferSequence, typename _CompletionToken>
1315 __deduced_t<_CompletionToken, void(error_code, size_t)>
1316 async_receive_from(const _MutableBufferSequence& __buffers,
1317 endpoint_type& __sender,
1318 _CompletionToken&& __token)
1320 return async_receive_from(__buffers, __sender,
1321 socket_base::message_flags(),
1322 std::forward<_CompletionToken>(__token));
1325 template<typename _MutableBufferSequence, typename _CompletionToken>
1326 __deduced_t<_CompletionToken, void(error_code, size_t)>
1327 async_receive_from(const _MutableBufferSequence& __buffers,
1328 endpoint_type& __sender,
1329 socket_base::message_flags __flags,
1330 _CompletionToken&& __token)
1332 async_completion<_CompletionToken, void(error_code, size_t)>
1335 this->get_executor().context().async_wait( this->native_handle(),
1336 (int) socket_base::wait_read,
1337 [__h = std::move(__init.completion_handler),
1338 &__buffers, __flags = static_cast<int>(__flags),
1339 __sender = std::move(__sender),
1340 __fd = this->native_handle()]
1341 (error_code __ec) mutable {
1347 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1348 socket_base::__msg_hdr __msg(__buffers, __sender);
1349 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1352 __ec.assign(errno, generic_category());
1358 __sender.resize(__msg.msg_namelen);
1360 __h(__ec, __result);
1362 __h(std::make_error_code(errc::operation_not_supported), 0);
1365 return __init.result.get();
1368 template<typename _ConstBufferSequence>
1370 send(const _ConstBufferSequence& __buffers)
1372 return send(__buffers, socket_base::message_flags(),
1373 __throw_on_error{"basic_datagram_socket::send"});
1376 template<typename _ConstBufferSequence>
1378 send(const _ConstBufferSequence& __buffers, error_code& __ec)
1379 { return send(__buffers, socket_base::message_flags(), __ec); }
1381 template<typename _ConstBufferSequence>
1383 send(const _ConstBufferSequence& __buffers,
1384 socket_base::message_flags __flags)
1386 return send(__buffers, __flags,
1387 __throw_on_error{"basic_datagram_socket::send"});
1390 template<typename _ConstBufferSequence>
1392 send(const _ConstBufferSequence& __buffers,
1393 socket_base::message_flags __flags, error_code& __ec)
1395 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1396 socket_base::__msg_hdr __msg(__buffers);
1397 ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1398 static_cast<int>(__flags));
1401 __ec.assign(errno, generic_category());
1407 __ec = std::make_error_code(errc::operation_not_supported);
1412 template<typename _ConstBufferSequence, typename _CompletionToken>
1413 __deduced_t<_CompletionToken, void(error_code, size_t)>
1414 async_send(const _ConstBufferSequence& __buffers,
1415 _CompletionToken&& __token)
1417 return async_send(__buffers, socket_base::message_flags(),
1418 std::forward<_CompletionToken>(__token));
1421 template<typename _ConstBufferSequence, typename _CompletionToken>
1422 __deduced_t<_CompletionToken, void(error_code, size_t)>
1423 async_send(const _ConstBufferSequence& __buffers,
1424 socket_base::message_flags __flags,
1425 _CompletionToken&& __token)
1427 async_completion<_CompletionToken, void(error_code, size_t)>
1430 this->get_executor().context().async_wait( this->native_handle(),
1431 (int) socket_base::wait_write,
1432 [__h = std::move(__init.completion_handler),
1433 &__buffers, __flags = static_cast<int>(__flags),
1434 __fd = this->native_handle()]
1435 (error_code __ec) mutable {
1441 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1442 socket_base::__msg_hdr __msg(__buffers);
1443 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1446 __ec.assign(errno, generic_category());
1451 __h(__ec, __result);
1453 __h(std::make_error_code(errc::operation_not_supported), 0);
1456 return __init.result.get();
1459 template<typename _ConstBufferSequence>
1461 send_to(const _ConstBufferSequence& __buffers,
1462 const endpoint_type& __recipient)
1464 return send_to(__buffers, __recipient,
1465 socket_base::message_flags(),
1466 __throw_on_error{"basic_datagram_socket::send_to"});
1469 template<typename _ConstBufferSequence>
1471 send_to(const _ConstBufferSequence& __buffers,
1472 const endpoint_type& __recipient, error_code& __ec)
1474 return send_to(__buffers, __recipient,
1475 socket_base::message_flags(), __ec);
1478 template<typename _ConstBufferSequence>
1480 send_to(const _ConstBufferSequence& __buffers,
1481 const endpoint_type& __recipient,
1482 socket_base::message_flags __flags)
1484 return send_to(__buffers, __recipient, __flags,
1485 __throw_on_error{"basic_datagram_socket::send_to"});
1488 template<typename _ConstBufferSequence>
1490 send_to(const _ConstBufferSequence& __buffers,
1491 const endpoint_type& __recipient,
1492 socket_base::message_flags __flags, error_code& __ec)
1494 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1495 socket_base::__msg_hdr __msg(__buffers, __recipient);
1496 ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1497 static_cast<int>(__flags));
1500 __ec.assign(errno, generic_category());
1504 __recipient.resize(__msg.msg_namelen);
1507 __ec = std::make_error_code(errc::operation_not_supported);
1512 template<typename _ConstBufferSequence, typename _CompletionToken>
1513 __deduced_t<_CompletionToken, void(error_code, size_t)>
1514 async_send_to(const _ConstBufferSequence& __buffers,
1515 const endpoint_type& __recipient,
1516 _CompletionToken&& __token)
1518 return async_send_to(__buffers, __recipient,
1519 socket_base::message_flags(),
1520 std::forward<_CompletionToken>(__token));
1523 template<typename _ConstBufferSequence, typename _CompletionToken>
1524 __deduced_t<_CompletionToken, void(error_code, size_t)>
1525 async_send_to(const _ConstBufferSequence& __buffers,
1526 const endpoint_type& __recipient,
1527 socket_base::message_flags __flags,
1528 _CompletionToken&& __token)
1530 async_completion<_CompletionToken, void(error_code, size_t)>
1533 this->get_executor().context().async_wait( this->native_handle(),
1534 (int) socket_base::wait_write,
1535 [__h = std::move(__init.completion_handler),
1536 &__buffers, __flags = static_cast<int>(__flags),
1537 __recipient = std::move(__recipient),
1538 __fd = this->native_handle()]
1539 (error_code __ec) mutable {
1545 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1546 socket_base::__msg_hdr __msg(__buffers, __recipient);
1547 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1550 __ec.assign(errno, generic_category());
1556 __recipient.resize(__msg.msg_namelen);
1558 __h(__ec, __result);
1560 __h(std::make_error_code(errc::operation_not_supported), 0);
1563 return __init.result.get();
1567 template<typename _Protocol>
1568 class basic_stream_socket : public basic_socket<_Protocol>
1570 using __base = basic_socket<_Protocol>;
1575 using native_handle_type = int;
1576 using protocol_type = _Protocol;
1577 using endpoint_type = typename protocol_type::endpoint;
1579 // construct / copy / destroy:
1582 basic_stream_socket(io_context& __ctx) : __base(__ctx) { }
1584 basic_stream_socket(io_context& __ctx, const protocol_type& __protocol)
1585 : __base(__ctx, __protocol) { }
1587 basic_stream_socket(io_context& __ctx, const endpoint_type& __endpoint)
1588 : __base(__ctx, __endpoint) { }
1590 basic_stream_socket(io_context& __ctx, const protocol_type& __protocol,
1591 const native_handle_type& __native_socket)
1592 : __base(__ctx, __protocol, __native_socket) { }
1594 basic_stream_socket(const basic_stream_socket&) = delete;
1596 basic_stream_socket(basic_stream_socket&& __rhs) = default;
1598 template<typename _OtherProtocol, typename _Requires
1599 = _Require<is_convertible<_OtherProtocol, _Protocol>>>
1600 basic_stream_socket(basic_stream_socket<_OtherProtocol>&& __rhs)
1601 : __base(std::move(__rhs)) { }
1603 ~basic_stream_socket() = default;
1605 basic_stream_socket& operator=(const basic_stream_socket&) = delete;
1607 basic_stream_socket& operator=(basic_stream_socket&& __rhs) = default;
1609 template<class _OtherProtocol>
1610 enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
1611 basic_stream_socket&>
1612 operator=(basic_stream_socket<_OtherProtocol>&& __rhs)
1614 __base::operator=(std::move(__rhs));
1618 // basic_stream_socket operations:
1620 template<class _MutableBufferSequence>
1622 receive(const _MutableBufferSequence& __buffers)
1624 return receive(__buffers, socket_base::message_flags(),
1625 __throw_on_error{"basic_stream_socket::receive"});
1628 template<class _MutableBufferSequence>
1630 receive(const _MutableBufferSequence& __buffers, error_code& __ec)
1631 { return receive(__buffers, socket_base::message_flags(), __ec); }
1633 template<class _MutableBufferSequence>
1635 receive(const _MutableBufferSequence& __buffers,
1636 socket_base::message_flags __flags)
1638 return receive(__buffers, __flags,
1639 __throw_on_error{"basic_stream_socket::receive"});
1642 template<class _MutableBufferSequence>
1644 receive(const _MutableBufferSequence& __buffers,
1645 socket_base::message_flags __flags, error_code& __ec)
1647 if (__buffer_empty(__buffers))
1652 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1653 socket_base::__msg_hdr __msg(__buffers);
1654 ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
1655 static_cast<int>(__flags));
1661 __ec.assign(errno, generic_category());
1663 __ec = std::make_error_code(errc::operation_not_supported);
1668 template<class _MutableBufferSequence, class _CompletionToken>
1669 __deduced_t<_CompletionToken, void(error_code, size_t)>
1670 async_receive(const _MutableBufferSequence& __buffers,
1671 _CompletionToken&& __token)
1673 return async_receive(__buffers, socket_base::message_flags(),
1674 std::forward<_CompletionToken>(__token));
1677 template<class _MutableBufferSequence, class _CompletionToken>
1678 __deduced_t<_CompletionToken, void(error_code, size_t)>
1679 async_receive(const _MutableBufferSequence& __buffers,
1680 socket_base::message_flags __flags,
1681 _CompletionToken&& __token)
1683 async_completion<_CompletionToken, void(error_code, size_t)>
1686 if (__buffer_empty(__buffers))
1688 auto __ex = net::get_associated_executor(
1689 __init.completion_handler, this->get_executor());
1690 auto __a = get_associated_allocator(
1691 __init.completion_handler, std::allocator<void>());
1693 [__h=std::move(__init.completion_handler)] () mutable
1694 { __h(error_code{}, 0); }, __a);
1695 return __init.result.get();
1698 this->get_executor().context().async_wait(this->native_handle(),
1699 (int) socket_base::wait_read,
1700 [__h = std::move(__init.completion_handler),
1701 &__buffers, __flags = static_cast<int>(__flags),
1702 __fd = this->native_handle()]
1703 (error_code __ec) mutable {
1709 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1710 socket_base::__msg_hdr __msg(__buffers);
1711 ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
1714 __ec.assign(errno, generic_category());
1719 __h(__ec, __result);
1721 __h(std::make_error_code(errc::operation_not_supported), 0);
1724 return __init.result.get();
1727 template<class _ConstBufferSequence>
1729 send(const _ConstBufferSequence& __buffers)
1731 return send(__buffers, socket_base::message_flags(),
1732 __throw_on_error{"basic_stream_socket::send"});
1735 template<class _ConstBufferSequence>
1737 send(const _ConstBufferSequence& __buffers, error_code& __ec)
1738 { return send(__buffers, socket_base::message_flags(), __ec); }
1740 template<class _ConstBufferSequence>
1742 send(const _ConstBufferSequence& __buffers,
1743 socket_base::message_flags __flags)
1745 return send(__buffers, socket_base::message_flags(),
1746 __throw_on_error{"basic_stream_socket::send"});
1749 template<class _ConstBufferSequence>
1751 send(const _ConstBufferSequence& __buffers,
1752 socket_base::message_flags __flags, error_code& __ec)
1754 if (__buffer_empty(__buffers))
1759 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1760 socket_base::__msg_hdr __msg(__buffers);
1761 ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
1762 static_cast<int>(__flags));
1768 __ec.assign(errno, generic_category());
1770 __ec = std::make_error_code(errc::operation_not_supported);
1775 template<class _ConstBufferSequence, class _CompletionToken>
1776 __deduced_t<_CompletionToken, void(error_code, size_t)>
1777 async_send(const _ConstBufferSequence& __buffers,
1778 _CompletionToken&& __token)
1780 return async_send(__buffers, socket_base::message_flags(),
1781 std::forward<_CompletionToken>(__token));
1784 template<class _ConstBufferSequence, class _CompletionToken>
1785 __deduced_t<_CompletionToken, void(error_code, size_t)>
1786 async_send(const _ConstBufferSequence& __buffers,
1787 socket_base::message_flags __flags,
1788 _CompletionToken&& __token)
1790 async_completion<_CompletionToken, void(error_code, size_t)>
1793 if (__buffer_empty(__buffers))
1795 auto __ex = net::get_associated_executor(
1796 __init.completion_handler, this->get_executor());
1797 auto __a = get_associated_allocator(
1798 __init.completion_handler, std::allocator<void>());
1800 [__h=std::move(__init.completion_handler)] () mutable
1801 { __h(error_code{}, 0); }, __a);
1802 return __init.result.get();
1805 this->get_executor().context().async_wait(this->native_handle(),
1806 (int) socket_base::wait_write,
1807 [__h = std::move(__init.completion_handler),
1808 &__buffers, __flags = static_cast<int>(__flags),
1809 __fd = this->native_handle()]
1810 (error_code __ec) mutable {
1816 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1817 socket_base::__msg_hdr __msg(__buffers);
1818 ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
1821 __ec.assign(errno, generic_category());
1826 __h(__ec, __result);
1828 __h(std::make_error_code(errc::operation_not_supported), 0);
1831 return __init.result.get();
1834 template<class _MutableBufferSequence>
1836 read_some(const _MutableBufferSequence& __buffers)
1838 return receive(__buffers,
1839 __throw_on_error{"basic_stream_socket::read_some"});
1842 template<class _MutableBufferSequence>
1844 read_some(const _MutableBufferSequence& __buffers, error_code& __ec)
1845 { return receive(__buffers, __ec); }
1847 template<class _MutableBufferSequence, class _CompletionToken>
1848 __deduced_t<_CompletionToken, void(error_code, size_t)>
1849 async_read_some(const _MutableBufferSequence& __buffers,
1850 _CompletionToken&& __token)
1852 return async_receive(__buffers,
1853 std::forward<_CompletionToken>(__token));
1856 template<class _ConstBufferSequence>
1858 write_some(const _ConstBufferSequence& __buffers)
1860 return send(__buffers,
1861 __throw_on_error{"basic_stream_socket:write_some"});
1864 template<class _ConstBufferSequence>
1866 write_some(const _ConstBufferSequence& __buffers, error_code& __ec)
1867 { return send(__buffers, __ec); }
1869 template<class _ConstBufferSequence, class _CompletionToken>
1870 __deduced_t<_CompletionToken, void(error_code, size_t)>
1871 async_write_some(const _ConstBufferSequence& __buffers,
1872 _CompletionToken&& __token)
1874 return async_send(__buffers,
1875 std::forward<_CompletionToken>(__token));
1879 template<typename _AcceptableProtocol>
1880 class basic_socket_acceptor
1881 : public socket_base, private __basic_socket_impl<_AcceptableProtocol>
1883 using __base = __basic_socket_impl<_AcceptableProtocol>;
1888 using executor_type = io_context::executor_type;
1889 using native_handle_type = int;
1890 using protocol_type = _AcceptableProtocol;
1891 using endpoint_type = typename protocol_type::endpoint;
1892 using socket_type = typename protocol_type::socket;
1894 static_assert(__detail::__acceptable_protocol<protocol_type>,
1895 "protocol_type meets the AcceptableProtocol requirements");
1897 // construct / copy / destroy:
1900 basic_socket_acceptor(io_context& __ctx)
1901 : __base(__ctx), _M_protocol(endpoint_type{}.protocol()) { }
1903 basic_socket_acceptor(io_context& __ctx,
1904 const protocol_type& __protocol)
1905 : __base(__ctx), _M_protocol(__protocol)
1906 { open(__protocol); }
1908 basic_socket_acceptor(io_context& __ctx, const endpoint_type& __endpoint,
1909 [[__maybe_unused__]] bool __reuse_addr = true)
1910 : basic_socket_acceptor(__ctx, __endpoint.protocol())
1912 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
1914 set_option(reuse_address(true));
1920 basic_socket_acceptor(io_context& __ctx, const protocol_type& __protocol,
1921 const native_handle_type& __native_acceptor)
1922 : basic_socket_acceptor(__ctx, __protocol)
1923 { assign(__protocol, __native_acceptor); }
1925 basic_socket_acceptor(const basic_socket_acceptor&) = delete;
1927 basic_socket_acceptor(basic_socket_acceptor&&) = default;
1929 template<typename _OtherProtocol, typename _Requires
1930 = _Require<is_convertible<_OtherProtocol, protocol_type>>>
1931 basic_socket_acceptor(basic_socket_acceptor<_OtherProtocol>&& __rhs)
1932 : __base(std::move(__rhs)) { }
1934 ~basic_socket_acceptor() = default;
1936 basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete;
1938 basic_socket_acceptor& operator=(basic_socket_acceptor&&) = default;
1940 template<class _OtherProtocol>
1941 enable_if_t<is_convertible<_OtherProtocol, protocol_type>::value,
1942 basic_socket_acceptor&>
1943 operator=(basic_socket_acceptor<_OtherProtocol>&& __rhs)
1945 __base::operator=(std::move(__rhs));
1949 // basic_socket_acceptor operations:
1951 executor_type get_executor() noexcept { return __base::get_executor(); }
1954 native_handle() noexcept { return __base::native_handle(); }
1957 open(const protocol_type& __protocol = protocol_type())
1958 { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); }
1961 open(const protocol_type& __protocol, error_code& __ec)
1962 { __base::open(__protocol, __ec); }
1965 assign(const protocol_type& __protocol,
1966 const native_handle_type& __native_acceptor)
1968 assign(__protocol, __native_acceptor,
1969 __throw_on_error{"basic_socket_acceptor::assign"});
1973 assign(const protocol_type& __protocol,
1974 const native_handle_type& __native_acceptor,
1976 { __base::assign(__protocol, __native_acceptor, __ec); }
1978 native_handle_type release()
1979 { return release(__throw_on_error{"basic_socket_acceptor::release"}); }
1981 native_handle_type release(error_code& __ec)
1982 { return __base::release(__ec); }
1984 _GLIBCXX_NODISCARD bool
1985 is_open() const noexcept { return __base::is_open(); }
1988 close() { close(__throw_on_error{"basic_socket_acceptor::close"}); }
1991 close(error_code& __ec) { __base::_close(__ec); }
1994 cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); }
1997 cancel(error_code& __ec) { __base::cancel(__ec); }
1999 template<typename _SettableSocketOption>
2001 set_option(const _SettableSocketOption& __option)
2003 set_option(__option,
2004 __throw_on_error{"basic_socket_acceptor::set_option"});
2007 template<typename _SettableSocketOption>
2009 set_option(const _SettableSocketOption& __option, error_code& __ec)
2010 { __base::set_option(__option, __ec); }
2012 template<typename _GettableSocketOption>
2014 get_option(_GettableSocketOption& __option) const
2016 get_option(__option,
2017 __throw_on_error{"basic_socket_acceptor::get_option"});
2020 template<typename _GettableSocketOption>
2022 get_option(_GettableSocketOption& __option, error_code& __ec) const
2023 { __base::get_option(__option, __ec); }
2025 template<typename _IoControlCommand>
2027 io_control(_IoControlCommand& __command)
2029 io_control(__command,
2030 __throw_on_error{"basic_socket_acceptor::io_control"});
2033 template<typename _IoControlCommand>
2035 io_control(_IoControlCommand& __command, error_code& __ec)
2036 { __base::io_control(__command, __ec); }
2039 non_blocking(bool __mode)
2041 non_blocking(__mode,
2042 __throw_on_error{"basic_socket_acceptor::non_blocking"});
2046 non_blocking(bool __mode, error_code& __ec)
2047 { __base::non_blocking(__mode, __ec); }
2049 bool non_blocking() const { return __base::non_blocking(); }
2052 native_non_blocking(bool __mode)
2054 native_non_blocking(__mode, __throw_on_error{
2055 "basic_socket_acceptor::native_non_blocking"});
2059 native_non_blocking(bool __mode, error_code& __ec)
2060 { __base::native_non_blocking(__mode, __ec); }
2063 native_non_blocking() const
2064 { return __base::native_non_blocking(); }
2067 bind(const endpoint_type& __endpoint)
2069 return bind(__endpoint,
2070 __throw_on_error{"basic_socket_acceptor::bind"});
2074 bind(const endpoint_type& __endpoint, error_code& __ec)
2075 { __base::bind(__endpoint, __ec); }
2078 listen(int __backlog = max_listen_connections)
2080 return listen(__backlog,
2081 __throw_on_error{"basic_socket_acceptor::listen"});
2085 listen(int __backlog, error_code& __ec)
2087 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2088 if (::listen(native_handle(), __backlog) == -1)
2089 __ec.assign(errno, generic_category());
2093 __ec = std::make_error_code(errc::operation_not_supported);
2098 local_endpoint() const
2100 return local_endpoint(
2101 __throw_on_error{"basic_socket_acceptor::local_endpoint"});
2105 local_endpoint(error_code& __ec) const
2106 { return __base::local_endpoint(__ec); }
2109 enable_connection_aborted(bool __mode)
2110 { __base::_M_bits.enable_connection_aborted = __mode; }
2113 enable_connection_aborted() const
2114 { return __base::_M_bits.enable_connection_aborted; }
2118 { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); }
2121 accept(error_code& __ec)
2122 { return accept(get_executor().context(), __ec); }
2124 socket_type accept(io_context& __ctx)
2126 return accept(__ctx,
2127 __throw_on_error{"basic_socket_acceptor::accept"});
2131 accept(io_context& __ctx, error_code& __ec)
2133 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2136 int __h = ::accept(native_handle(), nullptr, 0);
2140 return socket_type{__ctx, _M_protocol, __h};
2142 } while (errno == ECONNABORTED && enable_connection_aborted());
2143 __ec.assign(errno, generic_category());
2145 __ec = std::make_error_code(errc::operation_not_supported);
2147 return socket_type{__ctx};
2150 template<class _CompletionToken>
2151 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2152 async_accept(_CompletionToken&& __token)
2154 return async_accept(get_executor().context(),
2155 std::forward<_CompletionToken>(__token));
2158 template<class _CompletionToken>
2159 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2160 async_accept(io_context& __ctx, _CompletionToken&& __token)
2162 async_completion<_CompletionToken, void(error_code, socket_type)>
2165 __ctx.async_wait(native_handle(),
2166 (int) socket_base::wait_read,
2167 [__h = std::move(__init.completion_handler),
2168 __connabort = enable_connection_aborted(),
2169 __fd = native_handle(),
2170 __protocol = _M_protocol,
2173 (error_code __ec) mutable {
2176 __h(__ec, socket_type(__ctx));
2179 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2182 int __newfd = ::accept(__fd, nullptr, 0);
2186 __h(__ec, socket_type{__ctx, __protocol, __newfd});
2189 } while (errno == ECONNABORTED && __connabort);
2190 __ec.assign(errno, generic_category());
2191 __h(__ec, socket_type(__ctx));
2193 __h(std::make_error_code(errc::operation_not_supported), 0);
2196 return __init.result.get();
2200 accept(endpoint_type& __endpoint)
2202 return accept(get_executor().context(), __endpoint,
2203 __throw_on_error{"basic_socket_acceptor::accept"});
2207 accept(endpoint_type& __endpoint, error_code& __ec)
2208 { return accept(get_executor().context(), __endpoint, __ec); }
2211 accept(io_context& __ctx, endpoint_type& __endpoint)
2213 return accept(__ctx, __endpoint,
2214 __throw_on_error{"basic_socket_acceptor::accept"});
2218 accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec)
2220 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2223 socklen_t __len = __endpoint.capacity();
2224 int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(),
2228 __endpoint.resize(__len);
2229 return socket_type{__ctx, _M_protocol, __h};
2231 } while (errno == ECONNABORTED && enable_connection_aborted());
2232 __ec.assign(errno, generic_category());
2234 __ec = std::make_error_code(errc::operation_not_supported);
2236 return socket_type{__ctx};
2239 template<class _CompletionToken>
2240 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2241 async_accept(endpoint_type& __endpoint,
2242 _CompletionToken&& __token)
2244 return async_accept(get_executor().context(), __endpoint,
2245 std::forward<_CompletionToken>(__token));
2248 template<class _CompletionToken>
2249 __deduced_t<_CompletionToken, void(error_code, socket_type)>
2250 async_accept(io_context& __ctx, endpoint_type& __endpoint,
2251 _CompletionToken&& __token)
2253 async_completion<_CompletionToken, void(error_code, socket_type)>
2256 __ctx.async_wait(native_handle(),
2257 (int) socket_base::wait_read,
2258 [__h = std::move(__init.completion_handler),
2259 __ep = std::move(__endpoint),
2260 __connabort = enable_connection_aborted(),
2261 __fd = native_handle(),
2264 (error_code __ec) mutable {
2267 __h(__ec, socket_type(__ctx));
2270 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
2273 socklen_t __len = __ep.capacity();
2274 int __newfd = ::accept(__fd, __ep.data, &__len);
2278 auto __protocol = __ep.protocol();
2280 __h(__ec, socket_type{__ctx, __protocol, __newfd});
2283 } while (errno == ECONNABORTED && __connabort);
2284 __ec.assign(errno, generic_category());
2286 __ec = std::make_error_code(errc::operation_not_supported);
2288 __h(__ec, socket_type(__ctx));
2290 return __init.result.get();
2295 { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); }
2298 wait(wait_type __w, error_code& __ec)
2300 #ifdef _GLIBCXX_HAVE_POLL_H
2302 __fds.fd = native_handle();
2303 __fds.events = __w; // __w | POLLIN;
2304 if (::poll(&__fds, 1, -1) == -1)
2305 __ec.assign(errno, generic_category());
2309 __ec = std::make_error_code(errc::operation_not_supported);
2313 template<class _CompletionToken>
2314 __deduced_t<_CompletionToken, void(error_code)>
2315 async_wait(wait_type __w, _CompletionToken&& __token)
2317 async_completion<_CompletionToken, void(error_code)> __init{__token};
2318 get_executor().context().async_wait( native_handle(),
2319 static_cast<int>(__w),
2320 [__h = std::move(__init.completion_handler)]
2321 (error_code __ec) mutable {
2324 return __init.result.get();
2328 protocol_type _M_protocol;
2333 /** @brief Socket streams
2337 template<typename _Protocol, typename _Clock, typename _WaitTraits>
2338 class basic_socket_streambuf : public basic_streambuf<char>
2343 using protocol_type = _Protocol;
2344 using endpoint_type = typename protocol_type::endpoint;
2345 using clock_type = _Clock;
2346 using time_point = typename clock_type::time_point;
2347 using duration = typename clock_type::duration;
2348 using wait_traits_type = _WaitTraits;
2350 // construct / copy / destroy:
2352 basic_socket_streambuf() : _M_socket(_S_ctx()) { }
2355 basic_socket_streambuf(basic_stream_socket<protocol_type> __s)
2356 : _M_socket(std::move(__s)) { }
2358 basic_socket_streambuf(const basic_socket_streambuf&) = delete;
2360 basic_socket_streambuf(basic_socket_streambuf&& __rhs); // TODO
2363 virtual ~basic_socket_streambuf(); // TODO
2365 basic_socket_streambuf& operator=(const basic_socket_streambuf&) = delete;
2367 basic_socket_streambuf& operator=(basic_socket_streambuf&& __rhs); // TODO
2371 basic_socket_streambuf* connect(const endpoint_type& __e); // TODO
2373 template<typename... _Args>
2374 basic_socket_streambuf* connect(_Args&&... ); // TODO
2376 basic_socket_streambuf* close(); // TODO
2378 basic_socket<protocol_type>& socket() { return _M_socket; }
2380 error_code error() const noexcept { return _M_ec; }
2382 time_point expiry() const { return _M_expiry; }
2385 expires_at(const time_point& __t)
2386 { _M_expiry = __t; }
2389 expires_after(const duration& __d)
2390 { expires_at(clock_type::now() + __d); }
2393 // overridden virtual functions: // TODO
2394 virtual int_type underflow() override;
2395 virtual int_type pbackfail(int_type __c = traits_type::eof()) override;
2396 virtual int_type overflow(int_type __c = traits_type::eof()) override;
2397 virtual int sync() override;
2398 virtual streambuf* setbuf(char_type* __s, streamsize __n) override;
2404 static io_context __ctx;
2408 basic_stream_socket<protocol_type> _M_socket;
2410 time_point _M_expiry{ time_point::max() };
2413 template<typename _Protocol, class _Clock, typename _WaitTraits>
2414 class basic_socket_iostream : public basic_iostream<char>
2416 using __streambuf_type
2417 = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>;
2422 using protocol_type = _Protocol;
2423 using endpoint_type = typename protocol_type::endpoint;
2424 using clock_type = _Clock;
2425 using time_point = typename clock_type::time_point;
2426 using duration = typename clock_type::duration;
2427 using wait_traits_type = _WaitTraits;
2429 // construct / copy / destroy:
2431 // TODO base-from-member ?
2432 basic_socket_iostream() : basic_iostream(nullptr), _M_sb()
2434 this->init(std::addressof(_M_sb));
2435 this->setf(std::ios::unitbuf);
2439 basic_socket_iostream(basic_stream_socket<protocol_type> __s)
2440 : basic_iostream(nullptr), _M_sb(std::move(__s))
2442 this->init(std::addressof(_M_sb));
2443 this->setf(std::ios::unitbuf);
2446 basic_socket_iostream(const basic_socket_iostream&) = delete;
2448 basic_socket_iostream(basic_socket_iostream&& __rhs)
2449 : basic_iostream(nullptr), _M_sb(std::move(__rhs._M_sb))
2452 // XXX ??? this->init(std::addressof(_M_sb));
2453 this->set_rdbuf(std::addressof(_M_sb));
2456 template<typename... _Args>
2458 basic_socket_iostream(_Args&&... __args)
2459 : basic_iostream(nullptr), _M_sb()
2461 this->init(std::addressof(_M_sb));
2462 this->setf(std::ios::unitbuf);
2463 connect(forward<_Args>(__args)...);
2466 basic_socket_iostream& operator=(const basic_socket_iostream&) = delete;
2468 basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO
2472 template<typename... _Args>
2474 connect(_Args&&... __args)
2476 if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr)
2477 this->setstate(failbit);
2483 if (rdbuf()->close() == nullptr)
2484 this->setstate(failbit);
2487 basic_socket_streambuf<protocol_type, clock_type, wait_traits_type>*
2489 { return const_cast<__streambuf_type*>(std::addressof(_M_sb)); }
2491 basic_socket<protocol_type>& socket() { return rdbuf()->socket(); }
2492 error_code error() const noexcept { return rdbuf()->error(); }
2494 time_point expiry() const { return rdbuf()->expiry(); }
2495 void expires_at(const time_point& __t) { rdbuf()->expires_at(__t); }
2496 void expires_after(const duration& __d) { rdbuf()->expires_after(__d); }
2499 __streambuf_type _M_sb;
2504 /** @brief synchronous connect operations
2508 template<typename _Protocol, typename _EndpointSequence,
2509 typename _ConnectCondition>
2510 inline typename _Protocol::endpoint
2511 connect(basic_socket<_Protocol>& __s,
2512 const _EndpointSequence& __endpoints,
2513 _ConnectCondition __c, error_code& __ec)
2516 bool __found = false;
2517 for (auto& __ep : __endpoints)
2519 if (__c(__ec, __ep))
2524 __s.open(__ep.protocol(), __ec);
2526 __s.connect(__ep, __ec);
2532 __ec = socket_errc::not_found;
2533 return typename _Protocol::endpoint{};
2536 template<typename _Protocol, typename _InputIterator,
2537 typename _ConnectCondition>
2538 inline _InputIterator
2539 connect(basic_socket<_Protocol>& __s,
2540 _InputIterator __first, _InputIterator __last,
2541 _ConnectCondition __c, error_code& __ec)
2544 bool __found = false;
2545 for (auto __i = __first; __i != __last; ++__i)
2547 if (__c(__ec, *__i))
2552 __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec);
2554 __s.connect(*__i, __ec);
2560 __ec = socket_errc::not_found;
2564 template<typename _Protocol, typename _EndpointSequence,
2565 typename _ConnectCondition>
2566 inline typename _Protocol::endpoint
2567 connect(basic_socket<_Protocol>& __s,
2568 const _EndpointSequence& __endpoints,
2569 _ConnectCondition __c)
2571 return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"});
2574 template<typename _Protocol, typename _InputIterator,
2575 typename _ConnectCondition>
2576 inline _InputIterator
2577 connect(basic_socket<_Protocol>& __s,
2578 _InputIterator __first, _InputIterator __last,
2579 _ConnectCondition __c)
2581 return net::connect(__s, __first, __last, __c,
2582 __throw_on_error{"connect"});
2585 template<typename _Protocol, typename _EndpointSequence>
2586 inline typename _Protocol::endpoint
2587 connect(basic_socket<_Protocol>& __s,
2588 const _EndpointSequence& __endpoints)
2590 return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2591 __throw_on_error{"connect"});
2594 template<typename _Protocol, typename _EndpointSequence>
2595 inline typename _Protocol::endpoint
2596 connect(basic_socket<_Protocol>& __s,
2597 const _EndpointSequence& __endpoints,
2600 return net::connect(__s, __endpoints, [](auto, auto){ return true; },
2604 template<typename _Protocol, typename _InputIterator>
2605 inline _InputIterator
2606 connect(basic_socket<_Protocol>& __s,
2607 _InputIterator __first, _InputIterator __last)
2609 return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2610 __throw_on_error{"connect"});
2613 template<typename _Protocol, typename _InputIterator>
2614 inline _InputIterator
2615 connect(basic_socket<_Protocol>& __s,
2616 _InputIterator __first, _InputIterator __last,
2619 return net::connect(__s, __first, __last, [](auto, auto){ return true; },
2625 /** @brief asynchronous connect operations
2629 template<typename _Protocol, typename _EndpointSequence,
2630 typename _ConnectCondition, typename _CompletionToken>
2632 __deduced_t<_CompletionToken,
2633 void(error_code, typename _Protocol::endpoint)>
2634 async_connect(basic_socket<_Protocol>& __s,
2635 const _EndpointSequence& __endpoints,
2636 _ConnectCondition __c, _CompletionToken&& __token); // TODO
2638 template<typename _Protocol, typename _EndpointSequence,
2639 typename _CompletionToken>
2641 __deduced_t<_CompletionToken,
2642 void(error_code, typename _Protocol::endpoint)>
2643 async_connect(basic_socket<_Protocol>& __s,
2644 const _EndpointSequence& __endpoints,
2645 _CompletionToken&& __token)
2647 return net::async_connect(__s, __endpoints,
2648 [](auto, auto){ return true; },
2649 forward<_CompletionToken>(__token));
2652 template<typename _Protocol, typename _InputIterator,
2653 typename _ConnectCondition, typename _CompletionToken>
2655 __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
2656 async_connect(basic_socket<_Protocol>& __s,
2657 _InputIterator __first, _InputIterator __last,
2658 _ConnectCondition __c, _CompletionToken&& __token); // TODO
2660 template<typename _Protocol, typename _InputIterator,
2661 typename _CompletionToken>
2663 __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
2664 async_connect(basic_socket<_Protocol>& __s,
2665 _InputIterator __first, _InputIterator __last,
2666 _CompletionToken&& __token)
2668 return net::async_connect(__s, __first, __last,
2669 [](auto, auto){ return true; },
2670 forward<_CompletionToken>(__token));
2675 #endif // _GLIBCXX_HAVE_UNISTD_H
2681 } // namespace experimental
2683 _GLIBCXX_END_NAMESPACE_VERSION
2688 #endif // _GLIBCXX_EXPERIMENTAL_SOCKET