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