MySQL 8.0.33
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#if defined(ALL_COMPILERS_FULLY_SUPPORT_CPP14)
872 // the define ALL_COMPILERS_FULLY_SUPPORT_CPP14 is a placeholder.
873 //
874 // The code below assumes the compiler supports generalized lambda
875 // capture from C++14, allowing use move the ownership into the lambda.
876 //
877 // The code works with:
878 //
879 // - gcc 5.x and later
880 // - clang 4 and later
881 // - MSVC ...
882 //
883 // but it fails for move-only completion handlers with:
884 //
885 // - sun pro 15.6
886 //
887 // As soon as sun pro is fixed or supported for it is dropped,
888 // C++11 implementation below and this comment can be removed.
889 template <typename CompletionToken>
890 auto async_wait(wait_type w, CompletionToken &&token) {
891 async_completion<CompletionToken, void(std::error_code)> init{token};
892
893 get_executor().context().async_wait(
894 native_handle(), w,
895 [__compl_handler = std::move(init.completion_handler)](
896 std::error_code ec) mutable { __compl_handler(ec); });
897
898 return init.result.get();
899 }
900#else
901 // C++11 compatible implementation of async_wait() which allows move-only
902 // completion handlers
903 //
904 // to be removed, once all supported compilers fully support C++14 generalized
905 // lambda capture
906
907 template <typename CompletionToken>
908 typename async_result<std::decay_t<CompletionToken>,
909 void(std::error_code)>::return_type
910 async_wait(wait_type w, CompletionToken &&token) {
911 async_completion<CompletionToken, void(std::error_code)> init{token};
912
913 using async_completion_handler_type =
914 typename decltype(init)::completion_handler_type;
915
916 // capture the completion handler
917 class ClosureType {
918 public:
919 explicit ClosureType(async_completion_handler_type &&compl_handler)
920 : compl_handler_{
921 std::forward<decltype(compl_handler)>(compl_handler)} {}
922
923 void operator()(std::error_code ec) { compl_handler_(ec); }
924
925 private:
926 async_completion_handler_type compl_handler_;
927 };
928
929 // get native-handle before std::move()ing the completion handler into the
930 // async_wait(). Otherwise the native_handle() may refer to the moved-from
931 // object
932 const auto handle = native_handle();
933
934 get_executor().context().async_wait(
935 handle, w,
936 ClosureType(std::forward<async_completion_handler_type>(
937 init.completion_handler)));
938
939 return init.result.get();
940 }
941#endif
942
943 protected:
944 explicit basic_socket(io_context &ctx) : __base{ctx} {}
945
947 : __base{ctx, proto} {}
948
951 : __base{ctx} {
952 assign(proto, native_handle);
953 }
954
955 // as demanded by networking-ts
956 // NOLINTNEXTLINE(hicpp-use-equals-delete,modernize-use-equals-delete)
957 basic_socket(const basic_socket &) = delete;
958 // NOLINTNEXTLINE(hicpp-use-equals-delete,modernize-use-equals-delete)
960 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
961 basic_socket(basic_socket &&other) = default;
962 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
964
965 ~basic_socket() = default;
966};
967
968// 18.7 [socket.dgram]
969template <typename Protocol>
970class basic_datagram_socket : public basic_socket<Protocol> {
972
973 public:
976 using endpoint_type = typename protocol_type::endpoint;
977 using error_type = std::error_code;
978
979 explicit basic_datagram_socket(io_context &ctx) : __base(ctx) {}
981 : __base(ctx, proto) {}
982
985
986 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
988 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
990
992
993 //
996 : __base(ctx, protocol, native_handle) {}
997
998 template <class MutableBufferSequence>
1000 const MutableBufferSequence &buffers, socket_base::message_flags flags) {
1001 socket_base::msg_hdr msg(buffers);
1002
1003 return this->get_executor().context().socket_service()->recvmsg(
1005 }
1006
1007 template <class MutableBufferSequence>
1009 const MutableBufferSequence &buffers) {
1010 return receive(buffers, 0);
1011 }
1012
1013 template <class MutableBufferSequence>
1015 const MutableBufferSequence &buffers, endpoint_type &sender,
1017 socket_base::msg_hdr msg(buffers);
1018 msg.set_sender(sender);
1019
1020 auto res = this->get_executor().context().socket_service()->recvmsg(
1022
1023 if (res) {
1024 // resize the endpoint
1025 msg.resize_sender(sender);
1026 }
1027
1028 return res;
1029 }
1030
1031 template <class MutableBufferSequence>
1033 const MutableBufferSequence &buffers, endpoint_type &sender) {
1034 return receive_from(buffers, sender, 0);
1035 }
1036
1037 template <class MutableBufferSequence>
1039 const MutableBufferSequence &buffers) {
1040 return receive(buffers);
1041 }
1042
1043 template <class ConstBufferSequence>
1045 const ConstBufferSequence &buffers, socket_base::message_flags flags) {
1047 "");
1048 socket_base::msg_hdr msg(buffers);
1049
1050 return this->get_executor().context().socket_service()->sendmsg(
1052 }
1053
1054 template <class ConstBufferSequence>
1056 const ConstBufferSequence &buffers) {
1058 "");
1059 return send(buffers, 0);
1060 }
1061
1062 template <class ConstBufferSequence>
1064 const ConstBufferSequence &buffers, const endpoint_type &recipient,
1067 "");
1068 socket_base::msg_hdr msg(buffers);
1069 msg.set_recipient(recipient);
1070
1071 return this->get_executor().context().socket_service()->sendmsg(
1073 }
1074
1075 template <class ConstBufferSequence>
1077 const ConstBufferSequence &buffers, const endpoint_type &recipient) {
1079 "");
1080 return send_to(buffers, recipient, 0);
1081 }
1082
1083 template <class ConstBufferSequence>
1085 const ConstBufferSequence &buffers) {
1087 "");
1088 return send(buffers);
1089 }
1090
1092 socket_base::shutdown_type st) const {
1093 return __base::shutdown(st);
1094 }
1095
1096 template <class MutableBufferSequence, class CompletionToken>
1097 auto async_receive(const MutableBufferSequence &buffers,
1099 CompletionToken &&token) {
1100 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1101 token};
1102
1103 if ((flags & socket_base::message_peek).any()) {
1104 // required by std::
1105 init.completion_handler(make_error_code(std::errc::invalid_argument), 0);
1106
1107 return init.result.get();
1108 }
1109
1110 this->get_executor().context().async_wait(
1111 this->native_handle(), socket_base::wait_read,
1112 [this, __compl_handler = std::move(init.completion_handler), &buffers,
1113 __fd = this->native_handle(),
1114 __flags = flags](std::error_code ec) mutable {
1115 if (ec) {
1116 __compl_handler(ec, 0);
1117 return;
1118 }
1119
1120 socket_base::msg_hdr msgs(buffers);
1121
1122 auto res = this->get_executor().context().socket_service()->recvmsg(
1123 __fd, msgs, __flags);
1124 if (!res) {
1125 __compl_handler(res.error(), 0);
1126 } else {
1127 __compl_handler({}, res.value());
1128 }
1129 });
1130
1131 return init.result.get();
1132 }
1133
1134 template <class MutableBufferSequence, class CompletionToken>
1135 auto async_receive(const MutableBufferSequence &buffers,
1136 CompletionToken &&token) {
1137 return async_receive(buffers, 0, std::forward<CompletionToken>(token));
1138 }
1139};
1140
1141// 18.8 [socket.stream]
1142template <typename Protocol>
1143class basic_stream_socket : public basic_socket<Protocol> {
1145
1146 public:
1149 using endpoint_type = typename protocol_type::endpoint;
1150 using error_type = std::error_code;
1151
1152 explicit basic_stream_socket(io_context &ctx) : __base(ctx) {}
1154 : __base(ctx, proto) {}
1155
1158 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
1160 // NOLINTNEXTLINE(hicpp-noexcept-move,performance-noexcept-move-constructor)
1162
1164 //
1167 : __base(ctx, protocol, native_handle) {}
1168
1169 template <class MutableBufferSequence>
1171 const MutableBufferSequence &buffers, socket_base::message_flags flags) {
1172 if (buffer_size(buffers) == 0) return 0;
1173
1174 socket_base::msg_hdr msg(buffers);
1175
1176 auto res = this->get_executor().context().socket_service()->recvmsg(
1178
1179 if (res && res.value() == 0) {
1180 // remote did a orderly shutdown
1182 }
1183
1184 return res;
1185 }
1186
1187 template <class MutableBufferSequence>
1189 const MutableBufferSequence &buffers) {
1190 return receive(buffers, 0);
1191 }
1192
1193 template <class MutableBufferSequence>
1195 const MutableBufferSequence &buffers) {
1196 return receive(buffers);
1197 }
1198
1199 template <class ConstBufferSequence>
1201 const ConstBufferSequence &buffers, socket_base::message_flags flags) {
1203 "");
1204 if (buffer_size(buffers) == 0) return 0;
1205
1206 socket_base::msg_hdr msg(buffers);
1207
1208 auto res = this->get_executor().context().socket_service()->sendmsg(
1210
1211 if (res && res.value() == 0) {
1212 // remote did a orderly shutdown
1214 }
1215
1216 return res;
1217 }
1218
1219 template <class ConstBufferSequence>
1221 const ConstBufferSequence &buffers) {
1223 "");
1224 return send(buffers, 0);
1225 }
1226
1227 template <class ConstBufferSequence>
1229 const ConstBufferSequence &buffers) {
1231 "");
1232 return send(buffers);
1233 }
1234
1236 socket_base::shutdown_type st) const {
1237 return __base::shutdown(st);
1238 }
1239
1240 template <class MutableBufferSequence, class CompletionToken>
1241 auto async_receive(const MutableBufferSequence &buffers,
1243 CompletionToken &&token) {
1244 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1245 token};
1246 if ((flags & socket_base::message_peek).any()) {
1247 // required by std::
1248 init.completion_handler(make_error_code(std::errc::invalid_argument), 0);
1249
1250 return init.result.get();
1251 }
1252
1253 if (buffer_size(buffers) == 0) {
1254 init.completion_handler({}, 0);
1255
1256 return init.result.get();
1257 }
1258
1259 /*
1260 * as we use C++14, we could use a lambda here which supports movable
1261 * arguments, but sun-cc 15.6 generates the wrong constructor:
1262 *
1263 * "...::{lambda at socket.h,1203:9}::<constructor>(
1264 * net::basic_stream_socket<net::ip::tcp>*,
1265 * const server_mock::MySQLServerMockSessionClassic::StateMachine&,
1266 * const std::list<net::const_buffer>&, int, std::bitset<31>&)"
1267 *
1268 * The "const StateMachine &" should have been "StateMachine &&".
1269 */
1270
1271 using compl_handler_type = typename decltype(init)::completion_handler_type;
1272
1273 class Completor {
1274 public:
1275 Completor(net::impl::socket::SocketServiceBase *socket_service,
1276 compl_handler_type &&compl_handler,
1277 const MutableBufferSequence &buffers,
1280 : socket_service_{socket_service},
1281 compl_handler_(std::move(compl_handler)),
1282 buffers_{buffers},
1283 native_handle_{native_handle},
1284 flags_{flags} {}
1285
1286 Completor(const Completor &) = delete;
1287 Completor(Completor &&) = default;
1288
1289 void operator()(std::error_code ec) {
1290 if (ec) {
1291 compl_handler_(ec, 0);
1292 return;
1293 }
1294
1295 socket_base::msg_hdr msgs(buffers_);
1296
1297 const auto res = socket_service_->recvmsg(native_handle_, msgs, flags_);
1298 if (!res) {
1299 compl_handler_(res.error(), 0);
1300 } else if (res.value() == 0) {
1301 // remote did a orderly shutdown
1302 compl_handler_(make_error_code(stream_errc::eof), 0);
1303 } else {
1304 compl_handler_({}, res.value());
1305 }
1306
1307 return;
1308 }
1309
1310 private:
1311 net::impl::socket::SocketServiceBase *socket_service_;
1312 compl_handler_type compl_handler_;
1313 const MutableBufferSequence &buffers_;
1314 impl::socket::native_handle_type native_handle_;
1316 };
1317
1318 this->get_executor().context().async_wait(
1319 this->native_handle(), socket_base::wait_read,
1320 Completor(this->get_executor().context().socket_service(),
1321 std::move(init.completion_handler), buffers,
1322 this->native_handle(), flags));
1323
1324 return init.result.get();
1325 }
1326
1327 template <class MutableBufferSequence, class CompletionToken>
1328 auto async_receive(const MutableBufferSequence &buffers,
1329 CompletionToken &&token) {
1330 return async_receive(buffers, 0, std::forward<CompletionToken>(token));
1331 }
1332
1333 template <class ConstBufferSequence, class CompletionToken>
1334 auto async_send(const ConstBufferSequence &buffers,
1335 socket_base::message_flags flags, CompletionToken &&token) {
1337 "");
1338 async_completion<CompletionToken, void(std::error_code, size_t)> init{
1339 token};
1340 if (buffer_size(buffers) == 0) {
1341 init.completion_handler({}, 0);
1342
1343 return init.result.get();
1344 }
1345
1346 // see async_receive() for why this isn't a lambda.
1347 using compl_handler_type = typename decltype(init)::completion_handler_type;
1348
1349 class Completor {
1350 public:
1351 Completor(net::impl::socket::SocketServiceBase *socket_service,
1352 compl_handler_type &&compl_handler,
1353 const ConstBufferSequence &buffers,
1356 : socket_service_{socket_service},
1357 compl_handler_(std::move(compl_handler)),
1358 buffers_{buffers},
1359 native_handle_{native_handle},
1360 flags_{flags} {}
1361
1362 Completor(const Completor &) = delete;
1363 Completor(Completor &&) = default;
1364
1365 void operator()(std::error_code ec) {
1366 if (ec) {
1367 compl_handler_(ec, 0);
1368 return;
1369 }
1370
1371 socket_base::msg_hdr msgs(buffers_);
1372
1373 const auto res = socket_service_->sendmsg(native_handle_, msgs, flags_);
1374 if (!res) {
1375 compl_handler_(res.error(), 0);
1376 } else {
1377 compl_handler_({}, res.value());
1378 }
1379
1380 return;
1381 }
1382
1383 net::impl::socket::SocketServiceBase *socket_service_;
1384 compl_handler_type compl_handler_;
1385 const ConstBufferSequence &buffers_;
1386 impl::socket::native_handle_type native_handle_;
1388 };
1389
1390 // do something
1391 this->get_executor().context().async_wait(
1392 this->native_handle(), socket_base::wait_write,
1393 Completor(this->get_executor().context().socket_service(),
1394 std::move(init.completion_handler), buffers,
1395 this->native_handle(), flags));
1396
1397 return init.result.get();
1398 }
1399
1400 template <class ConstBufferSequence, class CompletionToken>
1401 auto async_send(const ConstBufferSequence &buffers, CompletionToken &&token) {
1403 "");
1404 return async_send(buffers, 0, std::forward<CompletionToken>(token));
1405 }
1406};
1407
1408// 18.9 [socket.acceptor]
1409template <typename AcceptableProtocol>
1411 private basic_socket_impl<AcceptableProtocol> {
1413
1414 public:
1417 using protocol_type = AcceptableProtocol;
1419 using endpoint_type = typename protocol_type::endpoint;
1420 using error_type = std::error_code;
1421
1423 : __base(ctx), protocol_{endpoint_type().protocol()} {}
1424
1425 executor_type get_executor() noexcept { return __base::get_executor(); }
1426
1428 const protocol_type &protocol = protocol_type(), int flags = 0) {
1429 return __base::open(protocol, flags);
1430 }
1431
1433 const protocol_type &protocol,
1434 const native_handle_type &native_acceptor) {
1435 return __base::assign(protocol, native_acceptor);
1436 }
1437
1439 return __base::release();
1440 }
1441
1443
1444 constexpr bool is_open() const { return __base::is_open(); }
1445
1447
1448 stdx::expected<void, error_type> cancel() { return __base::cancel(); }
1449
1450 template <typename SettableSocketOption>
1452 const SettableSocketOption &option) {
1453 return __base::set_option(option);
1454 }
1455
1456 template <typename GettableSocketOption>
1458 GettableSocketOption &option) const {
1459 return __base::get_option(option);
1460 }
1461
1462 bool non_blocking() const { return __base::non_blocking(); }
1463
1465 return __base::non_blocking(mode);
1466 }
1467
1469
1472 }
1473
1475 return __base::bind(endpoint);
1476 }
1477
1479 return __base::listen(backlog);
1480 }
1481
1483 return __base::local_endpoint();
1484 }
1485
1486 // enable_connection_aborted(bool) - not implemented
1487
1488 bool enable_connection_aborted() const { return enable_connection_aborted_; }
1489
1491 return accept(get_executor().context(), flags);
1492 }
1493
1495 int flags = 0) {
1496 // in case of ECONNABORTED, retry if not explicitly enabled
1497 while (true) {
1498 auto accept_res = __base::accept(io_ctx, flags);
1499
1500 if (accept_res || enable_connection_aborted() ||
1501 accept_res.error() !=
1502 make_error_condition(std::errc::connection_aborted)) {
1503 return accept_res;
1504 }
1505 }
1506 }
1507
1509 int flags = 0) {
1510 return accept(get_executor().context(), endpoint, flags);
1511 }
1512
1514 endpoint_type &endpoint,
1515 int flags = 0) {
1516 // in case of ECONNABORTED, retry if not explicitly enabled
1517 while (true) {
1518 auto accept_res = __base::accept(io_ctx, endpoint, flags);
1519
1520 if (accept_res || enable_connection_aborted() ||
1521 accept_res.error() !=
1522 make_error_condition(std::errc::connection_aborted)) {
1523 return accept_res;
1524 }
1525 }
1526 }
1527
1528 template <class CompletionToken>
1529 auto async_accept(io_context &io_ctx, CompletionToken &&token) {
1530 async_completion<CompletionToken, void(std::error_code, socket_type)> init{
1531 token};
1532
1533 // do something
1534 io_ctx.get_executor().context().async_wait(
1535 native_handle(), socket_base::wait_read,
1536 [this, __compl_handler = std::move(init.completion_handler),
1537 __protocol = protocol_, __fd = native_handle(),
1538 &io_ctx](std::error_code ec) mutable {
1539 if (ec) {
1540 __compl_handler(ec, socket_type(io_ctx));
1541 return;
1542 }
1543
1544 while (true) {
1545 auto res = this->get_executor().context().socket_service()->accept(
1546 __fd, nullptr, nullptr);
1547
1548 if (!res && !enable_connection_aborted() &&
1549 res.error() ==
1550 make_error_condition(std::errc::connection_aborted)) {
1551 continue;
1552 }
1553
1554 if (!res) {
1555 __compl_handler(res.error(), socket_type(io_ctx));
1556 } else {
1557 __compl_handler({}, socket_type{io_ctx, __protocol, res.value()});
1558 }
1559 return;
1560 }
1561 });
1562
1563 return init.result.get();
1564 }
1565
1566 template <class CompletionToken>
1567 auto async_accept(endpoint_type &endpoint, CompletionToken &&token) {
1568 return async_accept(get_executor().context(), endpoint,
1569 std::forward<CompletionToken>(token));
1570 }
1571
1572 /**
1573 * accept a connection with endpoint async'.
1574 *
1575 * - returns immediately
1576 * - calls completiontoken when finished
1577 *
1578 * @param [in,out] io_ctx io-context to execute the waiting/execution in
1579 * @param [out] endpoint remote endpoint of the accepted connection
1580 * @param [in] token completion token of type 'void(std::error_code,
1581 * socket_type)'
1582 */
1583 template <class CompletionToken>
1584 auto async_accept(io_context &io_ctx, endpoint_type &endpoint,
1585 CompletionToken &&token) {
1586 async_completion<CompletionToken, void(std::error_code, socket_type)> init{
1587 token};
1588
1589 // - wait for acceptor to become readable
1590 // - accept() it.
1591 // - call completion with socket
1592 io_ctx.get_executor().context().async_wait(
1593 native_handle(), socket_base::wait_read,
1594 [this, __compl_handler = std::move(init.completion_handler),
1595 __protocol = protocol_, __fd = native_handle(), &__ep = endpoint,
1596 &io_ctx](std::error_code ec) mutable {
1597 if (ec) {
1598 __compl_handler(ec, socket_type(io_ctx));
1599 return;
1600 }
1601
1602 while (true) {
1603 socklen_t endpoint_len = __ep.capacity();
1604
1605 auto res = this->get_executor().context().socket_service()->accept(
1606 __fd, static_cast<sockaddr *>(__ep.data()), &endpoint_len);
1607
1608 if (!res && !enable_connection_aborted() &&
1609 res.error() ==
1610 make_error_condition(std::errc::connection_aborted)) {
1611 continue;
1612 }
1613
1614 if (!res) {
1615 __compl_handler(res.error(), socket_type(io_ctx));
1616 } else {
1617 __ep.resize(endpoint_len);
1618
1619 __compl_handler({}, socket_type{io_ctx, __protocol, res.value()});
1620 }
1621 return;
1622 }
1623 });
1624
1625 return init.result.get();
1626 }
1627
1628 template <class CompletionToken>
1629 auto async_accept(CompletionToken &&token) {
1630 return async_accept(get_executor().context(),
1631 std::forward<CompletionToken>(token));
1632 }
1633
1635 return __base::wait(wt);
1636 }
1637
1638#if defined(ALL_COMPILERS_FULLY_SUPPORT_CPP14)
1639 // the define ALL_COMPILERS_FULLY_SUPPORT_CPP14 is a placeholder.
1640 //
1641 // The code below assumes the compiler supports generalized lambda
1642 // capture from C++14, allowing use move the ownership into the lambda.
1643 //
1644 // The code works with:
1645 //
1646 // - gcc 5.x and later
1647 // - clang 4 and later
1648 // - MSVC ...
1649 //
1650 // but it fails for move-only completion handlers with:
1651 //
1652 // - sun pro 15.6
1653 //
1654 // As soon as sun pro is fixed or supported for it is dropped,
1655 // C++11 implementation below and this comment can be removed.
1656 template <typename CompletionToken>
1657 auto async_wait(wait_type w, CompletionToken &&token) {
1658 async_completion<CompletionToken, void(std::error_code)> init{token};
1659
1660 get_executor().context().async_wait(
1661 native_handle(), w,
1662 [__compl_handler = std::move(init.completion_handler)](
1663 std::error_code ec) mutable { __compl_handler(ec); });
1664
1665 return init.result.get();
1666 }
1667#else
1668 // C++11 compatible implementation of async_wait() which allows move-only
1669 // completion handlers
1670 //
1671 // to be removed, once all supported compilers fully support C++14 generalized
1672 // lambda capture
1673
1674 template <typename CompletionToken>
1675 typename async_result<std::decay_t<CompletionToken>,
1676 void(std::error_code)>::return_type
1677 async_wait(wait_type w, CompletionToken &&token) {
1678 async_completion<CompletionToken, void(std::error_code)> init{token};
1679
1680 using async_completion_handler_type =
1681 typename decltype(init)::completion_handler_type;
1682
1683 // capture the completion handler
1684 class ClosureType {
1685 public:
1686 explicit ClosureType(async_completion_handler_type &&compl_handler)
1687 : compl_handler_{
1688 std::forward<decltype(compl_handler)>(compl_handler)} {}
1689
1690 void operator()(std::error_code ec) { compl_handler_(ec); }
1691
1692 private:
1693 async_completion_handler_type compl_handler_;
1694 };
1695
1696 // get native-handle before std::move()ing the completion handler into the
1697 // async_wait(). Otherwise the native_handle() may refer to the moved-from
1698 // object
1699 const auto handle = native_handle();
1700
1701 get_executor().context().async_wait(
1702 handle, w,
1703 ClosureType(std::forward<async_completion_handler_type>(
1704 init.completion_handler)));
1705
1706 return init.result.get();
1707 }
1708#endif
1709
1710 private:
1712 bool enable_connection_aborted_{false};
1713};
1714
1715// 20.1 [socket.algo.connect]
1716
1717/**
1718 * connect to the first endpoint that is connectable from a sequence of
1719 * endpoints.
1720 *
1721 * @param s socket that should be connected to an endpoint
1722 * @param endpoints a sequence of endpoints
1723 * @param c ConnectionCondition that must return true if the provided endpoint
1724 * should be attempted to be connected to
1725 *
1726 * @returns endpoint the connect succeeded for on success, last error-code
1727 * otherwise
1728 */
1729template <class Protocol, class EndpointSequence, class ConnectCondition>
1731 basic_socket<Protocol> &s, const EndpointSequence &endpoints,
1732 ConnectCondition c) {
1733 return connect(s, std::begin(endpoints), std::end(endpoints), c);
1734}
1735
1736/**
1737 * connect to the first endpoint that is connectable.
1738 *
1739 * @param s socket that should be connected to an endpoint
1740 * @param endpoints a sequence of endpoints
1741 *
1742 * @returns endpoint the connect succeeded for on success, last error-code
1743 * otherwise
1744 */
1745template <class Protocol, class EndpointSequence>
1747 basic_socket<Protocol> &s, const EndpointSequence &endpoints) {
1748 return connect(s, endpoints, [](auto, auto) { return true; });
1749}
1750
1751/**
1752 * connect to the first endpoint that is connectable from a range [first, last).
1753 *
1754 * @param s socket that should be connected to an endpoint
1755 * @param first iterator to the first endpoint
1756 * @param last iterator after to the last endpoint
1757 * @param c ConnectionCondition that must return true if the provided endpoint
1758 * should be attempted to be connected to
1759 *
1760 * @returns endpoint the connect succeeded for on success, last error-code
1761 * otherwise
1762 */
1763template <class Protocol, class InputIterator, class ConnectCondition>
1765 basic_socket<Protocol> &s, InputIterator first, InputIterator last,
1766 ConnectCondition c) {
1767 // capture that last error-code for the connect-condition
1768 std::error_code ec;
1769
1770 for (InputIterator cur = first; cur != last; ++cur) {
1771 // check if the endpoint should be connected to
1772 if (!c(ec, *cur)) continue;
1773
1774 auto res = s.close();
1775 if (!res) {
1776 ec = res.error();
1777 continue;
1778 }
1779
1780 res = s.open(typename Protocol::endpoint(*cur).protocol());
1781 if (!res) {
1782 ec = res.error();
1783 continue;
1784 }
1785
1786 res = s.connect(*cur);
1787 if (!res) {
1788 ec = res.error();
1789 } else {
1790 return cur;
1791 }
1792 }
1793
1794 return stdx::make_unexpected(make_error_code(socket_errc::not_found));
1795}
1796
1797template <class Protocol, class InputIterator, class ConnectCondition>
1799 basic_socket<Protocol> &s, InputIterator first, InputIterator last) {
1800 return connect(s, first, last, [](auto, auto) { return true; });
1801}
1802
1803} // namespace net
1804
1805#if defined(MYSQL_HARNESS_HEADER_ONLY)
1807#endif
1808
1809#endif
Definition: protocol.h:32
Definition: executor.h:71
Definition: socket.h:970
stdx::expected< size_t, std::error_code > send_to(const ConstBufferSequence &buffers, const endpoint_type &recipient)
Definition: socket.h:1076
stdx::expected< size_t, std::error_code > receive_from(const MutableBufferSequence &buffers, endpoint_type &sender)
Definition: socket.h:1032
stdx::expected< bool, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:1091
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:980
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:999
basic_datagram_socket(io_context &ctx, const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:994
stdx::expected< size_t, std::error_code > receive_from(const MutableBufferSequence &buffers, endpoint_type &sender, socket_base::message_flags flags)
Definition: socket.h:1014
basic_datagram_socket(basic_datagram_socket &&other)=default
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers)
Definition: socket.h:1008
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1044
auto async_receive(const MutableBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1097
basic_datagram_socket & operator=(basic_datagram_socket &&)=default
stdx::expected< size_t, std::error_code > read_some(const MutableBufferSequence &buffers)
Definition: socket.h:1038
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers)
Definition: socket.h:1055
basic_datagram_socket(io_context &ctx)
Definition: socket.h:979
stdx::expected< size_t, std::error_code > send_to(const ConstBufferSequence &buffers, const endpoint_type &recipient, socket_base::message_flags flags)
Definition: socket.h:1063
stdx::expected< size_t, std::error_code > write_some(const ConstBufferSequence &buffers)
Definition: socket.h:1084
auto async_receive(const MutableBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1135
Definition: socket.h:1411
basic_socket_acceptor(io_context &ctx)
Definition: socket.h:1422
typename protocol_type::endpoint endpoint_type
Definition: socket.h:1419
auto async_accept(io_context &io_ctx, endpoint_type &endpoint, CompletionToken &&token)
accept a connection with endpoint async'.
Definition: socket.h:1584
std::error_code error_type
Definition: socket.h:1420
stdx::expected< endpoint_type, error_type > local_endpoint() const
Definition: socket.h:1482
bool native_non_blocking() const
Definition: socket.h:1468
bool non_blocking() const
Definition: socket.h:1462
stdx::expected< void, error_type > assign(const protocol_type &protocol, const native_handle_type &native_acceptor)
Definition: socket.h:1432
stdx::expected< native_handle_type, error_type > release()
Definition: socket.h:1438
async_result< std::decay_t< CompletionToken >, void(std::error_code)>::return_type async_wait(wait_type w, CompletionToken &&token)
Definition: socket.h:1677
stdx::expected< socket_type, error_type > accept(int flags=0)
Definition: socket.h:1490
native_handle_type native_handle() const
Definition: socket.h:1442
stdx::expected< void, error_type > listen(int backlog)
Definition: socket.h:1478
stdx::expected< void, error_type > open(const protocol_type &protocol=protocol_type(), int flags=0)
Definition: socket.h:1427
AcceptableProtocol protocol_type
Definition: socket.h:1417
stdx::expected< socket_type, error_type > accept(endpoint_type &endpoint, int flags=0)
Definition: socket.h:1508
typename protocol_type::socket socket_type
Definition: socket.h:1418
stdx::expected< void, error_type > bind(const endpoint_type &endpoint)
Definition: socket.h:1474
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, endpoint_type &endpoint, int flags=0)
Definition: socket.h:1513
stdx::expected< void, error_type > close()
Definition: socket.h:1446
auto async_accept(endpoint_type &endpoint, CompletionToken &&token)
Definition: socket.h:1567
executor_type get_executor() noexcept
Definition: socket.h:1425
protocol_type protocol_
Definition: socket.h:1711
stdx::expected< void, std::error_code > wait(socket_base::wait_type wt)
Definition: socket.h:1634
auto async_accept(CompletionToken &&token)
Definition: socket.h:1629
stdx::expected< void, error_type > cancel()
Definition: socket.h:1448
bool enable_connection_aborted() const
Definition: socket.h:1488
stdx::expected< void, std::error_code > native_non_blocking(bool mode)
Definition: socket.h:1470
auto async_accept(io_context &io_ctx, CompletionToken &&token)
Definition: socket.h:1529
stdx::expected< void, error_type > get_option(GettableSocketOption &option) const
Definition: socket.h:1457
stdx::expected< void, std::error_code > non_blocking(bool mode)
Definition: socket.h:1464
constexpr bool is_open() const
Definition: socket.h:1444
stdx::expected< socket_type, error_type > accept(io_context &io_ctx, int flags=0)
Definition: socket.h:1494
stdx::expected< void, error_type > set_option(const SettableSocketOption &option)
Definition: socket.h:1451
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
async_result< std::decay_t< CompletionToken >, void(std::error_code)>::return_type async_wait(wait_type w, CompletionToken &&token)
Definition: socket.h:910
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:946
basic_socket(io_context &ctx, const protocol_type &proto, const native_handle_type &native_handle)
Definition: socket.h:949
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:944
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:1143
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers)
Definition: socket.h:1220
stdx::expected< size_t, std::error_code > read_some(const MutableBufferSequence &buffers)
Definition: socket.h:1194
stdx::expected< void, error_type > shutdown(socket_base::shutdown_type st) const
Definition: socket.h:1235
stdx::expected< size_t, std::error_code > receive(const MutableBufferSequence &buffers)
Definition: socket.h:1188
basic_stream_socket(const basic_stream_socket &)=delete
auto async_send(const ConstBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1401
auto async_receive(const MutableBufferSequence &buffers, CompletionToken &&token)
Definition: socket.h:1328
stdx::expected< size_t, std::error_code > write_some(const ConstBufferSequence &buffers)
Definition: socket.h:1228
basic_stream_socket(io_context &ctx, const protocol_type &protocol, const native_handle_type &native_handle)
Definition: socket.h:1165
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:1170
auto async_send(const ConstBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1334
stdx::expected< size_t, std::error_code > send(const ConstBufferSequence &buffers, socket_base::message_flags flags)
Definition: socket.h:1200
basic_stream_socket(io_context &ctx)
Definition: socket.h:1152
basic_stream_socket & operator=(basic_stream_socket &&)=default
auto async_receive(const MutableBufferSequence &buffers, socket_base::message_flags flags, CompletionToken &&token)
Definition: socket.h:1241
basic_stream_socket & operator=(const basic_stream_socket &)=delete
basic_stream_socket(io_context &ctx, const protocol_type &proto)
Definition: socket.h:1153
Definition: socket_service_base.h:47
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:31
static std::string get_option(const mysql_harness::ConfigSection *section, const std::string &key, const std::string &def_value)
Definition: metadata_cache_plugin.cc:106
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:803
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:314
stdx::expected< InputIterator, std::error_code > connect(basic_socket< Protocol > &s, InputIterator first, InputIterator last)
Definition: socket.h:1798
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
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:191
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:63
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:260
double seconds()
Definition: task.cc:309