MySQL 9.1.0
Source Code Documentation
socket.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2020, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_HARNESS_NET_TS_SOCKET_H_
27#define MYSQL_HARNESS_NET_TS_SOCKET_H_
28
29#include <bitset>
30#include <stdexcept> // length_error
31#include <system_error>
32
33#ifdef _WIN32
34#include <WS2tcpip.h> // inet_ntop
35#include <WinSock2.h>
36#include <Windows.h>
37#else
38#include <sys/types.h> // before netinet* on FreeBSD for uint8_t
39
40#include <arpa/inet.h> // htons
41#include <netinet/in.h> // in_addr_t
42#include <netinet/ip6.h> // in6_addr_t
43#include <netinet/tcp.h> // TCP_NODELAY
44#include <sys/ioctl.h> // FIONREAD, SIOATMARK
45#include <termios.h> // TIOCOUTQ
46#ifdef __sun__
47#include <sys/filio.h> // FIONREAD
48#include <sys/sockio.h> // SIOATMARK
49#endif
50#endif
51
53
58
59namespace net {
60
61// 18.3 [socket.err]
62// implemented in impl/socket_error.h
63
64// 18.5 [socket.opt]
65
66namespace socket_option {
67
68/**
69 * base-class of socket options.
70 *
71 * can be used to implement type safe socket options.
72 *
73 * @see socket_option::integer
74 * @see socket_option::boolean
75 */
76template <int Level, int Name, class T, class V = T>
78 public:
79 using value_type = T;
80 using storage_type = V;
81
82 constexpr option_base() : value_{} {}
83
84 constexpr explicit option_base(value_type v)
85 : value_{static_cast<storage_type>(v)} {}
86
87 value_type value() const { return value_; }
88
89 template <typename Protocol>
90 constexpr int level(const Protocol & /* unused */) const noexcept {
91 return Level;
92 }
93
94 template <typename Protocol>
95 constexpr int name(const Protocol & /* unused */) const noexcept {
96 return Name;
97 }
98
99 template <typename Protocol>
100 const storage_type *data(const Protocol & /* unused */) const {
101 return std::addressof(value_);
102 }
103
104 template <typename Protocol>
105 storage_type *data(const Protocol & /* unused */) {
106 return std::addressof(value_);
107 }
108
109 template <typename Protocol>
110 constexpr size_t size(const Protocol & /* unused */) const {
111 return sizeof(value_);
112 }
113
114 template <class Protocol>
115 void resize(const Protocol & /* p */, size_t s) {
116 if (s != sizeof(value_)) {
117 throw std::length_error("size != sizeof(value_)");
118 }
119 }
120
121 private:
123};
124
125/**
126 * socket option that uses bool as value_type.
127 */
128template <int Level, int Name>
130
131/**
132 * socket option that uses int as value_type.
133 */
134template <int Level, int Name>
136
137} // namespace socket_option
138
139// 18.4 [socket.base]
140
142 public:
146 using error =
149
150 class linger;
151
158
160
166
171
172 enum class shutdown_type {
173#ifdef _WIN32
174 shutdown_receive = SD_RECEIVE,
175 shutdown_send = SD_SEND,
176 shutdown_both = SD_BOTH,
177#else
178 shutdown_receive = SHUT_RD,
179 shutdown_send = SHUT_WR,
180 shutdown_both = SHUT_RDWR,
181#endif
182 };
187
188 static const int max_listen_connections{SOMAXCONN};
189
190 protected:
191 // msg_hdr used by writev(), sendv(), sendmsg(), WSASend()
192 //
193 // windows and posix have slight different msghdr struct layouts.
195 std::array<impl::socket::iovec_base, 16> iov_{};
196
197 public:
198 template <class BufferSequence>
199 explicit msg_hdr(const BufferSequence &buffers)
200 : impl::socket::msghdr_base{} {
201 const size_t iovs_capacity = iov_.size();
202 const auto bufend = buffer_sequence_end(buffers);
203 size_t i = 0;
204
205 for (auto bufcur = buffer_sequence_begin(buffers);
206 (i < iovs_capacity) && (bufcur != bufend); ++i, ++bufcur) {
207#ifdef _WIN32
208 iov_[i].buf =
209 const_cast<CHAR *>(reinterpret_cast<const CHAR *>(bufcur->data()));
210 iov_[i].len = static_cast<DWORD>(bufcur->size());
211#else
212 iov_[i] = {const_cast<void *>(bufcur->data()), bufcur->size()};
213#endif
214 }
215
216#ifdef _WIN32
217 this->lpBuffers = iov_.data();
218 this->dwBufferCount = static_cast<DWORD>(i);
219#else
220 this->msg_iov = iov_.data();
221 this->msg_iovlen = i;
222#endif
223 }
224
225 /**
226 * set sender of the message.
227 *
228 * used by the UDP and Linux TCP Fast Open.
229 */
230 template <class endpoint_type>
231 void set_sender(endpoint_type &ep) {
232#ifdef _WIN32
233 this->name = static_cast<SOCKADDR *>(ep.data());
234 this->namelen = ep.capacity();
235#else
236 this->msg_name = ep.data();
237 this->msg_namelen = ep.capacity();
238#endif
239 }
240
241 /**
242 * set the size of the sender after data was received.
243 */
244 template <class endpoint_type>
245 void resize_sender(endpoint_type &ep) {
246#ifdef _WIN32
247 ep.resize(this->namelen);
248#else
249 ep.resize(this->msg_namelen);
250#endif
251 }
252
253 /**
254 * set recipient of the message.
255 */
256 template <class endpoint_type>
257 void set_recipient(const endpoint_type &ep) {
258#ifdef _WIN32
259 this->name =
260 const_cast<SOCKADDR *>(static_cast<const SOCKADDR *>(ep.data()));
261 this->namelen = ep.size();
262#else
263 this->msg_name = const_cast<void *>(ep.data());
264 this->msg_namelen = ep.size();
265#endif
266 }
267 };
268};
269
270// 18.5.1
271
272/**
273 * socket option for SO_LINGER
274 */
276 public:
277 linger() noexcept : value_{0, 0} {}
278
279 linger(bool e, std::chrono::seconds t) noexcept
280 : value_{e, static_cast<decltype(value_.l_linger)>(t.count())} {}
281
282 bool enabled() const noexcept { return value_.l_onoff != 0; }
283 void enabled(bool e) noexcept { value_.l_onoff = e; }
284
285 std::chrono::seconds timeout() const noexcept {
286 return std::chrono::seconds(value_.l_linger);
287 }
288 void timeout(std::chrono::seconds t) noexcept {
289 value_.l_linger = static_cast<int>(t.count());
290 }
291
292 template <class Protocol>
293 int level(const Protocol & /* p */) const noexcept {
294 return SOL_SOCKET;
295 }
296
297 template <class Protocol>
298 int name(const Protocol & /* p */) const noexcept {
299 return SO_LINGER;
300 }
301
302 template <class Protocol>
303 void *data(const Protocol & /* p */) noexcept {
304 return std::addressof(value_);
305 }
306
307 template <class Protocol>
308 const void *data(const Protocol & /* p */) const noexcept {
309 return std::addressof(value_);
310 }
311
312 template <class Protocol>
313 size_t size(const Protocol & /* p */) const noexcept {
314 return sizeof(value_);
315 }
316
317 template <class Protocol>
318 void resize(const Protocol & /* p */, size_t s) {
319 if (s != sizeof(value_)) {
320 throw std::length_error("size != sizeof(::linger)");
321 }
322 }
323
324 private:
326};
327
328/**
329 * template-less base-class of basic_socket_impl.
330 *
331 * all of the parts of basic_socket_impl that are not dependent on Protocol
332 * - native_handle
333 * - non-blocking flags
334 */
336 public:
339
340 constexpr explicit basic_socket_impl_base(io_context &ctx) : io_ctx_{&ctx} {}
341
344
346 : native_handle_{std::exchange(rhs.native_handle_,
348 non_blocking_{std::exchange(rhs.non_blocking_, 0)},
349 native_non_blocking_{std::exchange(rhs.native_non_blocking_, 0)},
350 io_ctx_{std::move(rhs.io_ctx_)} {}
351
354 std::exchange(rhs.native_handle_, impl::socket::kInvalidSocket);
355 non_blocking_ = std::exchange(rhs.non_blocking_, 0);
356 native_non_blocking_ = std::exchange(rhs.native_non_blocking_, 0);
357 io_ctx_ = rhs.io_ctx_;
358
359 return *this;
360 }
361
363
364 constexpr native_handle_type native_handle() const noexcept {
365 return native_handle_;
366 }
367
368 constexpr bool is_open() const noexcept {
370 }
371
372 constexpr bool non_blocking() const { return non_blocking_; }
373
375 if (!is_open()) {
376 return stdx::unexpected(
377 std::make_error_code(std::errc::bad_file_descriptor));
378 }
380
381 return {};
382 }
383
384 bool native_non_blocking() const {
385 if (static_cast<char>(-1) != native_non_blocking_)
387
389 if (res) native_non_blocking_ = *res;
390
392 }
393
395 if (!is_open()) {
396 return stdx::unexpected(
397 std::make_error_code(std::errc::bad_file_descriptor));
398 }
399
400 if (!mode && non_blocking()) {
401 return stdx::unexpected(
402 std::make_error_code(std::errc::invalid_argument));
403 }
404
405 auto res =
407 if (!res) return res;
408
409 native_non_blocking_ = mode ? 1 : 0;
410
411 return res;
412 }
413
415
417 if (is_open()) {
418 cancel();
419
420 auto res = io_ctx_->socket_service()->close(native_handle());
421
422 // after close() finished, the socket's state is undefined even if it
423 // failed. See "man close" on Linux.
425
426 return res;
427 }
428
429 return {};
430 }
431
433 if (!is_open()) {
434 return stdx::unexpected(make_error_code(std::errc::bad_file_descriptor));
435 }
436
438 return {};
439 }
440
442 if (is_open()) {
443 cancel();
444 }
445 return std::exchange(native_handle_, impl::socket::kInvalidSocket);
446 }
447
448 protected:
450
451 bool non_blocking_{false};
453#ifdef _WIN32
454 // on windows we can't detect the non-blocking state.
455 //
456 // Let's assume it defaults to 0. *fingerscross*
457 0
458#else
459 // on unixes we don't know what the state of non-blocking is after
460 // accept(), better check for it.
461 static_cast<char>(-1)
462#endif
463 };
464
466};
467
468// 18.6 [socket.basic]
469template <typename Protocol>
471 public:
473
476 using endpoint_type = typename protocol_type::endpoint;
477 using error_type = std::error_code;
479
480 constexpr explicit basic_socket_impl(io_context &ctx) noexcept
481 : __base{ctx} {}
482
486
488 if (this == std::addressof(rhs)) {
489 return *this;
490 }
491
492 close();
493 __base::operator=(std::move(rhs));
494
495 return *this;
496 }
497
499 if (is_open()) close();
500 }
501
503 const protocol_type &protocol = protocol_type(), int flags = 0) {
504 if (is_open()) {
506 }
507 auto res = io_ctx_->socket_service()->socket(
508 protocol.family(), protocol.type() | flags, protocol.protocol());
509 if (!res) return stdx::unexpected(res.error());
510#ifdef SOCK_NONBLOCK
511 if ((flags & SOCK_NONBLOCK) != 0) {
513 }
514#endif
515
516 return assign(protocol, res.value());
517 }
518
520 const protocol_type &protocol, const native_handle_type &native_handle) {
521 if (is_open()) {
523 }
524 protocol_ = protocol;
526
527 return {};
528 }
529
531 return io_ctx_->socket_service()->bind(
533 reinterpret_cast<const struct sockaddr *>(endpoint.data()),
534 endpoint.size());
535 }
536
538 struct sockaddr *endpoint_data,
539 socklen_t *endpoint_size,
540 int flags = 0) {
542 if (flags != 0) {
543 auto res = io_ctx_->socket_service()->accept4(
544 native_handle(), endpoint_data, endpoint_size, flags);
545 if (res) {
546 return socket_type{io_ctx, protocol_, res.value()};
547 } else if (res.error() != std::errc::operation_not_supported) {
548 return stdx::unexpected(res.error());
549 }
550
551 // otherwise fall through to accept without flags
552 }
553 auto res = io_ctx_->socket_service()->accept(native_handle(), endpoint_data,
554 endpoint_size);
555 if (!res) return stdx::unexpected(res.error());
556
557 return ret_type{std::in_place, io_ctx, protocol_, std::move(res.value())};
558 }
559
561 int flags = 0) {
562 return accept(io_ctx, static_cast<struct sockaddr *>(nullptr), nullptr,
563 flags);
564 }
565
567 endpoint_type &endpoint,
568 int flags = 0) {
569 socklen_t endpoint_len = endpoint.capacity();
570
571 auto res = accept(io_ctx, static_cast<struct sockaddr *>(endpoint.data()),
572 &endpoint_len, flags);
573 if (res) {
574 endpoint.resize(endpoint_len);
575 }
576 return res;
577 }
578
581 return io_ctx_->socket_service()->listen(native_handle(), backlog);
582 }
583
584 template <typename SettableSocketOption>
586 const SettableSocketOption &option) {
588 native_handle(), option.level(protocol_), option.name(protocol_),
589 option.data(protocol_), static_cast<socklen_t>(option.size(protocol_)));
590 }
591
592 template <typename GettableSocketOption>
594 GettableSocketOption &option) const {
595 socklen_t option_len = option.size(protocol_);
596 auto res = io_ctx_->socket_service()->getsockopt(
597 native_handle(), option.level(protocol_), option.name(protocol_),
598 option.data(protocol_), &option_len);
599
600 if (!res) return res;
601
602 option.resize(protocol_, option_len);
603
604 return {};
605 }
606
608 endpoint_type ep;
609 size_t ep_len = ep.capacity();
610
611 auto res = io_ctx_->socket_service()->getsockname(
612 native_handle(), reinterpret_cast<struct sockaddr *>(ep.data()),
613 &ep_len);
614 if (!res) return stdx::unexpected(res.error());
615
616 ep.resize(ep_len);
617
618 return ep;
619 }
620
622 endpoint_type ep;
623 size_t ep_len = ep.capacity();
624
625 auto res = io_ctx_->socket_service()->getpeername(
626 native_handle(), reinterpret_cast<struct sockaddr *>(ep.data()),
627 &ep_len);
628 if (!res) return stdx::unexpected(res.error());
629
630 ep.resize(ep_len);
631
632 return ep;
633 }
634
635 // NOLINTNEXTLINE(google-runtime-int)
636 template <unsigned long Name, class T>
637 class IoControl {
638 public:
639 using value_type = T;
640
641 constexpr IoControl() : val_{} {}
642
643 constexpr explicit IoControl(value_type v) : val_{v} {}
644
645 // NOLINTNEXTLINE(google-runtime-int)
646 constexpr unsigned long name() const { return Name; }
647
648 constexpr void *data() { return &val_; }
649
650 constexpr value_type value() const { return val_; }
651
652 private:
654 };
655
658#ifndef _WIN32
660#else
661 using io_control_socket_set_high_water_mark = IoControl<SIOCSHIWAT, int>;
662 using io_control_socket_get_high_water_mark = IoControl<SIOCGHIWAT, int>;
663 using io_control_socket_set_low_water_mark = IoControl<SIOCSLOWAT, int>;
664 using io_control_socket_get_low_water_mark = IoControl<SIOCGLOWAT, int>;
665#endif
666
667 template <class IoControlCommand>
668 stdx::expected<void, error_type> io_control(IoControlCommand &cmd) const {
669 return io_ctx_->socket_service()->ioctl(native_handle(), cmd.name(),
670 cmd.data());
671 }
672
675
676 auto res = io_control(ioc);
677 if (!res) return stdx::unexpected(res.error());
678
679 if (ioc.value() < 0) {
680 return stdx::unexpected(make_error_code(std::errc::invalid_seek));
681 }
682
683 // value is not negative, safe to cast to unsigned
684 return static_cast<size_t>(ioc.value());
685 }
686
689
690 auto res = io_control(ioc);
691 if (!res) return stdx::unexpected(res.error());
692
693 return ioc.value();
694 }
695
699 static_cast<int>(st));
700 }
701
703 return io_ctx_->socket_service()->wait(native_handle(), wt);
704 }
705
706 private:
708};
709
710template <typename Protocol>
711class basic_socket : public socket_base, private basic_socket_impl<Protocol> {
713
714 public:
719 using endpoint_type = typename protocol_type::endpoint;
720
722
724 const protocol_type &protocol, const native_handle_type &native_handle) {
725 return __base::assign(protocol, native_handle);
726 }
727
729 const protocol_type &protocol = protocol_type(), int flags = 0) {
730 return __base::open(protocol, flags);
731 }
732
734 if (!is_open()) {
735 auto res = open(endpoint.protocol());
736 if (!res) return res;
737 }
740 reinterpret_cast<const struct sockaddr *>(endpoint.data()),
741 endpoint.size());
742 }
743
744 template <class CompletionToken>
745 auto async_connect(const endpoint_type &endpoint, CompletionToken &&token) {
746 async_completion<CompletionToken, void(std::error_code)> init{token};
747
748 if (!is_open()) {
749 auto res = open(endpoint.protocol());
750 if (!res) {
751 init.completion_handler(res.error());
752
753 return;
754 }
755 }
756
757 net::defer(get_executor(), [this, endpoint,
758 __compl_handler =
759 std::move(init.completion_handler)]() {
760 // remember the non-blocking flag.
761 const auto old_non_blocking = native_non_blocking();
762 if (old_non_blocking == false) native_non_blocking(true);
763
764 auto res = connect(endpoint);
765
766 // restore the non-blocking flag if needed.
767 if (old_non_blocking == false) native_non_blocking(false);
768
769 if (res) {
770 __compl_handler({});
771 } else {
772 const auto ec = res.error();
773
774 if ((ec !=
775 make_error_condition(std::errc::operation_in_progress)) /* posix */
776 && (ec != make_error_condition(
777 std::errc::operation_would_block)) /* windows */) {
778 __compl_handler(ec);
779 } else {
780 get_executor().context().async_wait(
781 native_handle(), net::socket_base::wait_write,
782 [this, __compl_handler = std::move(__compl_handler)](
783 std::error_code error_code) mutable {
784 if (error_code) {
785 __compl_handler(error_code);
786 return;
787 }
788
789 // finish the non-blocking connect
790 net::socket_base::error so_error;
791
792 auto result = get_option(so_error);
793 if (!result) {
794 __compl_handler(result.error());
795 return;
796 }
797
798 // if so_error.value() is 0, the error_code will be 0 too
799 __compl_handler(
800 impl::socket::make_error_code(so_error.value()));
801 });
802 }
803 }
804 });
805
806 return init.result.get();
807 }
808
810 return __base::bind(endpoint);
811 }
812
814 return __base::native_handle();
815 }
816
817 template <typename SettableSocketOption>
819 const SettableSocketOption &option) {
820 return __base::set_option(option);
821 }
822
823 template <typename GettableSocketOption>
825 GettableSocketOption &option) const {
826 return __base::get_option(option);
827 }
828
830
831 stdx::expected<void, error_type> cancel() { return __base::cancel(); }
832
834 return __base::release();
835 }
836
837 constexpr bool is_open() const { return __base::is_open(); }
838
840 return __base::local_endpoint();
841 }
842
844 return __base::remote_endpoint();
845 }
846
848 return __base::available();
849 }
850
851 bool non_blocking() const { return __base::non_blocking(); }
852
854 return __base::non_blocking(mode);
855 }
856
858
861 }
862
864 return __base::wait(wt);
865 }
866
869 return __base::shutdown(st);
870 }
871
872 template <typename CompletionToken>
873 auto async_wait(wait_type w, CompletionToken &&token) {
874 async_completion<CompletionToken, void(std::error_code)> init{token};
875
876 get_executor().context().async_wait(
877 native_handle(), w,
878 [__compl_handler = std::move(init.completion_handler)](
879 std::error_code ec) mutable { __compl_handler(ec); });
880
881 return init.result.get();
882 }
883
884 protected:
885 explicit basic_socket(io_context &ctx) : __base{ctx} {}
886
888 : __base{ctx, proto} {}
889
892 : __base{ctx} {
893 assign(proto, native_handle);
894 }
895
896 // as demanded by networking-ts
897 // NOLINTNEXTLINE(hicpp-use-equals-delete,modernize-use-equals-delete)
898 basic_socket(const basic_socket &) = delete;
899 // NOLINTNEXTLINE(hicpp-use-equals-delete,modernize-use-equals-delete)
901 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
902 basic_socket(basic_socket &&other) = default;
903 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
905
906 ~basic_socket() = default;
907};
908
909// 18.7 [socket.dgram]
910template <typename Protocol>
911class basic_datagram_socket : public basic_socket<Protocol> {
913
914 public:
917 using endpoint_type = typename protocol_type::endpoint;
918 using error_type = std::error_code;
919
920 explicit basic_datagram_socket(io_context &ctx) : __base(ctx) {}
922 : __base(ctx, proto) {}
923
926
927 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
929 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
931
933
934 //
937 : __base(ctx, protocol, native_handle) {}
938
939 template <class MutableBufferSequence>
941 const MutableBufferSequence &buffers, socket_base::message_flags flags) {
942 socket_base::msg_hdr msg(buffers);
943
944 return this->get_executor().context().socket_service()->recvmsg(
946 }
947
948 template <class MutableBufferSequence>
950 const MutableBufferSequence &buffers) {
951 return receive(buffers, 0);
952 }
953
954 template <class MutableBufferSequence>
956 const MutableBufferSequence &buffers, endpoint_type &sender,
958 socket_base::msg_hdr msg(buffers);
959 msg.set_sender(sender);
960
961 auto res = this->get_executor().context().socket_service()->recvmsg(
963
964 if (res) {
965 // resize the endpoint
966 msg.resize_sender(sender);
967 }
968
969 return res;
970 }
971
972 template <class MutableBufferSequence>
974 const MutableBufferSequence &buffers, endpoint_type &sender) {
975 return receive_from(buffers, sender, 0);
976 }
977
978 template <class MutableBufferSequence>
980 const MutableBufferSequence &buffers) {
981 return receive(buffers);
982 }
983
984 template <class ConstBufferSequence>
986 const ConstBufferSequence &buffers, socket_base::message_flags flags) {
988 "");
989 socket_base::msg_hdr msg(buffers);
990
991 return this->get_executor().context().socket_service()->sendmsg(
993 }
994
995 template <class ConstBufferSequence>
997 const ConstBufferSequence &buffers) {
999 "");
1000 return send(buffers, 0);
1001 }
1002
1003 template <class ConstBufferSequence>
1005 const ConstBufferSequence &buffers, const endpoint_type &recipient,
1008 "");
1009 socket_base::msg_hdr msg(buffers);
1010 msg.set_recipient(recipient);
1011
1012 return this->get_executor().context().socket_service()->sendmsg(
1014 }
1015
1016 template <class ConstBufferSequence>
1018 const ConstBufferSequence &buffers, const endpoint_type &recipient) {
1020 "");
1021 return send_to(buffers, recipient, 0);
1022 }
1023
1024 template <class ConstBufferSequence>
1026 const ConstBufferSequence &buffers) {
1028 "");
1029 return send(buffers);
1030 }
1031
1033 socket_base::shutdown_type st) const {
1034 return __base::shutdown(st);
1035 }
1036
1037 template <class MutableBufferSequence, class CompletionToken>
1038 auto async_receive(const MutableBufferSequence &buffers,
1040 CompletionToken &&token) {
1041 static_assert(
1043
1044 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1045 token};
1046
1047 if ((flags & socket_base::message_peek).any()) {
1048 // required by std::
1049 init.completion_handler(make_error_code(std::errc::invalid_argument), 0);
1050
1051 return init.result.get();
1052 }
1053
1054 this->get_executor().context().async_wait(
1055 this->native_handle(), socket_base::wait_read,
1056 [socket_service = this->get_executor().context().socket_service(),
1057 compl_handler = std::move(init.completion_handler), &buffers,
1058 native_handle = this->native_handle(),
1059 flags](std::error_code ec) mutable {
1060 if (ec) {
1061 compl_handler(ec, 0);
1062 return;
1063 }
1064
1065 socket_base::msg_hdr msgs(buffers);
1066
1067 auto res = socket_service->recvmsg(native_handle, msgs, flags);
1068 if (!res) {
1069 compl_handler(res.error(), 0);
1070 } else {
1071 compl_handler({}, res.value());
1072 }
1073 });
1074
1075 return init.result.get();
1076 }
1077
1078 template <class MutableBufferSequence, class CompletionToken>
1079 auto async_receive(const MutableBufferSequence &buffers,
1080 CompletionToken &&token) {
1081 static_assert(
1083
1084 return async_receive(buffers, 0, std::forward<CompletionToken>(token));
1085 }
1086};
1087
1088// 18.8 [socket.stream]
1089template <typename Protocol>
1090class basic_stream_socket : public basic_socket<Protocol> {
1092
1093 public:
1096 using endpoint_type = typename protocol_type::endpoint;
1097 using error_type = std::error_code;
1098
1099 explicit basic_stream_socket(io_context &ctx) : __base(ctx) {}
1101 : __base(ctx, proto) {}
1102
1105 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
1107 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
1109
1111 //
1114 : __base(ctx, protocol, native_handle) {}
1115
1116 template <class MutableBufferSequence>
1118 const MutableBufferSequence &buffers, socket_base::message_flags flags) {
1119 if (buffer_size(buffers) == 0) return 0;
1120
1121 socket_base::msg_hdr msg(buffers);
1122
1123 auto res = this->get_executor().context().socket_service()->recvmsg(
1125
1126 if (res && res.value() == 0) {
1127 // remote did a orderly shutdown
1129 }
1130
1131 return res;
1132 }
1133
1134 template <class MutableBufferSequence>
1136 const MutableBufferSequence &buffers) {
1137 return receive(buffers, 0);
1138 }
1139
1140 template <class MutableBufferSequence>
1142 const MutableBufferSequence &buffers) {
1143 return receive(buffers);
1144 }
1145
1146 template <class ConstBufferSequence>
1148 const ConstBufferSequence &buffers, socket_base::message_flags flags) {
1150 "");
1151 if (buffer_size(buffers) == 0) return 0;
1152
1153 socket_base::msg_hdr msg(buffers);
1154
1155 auto res = this->get_executor().context().socket_service()->sendmsg(
1157
1158 if (res && res.value() == 0) {
1159 // remote did a orderly shutdown
1161 }
1162
1163 return res;
1164 }
1165
1166 template <class ConstBufferSequence>
1168 const ConstBufferSequence &buffers) {
1170 "");
1171 return send(buffers, 0);
1172 }
1173
1174 template <class ConstBufferSequence>
1176 const ConstBufferSequence &buffers) {
1178 "");
1179 return send(buffers);
1180 }
1181
1183 socket_base::shutdown_type st) const {
1184 return __base::shutdown(st);
1185 }
1186
1187 template <class MutableBufferSequence, class CompletionToken>
1188 auto async_receive(const MutableBufferSequence &buffers,
1190 CompletionToken &&token) {
1191 static_assert(
1193
1194 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1195 token};
1196 if ((flags & socket_base::message_peek).any()) {
1197 // required by std::
1198 init.completion_handler(make_error_code(std::errc::invalid_argument), 0);
1199
1200 return init.result.get();
1201 }
1202
1203 if (buffer_size(buffers) == 0) {
1204 init.completion_handler({}, 0);
1205
1206 return init.result.get();
1207 }
1208
1209 this->get_executor().context().async_wait(
1210 this->native_handle(), socket_base::wait_read,
1211 [socket_service = this->get_executor().context().socket_service(),
1212 compl_handler = std::move(init.completion_handler), buffers,
1213 native_handle = this->native_handle(), flags](std::error_code ec) {
1214 if (ec) {
1215 compl_handler(ec, 0);
1216 return;
1217 }
1218
1219 socket_base::msg_hdr msgs(buffers);
1220
1221 const auto res = socket_service->recvmsg(native_handle, msgs, flags);
1222 if (!res) {
1223 compl_handler(res.error(), 0);
1224 } else if (res.value() == 0) {
1225 // remote did a orderly shutdown
1226 compl_handler(make_error_code(stream_errc::eof), 0);
1227 } else {
1228 compl_handler({}, res.value());
1229 }
1230
1231 return;
1232 });
1233
1234 return init.result.get();
1235 }
1236
1237 template <class MutableBufferSequence, class CompletionToken>
1238 auto async_receive(const MutableBufferSequence &buffers,
1239 CompletionToken &&token) {
1240 static_assert(
1242
1243 return async_receive(buffers, 0, std::forward<CompletionToken>(token));
1244 }
1245
1246 template <class ConstBufferSequence, class CompletionToken>
1247 auto async_send(const ConstBufferSequence &buffers,
1248 socket_base::message_flags flags, CompletionToken &&token) {
1250 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1251 token};
1252 if (buffer_size(buffers) == 0) {
1253 init.completion_handler({}, 0);
1254
1255 return init.result.get();
1256 }
1257
1258 this->get_executor().context().async_wait(
1259 this->native_handle(), socket_base::wait_write,
1260 [socket_service = this->get_executor().context().socket_service(),
1261 compl_handler = std::move(init.completion_handler), buffers,
1262 native_handle = this->native_handle(), flags](std::error_code ec) {
1263 if (ec) {
1264 compl_handler(ec, 0);
1265 return;
1266 }
1267
1268 socket_base::msg_hdr msgs(buffers);
1269
1270 const auto res = socket_service->sendmsg(native_handle, msgs, flags);
1271 if (!res) {
1272 compl_handler(res.error(), 0);
1273 } else {
1274 compl_handler({}, res.value());
1275 }
1276
1277 return;
1278 });
1279
1280 return init.result.get();
1281 }
1282
1283 template <class ConstBufferSequence, class CompletionToken>
1284 auto async_send(const ConstBufferSequence &buffers, CompletionToken &&token) {
1286 return async_send(buffers, 0, std::forward<CompletionToken>(token));
1287 }
1288};
1289
1290// 18.9 [socket.acceptor]
1291template <typename AcceptableProtocol>
1293 private basic_socket_impl<AcceptableProtocol> {
1295
1296 public:
1299 using protocol_type = AcceptableProtocol;
1301 using endpoint_type = typename protocol_type::endpoint;
1302 using error_type = std::error_code;
1303
1305 : __base(ctx), protocol_{endpoint_type().protocol()} {}
1306
1307 executor_type get_executor() noexcept { return __base::get_executor(); }
1308
1310 const protocol_type &protocol = protocol_type(), int flags = 0) {
1311 return __base::open(protocol, flags);
1312 }
1313
1315 const protocol_type &protocol,
1316 const native_handle_type &native_acceptor) {
1317 return __base::assign(protocol, native_acceptor);
1318 }
1319
1321 return __base::release();
1322 }
1323
1325
1326 constexpr bool is_open() const { return __base::is_open(); }
1327
1329
1330 stdx::expected<void, error_type> cancel() { return __base::cancel(); }
1331
1332 template <typename SettableSocketOption>
1334 const SettableSocketOption &option) {
1335 return __base::set_option(option);
1336 }
1337
1338 template <typename GettableSocketOption>
1340 GettableSocketOption &option) const {
1341 return __base::get_option(option);
1342 }
1343
1344 bool non_blocking() const { return __base::non_blocking(); }
1345
1347 return __base::non_blocking(mode);
1348 }
1349
1351
1354 }
1355
1357 return __base::bind(endpoint);
1358 }
1359
1361 return __base::listen(backlog);
1362 }
1363
1365 return __base::local_endpoint();
1366 }
1367
1368 // enable_connection_aborted(bool) - not implemented
1369
1370 bool enable_connection_aborted() const { return enable_connection_aborted_; }
1371
1373 return accept(get_executor().context(), flags);
1374 }
1375
1377 int flags = 0) {
1378 // in case of ECONNABORTED, retry if not explicitly enabled
1379 while (true) {
1380 auto accept_res = __base::accept(io_ctx, flags);
1381
1382 if (accept_res || enable_connection_aborted() ||
1383 accept_res.error() !=
1384 make_error_condition(std::errc::connection_aborted)) {
1385 return accept_res;
1386 }
1387 }
1388 }
1389
1391 int flags = 0) {
1392 return accept(get_executor().context(), endpoint, flags);
1393 }
1394
1396 endpoint_type &endpoint,
1397 int flags = 0) {
1398 // in case of ECONNABORTED, retry if not explicitly enabled
1399 while (true) {
1400 auto accept_res = __base::accept(io_ctx, endpoint, flags);
1401
1402 if (accept_res || enable_connection_aborted() ||
1403 accept_res.error() !=
1404 make_error_condition(std::errc::connection_aborted)) {
1405 return accept_res;
1406 }
1407 }
1408 }
1409
1410 template <class CompletionToken>
1411 auto async_accept(io_context &io_ctx, CompletionToken &&token) {
1412 async_completion<CompletionToken, void(std::error_code, socket_type)> init{
1413 token};
1414
1415 // do something
1416 io_ctx.get_executor().context().async_wait(
1417 native_handle(), socket_base::wait_read,
1418 [this, __compl_handler = std::move(init.completion_handler),
1419 __protocol = protocol_, __fd = native_handle(),
1420 &io_ctx](std::error_code ec) mutable {
1421 if (ec) {
1422 __compl_handler(ec, socket_type(io_ctx));
1423 return;
1424 }
1425
1426 while (true) {
1427 auto res = this->get_executor().context().socket_service()->accept(
1428 __fd, nullptr, nullptr);
1429
1430 if (!res && !enable_connection_aborted() &&
1431 res.error() ==
1432 make_error_condition(std::errc::connection_aborted)) {
1433 continue;
1434 }
1435
1436 if (!res) {
1437 __compl_handler(res.error(), socket_type(io_ctx));
1438 } else {
1439 __compl_handler({}, socket_type{io_ctx, __protocol, res.value()});
1440 }
1441 return;
1442 }
1443 });
1444
1445 return init.result.get();
1446 }
1447
1448 template <class CompletionToken>
1449 auto async_accept(endpoint_type &endpoint, CompletionToken &&token) {
1450 return async_accept(get_executor().context(), endpoint,
1451 std::forward<CompletionToken>(token));
1452 }
1453
1454 /**
1455 * accept a connection with endpoint async'.
1456 *
1457 * - returns immediately
1458 * - calls completiontoken when finished
1459 *
1460 * @param [in,out] io_ctx io-context to execute the waiting/execution in
1461 * @param [out] endpoint remote endpoint of the accepted connection
1462 * @param [in] token completion token of type 'void(std::error_code,
1463 * socket_type)'
1464 */
1465 template <class CompletionToken>
1466 auto async_accept(io_context &io_ctx, endpoint_type &endpoint,
1467 CompletionToken &&token) {
1468 async_completion<CompletionToken, void(std::error_code, socket_type)> init{
1469 token};
1470
1471 // - wait for acceptor to become readable
1472 // - accept() it.
1473 // - call completion with socket
1474 io_ctx.get_executor().context().async_wait(
1475 native_handle(), socket_base::wait_read,
1476 [this, __compl_handler = std::move(init.completion_handler),
1477 __protocol = protocol_, __fd = native_handle(), &__ep = endpoint,
1478 &io_ctx](std::error_code ec) mutable {
1479 if (ec) {
1480 __compl_handler(ec, socket_type(io_ctx));
1481 return;
1482 }
1483
1484 while (true) {
1485 socklen_t endpoint_len = __ep.capacity();
1486
1487 auto res = this->get_executor().context().socket_service()->accept(
1488 __fd, static_cast<sockaddr *>(__ep.data()), &endpoint_len);
1489
1490 if (!res && !enable_connection_aborted() &&
1491 res.error() ==
1492 make_error_condition(std::errc::connection_aborted)) {
1493 continue;
1494 }
1495
1496 if (!res) {
1497 __compl_handler(res.error(), socket_type(io_ctx));
1498 } else {
1499 __ep.resize(endpoint_len);
1500
1501 __compl_handler({}, socket_type{io_ctx, __protocol, res.value()});
1502 }
1503 return;
1504 }
1505 });
1506
1507 return init.result.get();
1508 }
1509
1510 template <class CompletionToken>
1511 auto async_accept(CompletionToken &&token) {
1512 return async_accept(get_executor().context(),
1513 std::forward<CompletionToken>(token));
1514 }
1515
1517 return __base::wait(wt);
1518 }
1519
1520 template <typename CompletionToken>
1521 auto async_wait(wait_type w, CompletionToken &&token) {
1522 async_completion<CompletionToken, void(std::error_code)> init{token};
1523
1524 get_executor().context().async_wait(
1525 native_handle(), w,
1526 [compl_handler = std::move(init.completion_handler)](
1527 std::error_code ec) mutable { compl_handler(ec); });
1528
1529 return init.result.get();
1530 }
1531
1532 private:
1534 bool enable_connection_aborted_{false};
1535};
1536
1537// 20.1 [socket.algo.connect]
1538
1539/**
1540 * connect to the first endpoint that is connectable from a sequence of
1541 * endpoints.
1542 *
1543 * @param s socket that should be connected to an endpoint
1544 * @param endpoints a sequence of endpoints
1545 * @param c ConnectionCondition that must return true if the provided endpoint
1546 * should be attempted to be connected to
1547 *
1548 * @returns endpoint the connect succeeded for on success, last error-code
1549 * otherwise
1550 */
1551template <class Protocol, class EndpointSequence, class ConnectCondition>
1553 basic_socket<Protocol> &s, const EndpointSequence &endpoints,
1554 ConnectCondition c) {
1555 return connect(s, std::begin(endpoints), std::end(endpoints), c);
1556}
1557
1558/**
1559 * connect to the first endpoint that is connectable.
1560 *
1561 * @param s socket that should be connected to an endpoint
1562 * @param endpoints a sequence of endpoints
1563 *
1564 * @returns endpoint the connect succeeded for on success, last error-code
1565 * otherwise
1566 */
1567template <class Protocol, class EndpointSequence>
1569 basic_socket<Protocol> &s, const EndpointSequence &endpoints) {
1570 return connect(s, endpoints, [](auto, auto) { return true; });
1571}
1572
1573/**
1574 * connect to the first endpoint that is connectable from a range [first, last).
1575 *
1576 * @param s socket that should be connected to an endpoint
1577 * @param first iterator to the first endpoint
1578 * @param last iterator after to the last endpoint
1579 * @param c ConnectionCondition that must return true if the provided endpoint
1580 * should be attempted to be connected to
1581 *
1582 * @returns endpoint the connect succeeded for on success, last error-code
1583 * otherwise
1584 */
1585template <class Protocol, class InputIterator, class ConnectCondition>
1587 basic_socket<Protocol> &s, InputIterator first, InputIterator last,
1588 ConnectCondition c) {
1589 // capture that last error-code for the connect-condition
1590 std::error_code ec;
1591
1592 for (InputIterator cur = first; cur != last; ++cur) {
1593 // check if the endpoint should be connected to
1594 if (!c(ec, *cur)) continue;
1595
1596 auto res = s.close();
1597 if (!res) {
1598 ec = res.error();
1599 continue;
1600 }
1601
1602 res = s.open(typename Protocol::endpoint(*cur).protocol());
1603 if (!res) {
1604 ec = res.error();
1605 continue;
1606 }
1607
1608 res = s.connect(*cur);
1609 if (!res) {
1610 ec = res.error();
1611 } else {
1612 return cur;
1613 }
1614 }
1615
1616 return stdx::unexpected(make_error_code(socket_errc::not_found));
1617}
1618
1619template <class Protocol, class InputIterator, class ConnectCondition>
1621 basic_socket<Protocol> &s, InputIterator first, InputIterator last) {
1622 return connect(s, first, last, [](auto, auto) { return true; });
1623}
1624
1625} // namespace net
1626
1627#if defined(MYSQL_HARNESS_HEADER_ONLY)
1628#include "mysql/harness/net_ts/socket.cpp"
1629#endif
1630
1631#endif
Definition: protocol.h:33
Definition: executor.h:72
Definition: socket.h:911
stdx::expected< size_t, std::error_code > send_to(const ConstBufferSequence &buffers, const endpoint_type &recipient)
Definition: socket.h:1017
stdx::expected< size_t, std::error_code > receive_from(const MutableBufferSequence &buffers, endpoint_type &sender)
Definition: socket.h:973
stdx::expected< bool, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:1032
basic_datagram_socket & operator=(const basic_datagram_socket &)=delete
basic_datagram_socket(const basic_datagram_socket &)=delete
basic_datagram_socket(io_context &ctx, const protocol_type &proto)
Definition: socket.h:921
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:940
basic_datagram_socket(io_context &ctx, const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:935
stdx::expected< size_t, std::error_code > receive_from(const MutableBufferSequence &buffers, endpoint_type &sender, socket_base::message_flags flags)
Definition: socket.h:955
basic_datagram_socket(basic_datagram_socket &&other)=default
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers)
Definition: socket.h:949
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:985
auto async_receive(const MutableBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1038
basic_datagram_socket & operator=(basic_datagram_socket &&)=default
stdx::expected< size_t, std::error_code > read_some(const MutableBufferSequence &buffers)
Definition: socket.h:979
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers)
Definition: socket.h:996
basic_datagram_socket(io_context &ctx)
Definition: socket.h:920
stdx::expected< size_t, std::error_code > send_to(const ConstBufferSequence &buffers, const endpoint_type &recipient, socket_base::message_flags flags)
Definition: socket.h:1004
stdx::expected< size_t, std::error_code > write_some(const ConstBufferSequence &buffers)
Definition: socket.h:1025
auto async_receive(const MutableBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1079
Definition: socket.h:1293
basic_socket_acceptor(io_context &ctx)
Definition: socket.h:1304
typename protocol_type::endpoint endpoint_type
Definition: socket.h:1301
auto async_accept(io_context &io_ctx, endpoint_type &endpoint, CompletionToken &&token)
accept a connection with endpoint async'.
Definition: socket.h:1466
std::error_code error_type
Definition: socket.h:1302
stdx::expected< endpoint_type, error_type > local_endpoint() const
Definition: socket.h:1364
bool native_non_blocking() const
Definition: socket.h:1350
bool non_blocking() const
Definition: socket.h:1344
stdx::expected< void, error_type > assign(const protocol_type &protocol, const native_handle_type &native_acceptor)
Definition: socket.h:1314
stdx::expected< native_handle_type, error_type > release()
Definition: socket.h:1320
stdx::expected< socket_type, error_type > accept(int flags=0)
Definition: socket.h:1372
native_handle_type native_handle() const
Definition: socket.h:1324
stdx::expected< void, error_type > listen(int backlog)
Definition: socket.h:1360
stdx::expected< void, error_type > open(const protocol_type &protocol=protocol_type(), int flags=0)
Definition: socket.h:1309
AcceptableProtocol protocol_type
Definition: socket.h:1299
stdx::expected< socket_type, error_type > accept(endpoint_type &endpoint, int flags=0)
Definition: socket.h:1390
typename protocol_type::socket socket_type
Definition: socket.h:1300
stdx::expected< void, error_type > bind(const endpoint_type &endpoint)
Definition: socket.h:1356
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, endpoint_type &endpoint, int flags=0)
Definition: socket.h:1395
stdx::expected< void, error_type > close()
Definition: socket.h:1328
auto async_accept(endpoint_type &endpoint, CompletionToken &&token)
Definition: socket.h:1449
executor_type get_executor() noexcept
Definition: socket.h:1307
protocol_type protocol_
Definition: socket.h:1533
stdx::expected< void, std::error_code > wait(socket_base::wait_type wt)
Definition: socket.h:1516
auto async_accept(CompletionToken &&token)
Definition: socket.h:1511
stdx::expected< void, error_type > cancel()
Definition: socket.h:1330
bool enable_connection_aborted() const
Definition: socket.h:1370
stdx::expected< void, std::error_code > native_non_blocking(bool mode)
Definition: socket.h:1352
auto async_accept(io_context &io_ctx, CompletionToken &&token)
Definition: socket.h:1411
stdx::expected< void, error_type > get_option(GettableSocketOption &option) const
Definition: socket.h:1339
auto async_wait(wait_type w, CompletionToken &&token)
Definition: socket.h:1521
stdx::expected< void, std::error_code > non_blocking(bool mode)
Definition: socket.h:1346
constexpr bool is_open() const
Definition: socket.h:1326
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, int flags=0)
Definition: socket.h:1376
stdx::expected< void, error_type > set_option(const SettableSocketOption &option)
Definition: socket.h:1333
Definition: socket.h:637
constexpr IoControl(value_type v)
Definition: socket.h:643
constexpr value_type value() const
Definition: socket.h:650
constexpr IoControl()
Definition: socket.h:641
T value_type
Definition: socket.h:639
constexpr void * data()
Definition: socket.h:648
constexpr unsigned long name() const
Definition: socket.h:646
value_type val_
Definition: socket.h:653
template-less base-class of basic_socket_impl.
Definition: socket.h:335
stdx::expected< void, std::error_code > native_non_blocking(bool mode)
Definition: socket.h:394
io_context * io_ctx_
Definition: socket.h:465
basic_socket_impl_base & operator=(const basic_socket_impl_base &rhs)=delete
bool non_blocking_
Definition: socket.h:451
stdx::expected< void, std::error_code > non_blocking(bool mode)
Definition: socket.h:374
constexpr bool non_blocking() const
Definition: socket.h:372
constexpr native_handle_type native_handle() const noexcept
Definition: socket.h:364
constexpr basic_socket_impl_base(io_context &ctx)
Definition: socket.h:340
stdx::expected< native_handle_type, std::error_code > release()
Definition: socket.h:441
stdx::expected< void, std::error_code > cancel()
Definition: socket.h:432
native_handle_type native_handle_
Definition: socket.h:449
stdx::expected< void, std::error_code > close()
Definition: socket.h:416
char native_non_blocking_
Definition: socket.h:452
executor_type get_executor() noexcept
Definition: socket.h:414
impl::socket::native_handle_type native_handle_type
Definition: socket.h:337
basic_socket_impl_base(const basic_socket_impl_base &rhs)=delete
basic_socket_impl_base & operator=(basic_socket_impl_base &&rhs) noexcept
Definition: socket.h:352
bool native_non_blocking() const
Definition: socket.h:384
basic_socket_impl_base(basic_socket_impl_base &&rhs) noexcept
Definition: socket.h:345
constexpr bool is_open() const noexcept
Definition: socket.h:368
Definition: socket.h:470
typename protocol_type::socket socket_type
Definition: socket.h:478
basic_socket_impl(basic_socket_impl &&rhs)=default
Protocol protocol_type
Definition: socket.h:475
stdx::expected< endpoint_type, error_type > local_endpoint() const
Definition: socket.h:607
stdx::expected< void, error_type > bind(const endpoint_type &endpoint)
Definition: socket.h:530
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, int flags=0)
Definition: socket.h:560
~basic_socket_impl()
Definition: socket.h:498
stdx::expected< endpoint_type, error_type > remote_endpoint() const
Definition: socket.h:621
stdx::expected< void, error_type > open(const protocol_type &protocol=protocol_type(), int flags=0)
Definition: socket.h:502
stdx::expected< void, std::error_code > wait(socket_base::wait_type wt)
Definition: socket.h:702
stdx::expected< bool, error_type > at_mark() const
Definition: socket.h:687
typename protocol_type::endpoint endpoint_type
Definition: socket.h:476
stdx::expected< void, error_type > listen(int backlog=socket_base::max_listen_connections)
Definition: socket.h:579
basic_socket_impl(const basic_socket_impl &)=delete
stdx::expected< void, error_type > assign(const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:519
stdx::expected< void, error_type > get_option(GettableSocketOption &option) const
Definition: socket.h:593
stdx::expected< void, error_type > set_option(const SettableSocketOption &option)
Definition: socket.h:585
constexpr basic_socket_impl(io_context &ctx) noexcept
Definition: socket.h:480
protocol_type protocol_
Definition: socket.h:707
std::error_code error_type
Definition: socket.h:477
stdx::expected< void, error_type > io_control(IoControlCommand &cmd) const
Definition: socket.h:668
stdx::expected< void, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:696
basic_socket_impl & operator=(basic_socket_impl &&rhs) noexcept
Definition: socket.h:487
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, endpoint_type &endpoint, int flags=0)
Definition: socket.h:566
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, struct sockaddr *endpoint_data, socklen_t *endpoint_size, int flags=0)
Definition: socket.h:537
stdx::expected< size_t, error_type > available() const
Definition: socket.h:673
basic_socket_impl & operator=(const basic_socket_impl &)=delete
Definition: socket.h:711
stdx::expected< void, error_type > cancel()
Definition: socket.h:831
stdx::expected< size_t, error_type > available() const
Definition: socket.h:847
stdx::expected< void, std::error_code > native_non_blocking(bool mode)
Definition: socket.h:859
stdx::expected< void, error_type > set_option(const SettableSocketOption &option)
Definition: socket.h:818
bool non_blocking() const
Definition: socket.h:851
Protocol protocol_type
Definition: socket.h:716
stdx::expected< native_handle_type, error_type > release()
Definition: socket.h:833
stdx::expected< void, error_type > close()
Definition: socket.h:829
~basic_socket()=default
auto async_wait(wait_type w, CompletionToken &&token)
Definition: socket.h:873
executor_type get_executor() noexcept
Definition: socket.h:721
stdx::expected< void, error_type > connect(const endpoint_type &endpoint)
Definition: socket.h:733
basic_socket(basic_socket &&other)=default
constexpr bool is_open() const
Definition: socket.h:837
native_handle_type native_handle() const noexcept
Definition: socket.h:813
stdx::expected< void, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:867
auto async_connect(const endpoint_type &endpoint, CompletionToken &&token)
Definition: socket.h:745
bool native_non_blocking() const
Definition: socket.h:857
stdx::expected< void, error_type > bind(const endpoint_type &endpoint)
Definition: socket.h:809
basic_socket & operator=(basic_socket &&)=default
basic_socket(const basic_socket &)=delete
stdx::expected< void, error_type > assign(const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:723
basic_socket & operator=(const basic_socket &)=delete
basic_socket(io_context &ctx, const protocol_type &proto)
Definition: socket.h:887
basic_socket(io_context &ctx, const protocol_type &proto, const native_handle_type &native_handle)
Definition: socket.h:890
stdx::expected< void, error_type > get_option(GettableSocketOption &option) const
Definition: socket.h:824
stdx::expected< endpoint_type, error_type > remote_endpoint() const
Definition: socket.h:843
stdx::expected< void, error_type > open(const protocol_type &protocol=protocol_type(), int flags=0)
Definition: socket.h:728
basic_socket(io_context &ctx)
Definition: socket.h:885
stdx::expected< endpoint_type, error_type > local_endpoint() const
Definition: socket.h:839
stdx::expected< void, std::error_code > non_blocking(bool mode)
Definition: socket.h:853
stdx::expected< void, std::error_code > wait(socket_base::wait_type wt)
Definition: socket.h:863
Definition: socket.h:1090
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers)
Definition: socket.h:1167
stdx::expected< size_t, std::error_code > read_some(const MutableBufferSequence &buffers)
Definition: socket.h:1141
stdx::expected< void, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:1182
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers)
Definition: socket.h:1135
basic_stream_socket(const basic_stream_socket &)=delete
auto async_send(const ConstBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1284
auto async_receive(const MutableBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1238
stdx::expected< size_t, std::error_code > write_some(const ConstBufferSequence &buffers)
Definition: socket.h:1175
basic_stream_socket(io_context &ctx, const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:1112
basic_stream_socket(basic_stream_socket &&other)=default
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1117
auto async_send(const ConstBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1247
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1147
basic_stream_socket(io_context &ctx)
Definition: socket.h:1099
basic_stream_socket & operator=(basic_stream_socket &&)=default
auto async_receive(const MutableBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1188
basic_stream_socket & operator=(const basic_stream_socket &)=delete
basic_stream_socket(io_context &ctx, const protocol_type &proto)
Definition: socket.h:1100
virtual stdx::expected< void, error_type > ioctl(native_handle_type native_handle, unsigned long cmd, void *data) const =0
virtual stdx::expected< void, error_type > bind(native_handle_type native_handle, const struct sockaddr *addr, size_t addr_len) const =0
virtual stdx::expected< void, error_type > getsockopt(native_handle_type native_handle, int level, int optname, void *optval, socklen_t *optlen) const =0
virtual stdx::expected< void, error_type > getsockname(native_handle_type native_handle, struct sockaddr *addr, size_t *addr_len) const =0
virtual stdx::expected< native_handle_type, error_type > socket(int family, int sock_type, int protocol) const =0
virtual stdx::expected< void, error_type > close(native_handle_type native_handle) const =0
virtual stdx::expected< void, error_type > getpeername(native_handle_type native_handle, struct sockaddr *addr, size_t *addr_len) const =0
virtual stdx::expected< native_handle_type, error_type > accept(native_handle_type native_handle, struct sockaddr *addr, socklen_t *addr_len) const =0
virtual stdx::expected< native_handle_type, error_type > accept4(native_handle_type native_handle, struct sockaddr *addr, socklen_t *addr_len, int flags=0) const =0
virtual stdx::expected< void, error_type > setsockopt(native_handle_type native_handle, int level, int optname, const void *optval, socklen_t optlen) const =0
virtual stdx::expected< bool, error_type > native_non_blocking(native_handle_type native_handle) const =0
virtual stdx::expected< void, error_type > listen(native_handle_type native_handle, int backlog) const =0
virtual stdx::expected< void, error_type > connect(native_handle_type native_handle, const struct sockaddr *addr, size_t addr_len) const =0
virtual stdx::expected< void, error_type > wait(native_handle_type fd, wait_type wt) const =0
virtual stdx::expected< void, error_type > shutdown(native_handle_type fd, int how) const =0
Definition: io_context.h:991
io_context & context() const noexcept
Definition: io_context.h:1003
Definition: io_context.h:61
impl::socket::SocketServiceBase * socket_service() const
Definition: io_context.h:135
void async_wait(native_handle_type fd, impl::socket::wait_type wt, Op &&op)
Definition: io_context.h:483
executor_type get_executor() noexcept
Definition: io_context.h:1081
stdx::expected< void, std::error_code > cancel(native_handle_type fd)
cancel all async-ops of a file-descriptor.
Definition: io_context.h:1088
socket option for SO_LINGER
Definition: socket.h:275
linger() noexcept
Definition: socket.h:277
int level(const Protocol &) const noexcept
Definition: socket.h:293
linger(bool e, std::chrono::seconds t) noexcept
Definition: socket.h:279
std::chrono::seconds timeout() const noexcept
Definition: socket.h:285
int name(const Protocol &) const noexcept
Definition: socket.h:298
::linger value_
Definition: socket.h:325
void timeout(std::chrono::seconds t) noexcept
Definition: socket.h:288
void resize(const Protocol &, size_t s)
Definition: socket.h:318
void * data(const Protocol &) noexcept
Definition: socket.h:303
size_t size(const Protocol &) const noexcept
Definition: socket.h:313
void enabled(bool e) noexcept
Definition: socket.h:283
const void * data(const Protocol &) const noexcept
Definition: socket.h:308
bool enabled() const noexcept
Definition: socket.h:282
Definition: socket.h:194
void set_recipient(const endpoint_type &ep)
set recipient of the message.
Definition: socket.h:257
void set_sender(endpoint_type &ep)
set sender of the message.
Definition: socket.h:231
void resize_sender(endpoint_type &ep)
set the size of the sender after data was received.
Definition: socket.h:245
std::array< impl::socket::iovec_base, 16 > iov_
Definition: socket.h:195
msg_hdr(const BufferSequence &buffers)
Definition: socket.h:199
Definition: socket.h:141
static constexpr wait_type wait_read
Definition: socket.h:168
static constexpr message_flags message_peek
Definition: socket.h:161
shutdown_type
Definition: socket.h:172
static constexpr shutdown_type shutdown_both
Definition: socket.h:186
static constexpr shutdown_type shutdown_receive
Definition: socket.h:183
static constexpr message_flags message_do_not_route
Definition: socket.h:164
static constexpr message_flags message_out_of_band
Definition: socket.h:162
impl::socket::message_flags message_flags
Definition: socket.h:159
static const int max_listen_connections
Definition: socket.h:188
static constexpr shutdown_type shutdown_send
Definition: socket.h:185
static constexpr wait_type wait_write
Definition: socket.h:169
static constexpr wait_type wait_error
Definition: socket.h:170
base-class of socket options.
Definition: socket.h:77
storage_type * data(const Protocol &)
Definition: socket.h:105
constexpr option_base()
Definition: socket.h:82
constexpr int name(const Protocol &) const noexcept
Definition: socket.h:95
storage_type value_
Definition: socket.h:122
constexpr int level(const Protocol &) const noexcept
Definition: socket.h:90
V storage_type
Definition: socket.h:80
T value_type
Definition: socket.h:79
constexpr size_t size(const Protocol &) const
Definition: socket.h:110
void resize(const Protocol &, size_t s)
Definition: socket.h:115
value_type value() const
Definition: socket.h:87
const storage_type * data(const Protocol &) const
Definition: socket.h:100
constexpr option_base(value_type v)
Definition: socket.h:84
Definition: expected.h:286
static int flags[50]
Definition: hp_test1.cc:40
mysql_service_status_t send(const char *tag, const unsigned char *data, const size_t data_length) noexcept
Definition: message_service.cc:33
Definition: http_server_component.cc:34
std::error_code make_error_code(DynamicLoaderErrc ec)
make error_code from a DynamicLoaderErrc.
Definition: dynamic_loader.cc:79
const char * begin(const char *const c)
Definition: base64.h:44
stdx::expected< void, error_type > listen(native_handle_type native_handle, int backlog)
Definition: socket.h:149
stdx::expected< native_handle_type, error_type > socket(int family, int sock_type, int protocol)
Definition: socket.h:63
stdx::expected< void, std::error_code > init()
Definition: socket.h:669
stdx::expected< void, error_type > bind(native_handle_type native_handle, const struct sockaddr *addr, size_t addr_len)
wrap bind() in a portable way.
Definition: socket.h:339
stdx::expected< void, error_type > native_non_blocking(native_handle_type native_handle, bool on)
Definition: socket.h:121
stdx::expected< native_handle_type, error_type > accept(native_handle_type native_handle, struct sockaddr *addr, socklen_t *addr_len)
wrap accept() in a portable way.
Definition: socket.h:367
stdx::expected< void, std::error_code > close(native_handle_type native_handle)
Definition: socket.h:75
wait_type
Definition: socket_constants.h:86
::msghdr msghdr_base
Definition: socket_constants.h:60
static constexpr message_flags message_out_of_band
Definition: socket_constants.h:67
static constexpr message_flags message_do_not_route
Definition: socket_constants.h:68
std::error_code error_type
Definition: socket_constants.h:55
std::bitset< 31 > message_flags
Definition: socket_constants.h:64
static constexpr message_flags message_peek
Definition: socket_constants.h:66
stdx::expected< void, error_type > shutdown(native_handle_type fd, int how)
Definition: socket.h:659
int native_handle_type
Definition: socket_constants.h:51
constexpr const native_handle_type kInvalidSocket
Definition: socket_constants.h:52
stdx::expected< void, error_type > wait(native_handle_type fd, wait_type wt)
Definition: socket.h:632
Definition: buffer.h:45
const const_buffer * buffer_sequence_end(const const_buffer &b) noexcept
Definition: buffer.h:185
auto defer(CompletionToken &&token)
Definition: executor.h:779
const const_buffer * buffer_sequence_begin(const const_buffer &b) noexcept
Definition: buffer.h:180
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:313
stdx::expected< InputIterator, std::error_code > connect(basic_socket< Protocol > &s, InputIterator first, InputIterator last)
Definition: socket.h:1620
std::error_condition make_error_condition(net::stream_errc e) noexcept
Definition: buffer.h:107
std::error_code make_error_code(net::stream_errc e) noexcept
Definition: buffer.h:103
stdx::expected< int, std::error_code > open(const char *fname, int flags, mode_t mode) noexcept
Definition: file_handle.cc:79
mode
Definition: file_handle.h:61
native_handle_type native_handle()
Definition: process.h:56
unexpected(E) -> unexpected< E >
struct sockaddr sockaddr
Definition: sock_probe_win32.h:63
case opt name
Definition: sslopt-case.h:29
Definition: buffer.h:259
Definition: buffer.h:256
double seconds()
Definition: task.cc:310