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_SERVICE_FINALS_HPP
11 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SERVICE_FINALS_HPP
12 :
13 : /* Parameterized final service types for reactor backends.
14 :
15 : One service template per protocol (TCP, local stream, UDP, local
16 : datagram, TCP acceptor, local stream acceptor) because each abstract
17 : service base declares different virtual methods.
18 : */
19 :
20 : #include <boost/corosio/native/detail/reactor/reactor_socket_finals.hpp>
21 : #include <boost/corosio/native/detail/reactor/reactor_socket_service.hpp>
22 : #include <boost/corosio/native/detail/reactor/reactor_acceptor_service.hpp>
23 : #include <boost/corosio/detail/tcp_service.hpp>
24 : #include <boost/corosio/detail/udp_service.hpp>
25 : #include <boost/corosio/detail/local_stream_service.hpp>
26 : #include <boost/corosio/detail/local_datagram_service.hpp>
27 :
28 : #include <boost/corosio/native/detail/make_err.hpp>
29 :
30 : #include <system_error>
31 : #include <unistd.h>
32 :
33 : namespace boost::corosio::detail {
34 :
35 : // ============================================================
36 : // Shared socket creation helpers
37 : // ============================================================
38 :
39 : template<class Traits, class SocketFinal>
40 : std::error_code
41 HIT 8666 : do_open_socket(
42 : SocketFinal* socket_impl,
43 : int family, int type, int protocol,
44 : bool is_ip) noexcept
45 : {
46 8666 : socket_impl->close_socket();
47 :
48 8666 : int fd = Traits::create_socket(family, type, protocol);
49 8666 : if (fd < 0)
50 MIS 0 : return make_err(errno);
51 :
52 : std::error_code ec = is_ip
53 HIT 8666 : ? Traits::configure_ip_socket(fd, family)
54 28 : : Traits::configure_local_socket(fd);
55 :
56 8666 : if (ec)
57 : {
58 MIS 0 : ::close(fd);
59 0 : return ec;
60 : }
61 :
62 HIT 8666 : socket_impl->init_and_register(fd);
63 8666 : return {};
64 : }
65 :
66 : template<class Traits, class SocketFinal>
67 : std::error_code
68 28 : do_assign_fd(
69 : SocketFinal* socket_impl,
70 : int fd) noexcept
71 : {
72 28 : socket_impl->close_socket();
73 28 : socket_impl->init_and_register(fd);
74 28 : return {};
75 : }
76 :
77 : template<class Traits, class AccFinal>
78 : std::error_code
79 158 : do_open_acceptor(
80 : AccFinal* acc_impl,
81 : int family, int type, int protocol,
82 : bool is_ip) noexcept
83 : {
84 158 : acc_impl->close_socket();
85 :
86 158 : int fd = Traits::create_socket(family, type, protocol);
87 158 : if (fd < 0)
88 MIS 0 : return make_err(errno);
89 :
90 : std::error_code ec = is_ip
91 HIT 158 : ? Traits::configure_ip_acceptor(fd, family)
92 12 : : Traits::configure_local_socket(fd);
93 :
94 158 : if (ec)
95 : {
96 MIS 0 : ::close(fd);
97 0 : return ec;
98 : }
99 :
100 HIT 158 : acc_impl->init_acceptor_fd(fd);
101 158 : return {};
102 : }
103 :
104 : // ============================================================
105 : // TCP service
106 : // ============================================================
107 :
108 : template<class Traits, class SocketFinal>
109 : class reactor_tcp_service_final final
110 : : public reactor_socket_service<
111 : reactor_tcp_service_final<Traits, SocketFinal>,
112 : tcp_service,
113 : typename Traits::scheduler_type,
114 : SocketFinal>
115 : {
116 : using base_service = reactor_socket_service<
117 : reactor_tcp_service_final, tcp_service,
118 : typename Traits::scheduler_type, SocketFinal>;
119 : friend base_service;
120 :
121 : public:
122 587 : explicit reactor_tcp_service_final(capy::execution_context& ctx)
123 587 : : base_service(ctx) {}
124 :
125 8558 : std::error_code open_socket(
126 : tcp_socket::implementation& impl,
127 : int family, int type, int protocol) override
128 : {
129 8558 : return do_open_socket<Traits>(
130 : static_cast<SocketFinal*>(&impl),
131 8558 : family, type, protocol, true);
132 : }
133 :
134 12 : std::error_code bind_socket(
135 : tcp_socket::implementation& impl, endpoint ep) override
136 : {
137 12 : return static_cast<SocketFinal*>(&impl)->do_bind(ep);
138 : }
139 :
140 MIS 0 : void pre_shutdown(SocketFinal* impl) noexcept
141 : {
142 0 : impl->hook_.pre_shutdown(impl->native_handle());
143 0 : }
144 :
145 HIT 25643 : void pre_destroy(SocketFinal* impl) noexcept
146 : {
147 25643 : impl->hook_.pre_destroy(impl->native_handle());
148 25643 : }
149 : };
150 :
151 : // ============================================================
152 : // Local stream service
153 : // ============================================================
154 :
155 : template<class Traits, class SocketFinal>
156 : class reactor_local_stream_service_final final
157 : : public reactor_socket_service<
158 : reactor_local_stream_service_final<Traits, SocketFinal>,
159 : local_stream_service,
160 : typename Traits::scheduler_type,
161 : SocketFinal>
162 : {
163 : using base_service = reactor_socket_service<
164 : reactor_local_stream_service_final, local_stream_service,
165 : typename Traits::scheduler_type, SocketFinal>;
166 : friend base_service;
167 :
168 : public:
169 587 : explicit reactor_local_stream_service_final(capy::execution_context& ctx)
170 587 : : base_service(ctx) {}
171 :
172 8 : std::error_code open_socket(
173 : local_stream_socket::implementation& impl,
174 : int family, int type, int protocol) override
175 : {
176 8 : return do_open_socket<Traits>(
177 : static_cast<SocketFinal*>(&impl),
178 8 : family, type, protocol, false);
179 : }
180 :
181 16 : std::error_code assign_socket(
182 : local_stream_socket::implementation& impl, int fd) override
183 : {
184 16 : return do_assign_fd<Traits>(
185 16 : static_cast<SocketFinal*>(&impl), fd);
186 : }
187 : };
188 :
189 : // ============================================================
190 : // UDP service
191 : // ============================================================
192 :
193 : template<class Traits, class SocketFinal>
194 : class reactor_udp_service_final final
195 : : public reactor_socket_service<
196 : reactor_udp_service_final<Traits, SocketFinal>,
197 : udp_service,
198 : typename Traits::scheduler_type,
199 : SocketFinal>
200 : {
201 : using base_service = reactor_socket_service<
202 : reactor_udp_service_final, udp_service,
203 : typename Traits::scheduler_type, SocketFinal>;
204 : friend base_service;
205 :
206 : public:
207 587 : explicit reactor_udp_service_final(capy::execution_context& ctx)
208 587 : : base_service(ctx) {}
209 :
210 80 : std::error_code open_datagram_socket(
211 : udp_socket::implementation& impl,
212 : int family, int type, int protocol) override
213 : {
214 80 : return do_open_socket<Traits>(
215 : static_cast<SocketFinal*>(&impl),
216 80 : family, type, protocol, true);
217 : }
218 :
219 48 : std::error_code bind_datagram(
220 : udp_socket::implementation& impl, endpoint ep) override
221 : {
222 48 : return static_cast<SocketFinal*>(&impl)->do_bind(ep);
223 : }
224 : };
225 :
226 : // ============================================================
227 : // Local datagram service
228 : // ============================================================
229 :
230 : template<class Traits, class SocketFinal>
231 : class reactor_local_dgram_service_final final
232 : : public reactor_socket_service<
233 : reactor_local_dgram_service_final<Traits, SocketFinal>,
234 : local_datagram_service,
235 : typename Traits::scheduler_type,
236 : SocketFinal>
237 : {
238 : using base_service = reactor_socket_service<
239 : reactor_local_dgram_service_final, local_datagram_service,
240 : typename Traits::scheduler_type, SocketFinal>;
241 : friend base_service;
242 :
243 : public:
244 587 : explicit reactor_local_dgram_service_final(capy::execution_context& ctx)
245 587 : : base_service(ctx) {}
246 :
247 20 : std::error_code open_socket(
248 : local_datagram_socket::implementation& impl,
249 : int family, int type, int protocol) override
250 : {
251 20 : return do_open_socket<Traits>(
252 : static_cast<SocketFinal*>(&impl),
253 20 : family, type, protocol, false);
254 : }
255 :
256 12 : std::error_code assign_socket(
257 : local_datagram_socket::implementation& impl, int fd) override
258 : {
259 12 : return do_assign_fd<Traits>(
260 12 : static_cast<SocketFinal*>(&impl), fd);
261 : }
262 :
263 16 : std::error_code bind_socket(
264 : local_datagram_socket::implementation& impl,
265 : corosio::local_endpoint ep) override
266 : {
267 16 : return static_cast<SocketFinal*>(&impl)->do_bind(ep);
268 : }
269 : };
270 :
271 : // ============================================================
272 : // Acceptor service
273 : // ============================================================
274 :
275 : template<class Traits, class ServiceBase, class AccFinal,
276 : class StreamServiceFinal, class Endpoint>
277 : class reactor_acceptor_service_final final
278 : : public reactor_acceptor_service<
279 : reactor_acceptor_service_final<Traits, ServiceBase, AccFinal,
280 : StreamServiceFinal, Endpoint>,
281 : ServiceBase,
282 : typename Traits::scheduler_type,
283 : AccFinal,
284 : StreamServiceFinal>
285 : {
286 : using base_service = reactor_acceptor_service<
287 : reactor_acceptor_service_final,
288 : ServiceBase,
289 : typename Traits::scheduler_type,
290 : AccFinal,
291 : StreamServiceFinal>;
292 : friend base_service;
293 :
294 : public:
295 1174 : explicit reactor_acceptor_service_final(capy::execution_context& ctx)
296 1174 : : base_service(ctx)
297 : {
298 : // Look up the concrete stream service directly by its type.
299 : // Avoids dynamic_cast which can fail across template boundaries
300 : // on some platforms (FreeBSD clang RTTI/visibility).
301 1174 : this->stream_svc_ =
302 1174 : this->ctx_.template find_service<StreamServiceFinal>();
303 1174 : }
304 :
305 158 : std::error_code open_acceptor_socket(
306 : typename AccFinal::impl_base_type& impl,
307 : int family, int type, int protocol) override
308 : {
309 158 : return do_open_acceptor<Traits>(
310 : static_cast<AccFinal*>(&impl),
311 : family, type, protocol,
312 158 : std::is_same_v<Endpoint, endpoint>);
313 : }
314 :
315 156 : std::error_code bind_acceptor(
316 : typename AccFinal::impl_base_type& impl,
317 : Endpoint ep) override
318 : {
319 156 : return static_cast<AccFinal*>(&impl)->do_bind(ep);
320 : }
321 :
322 140 : std::error_code listen_acceptor(
323 : typename AccFinal::impl_base_type& impl,
324 : int backlog) override
325 : {
326 140 : return static_cast<AccFinal*>(&impl)->do_listen(backlog);
327 : }
328 : };
329 :
330 : } // namespace boost::corosio::detail
331 :
332 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SERVICE_FINALS_HPP
|