source: Daodan/MSYS2/mingw32/include/c++/11.2.0/experimental/socket@ 1181

Last change on this file since 1181 was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

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