include/boost/corosio/native/native_local_datagram_socket.hpp

100.0% Lines (92 / 92) 100.0% Functions (46 / 46)
native_local_datagram_socket.hpp
f(x) Functions (46)
Function Calls Lines Blocks
boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::get_impl() :77 10x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::get_impl() :77 10x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::native_send_to_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::const_buffer, boost::corosio::local_endpoint, int) :91 4x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::native_send_to_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::const_buffer, boost::corosio::local_endpoint, int) :91 4x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :104 2x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_to_awaitable<boost::capy::const_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :104 2x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::native_recv_from_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer, boost::corosio::local_endpoint&, int) :122 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::native_recv_from_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::mutable_buffer, boost::corosio::local_endpoint&, int) :122 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :135 1x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_from_awaitable<boost::capy::mutable_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :135 1x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::corosio::wait_type) :148 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_wait_awaitable::native_wait_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::corosio::wait_type) :148 2x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_wait_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :156 1x 100.0% 80.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_wait_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :156 1x 100.0% 80.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::corosio::local_endpoint) :169 5x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_connect_awaitable::native_connect_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::corosio::local_endpoint) :169 5x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_connect_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :178 4x 100.0% 80.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_connect_awaitable::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :178 4x 100.0% 80.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_awaitable<boost::capy::const_buffer>::native_send_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::const_buffer, int) :193 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_awaitable<boost::capy::const_buffer>::native_send_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::const_buffer, int) :193 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_send_awaitable<boost::capy::const_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :204 1x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_send_awaitable<boost::capy::const_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :204 1x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::native_recv_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>&, boost::capy::mutable_buffer, int) :220 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::native_recv_awaitable(boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>&, boost::capy::mutable_buffer, int) :220 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :231 1x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_recv_awaitable<boost::capy::mutable_buffer>::dispatch(boost::capy::continuation&, boost::capy::executor_ref) const :231 1x 100.0% 75.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::native_local_datagram_socket(boost::capy::execution_context&) :244 15x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::native_local_datagram_socket(boost::capy::execution_context&) :244 15x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint, boost::corosio::message_flags) :289 4x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint, boost::corosio::message_flags) :289 4x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint) :303 4x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send_to<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::local_endpoint) :303 4x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&, boost::corosio::message_flags) :320 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&, boost::corosio::message_flags) :320 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&) :335 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv_from<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::local_endpoint&) :335 3x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::connect(boost::corosio::local_endpoint) :351 5x 100.0% 100.0% boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::connect(boost::corosio::local_endpoint) :351 5x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::message_flags) :370 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&, boost::corosio::message_flags) :370 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&) :380 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::send<boost::capy::const_buffer>(boost::capy::const_buffer const&) :380 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::message_flags) :396 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&, boost::corosio::message_flags) :396 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::epoll_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :406 3x 100.0% 100.0% auto boost::corosio::native_local_datagram_socket<boost::corosio::select_t{}>::recv<boost::capy::mutable_buffer>(boost::capy::mutable_buffer const&) :406 3x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_NATIVE_NATIVE_LOCAL_DATAGRAM_SOCKET_HPP
12 #define BOOST_COROSIO_NATIVE_NATIVE_LOCAL_DATAGRAM_SOCKET_HPP
13
14 #include <boost/corosio/detail/platform.hpp>
15
16 #if BOOST_COROSIO_POSIX
17
18 #include <boost/corosio/local_datagram_socket.hpp>
19 #include <boost/corosio/backend.hpp>
20 #include <boost/corosio/detail/op_base.hpp>
21
22 #ifndef BOOST_COROSIO_MRDOCS
23 #if BOOST_COROSIO_HAS_EPOLL
24 #include <boost/corosio/native/detail/epoll/epoll_types.hpp>
25 #endif
26
27 #if BOOST_COROSIO_HAS_SELECT
28 #include <boost/corosio/native/detail/select/select_types.hpp>
29 #endif
30
31 #if BOOST_COROSIO_HAS_KQUEUE
32 #include <boost/corosio/native/detail/kqueue/kqueue_types.hpp>
33 #endif
34
35 #if BOOST_COROSIO_HAS_URING
36 #include <boost/corosio/native/detail/uring/uring_types.hpp>
37 #endif
38 #endif // !BOOST_COROSIO_MRDOCS
39
40 namespace boost::corosio {
41
42 /** Sends and receives Unix domain datagrams, calling the backend directly.
43
44 This class template inherits from @ref local_datagram_socket. It
45 shadows the async operations (`send_to`, `recv_from`, `connect`,
46 `send`, `recv`) with versions that call the backend implementation
47 directly. The compiler can then inline through the entire call
48 chain.
49
50 Non-async operations (`open`, `close`, `cancel`, `bind`,
51 socket options) remain unchanged and dispatch through the
52 compiled library.
53
54 A `native_local_datagram_socket` IS-A `local_datagram_socket`
55 and can be passed to any function expecting
56 `local_datagram_socket&`, in which case virtual dispatch is
57 used transparently.
58
59 @tparam Backend A backend tag value (e.g., `epoll`) whose type
60 provides the concrete implementation types.
61
62 @par Thread Safety
63 Same as @ref local_datagram_socket.
64
65 @par Example
66 @par !example open_bind_recv
67
68 @see local_datagram_socket, epoll_t, iocp_t
69 */
70 template<auto Backend>
71 class native_local_datagram_socket : public local_datagram_socket
72 {
73 using backend_type = decltype(Backend);
74 using impl_type = typename backend_type::local_datagram_socket_type;
75 using service_type = typename backend_type::local_datagram_service_type;
76
77 20x impl_type& get_impl() noexcept
78 {
79 20x return *static_cast<impl_type*>(h_.get());
80 }
81
82 template<class ConstBufferSequence>
83 struct native_send_to_awaitable
84 : detail::bytes_op_base<native_send_to_awaitable<ConstBufferSequence>>
85 {
86 native_local_datagram_socket& self_;
87 ConstBufferSequence buffers_;
88 corosio::local_endpoint dest_;
89 int flags_;
90
91 8x native_send_to_awaitable(
92 native_local_datagram_socket& self,
93 ConstBufferSequence buffers,
94 corosio::local_endpoint dest,
95 int flags) noexcept
96 8x : self_(self)
97 8x , buffers_(std::move(buffers))
98 8x , dest_(dest)
99 8x , flags_(flags)
100 {
101 8x }
102
103 std::coroutine_handle<>
104 4x dispatch(capy::continuation& cont, capy::executor_ref ex) const
105 {
106 12x return self_.get_impl().send_to(
107 4x cont, ex, buffers_, dest_, flags_, this->token_, &this->ec_,
108 8x &this->bytes_);
109 }
110 };
111
112 template<class MutableBufferSequence>
113 struct native_recv_from_awaitable
114 : detail::bytes_op_base<
115 native_recv_from_awaitable<MutableBufferSequence>>
116 {
117 native_local_datagram_socket& self_;
118 MutableBufferSequence buffers_;
119 corosio::local_endpoint& source_;
120 int flags_;
121
122 6x native_recv_from_awaitable(
123 native_local_datagram_socket& self,
124 MutableBufferSequence buffers,
125 corosio::local_endpoint& source,
126 int flags) noexcept
127 6x : self_(self)
128 6x , buffers_(std::move(buffers))
129 6x , source_(source)
130 6x , flags_(flags)
131 {
132 6x }
133
134 std::coroutine_handle<>
135 2x dispatch(capy::continuation& cont, capy::executor_ref ex) const
136 {
137 6x return self_.get_impl().recv_from(
138 2x cont, ex, buffers_, &source_, flags_, this->token_, &this->ec_,
139 4x &this->bytes_);
140 }
141 };
142
143 struct native_wait_awaitable : detail::void_op_base<native_wait_awaitable>
144 {
145 native_local_datagram_socket& self_;
146 wait_type w_;
147
148 4x native_wait_awaitable(
149 native_local_datagram_socket& self, wait_type w) noexcept
150 4x : self_(self)
151 4x , w_(w)
152 {
153 4x }
154
155 std::coroutine_handle<>
156 2x dispatch(capy::continuation& cont, capy::executor_ref ex) const
157 {
158 4x return self_.get_impl().wait(
159 4x cont, ex, w_, this->token_, &this->ec_);
160 }
161 };
162
163 struct native_connect_awaitable
164 : detail::void_op_base<native_connect_awaitable>
165 {
166 native_local_datagram_socket& self_;
167 corosio::local_endpoint endpoint_;
168
169 10x native_connect_awaitable(
170 native_local_datagram_socket& self,
171 corosio::local_endpoint ep) noexcept
172 10x : self_(self)
173 10x , endpoint_(ep)
174 {
175 10x }
176
177 std::coroutine_handle<>
178 8x dispatch(capy::continuation& cont, capy::executor_ref ex) const
179 {
180 24x return self_.get_impl().connect(
181 24x cont, ex, endpoint_, this->token_, &this->ec_);
182 }
183 };
184
185 template<class ConstBufferSequence>
186 struct native_send_awaitable
187 : detail::bytes_op_base<native_send_awaitable<ConstBufferSequence>>
188 {
189 native_local_datagram_socket& self_;
190 ConstBufferSequence buffers_;
191 int flags_;
192
193 6x native_send_awaitable(
194 native_local_datagram_socket& self,
195 ConstBufferSequence buffers,
196 int flags) noexcept
197 6x : self_(self)
198 6x , buffers_(std::move(buffers))
199 6x , flags_(flags)
200 {
201 6x }
202
203 std::coroutine_handle<>
204 2x dispatch(capy::continuation& cont, capy::executor_ref ex) const
205 {
206 6x return self_.get_impl().send(
207 2x cont, ex, buffers_, flags_, this->token_, &this->ec_,
208 4x &this->bytes_);
209 }
210 };
211
212 template<class MutableBufferSequence>
213 struct native_recv_awaitable
214 : detail::bytes_op_base<native_recv_awaitable<MutableBufferSequence>>
215 {
216 native_local_datagram_socket& self_;
217 MutableBufferSequence buffers_;
218 int flags_;
219
220 6x native_recv_awaitable(
221 native_local_datagram_socket& self,
222 MutableBufferSequence buffers,
223 int flags) noexcept
224 6x : self_(self)
225 6x , buffers_(std::move(buffers))
226 6x , flags_(flags)
227 {
228 6x }
229
230 std::coroutine_handle<>
231 2x dispatch(capy::continuation& cont, capy::executor_ref ex) const
232 {
233 6x return self_.get_impl().recv(
234 2x cont, ex, buffers_, flags_, this->token_, &this->ec_,
235 4x &this->bytes_);
236 }
237 };
238
239 public:
240 /** Construct a native socket from an execution context.
241
242 @param ctx The execution context that owns this socket.
243 */
244 30x explicit native_local_datagram_socket(capy::execution_context& ctx)
245 30x : local_datagram_socket(handle(ctx, ctx.use_service<service_type>()))
246 {
247 30x }
248
249 /** Construct a native socket from an executor.
250
251 @param ex The executor whose context owns the socket.
252 */
253 template<class Ex>
254 requires(!std::same_as<
255 std::remove_cvref_t<Ex>,
256 native_local_datagram_socket>) &&
257 capy::Executor<Ex>
258 explicit native_local_datagram_socket(Ex const& ex)
259 : native_local_datagram_socket(ex.context())
260 {
261 }
262
263 /// Move construct.
264 native_local_datagram_socket(native_local_datagram_socket&&) noexcept =
265 default;
266
267 /// Move assign.
268 native_local_datagram_socket&
269 operator=(native_local_datagram_socket&&) noexcept = default;
270
271 /// Copy construction is disabled; the handle is uniquely owned.
272 native_local_datagram_socket(native_local_datagram_socket const&) = delete;
273 /// Copy assignment is disabled; the handle is uniquely owned.
274 native_local_datagram_socket&
275 operator=(native_local_datagram_socket const&) = delete;
276
277 /** Send a datagram to the specified destination.
278
279 Calls the backend implementation directly, bypassing virtual
280 dispatch. Otherwise identical to @ref local_datagram_socket::send_to.
281
282 @param buffers The buffer data to send.
283 @param dest The destination endpoint.
284 @param flags Message flags (e.g. `message_flags::do_not_route`).
285
286 @return An awaitable yielding the error code and the byte count sent.
287 */
288 template<capy::ConstBufferSequence CB>
289 8x [[nodiscard]] auto send_to(
290 CB const& buffers,
291 corosio::local_endpoint dest,
292 corosio::message_flags flags)
293 {
294 8x native_send_to_awaitable<CB> aw(
295 *this, buffers, dest, static_cast<int>(flags));
296 8x if (!is_open())
297 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
298 8x return aw;
299 }
300
301 /// @overload
302 template<capy::ConstBufferSequence CB>
303 8x [[nodiscard]] auto send_to(CB const& buffers, corosio::local_endpoint dest)
304 {
305 8x return send_to(buffers, dest, corosio::message_flags::none);
306 }
307
308 /** Receive a datagram and capture the sender's endpoint.
309
310 Calls the backend implementation directly, bypassing virtual
311 dispatch. Otherwise identical to @ref local_datagram_socket::recv_from.
312
313 @param buffers The buffers to receive into.
314 @param source Output endpoint for the sender's address.
315 @param flags Message flags (e.g. `message_flags::peek`).
316
317 @return An awaitable yielding the error code and the byte count received.
318 */
319 template<capy::MutableBufferSequence MB>
320 6x [[nodiscard]] auto recv_from(
321 MB const& buffers,
322 corosio::local_endpoint& source,
323 corosio::message_flags flags)
324 {
325 6x native_recv_from_awaitable<MB> aw(
326 *this, buffers, source, static_cast<int>(flags));
327 6x if (!is_open())
328 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
329 6x return aw;
330 }
331
332 /// @overload
333 template<capy::MutableBufferSequence MB>
334 [[nodiscard]] auto
335 6x recv_from(MB const& buffers, corosio::local_endpoint& source)
336 {
337 6x return recv_from(buffers, source, corosio::message_flags::none);
338 }
339
340 /** Asynchronously connect to set the default peer.
341
342 Calls the backend implementation directly, bypassing virtual
343 dispatch. Otherwise identical to @ref local_datagram_socket::connect.
344
345 If the socket is not already open, it is opened automatically.
346
347 @param ep The endpoint to set as the default destination.
348
349 @return An awaitable yielding the error code.
350 */
351 10x [[nodiscard]] auto connect(corosio::local_endpoint ep)
352 {
353 10x native_connect_awaitable aw(*this, ep);
354 10x if (!is_open())
355 2x aw.ec_ = open();
356 10x return aw;
357 }
358
359 /** Send a datagram to the connected peer.
360
361 Calls the backend implementation directly, bypassing virtual
362 dispatch. Otherwise identical to @ref local_datagram_socket::send.
363
364 @param buffers The buffer data to send.
365 @param flags Message flags (e.g. `message_flags::do_not_route`).
366
367 @return An awaitable yielding the error code and the byte count sent.
368 */
369 template<capy::ConstBufferSequence CB>
370 6x [[nodiscard]] auto send(CB const& buffers, corosio::message_flags flags)
371 {
372 6x native_send_awaitable<CB> aw(*this, buffers, static_cast<int>(flags));
373 6x if (!is_open())
374 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
375 6x return aw;
376 }
377
378 /// @overload
379 template<capy::ConstBufferSequence CB>
380 6x [[nodiscard]] auto send(CB const& buffers)
381 {
382 6x return send(buffers, corosio::message_flags::none);
383 }
384
385 /** Receive a datagram from the connected peer.
386
387 Calls the backend implementation directly, bypassing virtual
388 dispatch. Otherwise identical to @ref local_datagram_socket::recv.
389
390 @param buffers The buffers to receive into.
391 @param flags Message flags (e.g. `message_flags::peek`).
392
393 @return An awaitable yielding the error code and the byte count received.
394 */
395 template<capy::MutableBufferSequence MB>
396 6x [[nodiscard]] auto recv(MB const& buffers, corosio::message_flags flags)
397 {
398 6x native_recv_awaitable<MB> aw(*this, buffers, static_cast<int>(flags));
399 6x if (!is_open())
400 2x aw.ec_ = make_error_code(std::errc::bad_file_descriptor);
401 6x return aw;
402 }
403
404 /// @overload
405 template<capy::MutableBufferSequence MB>
406 6x [[nodiscard]] auto recv(MB const& buffers)
407 {
408 6x return recv(buffers, corosio::message_flags::none);
409 }
410
411 /** Asynchronously wait for the socket to be ready.
412
413 Calls the backend implementation directly, bypassing virtual
414 dispatch. Otherwise identical to @ref local_datagram_socket::wait.
415
416 @param w The wait direction (read, write, or error).
417
418 @return An awaitable yielding `results<>`.
419 */
420 4x [[nodiscard]] auto wait(wait_type w)
421 {
422 4x return native_wait_awaitable(*this, w);
423 }
424 };
425
426 } // namespace boost::corosio
427
428 #endif // BOOST_COROSIO_POSIX
429
430 #endif // BOOST_COROSIO_NATIVE_NATIVE_LOCAL_DATAGRAM_SOCKET_HPP
431