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