TLA Line data Source code
1 : //
2 : // Copyright (c) 2026 Steve Gerbino
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/corosio
9 : //
10 :
11 : #ifndef BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BASIC_SOCKET_HPP
12 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BASIC_SOCKET_HPP
13 :
14 : #include <boost/corosio/detail/intrusive.hpp>
15 : #include <boost/corosio/detail/native_handle.hpp>
16 : #include <boost/corosio/endpoint.hpp>
17 : #include <boost/corosio/native/detail/native_socket_base.hpp>
18 : #include <boost/corosio/native/detail/reactor/reactor_io_core.hpp>
19 : #include <boost/corosio/native/detail/make_err.hpp>
20 : #include <boost/corosio/native/detail/endpoint_convert.hpp>
21 :
22 : #include <memory>
23 : #include <mutex>
24 : #include <utility>
25 :
26 : #include <errno.h>
27 : #include <netinet/in.h>
28 : #include <sys/socket.h>
29 : #include <unistd.h>
30 :
31 : namespace boost::corosio::detail {
32 :
33 : /** CRTP base for reactor-backed socket implementations.
34 :
35 : Extracts the shared data members and virtual overrides that are
36 : identical across TCP (reactor_stream_socket) and UDP
37 : (reactor_datagram_socket). The register/park/cancel/teardown
38 : protocol lives in reactor_io_core.
39 :
40 : Derived classes provide CRTP callbacks that enumerate their
41 : specific op slots so cancel/close can iterate them generically.
42 :
43 : @tparam Derived The concrete socket type (CRTP).
44 : @tparam ImplBase The public vtable base (tcp_socket::implementation
45 : or udp_socket::implementation).
46 : @tparam Service The backend's service type.
47 : @tparam DescState The backend's descriptor_state type.
48 : @tparam Endpoint The endpoint type (endpoint or local_endpoint).
49 : */
50 : template<
51 : class Derived,
52 : class ImplBase,
53 : class Service,
54 : class DescState,
55 : class Endpoint = endpoint>
56 : class reactor_basic_socket
57 : : public native_socket_base<Derived, ImplBase, Endpoint>
58 : , public reactor_io_core<Derived, Service, DescState>
59 : , public intrusive_list<Derived>::node
60 : {
61 : friend Derived;
62 :
63 : template<class, class, class, class, class, class, class, class, class>
64 : friend class reactor_stream_socket;
65 :
66 : template<
67 : class,
68 : class,
69 : class,
70 : class,
71 : class,
72 : class,
73 : class,
74 : class,
75 : class,
76 : class,
77 : class>
78 : friend class reactor_datagram_socket;
79 :
80 : using core_type = reactor_io_core<Derived, Service, DescState>;
81 :
82 HIT 15094 : explicit reactor_basic_socket(Service& svc) noexcept : core_type(svc) {}
83 :
84 : protected:
85 : // fd_ / local_endpoint_ and the synchronous accessors (native_handle,
86 : // is_open, set_option/get_option, set_socket/set_local_endpoint, do_bind)
87 : // live in native_socket_base — the readiness/completion-agnostic base
88 : // shared with io_uring's sockets. The using-declarations make the
89 : // inherited members visible to this template's own unqualified
90 : // references below (two-phase lookup).
91 : using native_socket_base<Derived, ImplBase, Endpoint>::fd_;
92 : using native_socket_base<Derived, ImplBase, Endpoint>::local_endpoint_;
93 :
94 : public:
95 15094 : ~reactor_basic_socket() override = default;
96 :
97 : /** Assign the fd, initialize descriptor state, and register with
98 : the reactor.
99 :
100 : @param fd The descriptor to adopt.
101 :
102 : @return The error if the reactor rejects the descriptor, in
103 : which case the implementation is left closed and the caller
104 : retains ownership of @a fd; otherwise a default constructed
105 : error code.
106 : */
107 5478 : std::error_code init_and_register(int fd) noexcept
108 : {
109 5478 : fd_ = fd;
110 5478 : if (auto ec = this->register_fd(fd))
111 : {
112 3 : fd_ = -1;
113 3 : return ec;
114 : }
115 5475 : return {};
116 : }
117 :
118 : /// Cancel all pending operations.
119 278 : void do_cancel() noexcept
120 : {
121 278 : this->cancel_all();
122 278 : }
123 :
124 : /** Close the socket and cancel pending operations.
125 :
126 : Invoked by the derived class's close_socket(). The
127 : derived class may add backend-specific cleanup after
128 : calling this method.
129 : */
130 45437 : void do_close_socket() noexcept
131 : {
132 45437 : this->abandon_all();
133 45437 : this->unregister_fd(fd_);
134 45437 : if (fd_ >= 0)
135 : {
136 10077 : ::close(fd_);
137 10077 : fd_ = -1;
138 : }
139 45437 : local_endpoint_ = Endpoint{};
140 45437 : }
141 :
142 : /** Release the socket without closing the fd.
143 :
144 : Like do_close_socket() but does not call ::close().
145 : Returns the fd so the caller can take ownership.
146 : */
147 16 : native_handle_type do_release_socket() noexcept
148 : {
149 16 : this->abandon_all();
150 16 : native_handle_type released = fd_;
151 16 : this->unregister_fd(fd_);
152 16 : fd_ = -1;
153 16 : local_endpoint_ = Endpoint{};
154 16 : return released;
155 : }
156 : };
157 :
158 : } // namespace boost::corosio::detail
159 :
160 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BASIC_SOCKET_HPP
|