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