TLA Line data Source code
1 : //
2 : // Copyright (c) 2026 Michael Vandeberg
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/corosio
8 : //
9 :
10 : #ifndef BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SOCKET_FINALS_HPP
11 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SOCKET_FINALS_HPP
12 :
13 : /* Parameterized final socket and acceptor types for reactor backends.
14 :
15 : These templates are instantiated per-backend via Traits to produce
16 : the concrete socket types used by the public API. Each final type
17 : is a thin wrapper adding only protocol-specific details (ImplBase,
18 : Endpoint) to the CRTP base classes.
19 : */
20 :
21 : #include <boost/corosio/tcp_socket.hpp>
22 : #include <boost/corosio/udp_socket.hpp>
23 : #include <boost/corosio/local_stream_socket.hpp>
24 : #include <boost/corosio/local_datagram_socket.hpp>
25 : #include <boost/corosio/tcp_acceptor.hpp>
26 : #include <boost/corosio/local_stream_acceptor.hpp>
27 : #include <boost/corosio/shutdown_type.hpp>
28 :
29 : #include <boost/corosio/native/detail/reactor/reactor_stream_socket.hpp>
30 : #include <boost/corosio/native/detail/reactor/reactor_datagram_socket.hpp>
31 : #include <boost/corosio/native/detail/reactor/reactor_acceptor.hpp>
32 : #include <boost/corosio/native/detail/reactor/reactor_stream_ops.hpp>
33 : #include <boost/corosio/native/detail/reactor/reactor_datagram_ops.hpp>
34 :
35 : #include <boost/corosio/detail/tcp_acceptor_service.hpp>
36 : #include <boost/corosio/detail/local_stream_acceptor_service.hpp>
37 : #include <boost/corosio/native/detail/make_err.hpp>
38 :
39 : namespace boost::corosio::detail {
40 :
41 : // ============================================================
42 : // Forward declarations
43 : // ============================================================
44 :
45 : template<class Traits, class ImplBase, class Endpoint> class reactor_stream_socket_final;
46 : template<class Traits, class ImplBase, class Endpoint> class reactor_dgram_socket_final;
47 : template<class Traits, class AccImplBase, class Endpoint> class reactor_acceptor_final;
48 :
49 : template<class Traits, class SocketFinal> class reactor_tcp_service_final;
50 : template<class Traits, class SocketFinal> class reactor_local_stream_service_final;
51 : template<class Traits, class SocketFinal> class reactor_udp_service_final;
52 : template<class Traits, class SocketFinal> class reactor_local_dgram_service_final;
53 : template<class Traits, class ServiceBase, class AccFinal, class StreamServiceFinal, class Endpoint> class reactor_acceptor_service_final;
54 :
55 : // ============================================================
56 : // Op type aliases
57 : // ============================================================
58 :
59 : template<class Traits, class Endpoint>
60 : using stream_socket_t = reactor_stream_socket_final<Traits,
61 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
62 : tcp_socket::implementation,
63 : local_stream_socket::implementation>,
64 : Endpoint>;
65 :
66 : template<class Traits, class Endpoint>
67 : using stream_acceptor_t = reactor_acceptor_final<Traits,
68 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
69 : tcp_acceptor::implementation,
70 : local_stream_acceptor::implementation>,
71 : Endpoint>;
72 :
73 : template<class Traits, class Endpoint>
74 : using stream_base_op = reactor_stream_base_op<
75 : Traits, stream_socket_t<Traits, Endpoint>,
76 : stream_acceptor_t<Traits, Endpoint>, Endpoint>;
77 :
78 : template<class Traits, class Endpoint>
79 : using stream_connect_op = reactor_stream_connect_op<
80 : Traits, stream_socket_t<Traits, Endpoint>,
81 : stream_acceptor_t<Traits, Endpoint>, Endpoint>;
82 :
83 : template<class Traits, class Endpoint>
84 : using stream_read_op = reactor_stream_read_op<
85 : Traits, stream_socket_t<Traits, Endpoint>,
86 : stream_acceptor_t<Traits, Endpoint>, Endpoint>;
87 :
88 : template<class Traits, class Endpoint>
89 : using stream_write_op = reactor_stream_write_op<
90 : Traits, stream_socket_t<Traits, Endpoint>,
91 : stream_acceptor_t<Traits, Endpoint>, Endpoint>;
92 :
93 : template<class Traits, class Endpoint>
94 : using stream_accept_op = reactor_stream_accept_op<
95 : Traits, stream_socket_t<Traits, Endpoint>,
96 : stream_acceptor_t<Traits, Endpoint>, Endpoint>;
97 :
98 : template<class Traits, class Endpoint>
99 : using dgram_socket_t = reactor_dgram_socket_final<Traits,
100 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
101 : udp_socket::implementation,
102 : local_datagram_socket::implementation>,
103 : Endpoint>;
104 :
105 : template<class Traits, class Endpoint>
106 : using dgram_connect_op = reactor_dgram_connect_op<
107 : Traits, dgram_socket_t<Traits, Endpoint>,
108 : stream_acceptor_t<Traits, endpoint>, Endpoint>;
109 :
110 : template<class Traits, class Endpoint>
111 : using dgram_send_to_op = reactor_dgram_send_to_op<
112 : Traits, dgram_socket_t<Traits, Endpoint>,
113 : stream_acceptor_t<Traits, endpoint>, Endpoint>;
114 :
115 : template<class Traits, class Endpoint>
116 : using dgram_recv_from_op = reactor_dgram_recv_from_op<
117 : Traits, dgram_socket_t<Traits, Endpoint>,
118 : stream_acceptor_t<Traits, endpoint>, Endpoint>;
119 :
120 : template<class Traits, class Endpoint>
121 : using dgram_send_op = reactor_dgram_send_op<
122 : Traits, dgram_socket_t<Traits, Endpoint>,
123 : stream_acceptor_t<Traits, endpoint>, Endpoint>;
124 :
125 : template<class Traits, class Endpoint>
126 : using dgram_recv_op = reactor_dgram_recv_op<
127 : Traits, dgram_socket_t<Traits, Endpoint>,
128 : stream_acceptor_t<Traits, endpoint>, Endpoint>;
129 :
130 : // ============================================================
131 : // Stream socket final
132 : // ============================================================
133 :
134 : // release_socket below cannot be marked 'override' unconditionally: it
135 : // overrides a pure virtual only when ImplBase is local_stream_socket::
136 : // implementation. For the tcp_socket::implementation instantiation the
137 : // base has no such virtual, so 'override' would fail to compile. Scope-
138 : // suppress clang's -Winconsistent-missing-override for the overriding
139 : // instantiation. clang-tidy's modernize-use-override is silenced
140 : // separately via NOLINTNEXTLINE below.
141 : BOOST_COROSIO_CLANG_WARNING_PUSH
142 : BOOST_COROSIO_CLANG_WARNING_DISABLE("-Winconsistent-missing-override")
143 :
144 : template<class Traits, class ImplBase, class Endpoint>
145 : class reactor_stream_socket_final final
146 : : public reactor_stream_socket<
147 : reactor_stream_socket_final<Traits, ImplBase, Endpoint>,
148 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
149 : reactor_tcp_service_final<
150 : Traits, reactor_stream_socket_final<Traits, ImplBase, Endpoint>>,
151 : reactor_local_stream_service_final<
152 : Traits, reactor_stream_socket_final<Traits, ImplBase, Endpoint>>>,
153 : stream_connect_op<Traits, Endpoint>,
154 : stream_read_op<Traits, Endpoint>,
155 : stream_write_op<Traits, Endpoint>,
156 : typename Traits::desc_state_type,
157 : ImplBase,
158 : Endpoint>
159 : {
160 : using service_type = std::conditional_t<std::is_same_v<Endpoint, endpoint>,
161 : reactor_tcp_service_final<Traits, reactor_stream_socket_final>,
162 : reactor_local_stream_service_final<Traits, reactor_stream_socket_final>>;
163 : friend service_type;
164 :
165 : public:
166 : using impl_base_type = ImplBase;
167 :
168 : /// Per-socket hook state (e.g., kqueue SO_LINGER tracking).
169 : [[no_unique_address]] typename Traits::stream_socket_hook hook_;
170 :
171 HIT 24072 : explicit reactor_stream_socket_final(service_type& svc) noexcept
172 24072 : : reactor_stream_socket_final::reactor_stream_socket(svc)
173 : {
174 24072 : }
175 :
176 24072 : ~reactor_stream_socket_final() override = default;
177 :
178 60 : std::error_code set_option(
179 : int level, int optname,
180 : void const* data, std::size_t size) noexcept override
181 : {
182 60 : return hook_.on_set_option(this->fd_, level, optname, data, size);
183 : }
184 :
185 : // Shadows reactor_stream_socket::close_socket so the hook fires on
186 : // every fd close path (user close(), service shutdown/destroy,
187 : // do_assign_fd reuse). The hook needs the fd before do_close_socket
188 : // resets it to -1.
189 72219 : void close_socket() noexcept
190 : {
191 72219 : hook_.pre_shutdown(this->fd_);
192 72219 : this->do_close_socket();
193 72219 : }
194 :
195 : // Overrides local_stream_socket::implementation::release_socket().
196 : // Cannot use 'override' — tcp_socket::implementation has no such method.
197 : // NOLINTNEXTLINE(modernize-use-override)
198 2 : native_handle_type release_socket() noexcept
199 : {
200 2 : hook_ = {};
201 2 : return this->do_release_socket();
202 : }
203 : };
204 :
205 : BOOST_COROSIO_CLANG_WARNING_POP
206 :
207 : // ============================================================
208 : // Datagram socket final
209 : // ============================================================
210 :
211 : // shutdown/bind/release_socket below cannot be marked 'override'
212 : // unconditionally: they override pure virtuals only when ImplBase is
213 : // local_datagram_socket::implementation. For the udp_socket::implementation
214 : // instantiation the base has no such virtuals, so 'override' would fail
215 : // to compile. Scope-suppress clang's -Winconsistent-missing-override for
216 : // the overriding instantiation. clang-tidy's modernize-use-override is
217 : // silenced separately via NOLINTNEXTLINE below.
218 : BOOST_COROSIO_CLANG_WARNING_PUSH
219 : BOOST_COROSIO_CLANG_WARNING_DISABLE("-Winconsistent-missing-override")
220 :
221 : template<class Traits, class ImplBase, class Endpoint>
222 : class reactor_dgram_socket_final final
223 : : public reactor_datagram_socket<
224 : reactor_dgram_socket_final<Traits, ImplBase, Endpoint>,
225 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
226 : reactor_udp_service_final<
227 : Traits, reactor_dgram_socket_final<Traits, ImplBase, Endpoint>>,
228 : reactor_local_dgram_service_final<
229 : Traits, reactor_dgram_socket_final<Traits, ImplBase, Endpoint>>>,
230 : dgram_connect_op<Traits, Endpoint>,
231 : dgram_send_to_op<Traits, Endpoint>,
232 : dgram_recv_from_op<Traits, Endpoint>,
233 : dgram_send_op<Traits, Endpoint>,
234 : dgram_recv_op<Traits, Endpoint>,
235 : typename Traits::desc_state_type,
236 : ImplBase,
237 : Endpoint>
238 : {
239 : using service_type = std::conditional_t<std::is_same_v<Endpoint, endpoint>,
240 : reactor_udp_service_final<Traits, reactor_dgram_socket_final>,
241 : reactor_local_dgram_service_final<Traits, reactor_dgram_socket_final>>;
242 : friend service_type;
243 :
244 : public:
245 : using impl_base_type = ImplBase;
246 :
247 128 : explicit reactor_dgram_socket_final(service_type& svc) noexcept
248 128 : : reactor_dgram_socket_final::reactor_datagram_socket(svc)
249 : {
250 128 : }
251 :
252 128 : ~reactor_dgram_socket_final() override = default;
253 :
254 : // Overrides local_datagram_socket pure virtuals.
255 : // Cannot use 'override' — udp_socket::implementation has no such methods.
256 : // NOLINTNEXTLINE(modernize-use-override)
257 MIS 0 : std::error_code shutdown(corosio::shutdown_type what) noexcept
258 : {
259 0 : return this->do_shutdown(static_cast<int>(what));
260 : }
261 :
262 : // NOLINTNEXTLINE(modernize-use-override)
263 0 : std::error_code bind(Endpoint ep) noexcept
264 : {
265 0 : return this->do_bind(ep);
266 : }
267 :
268 : // NOLINTNEXTLINE(modernize-use-override)
269 0 : native_handle_type release_socket() noexcept
270 : {
271 0 : return this->do_release_socket();
272 : }
273 : };
274 :
275 : BOOST_COROSIO_CLANG_WARNING_POP
276 :
277 : // ============================================================
278 : // Acceptor final
279 : // ============================================================
280 :
281 : template<class Traits, class Endpoint>
282 : using stream_service_for = std::conditional_t<std::is_same_v<Endpoint, endpoint>,
283 : reactor_tcp_service_final<Traits, stream_socket_t<Traits, Endpoint>>,
284 : reactor_local_stream_service_final<Traits, stream_socket_t<Traits, Endpoint>>>;
285 :
286 : // release_socket below cannot be marked 'override' unconditionally: it
287 : // overrides a pure virtual only when AccImplBase is
288 : // local_stream_acceptor::implementation. For the tcp_acceptor::implementation
289 : // instantiation the base has no such virtual, so 'override' would fail to
290 : // compile. Scope-suppress clang's -Winconsistent-missing-override for the
291 : // overriding instantiation. clang-tidy's modernize-use-override is silenced
292 : // separately via NOLINTNEXTLINE below.
293 : BOOST_COROSIO_CLANG_WARNING_PUSH
294 : BOOST_COROSIO_CLANG_WARNING_DISABLE("-Winconsistent-missing-override")
295 :
296 : template<class Traits, class AccImplBase, class Endpoint>
297 : class reactor_acceptor_final final
298 : : public reactor_acceptor<
299 : reactor_acceptor_final<Traits, AccImplBase, Endpoint>,
300 : reactor_acceptor_service_final<
301 : Traits,
302 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
303 : tcp_acceptor_service, local_stream_acceptor_service>,
304 : reactor_acceptor_final<Traits, AccImplBase, Endpoint>,
305 : stream_service_for<Traits, Endpoint>,
306 : Endpoint>,
307 : stream_base_op<Traits, Endpoint>,
308 : stream_accept_op<Traits, Endpoint>,
309 : typename Traits::desc_state_type,
310 : AccImplBase,
311 : Endpoint>
312 : {
313 : using acc_service_type = reactor_acceptor_service_final<
314 : Traits,
315 : std::conditional_t<std::is_same_v<Endpoint, endpoint>,
316 : tcp_acceptor_service, local_stream_acceptor_service>,
317 : reactor_acceptor_final,
318 : stream_service_for<Traits, Endpoint>,
319 : Endpoint>;
320 : friend acc_service_type;
321 :
322 : public:
323 HIT 163 : explicit reactor_acceptor_final(acc_service_type& svc) noexcept
324 163 : : reactor_acceptor_final::reactor_acceptor(svc)
325 : {
326 163 : }
327 :
328 163 : ~reactor_acceptor_final() override = default;
329 :
330 : using impl_base_type = AccImplBase;
331 :
332 : // NOLINTNEXTLINE(modernize-use-override)
333 MIS 0 : native_handle_type release_socket() noexcept
334 : {
335 0 : return this->do_release_socket();
336 : }
337 :
338 : std::coroutine_handle<> accept(
339 : std::coroutine_handle<>,
340 : capy::executor_ref,
341 : std::stop_token,
342 : std::error_code*,
343 : io_object::implementation**) override;
344 : };
345 :
346 : BOOST_COROSIO_CLANG_WARNING_POP
347 :
348 : } // namespace boost::corosio::detail
349 :
350 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SOCKET_FINALS_HPP
|