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