1 //
2 // basic_datagram_socket.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2018 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 ASIO_BASIC_DATAGRAM_SOCKET_HPP
12 #define 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 "asio/detail/config.hpp"
19 #include <cstddef>
20 #include "asio/basic_socket.hpp"
21 #include "asio/detail/handler_type_requirements.hpp"
22 #include "asio/detail/throw_error.hpp"
23 #include "asio/detail/type_traits.hpp"
24 #include "asio/error.hpp"
25 
26 #if defined(ASIO_ENABLE_OLD_SERVICES)
27 # include "asio/datagram_socket_service.hpp"
28 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
29 
30 #include "asio/detail/push_options.hpp"
31 
32 namespace asio {
33 
34 /// Provides datagram-oriented socket functionality.
35 /**
36  * The basic_datagram_socket class template provides asynchronous and blocking
37  * datagram-oriented socket functionality.
38  *
39  * @par Thread Safety
40  * @e Distinct @e objects: Safe.@n
41  * @e Shared @e objects: Unsafe.
42  */
43 template <typename Protocol
44     ASIO_SVC_TPARAM_DEF1(= datagram_socket_service<Protocol>)>
45 class basic_datagram_socket
46   : public basic_socket<Protocol ASIO_SVC_TARG>
47 {
48 public:
49   /// The native representation of a socket.
50 #if defined(GENERATING_DOCUMENTATION)
51   typedef implementation_defined native_handle_type;
52 #else
53   typedef typename basic_socket<
54     Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type;
55 #endif
56 
57   /// The protocol type.
58   typedef Protocol protocol_type;
59 
60   /// The endpoint type.
61   typedef typename Protocol::endpoint endpoint_type;
62 
63   /// Construct a basic_datagram_socket without opening it.
64   /**
65    * This constructor creates a datagram socket without opening it. The open()
66    * function must be called before data can be sent or received on the socket.
67    *
68    * @param io_context The io_context object that the datagram socket will use
69    * to dispatch handlers for any asynchronous operations performed on the
70    * socket.
71    */
basic_datagram_socket(asio::io_context & io_context)72   explicit basic_datagram_socket(asio::io_context& io_context)
73     : basic_socket<Protocol ASIO_SVC_TARG>(io_context)
74   {
75   }
76 
77   /// Construct and open a basic_datagram_socket.
78   /**
79    * This constructor creates and opens a datagram socket.
80    *
81    * @param io_context The io_context object that the datagram socket will use
82    * to dispatch handlers for any asynchronous operations performed on the
83    * socket.
84    *
85    * @param protocol An object specifying protocol parameters to be used.
86    *
87    * @throws asio::system_error Thrown on failure.
88    */
basic_datagram_socket(asio::io_context & io_context,const protocol_type & protocol)89   basic_datagram_socket(asio::io_context& io_context,
90       const protocol_type& protocol)
91     : basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol)
92   {
93   }
94 
95   /// Construct a basic_datagram_socket, opening it and binding it to the given
96   /// local endpoint.
97   /**
98    * This constructor creates a datagram socket and automatically opens it bound
99    * to the specified endpoint on the local machine. The protocol used is the
100    * protocol associated with the given endpoint.
101    *
102    * @param io_context The io_context object that the datagram socket will use
103    * to dispatch handlers for any asynchronous operations performed on the
104    * socket.
105    *
106    * @param endpoint An endpoint on the local machine to which the datagram
107    * socket will be bound.
108    *
109    * @throws asio::system_error Thrown on failure.
110    */
basic_datagram_socket(asio::io_context & io_context,const endpoint_type & endpoint)111   basic_datagram_socket(asio::io_context& io_context,
112       const endpoint_type& endpoint)
113     : basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint)
114   {
115   }
116 
117   /// Construct a basic_datagram_socket on an existing native socket.
118   /**
119    * This constructor creates a datagram socket object to hold an existing
120    * native socket.
121    *
122    * @param io_context The io_context object that the datagram socket will use
123    * to dispatch handlers for any asynchronous operations performed on the
124    * socket.
125    *
126    * @param protocol An object specifying protocol parameters to be used.
127    *
128    * @param native_socket The new underlying socket implementation.
129    *
130    * @throws asio::system_error Thrown on failure.
131    */
basic_datagram_socket(asio::io_context & io_context,const protocol_type & protocol,const native_handle_type & native_socket)132   basic_datagram_socket(asio::io_context& io_context,
133       const protocol_type& protocol, const native_handle_type& native_socket)
134     : basic_socket<Protocol ASIO_SVC_TARG>(
135         io_context, protocol, native_socket)
136   {
137   }
138 
139 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
140   /// Move-construct a basic_datagram_socket from another.
141   /**
142    * This constructor moves a datagram socket from one object to another.
143    *
144    * @param other The other basic_datagram_socket object from which the move
145    * will occur.
146    *
147    * @note Following the move, the moved-from object is in the same state as if
148    * constructed using the @c basic_datagram_socket(io_context&) constructor.
149    */
basic_datagram_socket(basic_datagram_socket && other)150   basic_datagram_socket(basic_datagram_socket&& other)
151     : basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
152   {
153   }
154 
155   /// Move-assign a basic_datagram_socket from another.
156   /**
157    * This assignment operator moves a datagram socket from one object to
158    * another.
159    *
160    * @param other The other basic_datagram_socket object from which the move
161    * will occur.
162    *
163    * @note Following the move, the moved-from object is in the same state as if
164    * constructed using the @c basic_datagram_socket(io_context&) constructor.
165    */
operator =(basic_datagram_socket && other)166   basic_datagram_socket& operator=(basic_datagram_socket&& other)
167   {
168     basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
169     return *this;
170   }
171 
172   /// Move-construct a basic_datagram_socket from a socket of another protocol
173   /// type.
174   /**
175    * This constructor moves a datagram socket from one object to another.
176    *
177    * @param other The other basic_datagram_socket object from which the move
178    * will occur.
179    *
180    * @note Following the move, the moved-from object is in the same state as if
181    * constructed using the @c basic_datagram_socket(io_context&) constructor.
182    */
183   template <typename Protocol1 ASIO_SVC_TPARAM1>
basic_datagram_socket(basic_datagram_socket<Protocol1 ASIO_SVC_TARG1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)184   basic_datagram_socket(
185       basic_datagram_socket<Protocol1 ASIO_SVC_TARG1>&& other,
186       typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
187     : basic_socket<Protocol ASIO_SVC_TARG>(std::move(other))
188   {
189   }
190 
191   /// Move-assign a basic_datagram_socket from a socket of another protocol
192   /// type.
193   /**
194    * This assignment operator moves a datagram socket from one object to
195    * another.
196    *
197    * @param other The other basic_datagram_socket object from which the move
198    * will occur.
199    *
200    * @note Following the move, the moved-from object is in the same state as if
201    * constructed using the @c basic_datagram_socket(io_context&) constructor.
202    */
203   template <typename Protocol1 ASIO_SVC_TPARAM1>
204   typename enable_if<is_convertible<Protocol1, Protocol>::value,
operator =(basic_datagram_socket<Protocol1 ASIO_SVC_TARG1> && other)205       basic_datagram_socket>::type& operator=(
206         basic_datagram_socket<Protocol1 ASIO_SVC_TARG1>&& other)
207   {
208     basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other));
209     return *this;
210   }
211 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
212 
213   /// Destroys the socket.
214   /**
215    * This function destroys the socket, cancelling any outstanding asynchronous
216    * operations associated with the socket as if by calling @c cancel.
217    */
~basic_datagram_socket()218   ~basic_datagram_socket()
219   {
220   }
221 
222   /// Send some data on a connected socket.
223   /**
224    * This function is used to send data on the datagram socket. The function
225    * call will block until the data has been sent successfully or an error
226    * occurs.
227    *
228    * @param buffers One ore more data buffers to be sent on the socket.
229    *
230    * @returns The number of bytes sent.
231    *
232    * @throws asio::system_error Thrown on failure.
233    *
234    * @note The send operation can only be used with a connected socket. Use
235    * the send_to function to send data on an unconnected datagram socket.
236    *
237    * @par Example
238    * To send a single data buffer use the @ref buffer function as follows:
239    * @code socket.send(asio::buffer(data, size)); @endcode
240    * See the @ref buffer documentation for information on sending multiple
241    * buffers in one go, and how to use it with arrays, boost::array or
242    * std::vector.
243    */
244   template <typename ConstBufferSequence>
send(const ConstBufferSequence & buffers)245   std::size_t send(const ConstBufferSequence& buffers)
246   {
247     asio::error_code ec;
248     std::size_t s = this->get_service().send(
249         this->get_implementation(), buffers, 0, ec);
250     asio::detail::throw_error(ec, "send");
251     return s;
252   }
253 
254   /// Send some data on a connected socket.
255   /**
256    * This function is used to send data on the datagram socket. The function
257    * call will block until the data has been sent successfully or an error
258    * occurs.
259    *
260    * @param buffers One ore more data buffers to be sent on the socket.
261    *
262    * @param flags Flags specifying how the send call is to be made.
263    *
264    * @returns The number of bytes sent.
265    *
266    * @throws asio::system_error Thrown on failure.
267    *
268    * @note The send operation can only be used with a connected socket. Use
269    * the send_to function to send data on an unconnected datagram socket.
270    */
271   template <typename ConstBufferSequence>
send(const ConstBufferSequence & buffers,socket_base::message_flags flags)272   std::size_t send(const ConstBufferSequence& buffers,
273       socket_base::message_flags flags)
274   {
275     asio::error_code ec;
276     std::size_t s = this->get_service().send(
277         this->get_implementation(), buffers, flags, ec);
278     asio::detail::throw_error(ec, "send");
279     return s;
280   }
281 
282   /// Send some data on a connected socket.
283   /**
284    * This function is used to send data on the datagram socket. The function
285    * call will block until the data has been sent successfully or an error
286    * occurs.
287    *
288    * @param buffers One or more data buffers to be sent on the socket.
289    *
290    * @param flags Flags specifying how the send call is to be made.
291    *
292    * @param ec Set to indicate what error occurred, if any.
293    *
294    * @returns The number of bytes sent.
295    *
296    * @note The send operation can only be used with a connected socket. Use
297    * the send_to function to send data on an unconnected datagram socket.
298    */
299   template <typename ConstBufferSequence>
send(const ConstBufferSequence & buffers,socket_base::message_flags flags,asio::error_code & ec)300   std::size_t send(const ConstBufferSequence& buffers,
301       socket_base::message_flags flags, asio::error_code& ec)
302   {
303     return this->get_service().send(
304         this->get_implementation(), buffers, flags, ec);
305   }
306 
307   /// Start an asynchronous send on a connected socket.
308   /**
309    * This function is used to asynchronously send data on the datagram socket.
310    * The function call always returns immediately.
311    *
312    * @param buffers One or more data buffers to be sent on the socket. Although
313    * the buffers object may be copied as necessary, ownership of the underlying
314    * memory blocks is retained by the caller, which must guarantee that they
315    * remain valid until the handler is called.
316    *
317    * @param handler The handler to be called when the send operation completes.
318    * Copies will be made of the handler as required. The function signature of
319    * the handler must be:
320    * @code void handler(
321    *   const asio::error_code& error, // Result of operation.
322    *   std::size_t bytes_transferred           // Number of bytes sent.
323    * ); @endcode
324    * Regardless of whether the asynchronous operation completes immediately or
325    * not, the handler will not be invoked from within this function. Invocation
326    * of the handler will be performed in a manner equivalent to using
327    * asio::io_context::post().
328    *
329    * @note The async_send operation can only be used with a connected socket.
330    * Use the async_send_to function to send data on an unconnected datagram
331    * socket.
332    *
333    * @par Example
334    * To send a single data buffer use the @ref buffer function as follows:
335    * @code
336    * socket.async_send(asio::buffer(data, size), handler);
337    * @endcode
338    * See the @ref buffer documentation for information on sending multiple
339    * buffers in one go, and how to use it with arrays, boost::array or
340    * std::vector.
341    */
342   template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))343   ASIO_INITFN_RESULT_TYPE(WriteHandler,
344       void (asio::error_code, std::size_t))
345   async_send(const ConstBufferSequence& buffers,
346       ASIO_MOVE_ARG(WriteHandler) handler)
347   {
348     // If you get an error on the following line it means that your handler does
349     // not meet the documented type requirements for a WriteHandler.
350     ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
351 
352 #if defined(ASIO_ENABLE_OLD_SERVICES)
353     return this->get_service().async_send(this->get_implementation(),
354         buffers, 0, ASIO_MOVE_CAST(WriteHandler)(handler));
355 #else // defined(ASIO_ENABLE_OLD_SERVICES)
356     async_completion<WriteHandler,
357       void (asio::error_code, std::size_t)> init(handler);
358 
359     this->get_service().async_send(this->get_implementation(),
360         buffers, 0, init.completion_handler);
361 
362     return init.result.get();
363 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
364   }
365 
366   /// Start an asynchronous send on a connected socket.
367   /**
368    * This function is used to asynchronously send data on the datagram socket.
369    * The function call always returns immediately.
370    *
371    * @param buffers One or more data buffers to be sent on the socket. Although
372    * the buffers object may be copied as necessary, ownership of the underlying
373    * memory blocks is retained by the caller, which must guarantee that they
374    * remain valid until the handler is called.
375    *
376    * @param flags Flags specifying how the send call is to be made.
377    *
378    * @param handler The handler to be called when the send operation completes.
379    * Copies will be made of the handler as required. The function signature of
380    * the handler must be:
381    * @code void handler(
382    *   const asio::error_code& error, // Result of operation.
383    *   std::size_t bytes_transferred           // Number of bytes sent.
384    * ); @endcode
385    * Regardless of whether the asynchronous operation completes immediately or
386    * not, the handler will not be invoked from within this function. Invocation
387    * of the handler will be performed in a manner equivalent to using
388    * asio::io_context::post().
389    *
390    * @note The async_send operation can only be used with a connected socket.
391    * Use the async_send_to function to send data on an unconnected datagram
392    * socket.
393    */
394   template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))395   ASIO_INITFN_RESULT_TYPE(WriteHandler,
396       void (asio::error_code, std::size_t))
397   async_send(const ConstBufferSequence& buffers,
398       socket_base::message_flags flags,
399       ASIO_MOVE_ARG(WriteHandler) handler)
400   {
401     // If you get an error on the following line it means that your handler does
402     // not meet the documented type requirements for a WriteHandler.
403     ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
404 
405 #if defined(ASIO_ENABLE_OLD_SERVICES)
406     return this->get_service().async_send(this->get_implementation(),
407         buffers, flags, ASIO_MOVE_CAST(WriteHandler)(handler));
408 #else // defined(ASIO_ENABLE_OLD_SERVICES)
409     async_completion<WriteHandler,
410       void (asio::error_code, std::size_t)> init(handler);
411 
412     this->get_service().async_send(this->get_implementation(),
413         buffers, flags, init.completion_handler);
414 
415     return init.result.get();
416 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
417   }
418 
419   /// Send a datagram to the specified endpoint.
420   /**
421    * This function is used to send a datagram to the specified remote endpoint.
422    * The function call will block until the data has been sent successfully or
423    * an error occurs.
424    *
425    * @param buffers One or more data buffers to be sent to the remote endpoint.
426    *
427    * @param destination The remote endpoint to which the data will be sent.
428    *
429    * @returns The number of bytes sent.
430    *
431    * @throws asio::system_error Thrown on failure.
432    *
433    * @par Example
434    * To send a single data buffer use the @ref buffer function as follows:
435    * @code
436    * asio::ip::udp::endpoint destination(
437    *     asio::ip::address::from_string("1.2.3.4"), 12345);
438    * socket.send_to(asio::buffer(data, size), destination);
439    * @endcode
440    * See the @ref buffer documentation for information on sending multiple
441    * buffers in one go, and how to use it with arrays, boost::array or
442    * std::vector.
443    */
444   template <typename ConstBufferSequence>
send_to(const ConstBufferSequence & buffers,const endpoint_type & destination)445   std::size_t send_to(const ConstBufferSequence& buffers,
446       const endpoint_type& destination)
447   {
448     asio::error_code ec;
449     std::size_t s = this->get_service().send_to(
450         this->get_implementation(), buffers, destination, 0, ec);
451     asio::detail::throw_error(ec, "send_to");
452     return s;
453   }
454 
455   /// Send a datagram to the specified endpoint.
456   /**
457    * This function is used to send a datagram to the specified remote endpoint.
458    * The function call will block until the data has been sent successfully or
459    * an error occurs.
460    *
461    * @param buffers One or more data buffers to be sent to the remote endpoint.
462    *
463    * @param destination The remote endpoint to which the data will be sent.
464    *
465    * @param flags Flags specifying how the send call is to be made.
466    *
467    * @returns The number of bytes sent.
468    *
469    * @throws asio::system_error Thrown on failure.
470    */
471   template <typename ConstBufferSequence>
send_to(const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags)472   std::size_t send_to(const ConstBufferSequence& buffers,
473       const endpoint_type& destination, socket_base::message_flags flags)
474   {
475     asio::error_code ec;
476     std::size_t s = this->get_service().send_to(
477         this->get_implementation(), buffers, destination, flags, ec);
478     asio::detail::throw_error(ec, "send_to");
479     return s;
480   }
481 
482   /// Send a datagram to the specified endpoint.
483   /**
484    * This function is used to send a datagram to the specified remote endpoint.
485    * The function call will block until the data has been sent successfully or
486    * an error occurs.
487    *
488    * @param buffers One or more data buffers to be sent to the remote endpoint.
489    *
490    * @param destination The remote endpoint to which the data will be sent.
491    *
492    * @param flags Flags specifying how the send call is to be made.
493    *
494    * @param ec Set to indicate what error occurred, if any.
495    *
496    * @returns The number of bytes sent.
497    */
498   template <typename ConstBufferSequence>
send_to(const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags,asio::error_code & ec)499   std::size_t send_to(const ConstBufferSequence& buffers,
500       const endpoint_type& destination, socket_base::message_flags flags,
501       asio::error_code& ec)
502   {
503     return this->get_service().send_to(this->get_implementation(),
504         buffers, destination, flags, ec);
505   }
506 
507   /// Start an asynchronous send.
508   /**
509    * This function is used to asynchronously send a datagram to the specified
510    * remote endpoint. The function call always returns immediately.
511    *
512    * @param buffers One or more data buffers to be sent to the remote endpoint.
513    * Although the buffers object may be copied as necessary, ownership of the
514    * underlying memory blocks is retained by the caller, which must guarantee
515    * that they remain valid until the handler is called.
516    *
517    * @param destination The remote endpoint to which the data will be sent.
518    * Copies will be made of the endpoint as required.
519    *
520    * @param handler The handler to be called when the send operation completes.
521    * Copies will be made of the handler as required. The function signature of
522    * the handler must be:
523    * @code void handler(
524    *   const asio::error_code& error, // Result of operation.
525    *   std::size_t bytes_transferred           // Number of bytes sent.
526    * ); @endcode
527    * Regardless of whether the asynchronous operation completes immediately or
528    * not, the handler will not be invoked from within this function. Invocation
529    * of the handler will be performed in a manner equivalent to using
530    * asio::io_context::post().
531    *
532    * @par Example
533    * To send a single data buffer use the @ref buffer function as follows:
534    * @code
535    * asio::ip::udp::endpoint destination(
536    *     asio::ip::address::from_string("1.2.3.4"), 12345);
537    * socket.async_send_to(
538    *     asio::buffer(data, size), destination, handler);
539    * @endcode
540    * See the @ref buffer documentation for information on sending multiple
541    * buffers in one go, and how to use it with arrays, boost::array or
542    * std::vector.
543    */
544   template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))545   ASIO_INITFN_RESULT_TYPE(WriteHandler,
546       void (asio::error_code, std::size_t))
547   async_send_to(const ConstBufferSequence& buffers,
548       const endpoint_type& destination,
549       ASIO_MOVE_ARG(WriteHandler) handler)
550   {
551     // If you get an error on the following line it means that your handler does
552     // not meet the documented type requirements for a WriteHandler.
553     ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
554 
555 #if defined(ASIO_ENABLE_OLD_SERVICES)
556     return this->get_service().async_send_to(
557         this->get_implementation(), buffers, destination, 0,
558         ASIO_MOVE_CAST(WriteHandler)(handler));
559 #else // defined(ASIO_ENABLE_OLD_SERVICES)
560     async_completion<WriteHandler,
561       void (asio::error_code, std::size_t)> init(handler);
562 
563     this->get_service().async_send_to(
564         this->get_implementation(), buffers, destination, 0,
565         init.completion_handler);
566 
567     return init.result.get();
568 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
569   }
570 
571   /// Start an asynchronous send.
572   /**
573    * This function is used to asynchronously send a datagram to the specified
574    * remote endpoint. The function call always returns immediately.
575    *
576    * @param buffers One or more data buffers to be sent to the remote endpoint.
577    * Although the buffers object may be copied as necessary, ownership of the
578    * underlying memory blocks is retained by the caller, which must guarantee
579    * that they remain valid until the handler is called.
580    *
581    * @param flags Flags specifying how the send call is to be made.
582    *
583    * @param destination The remote endpoint to which the data will be sent.
584    * Copies will be made of the endpoint as required.
585    *
586    * @param handler The handler to be called when the send operation completes.
587    * Copies will be made of the handler as required. The function signature of
588    * the handler must be:
589    * @code void handler(
590    *   const asio::error_code& error, // Result of operation.
591    *   std::size_t bytes_transferred           // Number of bytes sent.
592    * ); @endcode
593    * Regardless of whether the asynchronous operation completes immediately or
594    * not, the handler will not be invoked from within this function. Invocation
595    * of the handler will be performed in a manner equivalent to using
596    * asio::io_context::post().
597    */
598   template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))599   ASIO_INITFN_RESULT_TYPE(WriteHandler,
600       void (asio::error_code, std::size_t))
601   async_send_to(const ConstBufferSequence& buffers,
602       const endpoint_type& destination, socket_base::message_flags flags,
603       ASIO_MOVE_ARG(WriteHandler) handler)
604   {
605     // If you get an error on the following line it means that your handler does
606     // not meet the documented type requirements for a WriteHandler.
607     ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
608 
609 #if defined(ASIO_ENABLE_OLD_SERVICES)
610     return this->get_service().async_send_to(
611         this->get_implementation(), buffers, destination, flags,
612         ASIO_MOVE_CAST(WriteHandler)(handler));
613 #else // defined(ASIO_ENABLE_OLD_SERVICES)
614     async_completion<WriteHandler,
615       void (asio::error_code, std::size_t)> init(handler);
616 
617     this->get_service().async_send_to(
618         this->get_implementation(), buffers, destination, flags,
619         init.completion_handler);
620 
621     return init.result.get();
622 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
623   }
624 
625   /// Receive some data on a connected socket.
626   /**
627    * This function is used to receive data on the datagram socket. The function
628    * call will block until data has been received successfully or an error
629    * occurs.
630    *
631    * @param buffers One or more buffers into which the data will be received.
632    *
633    * @returns The number of bytes received.
634    *
635    * @throws asio::system_error Thrown on failure.
636    *
637    * @note The receive operation can only be used with a connected socket. Use
638    * the receive_from function to receive data on an unconnected datagram
639    * socket.
640    *
641    * @par Example
642    * To receive into a single data buffer use the @ref buffer function as
643    * follows:
644    * @code socket.receive(asio::buffer(data, size)); @endcode
645    * See the @ref buffer documentation for information on receiving into
646    * multiple buffers in one go, and how to use it with arrays, boost::array or
647    * std::vector.
648    */
649   template <typename MutableBufferSequence>
receive(const MutableBufferSequence & buffers)650   std::size_t receive(const MutableBufferSequence& buffers)
651   {
652     asio::error_code ec;
653     std::size_t s = this->get_service().receive(
654         this->get_implementation(), buffers, 0, ec);
655     asio::detail::throw_error(ec, "receive");
656     return s;
657   }
658 
659   /// Receive some data on a connected socket.
660   /**
661    * This function is used to receive data on the datagram socket. The function
662    * call will block until data has been received successfully or an error
663    * occurs.
664    *
665    * @param buffers One or more buffers into which the data will be received.
666    *
667    * @param flags Flags specifying how the receive call is to be made.
668    *
669    * @returns The number of bytes received.
670    *
671    * @throws asio::system_error Thrown on failure.
672    *
673    * @note The receive operation can only be used with a connected socket. Use
674    * the receive_from function to receive data on an unconnected datagram
675    * socket.
676    */
677   template <typename MutableBufferSequence>
receive(const MutableBufferSequence & buffers,socket_base::message_flags flags)678   std::size_t receive(const MutableBufferSequence& buffers,
679       socket_base::message_flags flags)
680   {
681     asio::error_code ec;
682     std::size_t s = this->get_service().receive(
683         this->get_implementation(), buffers, flags, ec);
684     asio::detail::throw_error(ec, "receive");
685     return s;
686   }
687 
688   /// Receive some data on a connected socket.
689   /**
690    * This function is used to receive data on the datagram socket. The function
691    * call will block until data has been received successfully or an error
692    * occurs.
693    *
694    * @param buffers One or more buffers into which the data will be received.
695    *
696    * @param flags Flags specifying how the receive call is to be made.
697    *
698    * @param ec Set to indicate what error occurred, if any.
699    *
700    * @returns The number of bytes received.
701    *
702    * @note The receive operation can only be used with a connected socket. Use
703    * the receive_from function to receive data on an unconnected datagram
704    * socket.
705    */
706   template <typename MutableBufferSequence>
receive(const MutableBufferSequence & buffers,socket_base::message_flags flags,asio::error_code & ec)707   std::size_t receive(const MutableBufferSequence& buffers,
708       socket_base::message_flags flags, asio::error_code& ec)
709   {
710     return this->get_service().receive(
711         this->get_implementation(), buffers, flags, ec);
712   }
713 
714   /// Start an asynchronous receive on a connected socket.
715   /**
716    * This function is used to asynchronously receive data from the datagram
717    * socket. The function call always returns immediately.
718    *
719    * @param buffers One or more buffers into which the data will be received.
720    * Although the buffers object may be copied as necessary, ownership of the
721    * underlying memory blocks is retained by the caller, which must guarantee
722    * that they remain valid until the handler is called.
723    *
724    * @param handler The handler to be called when the receive operation
725    * completes. Copies will be made of the handler as required. The function
726    * signature of the handler must be:
727    * @code void handler(
728    *   const asio::error_code& error, // Result of operation.
729    *   std::size_t bytes_transferred           // Number of bytes received.
730    * ); @endcode
731    * Regardless of whether the asynchronous operation completes immediately or
732    * not, the handler will not be invoked from within this function. Invocation
733    * of the handler will be performed in a manner equivalent to using
734    * asio::io_context::post().
735    *
736    * @note The async_receive operation can only be used with a connected socket.
737    * Use the async_receive_from function to receive data on an unconnected
738    * datagram socket.
739    *
740    * @par Example
741    * To receive into a single data buffer use the @ref buffer function as
742    * follows:
743    * @code
744    * socket.async_receive(asio::buffer(data, size), handler);
745    * @endcode
746    * See the @ref buffer documentation for information on receiving into
747    * multiple buffers in one go, and how to use it with arrays, boost::array or
748    * std::vector.
749    */
750   template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))751   ASIO_INITFN_RESULT_TYPE(ReadHandler,
752       void (asio::error_code, std::size_t))
753   async_receive(const MutableBufferSequence& buffers,
754       ASIO_MOVE_ARG(ReadHandler) handler)
755   {
756     // If you get an error on the following line it means that your handler does
757     // not meet the documented type requirements for a ReadHandler.
758     ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
759 
760 #if defined(ASIO_ENABLE_OLD_SERVICES)
761     return this->get_service().async_receive(this->get_implementation(),
762         buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler));
763 #else // defined(ASIO_ENABLE_OLD_SERVICES)
764     async_completion<ReadHandler,
765       void (asio::error_code, std::size_t)> init(handler);
766 
767     this->get_service().async_receive(this->get_implementation(),
768         buffers, 0, init.completion_handler);
769 
770     return init.result.get();
771 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
772   }
773 
774   /// Start an asynchronous receive on a connected socket.
775   /**
776    * This function is used to asynchronously receive data from the datagram
777    * socket. The function call always returns immediately.
778    *
779    * @param buffers One or more buffers into which the data will be received.
780    * Although the buffers object may be copied as necessary, ownership of the
781    * underlying memory blocks is retained by the caller, which must guarantee
782    * that they remain valid until the handler is called.
783    *
784    * @param flags Flags specifying how the receive call is to be made.
785    *
786    * @param handler The handler to be called when the receive operation
787    * completes. Copies will be made of the handler as required. The function
788    * signature of the handler must be:
789    * @code void handler(
790    *   const asio::error_code& error, // Result of operation.
791    *   std::size_t bytes_transferred           // Number of bytes received.
792    * ); @endcode
793    * Regardless of whether the asynchronous operation completes immediately or
794    * not, the handler will not be invoked from within this function. Invocation
795    * of the handler will be performed in a manner equivalent to using
796    * asio::io_context::post().
797    *
798    * @note The async_receive operation can only be used with a connected socket.
799    * Use the async_receive_from function to receive data on an unconnected
800    * datagram socket.
801    */
802   template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))803   ASIO_INITFN_RESULT_TYPE(ReadHandler,
804       void (asio::error_code, std::size_t))
805   async_receive(const MutableBufferSequence& buffers,
806       socket_base::message_flags flags,
807       ASIO_MOVE_ARG(ReadHandler) handler)
808   {
809     // If you get an error on the following line it means that your handler does
810     // not meet the documented type requirements for a ReadHandler.
811     ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
812 
813 #if defined(ASIO_ENABLE_OLD_SERVICES)
814     return this->get_service().async_receive(this->get_implementation(),
815         buffers, flags, ASIO_MOVE_CAST(ReadHandler)(handler));
816 #else // defined(ASIO_ENABLE_OLD_SERVICES)
817     async_completion<ReadHandler,
818       void (asio::error_code, std::size_t)> init(handler);
819 
820     this->get_service().async_receive(this->get_implementation(),
821         buffers, flags, init.completion_handler);
822 
823     return init.result.get();
824 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
825   }
826 
827   /// Receive a datagram with the endpoint of the sender.
828   /**
829    * This function is used to receive a datagram. The function call will block
830    * until data has been received successfully or an error occurs.
831    *
832    * @param buffers One or more buffers into which the data will be received.
833    *
834    * @param sender_endpoint An endpoint object that receives the endpoint of
835    * the remote sender of the datagram.
836    *
837    * @returns The number of bytes received.
838    *
839    * @throws asio::system_error Thrown on failure.
840    *
841    * @par Example
842    * To receive into a single data buffer use the @ref buffer function as
843    * follows:
844    * @code
845    * asio::ip::udp::endpoint sender_endpoint;
846    * socket.receive_from(
847    *     asio::buffer(data, size), sender_endpoint);
848    * @endcode
849    * See the @ref buffer documentation for information on receiving into
850    * multiple buffers in one go, and how to use it with arrays, boost::array or
851    * std::vector.
852    */
853   template <typename MutableBufferSequence>
receive_from(const MutableBufferSequence & buffers,endpoint_type & sender_endpoint)854   std::size_t receive_from(const MutableBufferSequence& buffers,
855       endpoint_type& sender_endpoint)
856   {
857     asio::error_code ec;
858     std::size_t s = this->get_service().receive_from(
859         this->get_implementation(), buffers, sender_endpoint, 0, ec);
860     asio::detail::throw_error(ec, "receive_from");
861     return s;
862   }
863 
864   /// Receive a datagram with the endpoint of the sender.
865   /**
866    * This function is used to receive a datagram. The function call will block
867    * until data has been received successfully or an error occurs.
868    *
869    * @param buffers One or more buffers into which the data will be received.
870    *
871    * @param sender_endpoint An endpoint object that receives the endpoint of
872    * the remote sender of the datagram.
873    *
874    * @param flags Flags specifying how the receive call is to be made.
875    *
876    * @returns The number of bytes received.
877    *
878    * @throws asio::system_error Thrown on failure.
879    */
880   template <typename MutableBufferSequence>
receive_from(const MutableBufferSequence & buffers,endpoint_type & sender_endpoint,socket_base::message_flags flags)881   std::size_t receive_from(const MutableBufferSequence& buffers,
882       endpoint_type& sender_endpoint, socket_base::message_flags flags)
883   {
884     asio::error_code ec;
885     std::size_t s = this->get_service().receive_from(
886         this->get_implementation(), buffers, sender_endpoint, flags, ec);
887     asio::detail::throw_error(ec, "receive_from");
888     return s;
889   }
890 
891   /// Receive a datagram with the endpoint of the sender.
892   /**
893    * This function is used to receive a datagram. The function call will block
894    * until data has been received successfully or an error occurs.
895    *
896    * @param buffers One or more buffers into which the data will be received.
897    *
898    * @param sender_endpoint An endpoint object that receives the endpoint of
899    * the remote sender of the datagram.
900    *
901    * @param flags Flags specifying how the receive call is to be made.
902    *
903    * @param ec Set to indicate what error occurred, if any.
904    *
905    * @returns The number of bytes received.
906    */
907   template <typename MutableBufferSequence>
receive_from(const MutableBufferSequence & buffers,endpoint_type & sender_endpoint,socket_base::message_flags flags,asio::error_code & ec)908   std::size_t receive_from(const MutableBufferSequence& buffers,
909       endpoint_type& sender_endpoint, socket_base::message_flags flags,
910       asio::error_code& ec)
911   {
912     return this->get_service().receive_from(this->get_implementation(),
913         buffers, sender_endpoint, flags, ec);
914   }
915 
916   /// Start an asynchronous receive.
917   /**
918    * This function is used to asynchronously receive a datagram. The function
919    * call always returns immediately.
920    *
921    * @param buffers One or more buffers into which the data will be received.
922    * Although the buffers object may be copied as necessary, ownership of the
923    * underlying memory blocks is retained by the caller, which must guarantee
924    * that they remain valid until the handler is called.
925    *
926    * @param sender_endpoint An endpoint object that receives the endpoint of
927    * the remote sender of the datagram. Ownership of the sender_endpoint object
928    * is retained by the caller, which must guarantee that it is valid until the
929    * handler is called.
930    *
931    * @param handler The handler to be called when the receive operation
932    * completes. Copies will be made of the handler as required. The function
933    * signature of the handler must be:
934    * @code void handler(
935    *   const asio::error_code& error, // Result of operation.
936    *   std::size_t bytes_transferred           // Number of bytes received.
937    * ); @endcode
938    * Regardless of whether the asynchronous operation completes immediately or
939    * not, the handler will not be invoked from within this function. Invocation
940    * of the handler will be performed in a manner equivalent to using
941    * asio::io_context::post().
942    *
943    * @par Example
944    * To receive into a single data buffer use the @ref buffer function as
945    * follows:
946    * @code socket.async_receive_from(
947    *     asio::buffer(data, size), sender_endpoint, handler); @endcode
948    * See the @ref buffer documentation for information on receiving into
949    * multiple buffers in one go, and how to use it with arrays, boost::array or
950    * std::vector.
951    */
952   template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))953   ASIO_INITFN_RESULT_TYPE(ReadHandler,
954       void (asio::error_code, std::size_t))
955   async_receive_from(const MutableBufferSequence& buffers,
956       endpoint_type& sender_endpoint,
957       ASIO_MOVE_ARG(ReadHandler) handler)
958   {
959     // If you get an error on the following line it means that your handler does
960     // not meet the documented type requirements for a ReadHandler.
961     ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
962 
963 #if defined(ASIO_ENABLE_OLD_SERVICES)
964     return this->get_service().async_receive_from(
965         this->get_implementation(), buffers, sender_endpoint, 0,
966         ASIO_MOVE_CAST(ReadHandler)(handler));
967 #else // defined(ASIO_ENABLE_OLD_SERVICES)
968     async_completion<ReadHandler,
969       void (asio::error_code, std::size_t)> init(handler);
970 
971     this->get_service().async_receive_from(
972         this->get_implementation(), buffers, sender_endpoint, 0,
973         init.completion_handler);
974 
975     return init.result.get();
976 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
977   }
978 
979   /// Start an asynchronous receive.
980   /**
981    * This function is used to asynchronously receive a datagram. The function
982    * call always returns immediately.
983    *
984    * @param buffers One or more buffers into which the data will be received.
985    * Although the buffers object may be copied as necessary, ownership of the
986    * underlying memory blocks is retained by the caller, which must guarantee
987    * that they remain valid until the handler is called.
988    *
989    * @param sender_endpoint An endpoint object that receives the endpoint of
990    * the remote sender of the datagram. Ownership of the sender_endpoint object
991    * is retained by the caller, which must guarantee that it is valid until the
992    * handler is called.
993    *
994    * @param flags Flags specifying how the receive call is to be made.
995    *
996    * @param handler The handler to be called when the receive operation
997    * completes. Copies will be made of the handler as required. The function
998    * signature of the handler must be:
999    * @code void handler(
1000    *   const asio::error_code& error, // Result of operation.
1001    *   std::size_t bytes_transferred           // Number of bytes received.
1002    * ); @endcode
1003    * Regardless of whether the asynchronous operation completes immediately or
1004    * not, the handler will not be invoked from within this function. Invocation
1005    * of the handler will be performed in a manner equivalent to using
1006    * asio::io_context::post().
1007    */
1008   template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))1009   ASIO_INITFN_RESULT_TYPE(ReadHandler,
1010       void (asio::error_code, std::size_t))
1011   async_receive_from(const MutableBufferSequence& buffers,
1012       endpoint_type& sender_endpoint, socket_base::message_flags flags,
1013       ASIO_MOVE_ARG(ReadHandler) handler)
1014   {
1015     // If you get an error on the following line it means that your handler does
1016     // not meet the documented type requirements for a ReadHandler.
1017     ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1018 
1019 #if defined(ASIO_ENABLE_OLD_SERVICES)
1020     return this->get_service().async_receive_from(
1021         this->get_implementation(), buffers, sender_endpoint, flags,
1022         ASIO_MOVE_CAST(ReadHandler)(handler));
1023 #else // defined(ASIO_ENABLE_OLD_SERVICES)
1024     async_completion<ReadHandler,
1025       void (asio::error_code, std::size_t)> init(handler);
1026 
1027     this->get_service().async_receive_from(
1028         this->get_implementation(), buffers, sender_endpoint, flags,
1029         init.completion_handler);
1030 
1031     return init.result.get();
1032 #endif // defined(ASIO_ENABLE_OLD_SERVICES)
1033   }
1034 };
1035 
1036 } // namespace asio
1037 
1038 #include "asio/detail/pop_options.hpp"
1039 
1040 #endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP
1041