MySQL 8.0.37
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()) {
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()) {
397 std::make_error_code(std::errc::bad_file_descriptor));
398 }
399
400 if (!mode && non_blocking()) {
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()) {
435 make_error_code(std::errc::bad_file_descriptor));
436 }
437
439 return {};
440 }
441
443 if (is_open()) {
444 cancel();
445 }
446 return std::exchange(native_handle_, impl::socket::kInvalidSocket);
447 }
448
449 protected:
451
452 bool non_blocking_{false};
454#ifdef _WIN32
455 // on windows we can't detect the non-blocking state.
456 //
457 // Let's assume it defaults to 0. *fingerscross*
458 0
459#else
460 // on unixes we don't know what the state of non-blocking is after
461 // accept(), better check for it.
462 static_cast<char>(-1)
463#endif
464 };
465
467};
468
469// 18.6 [socket.basic]
470template <typename Protocol>
472 public:
474
477 using endpoint_type = typename protocol_type::endpoint;
478 using error_type = std::error_code;
480
481 constexpr explicit basic_socket_impl(io_context &ctx) noexcept
482 : __base{ctx} {}
483
487
489 if (this == std::addressof(rhs)) {
490 return *this;
491 }
492
493 close();
494 __base::operator=(std::move(rhs));
495
496 return *this;
497 }
498
500 if (is_open()) close();
501 }
502
504 const protocol_type &protocol = protocol_type(), int flags = 0) {
505 if (is_open()) {
507 }
508 auto res = io_ctx_->socket_service()->socket(
509 protocol.family(), protocol.type() | flags, protocol.protocol());
510 if (!res) return stdx::make_unexpected(res.error());
511#ifdef SOCK_NONBLOCK
512 if ((flags & SOCK_NONBLOCK) != 0) {
514 }
515#endif
516
517 return assign(protocol, res.value());
518 }
519
521 const protocol_type &protocol, const native_handle_type &native_handle) {
522 if (is_open()) {
524 }
525 protocol_ = protocol;
527
528 return {};
529 }
530
532 return io_ctx_->socket_service()->bind(
534 reinterpret_cast<const struct sockaddr *>(endpoint.data()),
535 endpoint.size());
536 }
537
539 struct sockaddr *endpoint_data,
540 socklen_t *endpoint_size,
541 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::make_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::make_unexpected(res.error());
556
557 return {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::make_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::make_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::make_unexpected(res.error());
678
679 if (ioc.value() < 0) {
680 return stdx::make_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::make_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 ec) mutable {
784 if (ec) {
785 __compl_handler(ec);
786 return;
787 }
788
789 // finish the non-blocking connect
790 net::socket_base::error so_error;
791
792 auto res = get_option(so_error);
793 if (!res) {
794 __compl_handler(res.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#if defined(ALL_COMPILERS_FULLY_SUPPORT_CPP14)
873 // the define ALL_COMPILERS_FULLY_SUPPORT_CPP14 is a placeholder.
874 //
875 // The code below assumes the compiler supports generalized lambda
876 // capture from C++14, allowing use move the ownership into the lambda.
877 //
878 // The code works with:
879 //
880 // - gcc 5.x and later
881 // - clang 4 and later
882 // - MSVC ...
883 //
884 // but it fails for move-only completion handlers with:
885 //
886 // - sun pro 15.6
887 //
888 // As soon as sun pro is fixed or supported for it is dropped,
889 // C++11 implementation below and this comment can be removed.
890 template <typename CompletionToken>
891 auto async_wait(wait_type w, CompletionToken &&token) {
892 async_completion<CompletionToken, void(std::error_code)> init{token};
893
894 get_executor().context().async_wait(
895 native_handle(), w,
896 [__compl_handler = std::move(init.completion_handler)](
897 std::error_code ec) mutable { __compl_handler(ec); });
898
899 return init.result.get();
900 }
901#else
902 // C++11 compatible implementation of async_wait() which allows move-only
903 // completion handlers
904 //
905 // to be removed, once all supported compilers fully support C++14 generalized
906 // lambda capture
907
908 template <typename CompletionToken>
909 typename async_result<std::decay_t<CompletionToken>,
910 void(std::error_code)>::return_type
911 async_wait(wait_type w, CompletionToken &&token) {
912 async_completion<CompletionToken, void(std::error_code)> init{token};
913
914 using async_completion_handler_type =
915 typename decltype(init)::completion_handler_type;
916
917 // capture the completion handler
918 class ClosureType {
919 public:
920 explicit ClosureType(async_completion_handler_type &&compl_handler)
921 : compl_handler_{
922 std::forward<decltype(compl_handler)>(compl_handler)} {}
923
924 void operator()(std::error_code ec) { compl_handler_(ec); }
925
926 private:
927 async_completion_handler_type compl_handler_;
928 };
929
930 // get native-handle before std::move()ing the completion handler into the
931 // async_wait(). Otherwise the native_handle() may refer to the moved-from
932 // object
933 const auto handle = native_handle();
934
935 get_executor().context().async_wait(
936 handle, w,
937 ClosureType(std::forward<async_completion_handler_type>(
938 init.completion_handler)));
939
940 return init.result.get();
941 }
942#endif
943
944 protected:
945 explicit basic_socket(io_context &ctx) : __base{ctx} {}
946
948 : __base{ctx, proto} {}
949
952 : __base{ctx} {
953 assign(proto, native_handle);
954 }
955
956 // as demanded by networking-ts
957 // NOLINTNEXTLINE(hicpp-use-equals-delete,modernize-use-equals-delete)
958 basic_socket(const basic_socket &) = delete;
959 // NOLINTNEXTLINE(hicpp-use-equals-delete,modernize-use-equals-delete)
961 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
962 basic_socket(basic_socket &&other) = default;
963 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
965
966 ~basic_socket() = default;
967};
968
969// 18.7 [socket.dgram]
970template <typename Protocol>
971class basic_datagram_socket : public basic_socket<Protocol> {
973
974 public:
977 using endpoint_type = typename protocol_type::endpoint;
978 using error_type = std::error_code;
979
980 explicit basic_datagram_socket(io_context &ctx) : __base(ctx) {}
982 : __base(ctx, proto) {}
983
986
987 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
989 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
991
993
994 //
997 : __base(ctx, protocol, native_handle) {}
998
999 template <class MutableBufferSequence>
1001 const MutableBufferSequence &buffers, socket_base::message_flags flags) {
1002 socket_base::msg_hdr msg(buffers);
1003
1004 return this->get_executor().context().socket_service()->recvmsg(
1006 }
1007
1008 template <class MutableBufferSequence>
1010 const MutableBufferSequence &buffers) {
1011 return receive(buffers, 0);
1012 }
1013
1014 template <class MutableBufferSequence>
1016 const MutableBufferSequence &buffers, endpoint_type &sender,
1018 socket_base::msg_hdr msg(buffers);
1019 msg.set_sender(sender);
1020
1021 auto res = this->get_executor().context().socket_service()->recvmsg(
1023
1024 if (res) {
1025 // resize the endpoint
1026 msg.resize_sender(sender);
1027 }
1028
1029 return res;
1030 }
1031
1032 template <class MutableBufferSequence>
1034 const MutableBufferSequence &buffers, endpoint_type &sender) {
1035 return receive_from(buffers, sender, 0);
1036 }
1037
1038 template <class MutableBufferSequence>
1040 const MutableBufferSequence &buffers) {
1041 return receive(buffers);
1042 }
1043
1044 template <class ConstBufferSequence>
1046 const ConstBufferSequence &buffers, socket_base::message_flags flags) {
1048 "");
1049 socket_base::msg_hdr msg(buffers);
1050
1051 return this->get_executor().context().socket_service()->sendmsg(
1053 }
1054
1055 template <class ConstBufferSequence>
1057 const ConstBufferSequence &buffers) {
1059 "");
1060 return send(buffers, 0);
1061 }
1062
1063 template <class ConstBufferSequence>
1065 const ConstBufferSequence &buffers, const endpoint_type &recipient,
1068 "");
1069 socket_base::msg_hdr msg(buffers);
1070 msg.set_recipient(recipient);
1071
1072 return this->get_executor().context().socket_service()->sendmsg(
1074 }
1075
1076 template <class ConstBufferSequence>
1078 const ConstBufferSequence &buffers, const endpoint_type &recipient) {
1080 "");
1081 return send_to(buffers, recipient, 0);
1082 }
1083
1084 template <class ConstBufferSequence>
1086 const ConstBufferSequence &buffers) {
1088 "");
1089 return send(buffers);
1090 }
1091
1093 socket_base::shutdown_type st) const {
1094 return __base::shutdown(st);
1095 }
1096
1097 template <class MutableBufferSequence, class CompletionToken>
1098 auto async_receive(const MutableBufferSequence &buffers,
1100 CompletionToken &&token) {
1101 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1102 token};
1103
1104 if ((flags & socket_base::message_peek).any()) {
1105 // required by std::
1106 init.completion_handler(make_error_code(std::errc::invalid_argument), 0);
1107
1108 return init.result.get();
1109 }
1110
1111 this->get_executor().context().async_wait(
1112 this->native_handle(), socket_base::wait_read,
1113 [this, __compl_handler = std::move(init.completion_handler), &buffers,
1114 __fd = this->native_handle(),
1115 __flags = flags](std::error_code ec) mutable {
1116 if (ec) {
1117 __compl_handler(ec, 0);
1118 return;
1119 }
1120
1121 socket_base::msg_hdr msgs(buffers);
1122
1123 auto res = this->get_executor().context().socket_service()->recvmsg(
1124 __fd, msgs, __flags);
1125 if (!res) {
1126 __compl_handler(res.error(), 0);
1127 } else {
1128 __compl_handler({}, res.value());
1129 }
1130 });
1131
1132 return init.result.get();
1133 }
1134
1135 template <class MutableBufferSequence, class CompletionToken>
1136 auto async_receive(const MutableBufferSequence &buffers,
1137 CompletionToken &&token) {
1138 return async_receive(buffers, 0, std::forward<CompletionToken>(token));
1139 }
1140};
1141
1142// 18.8 [socket.stream]
1143template <typename Protocol>
1144class basic_stream_socket : public basic_socket<Protocol> {
1146
1147 public:
1150 using endpoint_type = typename protocol_type::endpoint;
1151 using error_type = std::error_code;
1152
1153 explicit basic_stream_socket(io_context &ctx) : __base(ctx) {}
1155 : __base(ctx, proto) {}
1156
1159 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
1161 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
1163
1165 //
1168 : __base(ctx, protocol, native_handle) {}
1169
1170 template <class MutableBufferSequence>
1172 const MutableBufferSequence &buffers, socket_base::message_flags flags) {
1173 if (buffer_size(buffers) == 0) return 0;
1174
1175 socket_base::msg_hdr msg(buffers);
1176
1177 auto res = this->get_executor().context().socket_service()->recvmsg(
1179
1180 if (res && res.value() == 0) {
1181 // remote did a orderly shutdown
1183 }
1184
1185 return res;
1186 }
1187
1188 template <class MutableBufferSequence>
1190 const MutableBufferSequence &buffers) {
1191 return receive(buffers, 0);
1192 }
1193
1194 template <class MutableBufferSequence>
1196 const MutableBufferSequence &buffers) {
1197 return receive(buffers);
1198 }
1199
1200 template <class ConstBufferSequence>
1202 const ConstBufferSequence &buffers, socket_base::message_flags flags) {
1204 "");
1205 if (buffer_size(buffers) == 0) return 0;
1206
1207 socket_base::msg_hdr msg(buffers);
1208
1209 auto res = this->get_executor().context().socket_service()->sendmsg(
1211
1212 if (res && res.value() == 0) {
1213 // remote did a orderly shutdown
1215 }
1216
1217 return res;
1218 }
1219
1220 template <class ConstBufferSequence>
1222 const ConstBufferSequence &buffers) {
1224 "");
1225 return send(buffers, 0);
1226 }
1227
1228 template <class ConstBufferSequence>
1230 const ConstBufferSequence &buffers) {
1232 "");
1233 return send(buffers);
1234 }
1235
1237 socket_base::shutdown_type st) const {
1238 return __base::shutdown(st);
1239 }
1240
1241 template <class MutableBufferSequence, class CompletionToken>
1242 auto async_receive(const MutableBufferSequence &buffers,
1244 CompletionToken &&token) {
1245 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1246 token};
1247 if ((flags & socket_base::message_peek).any()) {
1248 // required by std::
1249 init.completion_handler(make_error_code(std::errc::invalid_argument), 0);
1250
1251 return init.result.get();
1252 }
1253
1254 if (buffer_size(buffers) == 0) {
1255 init.completion_handler({}, 0);
1256
1257 return init.result.get();
1258 }
1259
1260 /*
1261 * as we use C++14, we could use a lambda here which supports movable
1262 * arguments, but sun-cc 15.6 generates the wrong constructor:
1263 *
1264 * "...::{lambda at socket.h,1203:9}::<constructor>(
1265 * net::basic_stream_socket<net::ip::tcp>*,
1266 * const server_mock::MySQLServerMockSessionClassic::StateMachine&,
1267 * const std::list<net::const_buffer>&, int, std::bitset<31>&)"
1268 *
1269 * The "const StateMachine &" should have been "StateMachine &&".
1270 */
1271
1272 using compl_handler_type = typename decltype(init)::completion_handler_type;
1273
1274 class Completor {
1275 public:
1276 Completor(net::impl::socket::SocketServiceBase *socket_service,
1277 compl_handler_type &&compl_handler,
1278 const MutableBufferSequence &buffers,
1281 : socket_service_{socket_service},
1282 compl_handler_(std::move(compl_handler)),
1283 buffers_{buffers},
1284 native_handle_{native_handle},
1285 flags_{flags} {}
1286
1287 Completor(const Completor &) = delete;
1288 Completor(Completor &&) = default;
1289
1290 void operator()(std::error_code ec) {
1291 if (ec) {
1292 compl_handler_(ec, 0);
1293 return;
1294 }
1295
1296 socket_base::msg_hdr msgs(buffers_);
1297
1298 const auto res = socket_service_->recvmsg(native_handle_, msgs, flags_);
1299 if (!res) {
1300 compl_handler_(res.error(), 0);
1301 } else if (res.value() == 0) {
1302 // remote did a orderly shutdown
1303 compl_handler_(make_error_code(stream_errc::eof), 0);
1304 } else {
1305 compl_handler_({}, res.value());
1306 }
1307
1308 return;
1309 }
1310
1311 private:
1312 net::impl::socket::SocketServiceBase *socket_service_;
1313 compl_handler_type compl_handler_;
1314 const MutableBufferSequence &buffers_;
1315 impl::socket::native_handle_type native_handle_;
1317 };
1318
1319 this->get_executor().context().async_wait(
1320 this->native_handle(), socket_base::wait_read,
1321 Completor(this->get_executor().context().socket_service(),
1322 std::move(init.completion_handler), buffers,
1323 this->native_handle(), flags));
1324
1325 return init.result.get();
1326 }
1327
1328 template <class MutableBufferSequence, class CompletionToken>
1329 auto async_receive(const MutableBufferSequence &buffers,
1330 CompletionToken &&token) {
1331 return async_receive(buffers, 0, std::forward<CompletionToken>(token));
1332 }
1333
1334 template <class ConstBufferSequence, class CompletionToken>
1335 auto async_send(const ConstBufferSequence &buffers,
1336 socket_base::message_flags flags, CompletionToken &&token) {
1338 "");
1339 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1340 token};
1341 if (buffer_size(buffers) == 0) {
1342 init.completion_handler({}, 0);
1343
1344 return init.result.get();
1345 }
1346
1347 // see async_receive() for why this isn't a lambda.
1348 using compl_handler_type = typename decltype(init)::completion_handler_type;
1349
1350 class Completor {
1351 public:
1352 Completor(net::impl::socket::SocketServiceBase *socket_service,
1353 compl_handler_type &&compl_handler,
1354 const ConstBufferSequence &buffers,
1357 : socket_service_{socket_service},
1358 compl_handler_(std::move(compl_handler)),
1359 buffers_{buffers},
1360 native_handle_{native_handle},
1361 flags_{flags} {}
1362
1363 Completor(const Completor &) = delete;
1364 Completor(Completor &&) = default;
1365
1366 void operator()(std::error_code ec) {
1367 if (ec) {
1368 compl_handler_(ec, 0);
1369 return;
1370 }
1371
1372 socket_base::msg_hdr msgs(buffers_);
1373
1374 const auto res = socket_service_->sendmsg(native_handle_, msgs, flags_);
1375 if (!res) {
1376 compl_handler_(res.error(), 0);
1377 } else {
1378 compl_handler_({}, res.value());
1379 }
1380
1381 return;
1382 }
1383
1384 net::impl::socket::SocketServiceBase *socket_service_;
1385 compl_handler_type compl_handler_;
1386 const ConstBufferSequence &buffers_;
1387 impl::socket::native_handle_type native_handle_;
1389 };
1390
1391 // do something
1392 this->get_executor().context().async_wait(
1393 this->native_handle(), socket_base::wait_write,
1394 Completor(this->get_executor().context().socket_service(),
1395 std::move(init.completion_handler), buffers,
1396 this->native_handle(), flags));
1397
1398 return init.result.get();
1399 }
1400
1401 template <class ConstBufferSequence, class CompletionToken>
1402 auto async_send(const ConstBufferSequence &buffers, CompletionToken &&token) {
1404 "");
1405 return async_send(buffers, 0, std::forward<CompletionToken>(token));
1406 }
1407};
1408
1409// 18.9 [socket.acceptor]
1410template <typename AcceptableProtocol>
1412 private basic_socket_impl<AcceptableProtocol> {
1414
1415 public:
1418 using protocol_type = AcceptableProtocol;
1420 using endpoint_type = typename protocol_type::endpoint;
1421 using error_type = std::error_code;
1422
1424 : __base(ctx), protocol_{endpoint_type().protocol()} {}
1425
1426 executor_type get_executor() noexcept { return __base::get_executor(); }
1427
1429 const protocol_type &protocol = protocol_type(), int flags = 0) {
1430 return __base::open(protocol, flags);
1431 }
1432
1434 const protocol_type &protocol,
1435 const native_handle_type &native_acceptor) {
1436 return __base::assign(protocol, native_acceptor);
1437 }
1438
1440 return __base::release();
1441 }
1442
1444
1445 constexpr bool is_open() const { return __base::is_open(); }
1446
1448
1449 stdx::expected<void, error_type> cancel() { return __base::cancel(); }
1450
1451 template <typename SettableSocketOption>
1453 const SettableSocketOption &option) {
1454 return __base::set_option(option);
1455 }
1456
1457 template <typename GettableSocketOption>
1459 GettableSocketOption &option) const {
1460 return __base::get_option(option);
1461 }
1462
1463 bool non_blocking() const { return __base::non_blocking(); }
1464
1466 return __base::non_blocking(mode);
1467 }
1468
1470
1473 }
1474
1476 return __base::bind(endpoint);
1477 }
1478
1480 return __base::listen(backlog);
1481 }
1482
1484 return __base::local_endpoint();
1485 }
1486
1487 // enable_connection_aborted(bool) - not implemented
1488
1489 bool enable_connection_aborted() const { return enable_connection_aborted_; }
1490
1492 return accept(get_executor().context(), flags);
1493 }
1494
1496 int flags = 0) {
1497 // in case of ECONNABORTED, retry if not explicitly enabled
1498 while (true) {
1499 auto accept_res = __base::accept(io_ctx, flags);
1500
1501 if (accept_res || enable_connection_aborted() ||
1502 accept_res.error() !=
1503 make_error_condition(std::errc::connection_aborted)) {
1504 return accept_res;
1505 }
1506 }
1507 }
1508
1510 int flags = 0) {
1511 return accept(get_executor().context(), endpoint, flags);
1512 }
1513
1515 endpoint_type &endpoint,
1516 int flags = 0) {
1517 // in case of ECONNABORTED, retry if not explicitly enabled
1518 while (true) {
1519 auto accept_res = __base::accept(io_ctx, endpoint, flags);
1520
1521 if (accept_res || enable_connection_aborted() ||
1522 accept_res.error() !=
1523 make_error_condition(std::errc::connection_aborted)) {
1524 return accept_res;
1525 }
1526 }
1527 }
1528
1529 template <class CompletionToken>
1530 auto async_accept(io_context &io_ctx, CompletionToken &&token) {
1531 async_completion<CompletionToken, void(std::error_code, socket_type)> init{
1532 token};
1533
1534 // do something
1535 io_ctx.get_executor().context().async_wait(
1536 native_handle(), socket_base::wait_read,
1537 [this, __compl_handler = std::move(init.completion_handler),
1538 __protocol = protocol_, __fd = native_handle(),
1539 &io_ctx](std::error_code ec) mutable {
1540 if (ec) {
1541 __compl_handler(ec, socket_type(io_ctx));
1542 return;
1543 }
1544
1545 while (true) {
1546 auto res = this->get_executor().context().socket_service()->accept(
1547 __fd, nullptr, nullptr);
1548
1549 if (!res && !enable_connection_aborted() &&
1550 res.error() ==
1551 make_error_condition(std::errc::connection_aborted)) {
1552 continue;
1553 }
1554
1555 if (!res) {
1556 __compl_handler(res.error(), socket_type(io_ctx));
1557 } else {
1558 __compl_handler({}, socket_type{io_ctx, __protocol, res.value()});
1559 }
1560 return;
1561 }
1562 });
1563
1564 return init.result.get();
1565 }
1566
1567 template <class CompletionToken>
1568 auto async_accept(endpoint_type &endpoint, CompletionToken &&token) {
1569 return async_accept(get_executor().context(), endpoint,
1570 std::forward<CompletionToken>(token));
1571 }
1572
1573 /**
1574 * accept a connection with endpoint async'.
1575 *
1576 * - returns immediately
1577 * - calls completiontoken when finished
1578 *
1579 * @param [in,out] io_ctx io-context to execute the waiting/execution in
1580 * @param [out] endpoint remote endpoint of the accepted connection
1581 * @param [in] token completion token of type 'void(std::error_code,
1582 * socket_type)'
1583 */
1584 template <class CompletionToken>
1585 auto async_accept(io_context &io_ctx, endpoint_type &endpoint,
1586 CompletionToken &&token) {
1587 async_completion<CompletionToken, void(std::error_code, socket_type)> init{
1588 token};
1589
1590 // - wait for acceptor to become readable
1591 // - accept() it.
1592 // - call completion with socket
1593 io_ctx.get_executor().context().async_wait(
1594 native_handle(), socket_base::wait_read,
1595 [this, __compl_handler = std::move(init.completion_handler),
1596 __protocol = protocol_, __fd = native_handle(), &__ep = endpoint,
1597 &io_ctx](std::error_code ec) mutable {
1598 if (ec) {
1599 __compl_handler(ec, socket_type(io_ctx));
1600 return;
1601 }
1602
1603 while (true) {
1604 socklen_t endpoint_len = __ep.capacity();
1605
1606 auto res = this->get_executor().context().socket_service()->accept(
1607 __fd, static_cast<sockaddr *>(__ep.data()), &endpoint_len);
1608
1609 if (!res && !enable_connection_aborted() &&
1610 res.error() ==
1611 make_error_condition(std::errc::connection_aborted)) {
1612 continue;
1613 }
1614
1615 if (!res) {
1616 __compl_handler(res.error(), socket_type(io_ctx));
1617 } else {
1618 __ep.resize(endpoint_len);
1619
1620 __compl_handler({}, socket_type{io_ctx, __protocol, res.value()});
1621 }
1622 return;
1623 }
1624 });
1625
1626 return init.result.get();
1627 }
1628
1629 template <class CompletionToken>
1630 auto async_accept(CompletionToken &&token) {
1631 return async_accept(get_executor().context(),
1632 std::forward<CompletionToken>(token));
1633 }
1634
1636 return __base::wait(wt);
1637 }
1638
1639#if defined(ALL_COMPILERS_FULLY_SUPPORT_CPP14)
1640 // the define ALL_COMPILERS_FULLY_SUPPORT_CPP14 is a placeholder.
1641 //
1642 // The code below assumes the compiler supports generalized lambda
1643 // capture from C++14, allowing use move the ownership into the lambda.
1644 //
1645 // The code works with:
1646 //
1647 // - gcc 5.x and later
1648 // - clang 4 and later
1649 // - MSVC ...
1650 //
1651 // but it fails for move-only completion handlers with:
1652 //
1653 // - sun pro 15.6
1654 //
1655 // As soon as sun pro is fixed or supported for it is dropped,
1656 // C++11 implementation below and this comment can be removed.
1657 template <typename CompletionToken>
1658 auto async_wait(wait_type w, CompletionToken &&token) {
1659 async_completion<CompletionToken, void(std::error_code)> init{token};
1660
1661 get_executor().context().async_wait(
1662 native_handle(), w,
1663 [__compl_handler = std::move(init.completion_handler)](
1664 std::error_code ec) mutable { __compl_handler(ec); });
1665
1666 return init.result.get();
1667 }
1668#else
1669 // C++11 compatible implementation of async_wait() which allows move-only
1670 // completion handlers
1671 //
1672 // to be removed, once all supported compilers fully support C++14 generalized
1673 // lambda capture
1674
1675 template <typename CompletionToken>
1676 typename async_result<std::decay_t<CompletionToken>,
1677 void(std::error_code)>::return_type
1678 async_wait(wait_type w, CompletionToken &&token) {
1679 async_completion<CompletionToken, void(std::error_code)> init{token};
1680
1681 using async_completion_handler_type =
1682 typename decltype(init)::completion_handler_type;
1683
1684 // capture the completion handler
1685 class ClosureType {
1686 public:
1687 explicit ClosureType(async_completion_handler_type &&compl_handler)
1688 : compl_handler_{
1689 std::forward<decltype(compl_handler)>(compl_handler)} {}
1690
1691 void operator()(std::error_code ec) { compl_handler_(ec); }
1692
1693 private:
1694 async_completion_handler_type compl_handler_;
1695 };
1696
1697 // get native-handle before std::move()ing the completion handler into the
1698 // async_wait(). Otherwise the native_handle() may refer to the moved-from
1699 // object
1700 const auto handle = native_handle();
1701
1702 get_executor().context().async_wait(
1703 handle, w,
1704 ClosureType(std::forward<async_completion_handler_type>(
1705 init.completion_handler)));
1706
1707 return init.result.get();
1708 }
1709#endif
1710
1711 private:
1713 bool enable_connection_aborted_{false};
1714};
1715
1716// 20.1 [socket.algo.connect]
1717
1718/**
1719 * connect to the first endpoint that is connectable from a sequence of
1720 * endpoints.
1721 *
1722 * @param s socket that should be connected to an endpoint
1723 * @param endpoints a sequence of endpoints
1724 * @param c ConnectionCondition that must return true if the provided endpoint
1725 * should be attempted to be connected to
1726 *
1727 * @returns endpoint the connect succeeded for on success, last error-code
1728 * otherwise
1729 */
1730template <class Protocol, class EndpointSequence, class ConnectCondition>
1732 basic_socket<Protocol> &s, const EndpointSequence &endpoints,
1733 ConnectCondition c) {
1734 return connect(s, std::begin(endpoints), std::end(endpoints), c);
1735}
1736
1737/**
1738 * connect to the first endpoint that is connectable.
1739 *
1740 * @param s socket that should be connected to an endpoint
1741 * @param endpoints a sequence of endpoints
1742 *
1743 * @returns endpoint the connect succeeded for on success, last error-code
1744 * otherwise
1745 */
1746template <class Protocol, class EndpointSequence>
1748 basic_socket<Protocol> &s, const EndpointSequence &endpoints) {
1749 return connect(s, endpoints, [](auto, auto) { return true; });
1750}
1751
1752/**
1753 * connect to the first endpoint that is connectable from a range [first, last).
1754 *
1755 * @param s socket that should be connected to an endpoint
1756 * @param first iterator to the first endpoint
1757 * @param last iterator after to the last endpoint
1758 * @param c ConnectionCondition that must return true if the provided endpoint
1759 * should be attempted to be connected to
1760 *
1761 * @returns endpoint the connect succeeded for on success, last error-code
1762 * otherwise
1763 */
1764template <class Protocol, class InputIterator, class ConnectCondition>
1766 basic_socket<Protocol> &s, InputIterator first, InputIterator last,
1767 ConnectCondition c) {
1768 // capture that last error-code for the connect-condition
1769 std::error_code ec;
1770
1771 for (InputIterator cur = first; cur != last; ++cur) {
1772 // check if the endpoint should be connected to
1773 if (!c(ec, *cur)) continue;
1774
1775 auto res = s.close();
1776 if (!res) {
1777 ec = res.error();
1778 continue;
1779 }
1780
1781 res = s.open(typename Protocol::endpoint(*cur).protocol());
1782 if (!res) {
1783 ec = res.error();
1784 continue;
1785 }
1786
1787 res = s.connect(*cur);
1788 if (!res) {
1789 ec = res.error();
1790 } else {
1791 return cur;
1792 }
1793 }
1794
1795 return stdx::make_unexpected(make_error_code(socket_errc::not_found));
1796}
1797
1798template <class Protocol, class InputIterator, class ConnectCondition>
1800 basic_socket<Protocol> &s, InputIterator first, InputIterator last) {
1801 return connect(s, first, last, [](auto, auto) { return true; });
1802}
1803
1804} // namespace net
1805
1806#if defined(MYSQL_HARNESS_HEADER_ONLY)
1808#endif
1809
1810#endif
Definition: protocol.h:33
Definition: executor.h:72
Definition: socket.h:971
stdx::expected< size_t, std::error_code > send_to(const ConstBufferSequence &buffers, const endpoint_type &recipient)
Definition: socket.h:1077
stdx::expected< size_t, std::error_code > receive_from(const MutableBufferSequence &buffers, endpoint_type &sender)
Definition: socket.h:1033
stdx::expected< bool, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:1092
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:981
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1000
basic_datagram_socket(io_context &ctx, const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:995
stdx::expected< size_t, std::error_code > receive_from(const MutableBufferSequence &buffers, endpoint_type &sender, socket_base::message_flags flags)
Definition: socket.h:1015
basic_datagram_socket(basic_datagram_socket &&other)=default
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers)
Definition: socket.h:1009
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1045
auto async_receive(const MutableBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1098
basic_datagram_socket & operator=(basic_datagram_socket &&)=default
stdx::expected< size_t, std::error_code > read_some(const MutableBufferSequence &buffers)
Definition: socket.h:1039
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers)
Definition: socket.h:1056
basic_datagram_socket(io_context &ctx)
Definition: socket.h:980
stdx::expected< size_t, std::error_code > send_to(const ConstBufferSequence &buffers, const endpoint_type &recipient, socket_base::message_flags flags)
Definition: socket.h:1064
stdx::expected< size_t, std::error_code > write_some(const ConstBufferSequence &buffers)
Definition: socket.h:1085
auto async_receive(const MutableBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1136
Definition: socket.h:1412
basic_socket_acceptor(io_context &ctx)
Definition: socket.h:1423
typename protocol_type::endpoint endpoint_type
Definition: socket.h:1420
auto async_accept(io_context &io_ctx, endpoint_type &endpoint, CompletionToken &&token)
accept a connection with endpoint async'.
Definition: socket.h:1585
std::error_code error_type
Definition: socket.h:1421
stdx::expected< endpoint_type, error_type > local_endpoint() const
Definition: socket.h:1483
bool native_non_blocking() const
Definition: socket.h:1469
bool non_blocking() const
Definition: socket.h:1463
stdx::expected< void, error_type > assign(const protocol_type &protocol, const native_handle_type &native_acceptor)
Definition: socket.h:1433
stdx::expected< native_handle_type, error_type > release()
Definition: socket.h:1439
async_result< std::decay_t< CompletionToken >, void(std::error_code)>::return_type async_wait(wait_type w, CompletionToken &&token)
Definition: socket.h:1678
stdx::expected< socket_type, error_type > accept(int flags=0)
Definition: socket.h:1491
native_handle_type native_handle() const
Definition: socket.h:1443
stdx::expected< void, error_type > listen(int backlog)
Definition: socket.h:1479
stdx::expected< void, error_type > open(const protocol_type &protocol=protocol_type(), int flags=0)
Definition: socket.h:1428
AcceptableProtocol protocol_type
Definition: socket.h:1418
stdx::expected< socket_type, error_type > accept(endpoint_type &endpoint, int flags=0)
Definition: socket.h:1509
typename protocol_type::socket socket_type
Definition: socket.h:1419
stdx::expected< void, error_type > bind(const endpoint_type &endpoint)
Definition: socket.h:1475
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, endpoint_type &endpoint, int flags=0)
Definition: socket.h:1514
stdx::expected< void, error_type > close()
Definition: socket.h:1447
auto async_accept(endpoint_type &endpoint, CompletionToken &&token)
Definition: socket.h:1568
executor_type get_executor() noexcept
Definition: socket.h:1426
protocol_type protocol_
Definition: socket.h:1712
stdx::expected< void, std::error_code > wait(socket_base::wait_type wt)
Definition: socket.h:1635
auto async_accept(CompletionToken &&token)
Definition: socket.h:1630
stdx::expected< void, error_type > cancel()
Definition: socket.h:1449
bool enable_connection_aborted() const
Definition: socket.h:1489
stdx::expected< void, std::error_code > native_non_blocking(bool mode)
Definition: socket.h:1471
auto async_accept(io_context &io_ctx, CompletionToken &&token)
Definition: socket.h:1530
stdx::expected< void, error_type > get_option(GettableSocketOption &option) const
Definition: socket.h:1458
stdx::expected< void, std::error_code > non_blocking(bool mode)
Definition: socket.h:1465
constexpr bool is_open() const
Definition: socket.h:1445
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, int flags=0)
Definition: socket.h:1495
stdx::expected< void, error_type > set_option(const SettableSocketOption &option)
Definition: socket.h:1452
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:466
basic_socket_impl_base & operator=(const basic_socket_impl_base &rhs)=delete
bool non_blocking_
Definition: socket.h:452
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:442
stdx::expected< void, std::error_code > cancel()
Definition: socket.h:432
native_handle_type native_handle_
Definition: socket.h:450
stdx::expected< void, std::error_code > close()
Definition: socket.h:416
char native_non_blocking_
Definition: socket.h:453
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:471
typename protocol_type::socket socket_type
Definition: socket.h:479
basic_socket_impl(basic_socket_impl &&rhs)=default
Protocol protocol_type
Definition: socket.h:476
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:531
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, int flags=0)
Definition: socket.h:560
~basic_socket_impl()
Definition: socket.h:499
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:503
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:477
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:520
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:481
protocol_type protocol_
Definition: socket.h:707
std::error_code error_type
Definition: socket.h:478
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:488
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:538
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
async_result< std::decay_t< CompletionToken >, void(std::error_code)>::return_type async_wait(wait_type w, CompletionToken &&token)
Definition: socket.h:911
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:947
basic_socket(io_context &ctx, const protocol_type &proto, const native_handle_type &native_handle)
Definition: socket.h:950
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:945
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:1144
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers)
Definition: socket.h:1221
stdx::expected< size_t, std::error_code > read_some(const MutableBufferSequence &buffers)
Definition: socket.h:1195
stdx::expected< void, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:1236
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers)
Definition: socket.h:1189
basic_stream_socket(const basic_stream_socket &)=delete
auto async_send(const ConstBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1402
auto async_receive(const MutableBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1329
stdx::expected< size_t, std::error_code > write_some(const ConstBufferSequence &buffers)
Definition: socket.h:1229
basic_stream_socket(io_context &ctx, const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:1166
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:1171
auto async_send(const ConstBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1335
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1201
basic_stream_socket(io_context &ctx)
Definition: socket.h:1153
basic_stream_socket & operator=(basic_stream_socket &&)=default
auto async_receive(const MutableBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1242
basic_stream_socket & operator=(const basic_stream_socket &)=delete
basic_stream_socket(io_context &ctx, const protocol_type &proto)
Definition: socket.h:1154
Definition: socket_service_base.h:48
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:990
io_context & context() const noexcept
Definition: io_context.h:1002
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:1080
stdx::expected< void, std::error_code > cancel(native_handle_type fd)
cancel all async-ops of a file-descriptor.
Definition: io_context.h:1087
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:944
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: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:107
Definition: authentication.cc:36
std::error_code make_error_code(DynamicLoaderErrc ec)
make error_code from a DynamicLoaderErrc.
Definition: dynamic_loader.cc:79
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:673
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:663
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:636
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:804
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:315
stdx::expected< InputIterator, std::error_code > connect(basic_socket< Protocol > &s, InputIterator first, InputIterator last)
Definition: socket.h:1799
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
static int handle(int sql_errno, const char *sqlstate, const char *message, void *state)
Bridge function between the C++ API offered by this module and the C API of the parser service.
Definition: services.cc:64
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:60
native_handle_type native_handle()
Definition: process.h:56
constexpr auto make_unexpected(E &&e) -> unexpected< std::decay_t< E > >
Definition: expected.h:125
struct sockaddr sockaddr
Definition: sock_probe_win32.h:63
case opt name
Definition: sslopt-case.h:33
Definition: buffer.h:261
double seconds()
Definition: task.cc:310