include/boost/corosio/native/detail/select/select_local_datagram_service.hpp

57.1% Lines (68/119) 60.9% List of functions (14/23)
select_local_datagram_service.hpp
f(x) Functions (23)
Function Calls Lines Blocks
boost::corosio::detail::select_local_datagram_service::select_local_datagram_service(boost::capy::execution_context&) :46 229x 100.0% 100.0% boost::corosio::detail::select_local_send_to_op::cancel() :69 0 0.0% 0.0% boost::corosio::detail::select_local_recv_from_op::cancel() :78 0 0.0% 0.0% boost::corosio::detail::select_local_dgram_connect_op::cancel() :89 0 0.0% 0.0% boost::corosio::detail::select_local_dgram_send_op::cancel() :98 0 0.0% 0.0% boost::corosio::detail::select_local_dgram_recv_op::cancel() :107 0 0.0% 0.0% boost::corosio::detail::select_local_datagram_op::operator()() :118 6x 100.0% 100.0% boost::corosio::detail::select_local_recv_from_op::operator()() :124 2x 100.0% 100.0% boost::corosio::detail::select_local_dgram_connect_op::operator()() :130 0 0.0% 0.0% boost::corosio::detail::select_local_dgram_recv_op::operator()() :136 1x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::select_local_datagram_socket(boost::corosio::detail::select_local_datagram_service&) :144 17x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::~select_local_datagram_socket() :150 17x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::send_to(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, boost::corosio::local_endpoint, int, std::stop_token, std::error_code*, unsigned long*) :155 3x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::recv_from(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, boost::corosio::local_endpoint*, int, std::stop_token, std::error_code*, unsigned long*) :172 4x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::connect(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::local_endpoint, std::stop_token, std::error_code*) :188 0 0.0% 0.0% boost::corosio::detail::select_local_datagram_socket::send(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, int, std::stop_token, std::error_code*, unsigned long*) :202 4x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::recv(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, int, std::stop_token, std::error_code*, unsigned long*) :218 5x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::cancel() :231 0 0.0% 0.0% boost::corosio::detail::select_local_datagram_socket::close_socket() :237 66x 100.0% 100.0% boost::corosio::detail::select_local_datagram_socket::release_socket() :243 0 0.0% 0.0% boost::corosio::detail::select_local_datagram_service::open_socket(boost::corosio::local_datagram_socket::implementation&, int, int, int) :251 10x 61.3% 68.0% boost::corosio::detail::select_local_datagram_service::assign_socket(boost::corosio::local_datagram_socket::implementation&, int) :312 6x 92.9% 75.0% boost::corosio::detail::select_local_datagram_service::bind_socket(boost::corosio::local_datagram_socket::implementation&, boost::corosio::local_endpoint) :337 8x 100.0% 100.0%
Line TLA Hits 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_SELECT_SELECT_LOCAL_DATAGRAM_SERVICE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_SELECT_SELECT_LOCAL_DATAGRAM_SERVICE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_SELECT
16
17 #include <boost/corosio/detail/config.hpp>
18 #include <boost/corosio/detail/local_datagram_service.hpp>
19
20 #include <boost/corosio/native/detail/select/select_local_datagram_socket.hpp>
21 #include <boost/corosio/native/detail/select/select_scheduler.hpp>
22 #include <boost/corosio/native/detail/reactor/reactor_socket_service.hpp>
23
24 #include <boost/corosio/native/detail/reactor/reactor_op_complete.hpp>
25
26 #include <coroutine>
27 #include <mutex>
28
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <sys/select.h>
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #include <unistd.h>
35
36 namespace boost::corosio::detail {
37
38 class BOOST_COROSIO_DECL select_local_datagram_service final
39 : public reactor_socket_service<
40 select_local_datagram_service,
41 local_datagram_service,
42 select_scheduler,
43 select_local_datagram_socket>
44 {
45 public:
46 229x explicit select_local_datagram_service(capy::execution_context& ctx)
47 229x : reactor_socket_service(ctx)
48 {
49 229x }
50
51 std::error_code open_socket(
52 local_datagram_socket::implementation& impl,
53 int family,
54 int type,
55 int protocol) override;
56
57 std::error_code assign_socket(
58 local_datagram_socket::implementation& impl,
59 native_handle_type fd) override;
60
61 std::error_code bind_socket(
62 local_datagram_socket::implementation& impl,
63 corosio::local_endpoint ep) override;
64 };
65
66 // Cancellation for connectionless ops
67
68 inline void
69 select_local_send_to_op::cancel() noexcept
70 {
71 if (socket_impl_)
72 socket_impl_->cancel_single_op(*this);
73 else
74 request_cancel();
75 }
76
77 inline void
78 select_local_recv_from_op::cancel() noexcept
79 {
80 if (socket_impl_)
81 socket_impl_->cancel_single_op(*this);
82 else
83 request_cancel();
84 }
85
86 // Cancellation for connected-mode ops
87
88 inline void
89 select_local_dgram_connect_op::cancel() noexcept
90 {
91 if (socket_impl_)
92 socket_impl_->cancel_single_op(*this);
93 else
94 request_cancel();
95 }
96
97 inline void
98 select_local_dgram_send_op::cancel() noexcept
99 {
100 if (socket_impl_)
101 socket_impl_->cancel_single_op(*this);
102 else
103 request_cancel();
104 }
105
106 inline void
107 select_local_dgram_recv_op::cancel() noexcept
108 {
109 if (socket_impl_)
110 socket_impl_->cancel_single_op(*this);
111 else
112 request_cancel();
113 }
114
115 // Completion handlers
116
117 inline void
118 6x select_local_datagram_op::operator()()
119 {
120 6x complete_io_op(*this);
121 6x }
122
123 inline void
124 2x select_local_recv_from_op::operator()()
125 {
126 2x complete_datagram_op(*this, this->source_out);
127 2x }
128
129 inline void
130 select_local_dgram_connect_op::operator()()
131 {
132 complete_connect_op(*this);
133 }
134
135 inline void
136 1x select_local_dgram_recv_op::operator()()
137 {
138 // Datagram completion: do not map 0 bytes to EOF
139 1x complete_dgram_recv_op(*this);
140 1x }
141
142 // Socket construction/destruction
143
144 17x inline select_local_datagram_socket::select_local_datagram_socket(
145 17x select_local_datagram_service& svc) noexcept
146 17x : reactor_datagram_socket(svc)
147 {
148 17x }
149
150 17x inline select_local_datagram_socket::~select_local_datagram_socket() = default;
151
152 // Connectionless I/O
153
154 inline std::coroutine_handle<>
155 3x select_local_datagram_socket::send_to(
156 std::coroutine_handle<> h,
157 capy::executor_ref ex,
158 buffer_param buf,
159 corosio::local_endpoint dest,
160 int flags,
161 std::stop_token token,
162 std::error_code* ec,
163 std::size_t* bytes_out)
164 {
165 3x auto result = do_send_to(h, ex, buf, dest, flags, token, ec, bytes_out);
166 3x if (result == std::noop_coroutine())
167 3x svc_.scheduler().notify_reactor();
168 3x return result;
169 }
170
171 inline std::coroutine_handle<>
172 4x select_local_datagram_socket::recv_from(
173 std::coroutine_handle<> h,
174 capy::executor_ref ex,
175 buffer_param buf,
176 corosio::local_endpoint* source,
177 int flags,
178 std::stop_token token,
179 std::error_code* ec,
180 std::size_t* bytes_out)
181 {
182 4x return do_recv_from(h, ex, buf, source, flags, token, ec, bytes_out);
183 }
184
185 // Connected-mode I/O
186
187 inline std::coroutine_handle<>
188 select_local_datagram_socket::connect(
189 std::coroutine_handle<> h,
190 capy::executor_ref ex,
191 corosio::local_endpoint ep,
192 std::stop_token token,
193 std::error_code* ec)
194 {
195 auto result = do_connect(h, ex, ep, token, ec);
196 if (result == std::noop_coroutine())
197 svc_.scheduler().notify_reactor();
198 return result;
199 }
200
201 inline std::coroutine_handle<>
202 4x select_local_datagram_socket::send(
203 std::coroutine_handle<> h,
204 capy::executor_ref ex,
205 buffer_param buf,
206 int flags,
207 std::stop_token token,
208 std::error_code* ec,
209 std::size_t* bytes_out)
210 {
211 4x auto result = do_send(h, ex, buf, flags, token, ec, bytes_out);
212 4x if (result == std::noop_coroutine())
213 3x svc_.scheduler().notify_reactor();
214 4x return result;
215 }
216
217 inline std::coroutine_handle<>
218 5x select_local_datagram_socket::recv(
219 std::coroutine_handle<> h,
220 capy::executor_ref ex,
221 buffer_param buf,
222 int flags,
223 std::stop_token token,
224 std::error_code* ec,
225 std::size_t* bytes_out)
226 {
227 5x return do_recv(h, ex, buf, flags, token, ec, bytes_out);
228 }
229
230 inline void
231 select_local_datagram_socket::cancel() noexcept
232 {
233 do_cancel();
234 }
235
236 inline void
237 66x select_local_datagram_socket::close_socket() noexcept
238 {
239 66x do_close_socket();
240 66x }
241
242 inline native_handle_type
243 select_local_datagram_socket::release_socket() noexcept
244 {
245 return this->do_release_socket();
246 }
247
248 // Service implementations
249
250 inline std::error_code
251 10x select_local_datagram_service::open_socket(
252 local_datagram_socket::implementation& impl,
253 int family,
254 int type,
255 int protocol)
256 {
257 10x auto* select_impl = static_cast<select_local_datagram_socket*>(&impl);
258 10x select_impl->close_socket();
259
260 10x int fd = ::socket(family, type, protocol);
261 10x if (fd < 0)
262 return make_err(errno);
263
264 10x int flags = ::fcntl(fd, F_GETFL, 0);
265 10x if (flags == -1)
266 {
267 int errn = errno;
268 ::close(fd);
269 return make_err(errn);
270 }
271 10x if (::fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
272 {
273 int errn = errno;
274 ::close(fd);
275 return make_err(errn);
276 }
277 10x if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
278 {
279 int errn = errno;
280 ::close(fd);
281 return make_err(errn);
282 }
283
284 #ifdef SO_NOSIGPIPE
285 {
286 int one = 1;
287 ::setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one));
288 }
289 #endif
290
291 10x if (fd >= FD_SETSIZE)
292 {
293 ::close(fd);
294 return make_err(EMFILE);
295 }
296
297 10x select_impl->fd_ = fd;
298
299 10x select_impl->desc_state_.fd = fd;
300 {
301 10x std::lock_guard lock(select_impl->desc_state_.mutex);
302 10x select_impl->desc_state_.read_op = nullptr;
303 10x select_impl->desc_state_.write_op = nullptr;
304 10x select_impl->desc_state_.connect_op = nullptr;
305 10x }
306 10x scheduler().register_descriptor(fd, &select_impl->desc_state_);
307
308 10x return {};
309 }
310
311 inline std::error_code
312 6x select_local_datagram_service::assign_socket(
313 local_datagram_socket::implementation& impl,
314 native_handle_type fd)
315 {
316 6x if (fd < 0 || fd >= FD_SETSIZE)
317 return make_err(fd < 0 ? EBADF : EMFILE);
318
319 6x auto* select_impl = static_cast<select_local_datagram_socket*>(&impl);
320 6x select_impl->close_socket();
321
322 6x select_impl->fd_ = fd;
323
324 6x select_impl->desc_state_.fd = fd;
325 {
326 6x std::lock_guard lock(select_impl->desc_state_.mutex);
327 6x select_impl->desc_state_.read_op = nullptr;
328 6x select_impl->desc_state_.write_op = nullptr;
329 6x select_impl->desc_state_.connect_op = nullptr;
330 6x }
331 6x scheduler().register_descriptor(fd, &select_impl->desc_state_);
332
333 6x return {};
334 }
335
336 inline std::error_code
337 8x select_local_datagram_service::bind_socket(
338 local_datagram_socket::implementation& impl,
339 corosio::local_endpoint ep)
340 {
341 8x return static_cast<select_local_datagram_socket*>(&impl)->do_bind(ep);
342 }
343
344 } // namespace boost::corosio::detail
345
346 #endif // BOOST_COROSIO_HAS_SELECT
347
348 #endif // BOOST_COROSIO_NATIVE_DETAIL_SELECT_SELECT_LOCAL_DATAGRAM_SERVICE_HPP
349