include/boost/corosio/native/detail/epoll/epoll_udp_service.hpp

73.2% Lines (60/82) 81.8% List of functions (18/22)
f(x) Functions (22)
Function Calls Lines Blocks
boost::corosio::detail::epoll_udp_service::epoll_udp_service(boost::capy::execution_context&) :50 339x 100.0% 100.0% boost::corosio::detail::epoll_send_to_op::cancel() :67 0 0.0% 0.0% boost::corosio::detail::epoll_recv_from_op::cancel() :76 1x 80.0% 75.0% boost::corosio::detail::epoll_udp_connect_op::cancel() :87 0 0.0% 0.0% boost::corosio::detail::epoll_send_op::cancel() :96 0 0.0% 0.0% boost::corosio::detail::epoll_recv_op::cancel() :105 0 0.0% 0.0% boost::corosio::detail::epoll_datagram_op::operator()() :116 8x 100.0% 100.0% boost::corosio::detail::epoll_recv_from_op::operator()() :122 7x 100.0% 100.0% boost::corosio::detail::epoll_udp_connect_op::operator()() :128 5x 100.0% 100.0% boost::corosio::detail::epoll_recv_op::operator()() :134 2x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::epoll_udp_socket(boost::corosio::detail::epoll_udp_service&) :141 39x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::~epoll_udp_socket() :146 39x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::send_to(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, boost::corosio::endpoint, std::stop_token, std::error_code*, unsigned long*) :151 11x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::recv_from(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, boost::corosio::endpoint*, std::stop_token, std::error_code*, unsigned long*) :164 16x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::connect(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::endpoint, std::stop_token, std::error_code*) :179 6x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::send(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, std::stop_token, std::error_code*, unsigned long*) :190 3x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::recv(std::__n4861::coroutine_handle<void>, boost::capy::executor_ref, boost::corosio::buffer_param, std::stop_token, std::error_code*, unsigned long*) :202 2x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::remote_endpoint() const :214 2x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::cancel() :220 2x 100.0% 100.0% boost::corosio::detail::epoll_udp_socket::close_socket() :226 152x 100.0% 100.0% boost::corosio::detail::epoll_udp_service::open_datagram_socket(boost::corosio::udp_socket::implementation&, int, int, int) :232 37x 94.4% 94.0% boost::corosio::detail::epoll_udp_service::bind_datagram(boost::corosio::udp_socket::implementation&, boost::corosio::endpoint) :263 21x 100.0% 100.0%
Line 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_EPOLL_EPOLL_UDP_SERVICE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_UDP_SERVICE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_HAS_EPOLL
16
17 #include <boost/corosio/detail/config.hpp>
18 #include <boost/corosio/detail/udp_service.hpp>
19
20 #include <boost/corosio/native/detail/epoll/epoll_udp_socket.hpp>
21 #include <boost/corosio/native/detail/epoll/epoll_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 <netinet/in.h>
31 #include <sys/epoll.h>
32 #include <sys/socket.h>
33 #include <unistd.h>
34
35 namespace boost::corosio::detail {
36
37 /** epoll UDP service implementation.
38
39 Inherits from udp_service to enable runtime polymorphism.
40 Uses key_type = udp_service for service lookup.
41 */
42 class BOOST_COROSIO_DECL epoll_udp_service final
43 : public reactor_socket_service<
44 epoll_udp_service,
45 udp_service,
46 epoll_scheduler,
47 epoll_udp_socket>
48 {
49 public:
50 339x explicit epoll_udp_service(capy::execution_context& ctx)
51 339x : reactor_socket_service(ctx)
52 {
53 339x }
54
55 std::error_code open_datagram_socket(
56 udp_socket::implementation& impl,
57 int family,
58 int type,
59 int protocol) override;
60 std::error_code
61 bind_datagram(udp_socket::implementation& impl, endpoint ep) override;
62 };
63
64 // Cancellation for connectionless ops
65
66 inline void
67 epoll_send_to_op::cancel() noexcept
68 {
69 if (socket_impl_)
70 socket_impl_->cancel_single_op(*this);
71 else
72 request_cancel();
73 }
74
75 inline void
76 1x epoll_recv_from_op::cancel() noexcept
77 {
78 1x if (socket_impl_)
79 1x socket_impl_->cancel_single_op(*this);
80 else
81 request_cancel();
82 1x }
83
84 // Cancellation for connected-mode ops
85
86 inline void
87 epoll_udp_connect_op::cancel() noexcept
88 {
89 if (socket_impl_)
90 socket_impl_->cancel_single_op(*this);
91 else
92 request_cancel();
93 }
94
95 inline void
96 epoll_send_op::cancel() noexcept
97 {
98 if (socket_impl_)
99 socket_impl_->cancel_single_op(*this);
100 else
101 request_cancel();
102 }
103
104 inline void
105 epoll_recv_op::cancel() noexcept
106 {
107 if (socket_impl_)
108 socket_impl_->cancel_single_op(*this);
109 else
110 request_cancel();
111 }
112
113 // Completion handlers
114
115 inline void
116 8x epoll_datagram_op::operator()()
117 {
118 8x complete_io_op(*this);
119 8x }
120
121 inline void
122 7x epoll_recv_from_op::operator()()
123 {
124 7x complete_datagram_op(*this, this->source_out);
125 7x }
126
127 inline void
128 5x epoll_udp_connect_op::operator()()
129 {
130 5x complete_connect_op(*this);
131 5x }
132
133 inline void
134 2x epoll_recv_op::operator()()
135 {
136 2x complete_io_op(*this);
137 2x }
138
139 // Socket construction/destruction
140
141 39x inline epoll_udp_socket::epoll_udp_socket(epoll_udp_service& svc) noexcept
142 39x : reactor_datagram_socket(svc)
143 {
144 39x }
145
146 39x inline epoll_udp_socket::~epoll_udp_socket() = default;
147
148 // Connectionless I/O
149
150 inline std::coroutine_handle<>
151 11x epoll_udp_socket::send_to(
152 std::coroutine_handle<> h,
153 capy::executor_ref ex,
154 buffer_param buf,
155 endpoint dest,
156 std::stop_token token,
157 std::error_code* ec,
158 std::size_t* bytes_out)
159 {
160 11x return do_send_to(h, ex, buf, dest, token, ec, bytes_out);
161 }
162
163 inline std::coroutine_handle<>
164 16x epoll_udp_socket::recv_from(
165 std::coroutine_handle<> h,
166 capy::executor_ref ex,
167 buffer_param buf,
168 endpoint* source,
169 std::stop_token token,
170 std::error_code* ec,
171 std::size_t* bytes_out)
172 {
173 16x return do_recv_from(h, ex, buf, source, token, ec, bytes_out);
174 }
175
176 // Connected-mode I/O
177
178 inline std::coroutine_handle<>
179 6x epoll_udp_socket::connect(
180 std::coroutine_handle<> h,
181 capy::executor_ref ex,
182 endpoint ep,
183 std::stop_token token,
184 std::error_code* ec)
185 {
186 6x return do_connect(h, ex, ep, token, ec);
187 }
188
189 inline std::coroutine_handle<>
190 3x epoll_udp_socket::send(
191 std::coroutine_handle<> h,
192 capy::executor_ref ex,
193 buffer_param buf,
194 std::stop_token token,
195 std::error_code* ec,
196 std::size_t* bytes_out)
197 {
198 3x return do_send(h, ex, buf, token, ec, bytes_out);
199 }
200
201 inline std::coroutine_handle<>
202 2x epoll_udp_socket::recv(
203 std::coroutine_handle<> h,
204 capy::executor_ref ex,
205 buffer_param buf,
206 std::stop_token token,
207 std::error_code* ec,
208 std::size_t* bytes_out)
209 {
210 2x return do_recv(h, ex, buf, token, ec, bytes_out);
211 }
212
213 inline endpoint
214 2x epoll_udp_socket::remote_endpoint() const noexcept
215 {
216 2x return reactor_datagram_socket::remote_endpoint();
217 }
218
219 inline void
220 2x epoll_udp_socket::cancel() noexcept
221 {
222 2x do_cancel();
223 2x }
224
225 inline void
226 152x epoll_udp_socket::close_socket() noexcept
227 {
228 152x do_close_socket();
229 152x }
230
231 inline std::error_code
232 37x epoll_udp_service::open_datagram_socket(
233 udp_socket::implementation& impl, int family, int type, int protocol)
234 {
235 37x auto* epoll_impl = static_cast<epoll_udp_socket*>(&impl);
236 37x epoll_impl->close_socket();
237
238 37x int fd = ::socket(family, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
239 37x if (fd < 0)
240 return make_err(errno);
241
242 37x if (family == AF_INET6)
243 {
244 7x int one = 1;
245 7x ::setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
246 }
247
248 37x epoll_impl->fd_ = fd;
249
250 37x epoll_impl->desc_state_.fd = fd;
251 {
252 37x std::lock_guard lock(epoll_impl->desc_state_.mutex);
253 37x epoll_impl->desc_state_.read_op = nullptr;
254 37x epoll_impl->desc_state_.write_op = nullptr;
255 37x epoll_impl->desc_state_.connect_op = nullptr;
256 37x }
257 37x scheduler().register_descriptor(fd, &epoll_impl->desc_state_);
258
259 37x return {};
260 }
261
262 inline std::error_code
263 21x epoll_udp_service::bind_datagram(udp_socket::implementation& impl, endpoint ep)
264 {
265 21x return static_cast<epoll_udp_socket*>(&impl)->do_bind(ep);
266 }
267
268 } // namespace boost::corosio::detail
269
270 #endif // BOOST_COROSIO_HAS_EPOLL
271
272 #endif // BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_UDP_SERVICE_HPP
273