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