1//
2// basic_datagram_socket.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
12#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19#include <cstddef>
20#include <boost/asio/basic_socket.hpp>
21#include <boost/asio/detail/handler_type_requirements.hpp>
22#include <boost/asio/detail/non_const_lvalue.hpp>
23#include <boost/asio/detail/throw_error.hpp>
24#include <boost/asio/detail/type_traits.hpp>
25#include <boost/asio/error.hpp>
26
27#include <boost/asio/detail/push_options.hpp>
28
29namespace boost {
30namespace asio {
31
32#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
33#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL
34
35// Forward declaration with defaulted arguments.
36template <typename Protocol, typename Executor = any_io_executor>
37class basic_datagram_socket;
38
39#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
40
41/// Provides datagram-oriented socket functionality.
42/**
43 * The basic_datagram_socket class template provides asynchronous and blocking
44 * datagram-oriented socket functionality.
45 *
46 * @par Thread Safety
47 * @e Distinct @e objects: Safe.@n
48 * @e Shared @e objects: Unsafe.
49 *
50 * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect,
51 * and @c shutdown operations are thread safe with respect to each other, if
52 * the underlying operating system calls are also thread safe. This means that
53 * it is permitted to perform concurrent calls to these synchronous operations
54 * on a single socket object. Other synchronous operations, such as @c open or
55 * @c close, are not thread safe.
56 */
57template <typename Protocol, typename Executor>
58class basic_datagram_socket
59 : public basic_socket<Protocol, Executor>
60{
61private:
62 class initiate_async_send;
63 class initiate_async_send_to;
64 class initiate_async_receive;
65 class initiate_async_receive_from;
66
67public:
68 /// The type of the executor associated with the object.
69 typedef Executor executor_type;
70
71 /// Rebinds the socket type to another executor.
72 template <typename Executor1>
73 struct rebind_executor
74 {
75 /// The socket type when rebound to the specified executor.
76 typedef basic_datagram_socket<Protocol, Executor1> other;
77 };
78
79 /// The native representation of a socket.
80#if defined(GENERATING_DOCUMENTATION)
81 typedef implementation_defined native_handle_type;
82#else
83 typedef typename basic_socket<Protocol,
84 Executor>::native_handle_type native_handle_type;
85#endif
86
87 /// The protocol type.
88 typedef Protocol protocol_type;
89
90 /// The endpoint type.
91 typedef typename Protocol::endpoint endpoint_type;
92
93 /// Construct a basic_datagram_socket without opening it.
94 /**
95 * This constructor creates a datagram socket without opening it. The open()
96 * function must be called before data can be sent or received on the socket.
97 *
98 * @param ex The I/O executor that the socket will use, by default, to
99 * dispatch handlers for any asynchronous operations performed on the socket.
100 */
101 explicit basic_datagram_socket(const executor_type& ex)
102 : basic_socket<Protocol, Executor>(ex)
103 {
104 }
105
106 /// Construct a basic_datagram_socket without opening it.
107 /**
108 * This constructor creates a datagram socket without opening it. The open()
109 * function must be called before data can be sent or received on the socket.
110 *
111 * @param context An execution context which provides the I/O executor that
112 * the socket will use, by default, to dispatch handlers for any asynchronous
113 * operations performed on the socket.
114 */
115 template <typename ExecutionContext>
116 explicit basic_datagram_socket(ExecutionContext& context,
117 constraint_t<
118 is_convertible<ExecutionContext&, execution_context&>::value
119 > = 0)
120 : basic_socket<Protocol, Executor>(context)
121 {
122 }
123
124 /// Construct and open a basic_datagram_socket.
125 /**
126 * This constructor creates and opens a datagram socket.
127 *
128 * @param ex The I/O executor that the socket will use, by default, to
129 * dispatch handlers for any asynchronous operations performed on the socket.
130 *
131 * @param protocol An object specifying protocol parameters to be used.
132 *
133 * @throws boost::system::system_error Thrown on failure.
134 */
135 basic_datagram_socket(const executor_type& ex, const protocol_type& protocol)
136 : basic_socket<Protocol, Executor>(ex, protocol)
137 {
138 }
139
140 /// Construct and open a basic_datagram_socket.
141 /**
142 * This constructor creates and opens a datagram socket.
143 *
144 * @param context An execution context which provides the I/O executor that
145 * the socket will use, by default, to dispatch handlers for any asynchronous
146 * operations performed on the socket.
147 *
148 * @param protocol An object specifying protocol parameters to be used.
149 *
150 * @throws boost::system::system_error Thrown on failure.
151 */
152 template <typename ExecutionContext>
153 basic_datagram_socket(ExecutionContext& context,
154 const protocol_type& protocol,
155 constraint_t<
156 is_convertible<ExecutionContext&, execution_context&>::value,
157 defaulted_constraint
158 > = defaulted_constraint())
159 : basic_socket<Protocol, Executor>(context, protocol)
160 {
161 }
162
163 /// Construct a basic_datagram_socket, opening it and binding it to the given
164 /// local endpoint.
165 /**
166 * This constructor creates a datagram socket and automatically opens it bound
167 * to the specified endpoint on the local machine. The protocol used is the
168 * protocol associated with the given endpoint.
169 *
170 * @param ex The I/O executor that the socket will use, by default, to
171 * dispatch handlers for any asynchronous operations performed on the socket.
172 *
173 * @param endpoint An endpoint on the local machine to which the datagram
174 * socket will be bound.
175 *
176 * @throws boost::system::system_error Thrown on failure.
177 */
178 basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint)
179 : basic_socket<Protocol, Executor>(ex, endpoint)
180 {
181 }
182
183 /// Construct a basic_datagram_socket, opening it and binding it to the given
184 /// local endpoint.
185 /**
186 * This constructor creates a datagram socket and automatically opens it bound
187 * to the specified endpoint on the local machine. The protocol used is the
188 * protocol associated with the given endpoint.
189 *
190 * @param context An execution context which provides the I/O executor that
191 * the socket will use, by default, to dispatch handlers for any asynchronous
192 * operations performed on the socket.
193 *
194 * @param endpoint An endpoint on the local machine to which the datagram
195 * socket will be bound.
196 *
197 * @throws boost::system::system_error Thrown on failure.
198 */
199 template <typename ExecutionContext>
200 basic_datagram_socket(ExecutionContext& context,
201 const endpoint_type& endpoint,
202 constraint_t<
203 is_convertible<ExecutionContext&, execution_context&>::value
204 > = 0)
205 : basic_socket<Protocol, Executor>(context, endpoint)
206 {
207 }
208
209 /// Construct a basic_datagram_socket on an existing native socket.
210 /**
211 * This constructor creates a datagram socket object to hold an existing
212 * native socket.
213 *
214 * @param ex The I/O executor that the socket will use, by default, to
215 * dispatch handlers for any asynchronous operations performed on the socket.
216 *
217 * @param protocol An object specifying protocol parameters to be used.
218 *
219 * @param native_socket The new underlying socket implementation.
220 *
221 * @throws boost::system::system_error Thrown on failure.
222 */
223 basic_datagram_socket(const executor_type& ex,
224 const protocol_type& protocol, const native_handle_type& native_socket)
225 : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
226 {
227 }
228
229 /// Construct a basic_datagram_socket on an existing native socket.
230 /**
231 * This constructor creates a datagram socket object to hold an existing
232 * native socket.
233 *
234 * @param context An execution context which provides the I/O executor that
235 * the socket will use, by default, to dispatch handlers for any asynchronous
236 * operations performed on the socket.
237 *
238 * @param protocol An object specifying protocol parameters to be used.
239 *
240 * @param native_socket The new underlying socket implementation.
241 *
242 * @throws boost::system::system_error Thrown on failure.
243 */
244 template <typename ExecutionContext>
245 basic_datagram_socket(ExecutionContext& context,
246 const protocol_type& protocol, const native_handle_type& native_socket,
247 constraint_t<
248 is_convertible<ExecutionContext&, execution_context&>::value
249 > = 0)
250 : basic_socket<Protocol, Executor>(context, protocol, native_socket)
251 {
252 }
253
254 /// Move-construct a basic_datagram_socket from another.
255 /**
256 * This constructor moves a datagram socket from one object to another.
257 *
258 * @param other The other basic_datagram_socket object from which the move
259 * will occur.
260 *
261 * @note Following the move, the moved-from object is in the same state as if
262 * constructed using the @c basic_datagram_socket(const executor_type&)
263 * constructor.
264 */
265 basic_datagram_socket(basic_datagram_socket&& other) noexcept
266 : basic_socket<Protocol, Executor>(std::move(other))
267 {
268 }
269
270 /// Move-assign a basic_datagram_socket from another.
271 /**
272 * This assignment operator moves a datagram socket from one object to
273 * another.
274 *
275 * @param other The other basic_datagram_socket object from which the move
276 * will occur.
277 *
278 * @note Following the move, the moved-from object is in the same state as if
279 * constructed using the @c basic_datagram_socket(const executor_type&)
280 * constructor.
281 */
282 basic_datagram_socket& operator=(basic_datagram_socket&& other)
283 {
284 basic_socket<Protocol, Executor>::operator=(std::move(other));
285 return *this;
286 }
287
288 /// Move-construct a basic_datagram_socket from a socket of another protocol
289 /// type.
290 /**
291 * This constructor moves a datagram socket from one object to another.
292 *
293 * @param other The other basic_datagram_socket object from which the move
294 * will occur.
295 *
296 * @note Following the move, the moved-from object is in the same state as if
297 * constructed using the @c basic_datagram_socket(const executor_type&)
298 * constructor.
299 */
300 template <typename Protocol1, typename Executor1>
301 basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,
302 constraint_t<
303 is_convertible<Protocol1, Protocol>::value
304 && is_convertible<Executor1, Executor>::value
305 > = 0)
306 : basic_socket<Protocol, Executor>(std::move(other))
307 {
308 }
309
310 /// Move-assign a basic_datagram_socket from a socket of another protocol
311 /// type.
312 /**
313 * This assignment operator moves a datagram socket from one object to
314 * another.
315 *
316 * @param other The other basic_datagram_socket object from which the move
317 * will occur.
318 *
319 * @note Following the move, the moved-from object is in the same state as if
320 * constructed using the @c basic_datagram_socket(const executor_type&)
321 * constructor.
322 */
323 template <typename Protocol1, typename Executor1>
324 constraint_t<
325 is_convertible<Protocol1, Protocol>::value
326 && is_convertible<Executor1, Executor>::value,
327 basic_datagram_socket&
328 > operator=(basic_datagram_socket<Protocol1, Executor1>&& other)
329 {
330 basic_socket<Protocol, Executor>::operator=(std::move(other));
331 return *this;
332 }
333
334 /// Destroys the socket.
335 /**
336 * This function destroys the socket, cancelling any outstanding asynchronous
337 * operations associated with the socket as if by calling @c cancel.
338 */
339 ~basic_datagram_socket()
340 {
341 }
342
343 /// Send some data on a connected socket.
344 /**
345 * This function is used to send data on the datagram socket. The function
346 * call will block until the data has been sent successfully or an error
347 * occurs.
348 *
349 * @param buffers One ore more data buffers to be sent on the socket.
350 *
351 * @returns The number of bytes sent.
352 *
353 * @throws boost::system::system_error Thrown on failure.
354 *
355 * @note The send operation can only be used with a connected socket. Use
356 * the send_to function to send data on an unconnected datagram socket.
357 *
358 * @par Example
359 * To send a single data buffer use the @ref buffer function as follows:
360 * @code socket.send(boost::asio::buffer(data, size)); @endcode
361 * See the @ref buffer documentation for information on sending multiple
362 * buffers in one go, and how to use it with arrays, boost::array or
363 * std::vector.
364 */
365 template <typename ConstBufferSequence>
366 std::size_t send(const ConstBufferSequence& buffers)
367 {
368 boost::system::error_code ec;
369 std::size_t s = this->impl_.get_service().send(
370 this->impl_.get_implementation(), buffers, 0, ec);
371 boost::asio::detail::throw_error(err: ec, location: "send");
372 return s;
373 }
374
375 /// Send some data on a connected socket.
376 /**
377 * This function is used to send data on the datagram socket. The function
378 * call will block until the data has been sent successfully or an error
379 * occurs.
380 *
381 * @param buffers One ore more data buffers to be sent on the socket.
382 *
383 * @param flags Flags specifying how the send call is to be made.
384 *
385 * @returns The number of bytes sent.
386 *
387 * @throws boost::system::system_error Thrown on failure.
388 *
389 * @note The send operation can only be used with a connected socket. Use
390 * the send_to function to send data on an unconnected datagram socket.
391 */
392 template <typename ConstBufferSequence>
393 std::size_t send(const ConstBufferSequence& buffers,
394 socket_base::message_flags flags)
395 {
396 boost::system::error_code ec;
397 std::size_t s = this->impl_.get_service().send(
398 this->impl_.get_implementation(), buffers, flags, ec);
399 boost::asio::detail::throw_error(err: ec, location: "send");
400 return s;
401 }
402
403 /// Send some data on a connected socket.
404 /**
405 * This function is used to send data on the datagram socket. The function
406 * call will block until the data has been sent successfully or an error
407 * occurs.
408 *
409 * @param buffers One or more data buffers to be sent on the socket.
410 *
411 * @param flags Flags specifying how the send call is to be made.
412 *
413 * @param ec Set to indicate what error occurred, if any.
414 *
415 * @returns The number of bytes sent.
416 *
417 * @note The send operation can only be used with a connected socket. Use
418 * the send_to function to send data on an unconnected datagram socket.
419 */
420 template <typename ConstBufferSequence>
421 std::size_t send(const ConstBufferSequence& buffers,
422 socket_base::message_flags flags, boost::system::error_code& ec)
423 {
424 return this->impl_.get_service().send(
425 this->impl_.get_implementation(), buffers, flags, ec);
426 }
427
428 /// Start an asynchronous send on a connected socket.
429 /**
430 * This function is used to asynchronously send data on the datagram socket.
431 * It is an initiating function for an @ref asynchronous_operation, and always
432 * returns immediately.
433 *
434 * @param buffers One or more data buffers to be sent on the socket. Although
435 * the buffers object may be copied as necessary, ownership of the underlying
436 * memory blocks is retained by the caller, which must guarantee that they
437 * remain valid until the completion handler is called.
438 *
439 * @param token The @ref completion_token that will be used to produce a
440 * completion handler, which will be called when the send completes. Potential
441 * completion tokens include @ref use_future, @ref use_awaitable, @ref
442 * yield_context, or a function object with the correct completion signature.
443 * The function signature of the completion handler must be:
444 * @code void handler(
445 * const boost::system::error_code& error, // Result of operation.
446 * std::size_t bytes_transferred // Number of bytes sent.
447 * ); @endcode
448 * Regardless of whether the asynchronous operation completes immediately or
449 * not, the completion handler will not be invoked from within this function.
450 * On immediate completion, invocation of the handler will be performed in a
451 * manner equivalent to using boost::asio::post().
452 *
453 * @par Completion Signature
454 * @code void(boost::system::error_code, std::size_t) @endcode
455 *
456 * @note The async_send operation can only be used with a connected socket.
457 * Use the async_send_to function to send data on an unconnected datagram
458 * socket.
459 *
460 * @par Example
461 * To send a single data buffer use the @ref buffer function as follows:
462 * @code
463 * socket.async_send(boost::asio::buffer(data, size), handler);
464 * @endcode
465 * See the @ref buffer documentation for information on sending multiple
466 * buffers in one go, and how to use it with arrays, boost::array or
467 * std::vector.
468 *
469 * @par Per-Operation Cancellation
470 * On POSIX or Windows operating systems, this asynchronous operation supports
471 * cancellation for the following boost::asio::cancellation_type values:
472 *
473 * @li @c cancellation_type::terminal
474 *
475 * @li @c cancellation_type::partial
476 *
477 * @li @c cancellation_type::total
478 */
479 template <typename ConstBufferSequence,
480 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
481 std::size_t)) WriteToken = default_completion_token_t<executor_type>>
482 auto async_send(const ConstBufferSequence& buffers,
483 WriteToken&& token = default_completion_token_t<executor_type>())
484 -> decltype(
485 async_initiate<WriteToken,
486 void (boost::system::error_code, std::size_t)>(
487 declval<initiate_async_send>(), token,
488 buffers, socket_base::message_flags(0)))
489 {
490 return async_initiate<WriteToken,
491 void (boost::system::error_code, std::size_t)>(
492 initiate_async_send(this), token,
493 buffers, socket_base::message_flags(0));
494 }
495
496 /// Start an asynchronous send on a connected socket.
497 /**
498 * This function is used to asynchronously send data on the datagram socket.
499 * It is an initiating function for an @ref asynchronous_operation, and always
500 * returns immediately.
501 *
502 * @param buffers One or more data buffers to be sent on the socket. Although
503 * the buffers object may be copied as necessary, ownership of the underlying
504 * memory blocks is retained by the caller, which must guarantee that they
505 * remain valid until the completion handler is called.
506 *
507 * @param flags Flags specifying how the send call is to be made.
508 *
509 * @param token The @ref completion_token that will be used to produce a
510 * completion handler, which will be called when the send completes. Potential
511 * completion tokens include @ref use_future, @ref use_awaitable, @ref
512 * yield_context, or a function object with the correct completion signature.
513 * The function signature of the completion handler must be:
514 * @code void handler(
515 * const boost::system::error_code& error, // Result of operation.
516 * std::size_t bytes_transferred // Number of bytes sent.
517 * ); @endcode
518 * Regardless of whether the asynchronous operation completes immediately or
519 * not, the completion handler will not be invoked from within this function.
520 * On immediate completion, invocation of the handler will be performed in a
521 * manner equivalent to using boost::asio::post().
522 *
523 * @par Completion Signature
524 * @code void(boost::system::error_code, std::size_t) @endcode
525 *
526 * @note The async_send operation can only be used with a connected socket.
527 * Use the async_send_to function to send data on an unconnected datagram
528 * socket.
529 *
530 * @par Per-Operation Cancellation
531 * On POSIX or Windows operating systems, this asynchronous operation supports
532 * cancellation for the following boost::asio::cancellation_type values:
533 *
534 * @li @c cancellation_type::terminal
535 *
536 * @li @c cancellation_type::partial
537 *
538 * @li @c cancellation_type::total
539 */
540 template <typename ConstBufferSequence,
541 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
542 std::size_t)) WriteToken = default_completion_token_t<executor_type>>
543 auto async_send(const ConstBufferSequence& buffers,
544 socket_base::message_flags flags,
545 WriteToken&& token = default_completion_token_t<executor_type>())
546 -> decltype(
547 async_initiate<WriteToken,
548 void (boost::system::error_code, std::size_t)>(
549 declval<initiate_async_send>(), token, buffers, flags))
550 {
551 return async_initiate<WriteToken,
552 void (boost::system::error_code, std::size_t)>(
553 initiate_async_send(this), token, buffers, flags);
554 }
555
556 /// Send a datagram to the specified endpoint.
557 /**
558 * This function is used to send a datagram to the specified remote endpoint.
559 * The function call will block until the data has been sent successfully or
560 * an error occurs.
561 *
562 * @param buffers One or more data buffers to be sent to the remote endpoint.
563 *
564 * @param destination The remote endpoint to which the data will be sent.
565 *
566 * @returns The number of bytes sent.
567 *
568 * @throws boost::system::system_error Thrown on failure.
569 *
570 * @par Example
571 * To send a single data buffer use the @ref buffer function as follows:
572 * @code
573 * boost::asio::ip::udp::endpoint destination(
574 * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
575 * socket.send_to(boost::asio::buffer(data, size), destination);
576 * @endcode
577 * See the @ref buffer documentation for information on sending multiple
578 * buffers in one go, and how to use it with arrays, boost::array or
579 * std::vector.
580 */
581 template <typename ConstBufferSequence>
582 std::size_t send_to(const ConstBufferSequence& buffers,
583 const endpoint_type& destination)
584 {
585 boost::system::error_code ec;
586 std::size_t s = this->impl_.get_service().send_to(
587 this->impl_.get_implementation(), buffers, destination, 0, ec);
588 boost::asio::detail::throw_error(err: ec, location: "send_to");
589 return s;
590 }
591
592 /// Send a datagram to the specified endpoint.
593 /**
594 * This function is used to send a datagram to the specified remote endpoint.
595 * The function call will block until the data has been sent successfully or
596 * an error occurs.
597 *
598 * @param buffers One or more data buffers to be sent to the remote endpoint.
599 *
600 * @param destination The remote endpoint to which the data will be sent.
601 *
602 * @param flags Flags specifying how the send call is to be made.
603 *
604 * @returns The number of bytes sent.
605 *
606 * @throws boost::system::system_error Thrown on failure.
607 */
608 template <typename ConstBufferSequence>
609 std::size_t send_to(const ConstBufferSequence& buffers,
610 const endpoint_type& destination, socket_base::message_flags flags)
611 {
612 boost::system::error_code ec;
613 std::size_t s = this->impl_.get_service().send_to(
614 this->impl_.get_implementation(), buffers, destination, flags, ec);
615 boost::asio::detail::throw_error(err: ec, location: "send_to");
616 return s;
617 }
618
619 /// Send a datagram to the specified endpoint.
620 /**
621 * This function is used to send a datagram to the specified remote endpoint.
622 * The function call will block until the data has been sent successfully or
623 * an error occurs.
624 *
625 * @param buffers One or more data buffers to be sent to the remote endpoint.
626 *
627 * @param destination The remote endpoint to which the data will be sent.
628 *
629 * @param flags Flags specifying how the send call is to be made.
630 *
631 * @param ec Set to indicate what error occurred, if any.
632 *
633 * @returns The number of bytes sent.
634 */
635 template <typename ConstBufferSequence>
636 std::size_t send_to(const ConstBufferSequence& buffers,
637 const endpoint_type& destination, socket_base::message_flags flags,
638 boost::system::error_code& ec)
639 {
640 return this->impl_.get_service().send_to(this->impl_.get_implementation(),
641 buffers, destination, flags, ec);
642 }
643
644 /// Start an asynchronous send.
645 /**
646 * This function is used to asynchronously send a datagram to the specified
647 * remote endpoint. It is an initiating function for an @ref
648 * asynchronous_operation, and always returns immediately.
649 *
650 * @param buffers One or more data buffers to be sent to the remote endpoint.
651 * Although the buffers object may be copied as necessary, ownership of the
652 * underlying memory blocks is retained by the caller, which must guarantee
653 * that they remain valid until the completion handler is called.
654 *
655 * @param destination The remote endpoint to which the data will be sent.
656 * Copies will be made of the endpoint as required.
657 *
658 * @param token The @ref completion_token that will be used to produce a
659 * completion handler, which will be called when the send completes. Potential
660 * completion tokens include @ref use_future, @ref use_awaitable, @ref
661 * yield_context, or a function object with the correct completion signature.
662 * The function signature of the completion handler must be:
663 * @code void handler(
664 * const boost::system::error_code& error, // Result of operation.
665 * std::size_t bytes_transferred // Number of bytes sent.
666 * ); @endcode
667 * Regardless of whether the asynchronous operation completes immediately or
668 * not, the completion handler will not be invoked from within this function.
669 * On immediate completion, invocation of the handler will be performed in a
670 * manner equivalent to using boost::asio::post().
671 *
672 * @par Completion Signature
673 * @code void(boost::system::error_code, std::size_t) @endcode
674 *
675 * @par Example
676 * To send a single data buffer use the @ref buffer function as follows:
677 * @code
678 * boost::asio::ip::udp::endpoint destination(
679 * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
680 * socket.async_send_to(
681 * boost::asio::buffer(data, size), destination, handler);
682 * @endcode
683 * See the @ref buffer documentation for information on sending multiple
684 * buffers in one go, and how to use it with arrays, boost::array or
685 * std::vector.
686 *
687 * @par Per-Operation Cancellation
688 * On POSIX or Windows operating systems, this asynchronous operation supports
689 * cancellation for the following boost::asio::cancellation_type values:
690 *
691 * @li @c cancellation_type::terminal
692 *
693 * @li @c cancellation_type::partial
694 *
695 * @li @c cancellation_type::total
696 */
697 template <typename ConstBufferSequence,
698 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
699 std::size_t)) WriteToken = default_completion_token_t<executor_type>>
700 auto async_send_to(const ConstBufferSequence& buffers,
701 const endpoint_type& destination,
702 WriteToken&& token = default_completion_token_t<executor_type>())
703 -> decltype(
704 async_initiate<WriteToken,
705 void (boost::system::error_code, std::size_t)>(
706 declval<initiate_async_send_to>(), token, buffers,
707 destination, socket_base::message_flags(0)))
708 {
709 return async_initiate<WriteToken,
710 void (boost::system::error_code, std::size_t)>(
711 initiate_async_send_to(this), token, buffers,
712 destination, socket_base::message_flags(0));
713 }
714
715 /// Start an asynchronous send.
716 /**
717 * This function is used to asynchronously send a datagram to the specified
718 * remote endpoint. It is an initiating function for an @ref
719 * asynchronous_operation, and always returns immediately.
720 *
721 * @param buffers One or more data buffers to be sent to the remote endpoint.
722 * Although the buffers object may be copied as necessary, ownership of the
723 * underlying memory blocks is retained by the caller, which must guarantee
724 * that they remain valid until the completion handler is called.
725 *
726 * @param flags Flags specifying how the send call is to be made.
727 *
728 * @param destination The remote endpoint to which the data will be sent.
729 * Copies will be made of the endpoint as required.
730 *
731 * @param token The @ref completion_token that will be used to produce a
732 * completion handler, which will be called when the send completes. Potential
733 * completion tokens include @ref use_future, @ref use_awaitable, @ref
734 * yield_context, or a function object with the correct completion signature.
735 * The function signature of the completion handler must be:
736 * @code void handler(
737 * const boost::system::error_code& error, // Result of operation.
738 * std::size_t bytes_transferred // Number of bytes sent.
739 * ); @endcode
740 * Regardless of whether the asynchronous operation completes immediately or
741 * not, the completion handler will not be invoked from within this function.
742 * On immediate completion, invocation of the handler will be performed in a
743 * manner equivalent to using boost::asio::post().
744 *
745 * @par Completion Signature
746 * @code void(boost::system::error_code, std::size_t) @endcode
747 *
748 * @par Per-Operation Cancellation
749 * On POSIX or Windows operating systems, this asynchronous operation supports
750 * cancellation for the following boost::asio::cancellation_type values:
751 *
752 * @li @c cancellation_type::terminal
753 *
754 * @li @c cancellation_type::partial
755 *
756 * @li @c cancellation_type::total
757 */
758 template <typename ConstBufferSequence,
759 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
760 std::size_t)) WriteToken = default_completion_token_t<executor_type>>
761 auto async_send_to(const ConstBufferSequence& buffers,
762 const endpoint_type& destination, socket_base::message_flags flags,
763 WriteToken&& token = default_completion_token_t<executor_type>())
764 -> decltype(
765 async_initiate<WriteToken,
766 void (boost::system::error_code, std::size_t)>(
767 declval<initiate_async_send_to>(), token,
768 buffers, destination, flags))
769 {
770 return async_initiate<WriteToken,
771 void (boost::system::error_code, std::size_t)>(
772 initiate_async_send_to(this), token,
773 buffers, destination, flags);
774 }
775
776 /// Receive some data on a connected socket.
777 /**
778 * This function is used to receive data on the datagram socket. The function
779 * call will block until data has been received successfully or an error
780 * occurs.
781 *
782 * @param buffers One or more buffers into which the data will be received.
783 *
784 * @returns The number of bytes received.
785 *
786 * @throws boost::system::system_error Thrown on failure.
787 *
788 * @note The receive operation can only be used with a connected socket. Use
789 * the receive_from function to receive data on an unconnected datagram
790 * socket.
791 *
792 * @par Example
793 * To receive into a single data buffer use the @ref buffer function as
794 * follows:
795 * @code socket.receive(boost::asio::buffer(data, size)); @endcode
796 * See the @ref buffer documentation for information on receiving into
797 * multiple buffers in one go, and how to use it with arrays, boost::array or
798 * std::vector.
799 */
800 template <typename MutableBufferSequence>
801 std::size_t receive(const MutableBufferSequence& buffers)
802 {
803 boost::system::error_code ec;
804 std::size_t s = this->impl_.get_service().receive(
805 this->impl_.get_implementation(), buffers, 0, ec);
806 boost::asio::detail::throw_error(err: ec, location: "receive");
807 return s;
808 }
809
810 /// Receive some data on a connected socket.
811 /**
812 * This function is used to receive data on the datagram socket. The function
813 * call will block until data has been received successfully or an error
814 * occurs.
815 *
816 * @param buffers One or more buffers into which the data will be received.
817 *
818 * @param flags Flags specifying how the receive call is to be made.
819 *
820 * @returns The number of bytes received.
821 *
822 * @throws boost::system::system_error Thrown on failure.
823 *
824 * @note The receive operation can only be used with a connected socket. Use
825 * the receive_from function to receive data on an unconnected datagram
826 * socket.
827 */
828 template <typename MutableBufferSequence>
829 std::size_t receive(const MutableBufferSequence& buffers,
830 socket_base::message_flags flags)
831 {
832 boost::system::error_code ec;
833 std::size_t s = this->impl_.get_service().receive(
834 this->impl_.get_implementation(), buffers, flags, ec);
835 boost::asio::detail::throw_error(err: ec, location: "receive");
836 return s;
837 }
838
839 /// Receive some data on a connected socket.
840 /**
841 * This function is used to receive data on the datagram socket. The function
842 * call will block until data has been received successfully or an error
843 * occurs.
844 *
845 * @param buffers One or more buffers into which the data will be received.
846 *
847 * @param flags Flags specifying how the receive call is to be made.
848 *
849 * @param ec Set to indicate what error occurred, if any.
850 *
851 * @returns The number of bytes received.
852 *
853 * @note The receive operation can only be used with a connected socket. Use
854 * the receive_from function to receive data on an unconnected datagram
855 * socket.
856 */
857 template <typename MutableBufferSequence>
858 std::size_t receive(const MutableBufferSequence& buffers,
859 socket_base::message_flags flags, boost::system::error_code& ec)
860 {
861 return this->impl_.get_service().receive(
862 this->impl_.get_implementation(), buffers, flags, ec);
863 }
864
865 /// Start an asynchronous receive on a connected socket.
866 /**
867 * This function is used to asynchronously receive data from the datagram
868 * socket. It is an initiating function for an @ref asynchronous_operation,
869 * and always returns immediately.
870 *
871 * @param buffers One or more buffers into which the data will be received.
872 * Although the buffers object may be copied as necessary, ownership of the
873 * underlying memory blocks is retained by the caller, which must guarantee
874 * that they remain valid until the completion handler is called.
875 *
876 * @param token The @ref completion_token that will be used to produce a
877 * completion handler, which will be called when the receive completes.
878 * Potential completion tokens include @ref use_future, @ref use_awaitable,
879 * @ref yield_context, or a function object with the correct completion
880 * signature. The function signature of the completion handler must be:
881 * @code void handler(
882 * const boost::system::error_code& error, // Result of operation.
883 * std::size_t bytes_transferred // Number of bytes received.
884 * ); @endcode
885 * Regardless of whether the asynchronous operation completes immediately or
886 * not, the completion handler will not be invoked from within this function.
887 * On immediate completion, invocation of the handler will be performed in a
888 * manner equivalent to using boost::asio::post().
889 *
890 * @par Completion Signature
891 * @code void(boost::system::error_code, std::size_t) @endcode
892 *
893 * @note The async_receive operation can only be used with a connected socket.
894 * Use the async_receive_from function to receive data on an unconnected
895 * datagram socket.
896 *
897 * @par Example
898 * To receive into a single data buffer use the @ref buffer function as
899 * follows:
900 * @code
901 * socket.async_receive(boost::asio::buffer(data, size), handler);
902 * @endcode
903 * See the @ref buffer documentation for information on receiving into
904 * multiple buffers in one go, and how to use it with arrays, boost::array or
905 * std::vector.
906 *
907 * @par Per-Operation Cancellation
908 * On POSIX or Windows operating systems, this asynchronous operation supports
909 * cancellation for the following boost::asio::cancellation_type values:
910 *
911 * @li @c cancellation_type::terminal
912 *
913 * @li @c cancellation_type::partial
914 *
915 * @li @c cancellation_type::total
916 */
917 template <typename MutableBufferSequence,
918 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
919 std::size_t)) ReadToken = default_completion_token_t<executor_type>>
920 auto async_receive(const MutableBufferSequence& buffers,
921 ReadToken&& token = default_completion_token_t<executor_type>())
922 -> decltype(
923 async_initiate<ReadToken,
924 void (boost::system::error_code, std::size_t)>(
925 declval<initiate_async_receive>(), token,
926 buffers, socket_base::message_flags(0)))
927 {
928 return async_initiate<ReadToken,
929 void (boost::system::error_code, std::size_t)>(
930 initiate_async_receive(this), token,
931 buffers, socket_base::message_flags(0));
932 }
933
934 /// Start an asynchronous receive on a connected socket.
935 /**
936 * This function is used to asynchronously receive data from the datagram
937 * socket. It is an initiating function for an @ref asynchronous_operation,
938 * and always returns immediately.
939 *
940 * @param buffers One or more buffers into which the data will be received.
941 * Although the buffers object may be copied as necessary, ownership of the
942 * underlying memory blocks is retained by the caller, which must guarantee
943 * that they remain valid until the completion handler is called.
944 *
945 * @param flags Flags specifying how the receive call is to be made.
946 *
947 * @param token The @ref completion_token that will be used to produce a
948 * completion handler, which will be called when the receive completes.
949 * Potential completion tokens include @ref use_future, @ref use_awaitable,
950 * @ref yield_context, or a function object with the correct completion
951 * signature. The function signature of the completion handler must be:
952 * @code void handler(
953 * const boost::system::error_code& error, // Result of operation.
954 * std::size_t bytes_transferred // Number of bytes received.
955 * ); @endcode
956 * Regardless of whether the asynchronous operation completes immediately or
957 * not, the completion handler will not be invoked from within this function.
958 * On immediate completion, invocation of the handler will be performed in a
959 * manner equivalent to using boost::asio::post().
960 *
961 * @par Completion Signature
962 * @code void(boost::system::error_code, std::size_t) @endcode
963 *
964 * @note The async_receive operation can only be used with a connected socket.
965 * Use the async_receive_from function to receive data on an unconnected
966 * datagram socket.
967 *
968 * @par Per-Operation Cancellation
969 * On POSIX or Windows operating systems, this asynchronous operation supports
970 * cancellation for the following boost::asio::cancellation_type values:
971 *
972 * @li @c cancellation_type::terminal
973 *
974 * @li @c cancellation_type::partial
975 *
976 * @li @c cancellation_type::total
977 */
978 template <typename MutableBufferSequence,
979 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
980 std::size_t)) ReadToken = default_completion_token_t<executor_type>>
981 auto async_receive(const MutableBufferSequence& buffers,
982 socket_base::message_flags flags,
983 ReadToken&& token = default_completion_token_t<executor_type>())
984 -> decltype(
985 async_initiate<ReadToken,
986 void (boost::system::error_code, std::size_t)>(
987 declval<initiate_async_receive>(), token, buffers, flags))
988 {
989 return async_initiate<ReadToken,
990 void (boost::system::error_code, std::size_t)>(
991 initiate_async_receive(this), token, buffers, flags);
992 }
993
994 /// Receive a datagram with the endpoint of the sender.
995 /**
996 * This function is used to receive a datagram. The function call will block
997 * until data has been received successfully or an error occurs.
998 *
999 * @param buffers One or more buffers into which the data will be received.
1000 *
1001 * @param sender_endpoint An endpoint object that receives the endpoint of
1002 * the remote sender of the datagram.
1003 *
1004 * @returns The number of bytes received.
1005 *
1006 * @throws boost::system::system_error Thrown on failure.
1007 *
1008 * @par Example
1009 * To receive into a single data buffer use the @ref buffer function as
1010 * follows:
1011 * @code
1012 * boost::asio::ip::udp::endpoint sender_endpoint;
1013 * socket.receive_from(
1014 * boost::asio::buffer(data, size), sender_endpoint);
1015 * @endcode
1016 * See the @ref buffer documentation for information on receiving into
1017 * multiple buffers in one go, and how to use it with arrays, boost::array or
1018 * std::vector.
1019 */
1020 template <typename MutableBufferSequence>
1021 std::size_t receive_from(const MutableBufferSequence& buffers,
1022 endpoint_type& sender_endpoint)
1023 {
1024 boost::system::error_code ec;
1025 std::size_t s = this->impl_.get_service().receive_from(
1026 this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);
1027 boost::asio::detail::throw_error(err: ec, location: "receive_from");
1028 return s;
1029 }
1030
1031 /// Receive a datagram with the endpoint of the sender.
1032 /**
1033 * This function is used to receive a datagram. The function call will block
1034 * until data has been received successfully or an error occurs.
1035 *
1036 * @param buffers One or more buffers into which the data will be received.
1037 *
1038 * @param sender_endpoint An endpoint object that receives the endpoint of
1039 * the remote sender of the datagram.
1040 *
1041 * @param flags Flags specifying how the receive call is to be made.
1042 *
1043 * @returns The number of bytes received.
1044 *
1045 * @throws boost::system::system_error Thrown on failure.
1046 */
1047 template <typename MutableBufferSequence>
1048 std::size_t receive_from(const MutableBufferSequence& buffers,
1049 endpoint_type& sender_endpoint, socket_base::message_flags flags)
1050 {
1051 boost::system::error_code ec;
1052 std::size_t s = this->impl_.get_service().receive_from(
1053 this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
1054 boost::asio::detail::throw_error(err: ec, location: "receive_from");
1055 return s;
1056 }
1057
1058 /// Receive a datagram with the endpoint of the sender.
1059 /**
1060 * This function is used to receive a datagram. The function call will block
1061 * until data has been received successfully or an error occurs.
1062 *
1063 * @param buffers One or more buffers into which the data will be received.
1064 *
1065 * @param sender_endpoint An endpoint object that receives the endpoint of
1066 * the remote sender of the datagram.
1067 *
1068 * @param flags Flags specifying how the receive call is to be made.
1069 *
1070 * @param ec Set to indicate what error occurred, if any.
1071 *
1072 * @returns The number of bytes received.
1073 */
1074 template <typename MutableBufferSequence>
1075 std::size_t receive_from(const MutableBufferSequence& buffers,
1076 endpoint_type& sender_endpoint, socket_base::message_flags flags,
1077 boost::system::error_code& ec)
1078 {
1079 return this->impl_.get_service().receive_from(
1080 this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
1081 }
1082
1083 /// Start an asynchronous receive.
1084 /**
1085 * This function is used to asynchronously receive a datagram. It is an
1086 * initiating function for an @ref asynchronous_operation, and always returns
1087 * immediately.
1088 *
1089 * @param buffers One or more buffers into which the data will be received.
1090 * Although the buffers object may be copied as necessary, ownership of the
1091 * underlying memory blocks is retained by the caller, which must guarantee
1092 * that they remain valid until the completion handler is called.
1093 *
1094 * @param sender_endpoint An endpoint object that receives the endpoint of
1095 * the remote sender of the datagram. Ownership of the sender_endpoint object
1096 * is retained by the caller, which must guarantee that it is valid until the
1097 * completion handler is called.
1098 *
1099 * @param token The @ref completion_token that will be used to produce a
1100 * completion handler, which will be called when the receive completes.
1101 * Potential completion tokens include @ref use_future, @ref use_awaitable,
1102 * @ref yield_context, or a function object with the correct completion
1103 * signature. The function signature of the completion handler must be:
1104 * @code void handler(
1105 * const boost::system::error_code& error, // Result of operation.
1106 * std::size_t bytes_transferred // Number of bytes received.
1107 * ); @endcode
1108 * Regardless of whether the asynchronous operation completes immediately or
1109 * not, the completion handler will not be invoked from within this function.
1110 * On immediate completion, invocation of the handler will be performed in a
1111 * manner equivalent to using boost::asio::post().
1112 *
1113 * @par Completion Signature
1114 * @code void(boost::system::error_code, std::size_t) @endcode
1115 *
1116 * @par Example
1117 * To receive into a single data buffer use the @ref buffer function as
1118 * follows:
1119 * @code socket.async_receive_from(
1120 * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode
1121 * See the @ref buffer documentation for information on receiving into
1122 * multiple buffers in one go, and how to use it with arrays, boost::array or
1123 * std::vector.
1124 *
1125 * @par Per-Operation Cancellation
1126 * On POSIX or Windows operating systems, this asynchronous operation supports
1127 * cancellation for the following boost::asio::cancellation_type values:
1128 *
1129 * @li @c cancellation_type::terminal
1130 *
1131 * @li @c cancellation_type::partial
1132 *
1133 * @li @c cancellation_type::total
1134 */
1135 template <typename MutableBufferSequence,
1136 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1137 std::size_t)) ReadToken = default_completion_token_t<executor_type>>
1138 auto async_receive_from(const MutableBufferSequence& buffers,
1139 endpoint_type& sender_endpoint,
1140 ReadToken&& token = default_completion_token_t<executor_type>())
1141 -> decltype(
1142 async_initiate<ReadToken,
1143 void (boost::system::error_code, std::size_t)>(
1144 declval<initiate_async_receive_from>(), token, buffers,
1145 &sender_endpoint, socket_base::message_flags(0)))
1146 {
1147 return async_initiate<ReadToken,
1148 void (boost::system::error_code, std::size_t)>(
1149 initiate_async_receive_from(this), token, buffers,
1150 &sender_endpoint, socket_base::message_flags(0));
1151 }
1152
1153 /// Start an asynchronous receive.
1154 /**
1155 * This function is used to asynchronously receive a datagram. It is an
1156 * initiating function for an @ref asynchronous_operation, and always returns
1157 * immediately.
1158 *
1159 * @param buffers One or more buffers into which the data will be received.
1160 * Although the buffers object may be copied as necessary, ownership of the
1161 * underlying memory blocks is retained by the caller, which must guarantee
1162 * that they remain valid until the completion handler is called.
1163 *
1164 * @param sender_endpoint An endpoint object that receives the endpoint of
1165 * the remote sender of the datagram. Ownership of the sender_endpoint object
1166 * is retained by the caller, which must guarantee that it is valid until the
1167 * completion handler is called.
1168 *
1169 * @param flags Flags specifying how the receive call is to be made.
1170 *
1171 * @param token The @ref completion_token that will be used to produce a
1172 * completion handler, which will be called when the receive completes.
1173 * Potential completion tokens include @ref use_future, @ref use_awaitable,
1174 * @ref yield_context, or a function object with the correct completion
1175 * signature. The function signature of the completion handler must be:
1176 * @code void handler(
1177 * const boost::system::error_code& error, // Result of operation.
1178 * std::size_t bytes_transferred // Number of bytes received.
1179 * ); @endcode
1180 * Regardless of whether the asynchronous operation completes immediately or
1181 * not, the completion handler will not be invoked from within this function.
1182 * On immediate completion, invocation of the handler will be performed in a
1183 * manner equivalent to using boost::asio::post().
1184 *
1185 * @par Completion Signature
1186 * @code void(boost::system::error_code, std::size_t) @endcode
1187 *
1188 * @par Per-Operation Cancellation
1189 * On POSIX or Windows operating systems, this asynchronous operation supports
1190 * cancellation for the following boost::asio::cancellation_type values:
1191 *
1192 * @li @c cancellation_type::terminal
1193 *
1194 * @li @c cancellation_type::partial
1195 *
1196 * @li @c cancellation_type::total
1197 */
1198 template <typename MutableBufferSequence,
1199 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1200 std::size_t)) ReadToken = default_completion_token_t<executor_type>>
1201 auto async_receive_from(const MutableBufferSequence& buffers,
1202 endpoint_type& sender_endpoint, socket_base::message_flags flags,
1203 ReadToken&& token = default_completion_token_t<executor_type>())
1204 -> decltype(
1205 async_initiate<ReadToken,
1206 void (boost::system::error_code, std::size_t)>(
1207 declval<initiate_async_receive_from>(), token,
1208 buffers, &sender_endpoint, flags))
1209 {
1210 return async_initiate<ReadToken,
1211 void (boost::system::error_code, std::size_t)>(
1212 initiate_async_receive_from(this), token,
1213 buffers, &sender_endpoint, flags);
1214 }
1215
1216private:
1217 // Disallow copying and assignment.
1218 basic_datagram_socket(const basic_datagram_socket&) = delete;
1219 basic_datagram_socket& operator=(
1220 const basic_datagram_socket&) = delete;
1221
1222 class initiate_async_send
1223 {
1224 public:
1225 typedef Executor executor_type;
1226
1227 explicit initiate_async_send(basic_datagram_socket* self)
1228 : self_(self)
1229 {
1230 }
1231
1232 const executor_type& get_executor() const noexcept
1233 {
1234 return self_->get_executor();
1235 }
1236
1237 template <typename WriteHandler, typename ConstBufferSequence>
1238 void operator()(WriteHandler&& handler,
1239 const ConstBufferSequence& buffers,
1240 socket_base::message_flags flags) const
1241 {
1242 // If you get an error on the following line it means that your handler
1243 // does not meet the documented type requirements for a WriteHandler.
1244 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
1245
1246 detail::non_const_lvalue<WriteHandler> handler2(handler);
1247 self_->impl_.get_service().async_send(
1248 self_->impl_.get_implementation(), buffers, flags,
1249 handler2.value, self_->impl_.get_executor());
1250 }
1251
1252 private:
1253 basic_datagram_socket* self_;
1254 };
1255
1256 class initiate_async_send_to
1257 {
1258 public:
1259 typedef Executor executor_type;
1260
1261 explicit initiate_async_send_to(basic_datagram_socket* self)
1262 : self_(self)
1263 {
1264 }
1265
1266 const executor_type& get_executor() const noexcept
1267 {
1268 return self_->get_executor();
1269 }
1270
1271 template <typename WriteHandler, typename ConstBufferSequence>
1272 void operator()(WriteHandler&& handler,
1273 const ConstBufferSequence& buffers, const endpoint_type& destination,
1274 socket_base::message_flags flags) const
1275 {
1276 // If you get an error on the following line it means that your handler
1277 // does not meet the documented type requirements for a WriteHandler.
1278 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
1279
1280 detail::non_const_lvalue<WriteHandler> handler2(handler);
1281 self_->impl_.get_service().async_send_to(
1282 self_->impl_.get_implementation(), buffers, destination,
1283 flags, handler2.value, self_->impl_.get_executor());
1284 }
1285
1286 private:
1287 basic_datagram_socket* self_;
1288 };
1289
1290 class initiate_async_receive
1291 {
1292 public:
1293 typedef Executor executor_type;
1294
1295 explicit initiate_async_receive(basic_datagram_socket* self)
1296 : self_(self)
1297 {
1298 }
1299
1300 const executor_type& get_executor() const noexcept
1301 {
1302 return self_->get_executor();
1303 }
1304
1305 template <typename ReadHandler, typename MutableBufferSequence>
1306 void operator()(ReadHandler&& handler,
1307 const MutableBufferSequence& buffers,
1308 socket_base::message_flags flags) const
1309 {
1310 // If you get an error on the following line it means that your handler
1311 // does not meet the documented type requirements for a ReadHandler.
1312 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1313
1314 detail::non_const_lvalue<ReadHandler> handler2(handler);
1315 self_->impl_.get_service().async_receive(
1316 self_->impl_.get_implementation(), buffers, flags,
1317 handler2.value, self_->impl_.get_executor());
1318 }
1319
1320 private:
1321 basic_datagram_socket* self_;
1322 };
1323
1324 class initiate_async_receive_from
1325 {
1326 public:
1327 typedef Executor executor_type;
1328
1329 explicit initiate_async_receive_from(basic_datagram_socket* self)
1330 : self_(self)
1331 {
1332 }
1333
1334 const executor_type& get_executor() const noexcept
1335 {
1336 return self_->get_executor();
1337 }
1338
1339 template <typename ReadHandler, typename MutableBufferSequence>
1340 void operator()(ReadHandler&& handler,
1341 const MutableBufferSequence& buffers, endpoint_type* sender_endpoint,
1342 socket_base::message_flags flags) const
1343 {
1344 // If you get an error on the following line it means that your handler
1345 // does not meet the documented type requirements for a ReadHandler.
1346 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1347
1348 detail::non_const_lvalue<ReadHandler> handler2(handler);
1349 self_->impl_.get_service().async_receive_from(
1350 self_->impl_.get_implementation(), buffers, *sender_endpoint,
1351 flags, handler2.value, self_->impl_.get_executor());
1352 }
1353
1354 private:
1355 basic_datagram_socket* self_;
1356 };
1357};
1358
1359} // namespace asio
1360} // namespace boost
1361
1362#include <boost/asio/detail/pop_options.hpp>
1363
1364#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
1365

source code of boost/libs/asio/include/boost/asio/basic_datagram_socket.hpp