include/boost/corosio/native/detail/kqueue/kqueue_udp_service.hpp

69.3% Lines (70/101) 82.6% List of functions (19/23) 35.0% Branches (7/20)
f(x) Functions (23)
Function Calls Lines Branches Blocks
boost::corosio::detail::kqueue_udp_service::~kqueue_udp_service() :41 1125x 100.0% 100.0% boost::corosio::detail::kqueue_udp_service::kqueue_udp_service(boost::capy::execution_context&) :49 750x 100.0% 100.0% boost::corosio::detail::kqueue_send_to_op::cancel() :66 0 0.0% 0.0% 0.0% boost::corosio::detail::kqueue_recv_from_op::cancel() :75 1x 80.0% 50.0% 75.0% boost::corosio::detail::kqueue_udp_connect_op::cancel() :86 0 0.0% 0.0% 0.0% boost::corosio::detail::kqueue_send_op::cancel() :95 0 0.0% 0.0% 0.0% boost::corosio::detail::kqueue_recv_op::cancel() :104 0 0.0% 0.0% 0.0% boost::corosio::detail::kqueue_datagram_op::operator()() :115 10x 100.0% 100.0% boost::corosio::detail::kqueue_recv_from_op::operator()() :121 11x 100.0% 100.0% boost::corosio::detail::kqueue_udp_connect_op::operator()() :127 5x 100.0% 100.0% boost::corosio::detail::kqueue_recv_op::operator()() :133 2x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::kqueue_udp_socket(boost::corosio::detail::kqueue_udp_service&) :140 96x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::~kqueue_udp_socket() :145 96x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::send_to(std::__1::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, boost::corosio::endpoint, std::__1::stop_token, std::__1::error_code*, unsigned long*) :150 13x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::recv_from(std::__1::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, boost::corosio::endpoint*, std::__1::stop_token, std::__1::error_code*, unsigned long*) :163 19x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::connect(std::__1::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::endpoint, std::__1::stop_token, std::__1::error_code*) :178 6x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::send(std::__1::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, std::__1::stop_token, std::__1::error_code*, unsigned long*) :189 3x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::recv(std::__1::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, std::__1::stop_token, std::__1::error_code*, unsigned long*) :201 2x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::remote_endpoint() const :213 2x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::cancel() :219 3x 100.0% 100.0% boost::corosio::detail::kqueue_udp_socket::close_socket() :225 186x 100.0% 100.0% boost::corosio::detail::kqueue_udp_service::open_datagram_socket(boost::corosio::udp_socket::implementation&, int, int, int) :231 45x 71.4% 60.0% 66.0% boost::corosio::detail::kqueue_udp_service::bind_datagram(boost::corosio::udp_socket::implementation&, boost::corosio::endpoint) :290 25x 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
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_KQUEUE_KQUEUE_UDP_SERVICE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_KQUEUE_KQUEUE_UDP_SERVICE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_KQUEUE
16
17 #include <boost/corosio/detail/config.hpp>
18 #include <boost/corosio/detail/udp_service.hpp>
19
20 #include <boost/corosio/native/detail/kqueue/kqueue_udp_socket.hpp>
21 #include <boost/corosio/native/detail/kqueue/kqueue_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
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <netinet/in.h>
31 #include <sys/socket.h>
32 #include <unistd.h>
33
34 namespace boost::corosio::detail {
35
36 /** kqueue UDP service implementation.
37
38 Inherits from udp_service to enable runtime polymorphism.
39 Uses key_type = udp_service for service lookup.
40 */
41 class BOOST_COROSIO_DECL kqueue_udp_service final
42 : public reactor_socket_service<
43 kqueue_udp_service,
44 udp_service,
45 kqueue_scheduler,
46 kqueue_udp_socket>
47 {
48 public:
49 750x explicit kqueue_udp_service(capy::execution_context& ctx)
50 375x : reactor_socket_service(ctx)
51 750x {
52 750x }
53
54 std::error_code open_datagram_socket(
55 udp_socket::implementation& impl,
56 int family,
57 int type,
58 int protocol) override;
59 std::error_code
60 bind_datagram(udp_socket::implementation& impl, endpoint ep) override;
61 };
62
63 // Cancellation for connectionless ops
64
65 inline void
66 kqueue_send_to_op::cancel() noexcept
67 {
68 if (socket_impl_)
69 socket_impl_->cancel_single_op(*this);
70 else
71 request_cancel();
72 }
73
74 inline void
75 1x kqueue_recv_from_op::cancel() noexcept
76 {
77
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1x if (socket_impl_)
78 1x socket_impl_->cancel_single_op(*this);
79 else
80 request_cancel();
81 1x }
82
83 // Cancellation for connected-mode ops
84
85 inline void
86 kqueue_udp_connect_op::cancel() noexcept
87 {
88 if (socket_impl_)
89 socket_impl_->cancel_single_op(*this);
90 else
91 request_cancel();
92 }
93
94 inline void
95 kqueue_send_op::cancel() noexcept
96 {
97 if (socket_impl_)
98 socket_impl_->cancel_single_op(*this);
99 else
100 request_cancel();
101 }
102
103 inline void
104 kqueue_recv_op::cancel() noexcept
105 {
106 if (socket_impl_)
107 socket_impl_->cancel_single_op(*this);
108 else
109 request_cancel();
110 }
111
112 // Completion handlers
113
114 inline void
115 10x kqueue_datagram_op::operator()()
116 {
117 10x complete_io_op(*this);
118 10x }
119
120 inline void
121 11x kqueue_recv_from_op::operator()()
122 {
123 11x complete_datagram_op(*this, this->source_out);
124 11x }
125
126 inline void
127 5x kqueue_udp_connect_op::operator()()
128 {
129 5x complete_connect_op(*this);
130 5x }
131
132 inline void
133 2x kqueue_recv_op::operator()()
134 {
135 2x complete_io_op(*this);
136 2x }
137
138 // Socket construction/destruction
139
140 96x inline kqueue_udp_socket::kqueue_udp_socket(kqueue_udp_service& svc) noexcept
141 48x : reactor_datagram_socket(svc)
142 96x {
143 96x }
144
145 96x inline kqueue_udp_socket::~kqueue_udp_socket() = default;
146
147 // Connectionless I/O
148
149 inline std::coroutine_handle<>
150 13x kqueue_udp_socket::send_to(
151 std::coroutine_handle<> h,
152 capy::executor_ref ex,
153 buffer_param buf,
154 endpoint dest,
155 std::stop_token token,
156 std::error_code* ec,
157 std::size_t* bytes_out)
158 {
159 13x return do_send_to(h, ex, buf, dest, token, ec, bytes_out);
160 }
161
162 inline std::coroutine_handle<>
163 19x kqueue_udp_socket::recv_from(
164 std::coroutine_handle<> h,
165 capy::executor_ref ex,
166 buffer_param buf,
167 endpoint* source,
168 std::stop_token token,
169 std::error_code* ec,
170 std::size_t* bytes_out)
171 {
172 19x return do_recv_from(h, ex, buf, source, token, ec, bytes_out);
173 }
174
175 // Connected-mode I/O
176
177 inline std::coroutine_handle<>
178 6x kqueue_udp_socket::connect(
179 std::coroutine_handle<> h,
180 capy::executor_ref ex,
181 endpoint ep,
182 std::stop_token token,
183 std::error_code* ec)
184 {
185 6x return do_connect(h, ex, ep, token, ec);
186 }
187
188 inline std::coroutine_handle<>
189 3x kqueue_udp_socket::send(
190 std::coroutine_handle<> h,
191 capy::executor_ref ex,
192 buffer_param buf,
193 std::stop_token token,
194 std::error_code* ec,
195 std::size_t* bytes_out)
196 {
197 3x return do_send(h, ex, buf, token, ec, bytes_out);
198 }
199
200 inline std::coroutine_handle<>
201 2x kqueue_udp_socket::recv(
202 std::coroutine_handle<> h,
203 capy::executor_ref ex,
204 buffer_param buf,
205 std::stop_token token,
206 std::error_code* ec,
207 std::size_t* bytes_out)
208 {
209 2x return do_recv(h, ex, buf, token, ec, bytes_out);
210 }
211
212 inline endpoint
213 2x kqueue_udp_socket::remote_endpoint() const noexcept
214 {
215 2x return reactor_datagram_socket::remote_endpoint();
216 }
217
218 inline void
219 3x kqueue_udp_socket::cancel() noexcept
220 {
221 3x do_cancel();
222 3x }
223
224 inline void
225 186x kqueue_udp_socket::close_socket() noexcept
226 {
227 186x do_close_socket();
228 186x }
229
230 inline std::error_code
231 45x kqueue_udp_service::open_datagram_socket(
232 udp_socket::implementation& impl, int family, int type, int protocol)
233 {
234 45x auto* kq_impl = static_cast<kqueue_udp_socket*>(&impl);
235 45x kq_impl->close_socket();
236
237 45x int fd = ::socket(family, type, protocol);
238
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45x if (fd < 0)
239 return make_err(errno);
240
241
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 7 times.
45x if (family == AF_INET6)
242 {
243 7x int v6only = 1;
244 7x ::setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only));
245 7x }
246
247 45x int flags = ::fcntl(fd, F_GETFL, 0);
248
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45x if (flags == -1)
249 {
250 int errn = errno;
251 ::close(fd);
252 return make_err(errn);
253 }
254
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45x if (::fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
255 {
256 int errn = errno;
257 ::close(fd);
258 return make_err(errn);
259 }
260
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45x if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
261 {
262 int errn = errno;
263 ::close(fd);
264 return make_err(errn);
265 }
266
267 // SO_NOSIGPIPE on macOS (where MSG_NOSIGNAL doesn't exist)
268 #ifdef SO_NOSIGPIPE
269 {
270 45x int one = 1;
271 45x ::setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one));
272 }
273 #endif
274
275 45x kq_impl->fd_ = fd;
276
277 45x kq_impl->desc_state_.fd = fd;
278 {
279 45x std::lock_guard lock(kq_impl->desc_state_.mutex);
280 45x kq_impl->desc_state_.read_op = nullptr;
281 45x kq_impl->desc_state_.write_op = nullptr;
282 45x kq_impl->desc_state_.connect_op = nullptr;
283 45x }
284 45x scheduler().register_descriptor(fd, &kq_impl->desc_state_);
285
286 45x return {};
287 45x }
288
289 inline std::error_code
290 25x kqueue_udp_service::bind_datagram(udp_socket::implementation& impl, endpoint ep)
291 {
292 25x return static_cast<kqueue_udp_socket*>(&impl)->do_bind(ep);
293 }
294
295 } // namespace boost::corosio::detail
296
297 #endif // BOOST_COROSIO_HAS_KQUEUE
298
299 #endif // BOOST_COROSIO_NATIVE_DETAIL_KQUEUE_KQUEUE_UDP_SERVICE_HPP
300