1 //
2 // basic_seq_packet_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_SEQ_PACKET_SOCKET_HPP
12 #define BOOST_ASIO_BASIC_SEQ_PACKET_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/throw_error.hpp>
23 #include <boost/asio/error.hpp>
24 
25 #include <boost/asio/detail/push_options.hpp>
26 
27 namespace boost {
28 namespace asio {
29 
30 #if !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
31 #define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
32 
33 // Forward declaration with defaulted arguments.
34 template <typename Protocol, typename Executor = any_io_executor>
35 class basic_seq_packet_socket;
36 
37 #endif // !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
38 
39 /// Provides sequenced packet socket functionality.
40 /**
41  * The basic_seq_packet_socket class template provides asynchronous and blocking
42  * sequenced packet socket functionality.
43  *
44  * @par Thread Safety
45  * @e Distinct @e objects: Safe.@n
46  * @e Shared @e objects: Unsafe.
47  *
48  * Synchronous @c send, @c receive, and @c connect operations are thread safe
49  * with respect to each other, if the underlying operating system calls are
50  * also thread safe. This means that it is permitted to perform concurrent
51  * calls to these synchronous operations on a single socket object. Other
52  * synchronous operations, such as @c open or @c close, are not thread safe.
53  */
54 template <typename Protocol, typename Executor>
55 class basic_seq_packet_socket
56   : public basic_socket<Protocol, Executor>
57 {
58 public:
59   /// The type of the executor associated with the object.
60   typedef Executor executor_type;
61 
62   /// Rebinds the socket type to another executor.
63   template <typename Executor1>
64   struct rebind_executor
65   {
66     /// The socket type when rebound to the specified executor.
67     typedef basic_seq_packet_socket<Protocol, Executor1> other;
68   };
69 
70   /// The native representation of a socket.
71 #if defined(GENERATING_DOCUMENTATION)
72   typedef implementation_defined native_handle_type;
73 #else
74   typedef typename basic_socket<Protocol,
75     Executor>::native_handle_type native_handle_type;
76 #endif
77 
78   /// The protocol type.
79   typedef Protocol protocol_type;
80 
81   /// The endpoint type.
82   typedef typename Protocol::endpoint endpoint_type;
83 
84   /// Construct a basic_seq_packet_socket without opening it.
85   /**
86    * This constructor creates a sequenced packet socket without opening it. The
87    * socket needs to be opened and then connected or accepted before data can
88    * be sent or received on it.
89    *
90    * @param ex The I/O executor that the socket will use, by default, to
91    * dispatch handlers for any asynchronous operations performed on the socket.
92    */
basic_seq_packet_socket(const executor_type & ex)93   explicit basic_seq_packet_socket(const executor_type& ex)
94     : basic_socket<Protocol, Executor>(ex)
95   {
96   }
97 
98   /// Construct a basic_seq_packet_socket without opening it.
99   /**
100    * This constructor creates a sequenced packet socket without opening it. The
101    * socket needs to be opened and then connected or accepted before data can
102    * be sent or received on it.
103    *
104    * @param context An execution context which provides the I/O executor that
105    * the socket will use, by default, to dispatch handlers for any asynchronous
106    * operations performed on the socket.
107    */
108   template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext & context,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)109   explicit basic_seq_packet_socket(ExecutionContext& context,
110       typename constraint<
111         is_convertible<ExecutionContext&, execution_context&>::value
112       >::type = 0)
113     : basic_socket<Protocol, Executor>(context)
114   {
115   }
116 
117   /// Construct and open a basic_seq_packet_socket.
118   /**
119    * This constructor creates and opens a sequenced_packet socket. The socket
120    * needs to be connected or accepted before data can be sent or received on
121    * it.
122    *
123    * @param ex The I/O executor that the socket will use, by default, to
124    * dispatch handlers for any asynchronous operations performed on the socket.
125    *
126    * @param protocol An object specifying protocol parameters to be used.
127    *
128    * @throws boost::system::system_error Thrown on failure.
129    */
basic_seq_packet_socket(const executor_type & ex,const protocol_type & protocol)130   basic_seq_packet_socket(const executor_type& ex,
131       const protocol_type& protocol)
132     : basic_socket<Protocol, Executor>(ex, protocol)
133   {
134   }
135 
136   /// Construct and open a basic_seq_packet_socket.
137   /**
138    * This constructor creates and opens a sequenced_packet socket. The socket
139    * needs to be connected or accepted before data can be sent or received on
140    * it.
141    *
142    * @param context An execution context which provides the I/O executor that
143    * the socket will use, by default, to dispatch handlers for any asynchronous
144    * operations performed on the socket.
145    *
146    * @param protocol An object specifying protocol parameters to be used.
147    *
148    * @throws boost::system::system_error Thrown on failure.
149    */
150   template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext & context,const protocol_type & protocol,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value,defaulted_constraint>::type=defaulted_constraint ())151   basic_seq_packet_socket(ExecutionContext& context,
152       const protocol_type& protocol,
153       typename constraint<
154         is_convertible<ExecutionContext&, execution_context&>::value,
155         defaulted_constraint
156       >::type = defaulted_constraint())
157     : basic_socket<Protocol, Executor>(context, protocol)
158   {
159   }
160 
161   /// Construct a basic_seq_packet_socket, opening it and binding it to the
162   /// given local endpoint.
163   /**
164    * This constructor creates a sequenced packet socket and automatically opens
165    * it bound to the specified endpoint on the local machine. The protocol used
166    * is the protocol associated with the given endpoint.
167    *
168    * @param ex The I/O executor that the socket will use, by default, to
169    * dispatch handlers for any asynchronous operations performed on the socket.
170    *
171    * @param endpoint An endpoint on the local machine to which the sequenced
172    * packet socket will be bound.
173    *
174    * @throws boost::system::system_error Thrown on failure.
175    */
basic_seq_packet_socket(const executor_type & ex,const endpoint_type & endpoint)176   basic_seq_packet_socket(const executor_type& ex,
177       const endpoint_type& endpoint)
178     : basic_socket<Protocol, Executor>(ex, endpoint)
179   {
180   }
181 
182   /// Construct a basic_seq_packet_socket, opening it and binding it to the
183   /// given local endpoint.
184   /**
185    * This constructor creates a sequenced packet socket and automatically opens
186    * it bound to the specified endpoint on the local machine. The protocol used
187    * is the protocol associated with the given endpoint.
188    *
189    * @param context An execution context which provides the I/O executor that
190    * the socket will use, by default, to dispatch handlers for any asynchronous
191    * operations performed on the socket.
192    *
193    * @param endpoint An endpoint on the local machine to which the sequenced
194    * packet socket will be bound.
195    *
196    * @throws boost::system::system_error Thrown on failure.
197    */
198   template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext & context,const endpoint_type & endpoint,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)199   basic_seq_packet_socket(ExecutionContext& context,
200       const endpoint_type& endpoint,
201       typename constraint<
202         is_convertible<ExecutionContext&, execution_context&>::value
203       >::type = 0)
204     : basic_socket<Protocol, Executor>(context, endpoint)
205   {
206   }
207 
208   /// Construct a basic_seq_packet_socket on an existing native socket.
209   /**
210    * This constructor creates a sequenced packet socket object to hold an
211    * existing native socket.
212    *
213    * @param ex The I/O executor that the socket will use, by default, to
214    * dispatch handlers for any asynchronous operations performed on the socket.
215    *
216    * @param protocol An object specifying protocol parameters to be used.
217    *
218    * @param native_socket The new underlying socket implementation.
219    *
220    * @throws boost::system::system_error Thrown on failure.
221    */
basic_seq_packet_socket(const executor_type & ex,const protocol_type & protocol,const native_handle_type & native_socket)222   basic_seq_packet_socket(const executor_type& ex,
223       const protocol_type& protocol, const native_handle_type& native_socket)
224     : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
225   {
226   }
227 
228   /// Construct a basic_seq_packet_socket on an existing native socket.
229   /**
230    * This constructor creates a sequenced packet socket object to hold an
231    * existing native socket.
232    *
233    * @param context An execution context which provides the I/O executor that
234    * the socket will use, by default, to dispatch handlers for any asynchronous
235    * operations performed on the socket.
236    *
237    * @param protocol An object specifying protocol parameters to be used.
238    *
239    * @param native_socket The new underlying socket implementation.
240    *
241    * @throws boost::system::system_error Thrown on failure.
242    */
243   template <typename ExecutionContext>
basic_seq_packet_socket(ExecutionContext & context,const protocol_type & protocol,const native_handle_type & native_socket,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)244   basic_seq_packet_socket(ExecutionContext& context,
245       const protocol_type& protocol, const native_handle_type& native_socket,
246       typename constraint<
247         is_convertible<ExecutionContext&, execution_context&>::value
248       >::type = 0)
249     : basic_socket<Protocol, Executor>(context, protocol, native_socket)
250   {
251   }
252 
253 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
254   /// Move-construct a basic_seq_packet_socket from another.
255   /**
256    * This constructor moves a sequenced packet socket from one object to
257    * another.
258    *
259    * @param other The other basic_seq_packet_socket object from which the move
260    * will occur.
261    *
262    * @note Following the move, the moved-from object is in the same state as if
263    * constructed using the @c basic_seq_packet_socket(const executor_type&)
264    * constructor.
265    */
basic_seq_packet_socket(basic_seq_packet_socket && other)266   basic_seq_packet_socket(basic_seq_packet_socket&& other) BOOST_ASIO_NOEXCEPT
267     : basic_socket<Protocol, Executor>(std::move(other))
268   {
269   }
270 
271   /// Move-assign a basic_seq_packet_socket from another.
272   /**
273    * This assignment operator moves a sequenced packet socket from one object to
274    * another.
275    *
276    * @param other The other basic_seq_packet_socket object from which the move
277    * will occur.
278    *
279    * @note Following the move, the moved-from object is in the same state as if
280    * constructed using the @c basic_seq_packet_socket(const executor_type&)
281    * constructor.
282    */
operator =(basic_seq_packet_socket && other)283   basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
284   {
285     basic_socket<Protocol, Executor>::operator=(std::move(other));
286     return *this;
287   }
288 
289   /// Move-construct a basic_seq_packet_socket from a socket of another protocol
290   /// type.
291   /**
292    * This constructor moves a sequenced packet socket from one object to
293    * another.
294    *
295    * @param other The other basic_seq_packet_socket object from which the move
296    * will occur.
297    *
298    * @note Following the move, the moved-from object is in the same state as if
299    * constructed using the @c basic_seq_packet_socket(const executor_type&)
300    * constructor.
301    */
302   template <typename Protocol1, typename Executor1>
basic_seq_packet_socket(basic_seq_packet_socket<Protocol1,Executor1> && other,typename constraint<is_convertible<Protocol1,Protocol>::value && is_convertible<Executor1,Executor>::value>::type=0)303   basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
304       typename constraint<
305         is_convertible<Protocol1, Protocol>::value
306           && is_convertible<Executor1, Executor>::value
307       >::type = 0)
308     : basic_socket<Protocol, Executor>(std::move(other))
309   {
310   }
311 
312   /// Move-assign a basic_seq_packet_socket from a socket of another protocol
313   /// type.
314   /**
315    * This assignment operator moves a sequenced packet socket from one object to
316    * another.
317    *
318    * @param other The other basic_seq_packet_socket object from which the move
319    * will occur.
320    *
321    * @note Following the move, the moved-from object is in the same state as if
322    * constructed using the @c basic_seq_packet_socket(const executor_type&)
323    * constructor.
324    */
325   template <typename Protocol1, typename Executor1>
326   typename constraint<
327     is_convertible<Protocol1, Protocol>::value
328       && is_convertible<Executor1, Executor>::value,
329     basic_seq_packet_socket&
operator =(basic_seq_packet_socket<Protocol1,Executor1> && other)330   >::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
331   {
332     basic_socket<Protocol, Executor>::operator=(std::move(other));
333     return *this;
334   }
335 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
336 
337   /// Destroys the socket.
338   /**
339    * This function destroys the socket, cancelling any outstanding asynchronous
340    * operations associated with the socket as if by calling @c cancel.
341    */
~basic_seq_packet_socket()342   ~basic_seq_packet_socket()
343   {
344   }
345 
346   /// Send some data on the socket.
347   /**
348    * This function is used to send data on the sequenced packet socket. The
349    * function call will block until the data has been sent successfully, or an
350    * until error occurs.
351    *
352    * @param buffers One or more data buffers to be sent on the socket.
353    *
354    * @param flags Flags specifying how the send call is to be made.
355    *
356    * @returns The number of bytes sent.
357    *
358    * @throws boost::system::system_error Thrown on failure.
359    *
360    * @par Example
361    * To send a single data buffer use the @ref buffer function as follows:
362    * @code
363    * socket.send(boost::asio::buffer(data, size), 0);
364    * @endcode
365    * See the @ref buffer documentation for information on sending multiple
366    * buffers in one go, and how to use it with arrays, boost::array or
367    * std::vector.
368    */
369   template <typename ConstBufferSequence>
send(const ConstBufferSequence & buffers,socket_base::message_flags flags)370   std::size_t send(const ConstBufferSequence& buffers,
371       socket_base::message_flags flags)
372   {
373     boost::system::error_code ec;
374     std::size_t s = this->impl_.get_service().send(
375         this->impl_.get_implementation(), buffers, flags, ec);
376     boost::asio::detail::throw_error(ec, "send");
377     return s;
378   }
379 
380   /// Send some data on the socket.
381   /**
382    * This function is used to send data on the sequenced packet socket. The
383    * function call will block the data has been sent successfully, or an until
384    * error occurs.
385    *
386    * @param buffers One or more data buffers to be sent on the socket.
387    *
388    * @param flags Flags specifying how the send call is to be made.
389    *
390    * @param ec Set to indicate what error occurred, if any.
391    *
392    * @returns The number of bytes sent. Returns 0 if an error occurred.
393    *
394    * @note The send operation may not transmit all of the data to the peer.
395    * Consider using the @ref write function if you need to ensure that all data
396    * is written before the blocking operation completes.
397    */
398   template <typename ConstBufferSequence>
send(const ConstBufferSequence & buffers,socket_base::message_flags flags,boost::system::error_code & ec)399   std::size_t send(const ConstBufferSequence& buffers,
400       socket_base::message_flags flags, boost::system::error_code& ec)
401   {
402     return this->impl_.get_service().send(
403         this->impl_.get_implementation(), buffers, flags, ec);
404   }
405 
406   /// Start an asynchronous send.
407   /**
408    * This function is used to asynchronously send data on the sequenced packet
409    * socket. The function call always returns immediately.
410    *
411    * @param buffers One or more data buffers to be sent on the socket. Although
412    * the buffers object may be copied as necessary, ownership of the underlying
413    * memory blocks is retained by the caller, which must guarantee that they
414    * remain valid until the handler is called.
415    *
416    * @param flags Flags specifying how the send call is to be made.
417    *
418    * @param handler The handler to be called when the send operation completes.
419    * Copies will be made of the handler as required. The function signature of
420    * the handler must be:
421    * @code void handler(
422    *   const boost::system::error_code& error, // Result of operation.
423    *   std::size_t bytes_transferred           // Number of bytes sent.
424    * ); @endcode
425    * Regardless of whether the asynchronous operation completes immediately or
426    * not, the handler will not be invoked from within this function. On
427    * immediate completion, invocation of the handler will be performed in a
428    * manner equivalent to using boost::asio::post().
429    *
430    * @par Example
431    * To send a single data buffer use the @ref buffer function as follows:
432    * @code
433    * socket.async_send(boost::asio::buffer(data, size), 0, handler);
434    * @endcode
435    * See the @ref buffer documentation for information on sending multiple
436    * buffers in one go, and how to use it with arrays, boost::array or
437    * std::vector.
438    */
439   template <typename ConstBufferSequence,
440       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
441         std::size_t)) WriteHandler
442           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,void (boost::system::error_code,std::size_t))443   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
444       void (boost::system::error_code, std::size_t))
445   async_send(const ConstBufferSequence& buffers,
446       socket_base::message_flags flags,
447       BOOST_ASIO_MOVE_ARG(WriteHandler) handler
448         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
449   {
450     return async_initiate<WriteHandler,
451       void (boost::system::error_code, std::size_t)>(
452         initiate_async_send(this), handler, buffers, flags);
453   }
454 
455   /// Receive some data on the socket.
456   /**
457    * This function is used to receive data on the sequenced packet socket. The
458    * function call will block until data has been received successfully, or
459    * until an error occurs.
460    *
461    * @param buffers One or more buffers into which the data will be received.
462    *
463    * @param out_flags After the receive call completes, contains flags
464    * associated with the received data. For example, if the
465    * socket_base::message_end_of_record bit is set then the received data marks
466    * the end of a record.
467    *
468    * @returns The number of bytes received.
469    *
470    * @throws boost::system::system_error Thrown on failure. An error code of
471    * boost::asio::error::eof indicates that the connection was closed by the
472    * peer.
473    *
474    * @par Example
475    * To receive into a single data buffer use the @ref buffer function as
476    * follows:
477    * @code
478    * socket.receive(boost::asio::buffer(data, size), out_flags);
479    * @endcode
480    * See the @ref buffer documentation for information on receiving into
481    * multiple buffers in one go, and how to use it with arrays, boost::array or
482    * std::vector.
483    */
484   template <typename MutableBufferSequence>
receive(const MutableBufferSequence & buffers,socket_base::message_flags & out_flags)485   std::size_t receive(const MutableBufferSequence& buffers,
486       socket_base::message_flags& out_flags)
487   {
488     boost::system::error_code ec;
489     std::size_t s = this->impl_.get_service().receive_with_flags(
490         this->impl_.get_implementation(), buffers, 0, out_flags, ec);
491     boost::asio::detail::throw_error(ec, "receive");
492     return s;
493   }
494 
495   /// Receive some data on the socket.
496   /**
497    * This function is used to receive data on the sequenced packet socket. The
498    * function call will block until data has been received successfully, or
499    * until an error occurs.
500    *
501    * @param buffers One or more buffers into which the data will be received.
502    *
503    * @param in_flags Flags specifying how the receive call is to be made.
504    *
505    * @param out_flags After the receive call completes, contains flags
506    * associated with the received data. For example, if the
507    * socket_base::message_end_of_record bit is set then the received data marks
508    * the end of a record.
509    *
510    * @returns The number of bytes received.
511    *
512    * @throws boost::system::system_error Thrown on failure. An error code of
513    * boost::asio::error::eof indicates that the connection was closed by the
514    * peer.
515    *
516    * @note The receive operation may not receive all of the requested number of
517    * bytes. Consider using the @ref read function if you need to ensure that the
518    * requested amount of data is read before the blocking operation completes.
519    *
520    * @par Example
521    * To receive into a single data buffer use the @ref buffer function as
522    * follows:
523    * @code
524    * socket.receive(boost::asio::buffer(data, size), 0, out_flags);
525    * @endcode
526    * See the @ref buffer documentation for information on receiving into
527    * multiple buffers in one go, and how to use it with arrays, boost::array or
528    * std::vector.
529    */
530   template <typename MutableBufferSequence>
receive(const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags)531   std::size_t receive(const MutableBufferSequence& buffers,
532       socket_base::message_flags in_flags,
533       socket_base::message_flags& out_flags)
534   {
535     boost::system::error_code ec;
536     std::size_t s = this->impl_.get_service().receive_with_flags(
537         this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
538     boost::asio::detail::throw_error(ec, "receive");
539     return s;
540   }
541 
542   /// Receive some data on a connected socket.
543   /**
544    * This function is used to receive data on the sequenced packet socket. The
545    * function call will block until data has been received successfully, or
546    * until an error occurs.
547    *
548    * @param buffers One or more buffers into which the data will be received.
549    *
550    * @param in_flags Flags specifying how the receive call is to be made.
551    *
552    * @param out_flags After the receive call completes, contains flags
553    * associated with the received data. For example, if the
554    * socket_base::message_end_of_record bit is set then the received data marks
555    * the end of a record.
556    *
557    * @param ec Set to indicate what error occurred, if any.
558    *
559    * @returns The number of bytes received. Returns 0 if an error occurred.
560    *
561    * @note The receive operation may not receive all of the requested number of
562    * bytes. Consider using the @ref read function if you need to ensure that the
563    * requested amount of data is read before the blocking operation completes.
564    */
565   template <typename MutableBufferSequence>
receive(const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags & out_flags,boost::system::error_code & ec)566   std::size_t receive(const MutableBufferSequence& buffers,
567       socket_base::message_flags in_flags,
568       socket_base::message_flags& out_flags, boost::system::error_code& ec)
569   {
570     return this->impl_.get_service().receive_with_flags(
571         this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
572   }
573 
574   /// Start an asynchronous receive.
575   /**
576    * This function is used to asynchronously receive data from the sequenced
577    * packet socket. The function call always returns immediately.
578    *
579    * @param buffers One or more buffers into which the data will be received.
580    * Although the buffers object may be copied as necessary, ownership of the
581    * underlying memory blocks is retained by the caller, which must guarantee
582    * that they remain valid until the handler is called.
583    *
584    * @param out_flags Once the asynchronous operation completes, contains flags
585    * associated with the received data. For example, if the
586    * socket_base::message_end_of_record bit is set then the received data marks
587    * the end of a record. The caller must guarantee that the referenced
588    * variable remains valid until the handler is called.
589    *
590    * @param handler The handler to be called when the receive operation
591    * completes. Copies will be made of the handler as required. The function
592    * signature of the handler must be:
593    * @code void handler(
594    *   const boost::system::error_code& error, // Result of operation.
595    *   std::size_t bytes_transferred           // Number of bytes received.
596    * ); @endcode
597    * Regardless of whether the asynchronous operation completes immediately or
598    * not, the handler will not be invoked from within this function. On
599    * immediate completion, invocation of the handler will be performed in a
600    * manner equivalent to using boost::asio::post().
601    *
602    * @par Example
603    * To receive into a single data buffer use the @ref buffer function as
604    * follows:
605    * @code
606    * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler);
607    * @endcode
608    * See the @ref buffer documentation for information on receiving into
609    * multiple buffers in one go, and how to use it with arrays, boost::array or
610    * std::vector.
611    */
612   template <typename MutableBufferSequence,
613       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
614         std::size_t)) ReadHandler
615           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))616   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
617       void (boost::system::error_code, std::size_t))
618   async_receive(const MutableBufferSequence& buffers,
619       socket_base::message_flags& out_flags,
620       BOOST_ASIO_MOVE_ARG(ReadHandler) handler
621         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
622   {
623     return async_initiate<ReadHandler,
624       void (boost::system::error_code, std::size_t)>(
625         initiate_async_receive_with_flags(this), handler,
626         buffers, socket_base::message_flags(0), &out_flags);
627   }
628 
629   /// Start an asynchronous receive.
630   /**
631    * This function is used to asynchronously receive data from the sequenced
632    * data socket. The function call always returns immediately.
633    *
634    * @param buffers One or more buffers into which the data will be received.
635    * Although the buffers object may be copied as necessary, ownership of the
636    * underlying memory blocks is retained by the caller, which must guarantee
637    * that they remain valid until the handler is called.
638    *
639    * @param in_flags Flags specifying how the receive call is to be made.
640    *
641    * @param out_flags Once the asynchronous operation completes, contains flags
642    * associated with the received data. For example, if the
643    * socket_base::message_end_of_record bit is set then the received data marks
644    * the end of a record. The caller must guarantee that the referenced
645    * variable remains valid until the handler is called.
646    *
647    * @param handler The handler to be called when the receive operation
648    * completes. Copies will be made of the handler as required. The function
649    * signature of the handler must be:
650    * @code void handler(
651    *   const boost::system::error_code& error, // Result of operation.
652    *   std::size_t bytes_transferred           // Number of bytes received.
653    * ); @endcode
654    * Regardless of whether the asynchronous operation completes immediately or
655    * not, the handler will not be invoked from within this function. On
656    * immediate completion, invocation of the handler will be performed in a
657    * manner equivalent to using boost::asio::post().
658    *
659    * @par Example
660    * To receive into a single data buffer use the @ref buffer function as
661    * follows:
662    * @code
663    * socket.async_receive(
664    *     boost::asio::buffer(data, size),
665    *     0, out_flags, handler);
666    * @endcode
667    * See the @ref buffer documentation for information on receiving into
668    * multiple buffers in one go, and how to use it with arrays, boost::array or
669    * std::vector.
670    */
671   template <typename MutableBufferSequence,
672       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
673         std::size_t)) ReadHandler
674           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))675   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
676       void (boost::system::error_code, std::size_t))
677   async_receive(const MutableBufferSequence& buffers,
678       socket_base::message_flags in_flags,
679       socket_base::message_flags& out_flags,
680       BOOST_ASIO_MOVE_ARG(ReadHandler) handler
681         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
682   {
683     return async_initiate<ReadHandler,
684       void (boost::system::error_code, std::size_t)>(
685         initiate_async_receive_with_flags(this),
686         handler, buffers, in_flags, &out_flags);
687   }
688 
689 private:
690   // Disallow copying and assignment.
691   basic_seq_packet_socket(const basic_seq_packet_socket&) BOOST_ASIO_DELETED;
692   basic_seq_packet_socket& operator=(
693       const basic_seq_packet_socket&) BOOST_ASIO_DELETED;
694 
695   class initiate_async_send
696   {
697   public:
698     typedef Executor executor_type;
699 
initiate_async_send(basic_seq_packet_socket * self)700     explicit initiate_async_send(basic_seq_packet_socket* self)
701       : self_(self)
702     {
703     }
704 
get_executor() const705     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
706     {
707       return self_->get_executor();
708     }
709 
710     template <typename WriteHandler, typename ConstBufferSequence>
operator ()(BOOST_ASIO_MOVE_ARG (WriteHandler)handler,const ConstBufferSequence & buffers,socket_base::message_flags flags) const711     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
712         const ConstBufferSequence& buffers,
713         socket_base::message_flags flags) const
714     {
715       // If you get an error on the following line it means that your handler
716       // does not meet the documented type requirements for a WriteHandler.
717       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
718 
719       detail::non_const_lvalue<WriteHandler> handler2(handler);
720       self_->impl_.get_service().async_send(
721           self_->impl_.get_implementation(), buffers, flags,
722           handler2.value, self_->impl_.get_executor());
723     }
724 
725   private:
726     basic_seq_packet_socket* self_;
727   };
728 
729   class initiate_async_receive_with_flags
730   {
731   public:
732     typedef Executor executor_type;
733 
initiate_async_receive_with_flags(basic_seq_packet_socket * self)734     explicit initiate_async_receive_with_flags(basic_seq_packet_socket* self)
735       : self_(self)
736     {
737     }
738 
get_executor() const739     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
740     {
741       return self_->get_executor();
742     }
743 
744     template <typename ReadHandler, typename MutableBufferSequence>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,const MutableBufferSequence & buffers,socket_base::message_flags in_flags,socket_base::message_flags * out_flags) const745     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
746         const MutableBufferSequence& buffers,
747         socket_base::message_flags in_flags,
748         socket_base::message_flags* out_flags) const
749     {
750       // If you get an error on the following line it means that your handler
751       // does not meet the documented type requirements for a ReadHandler.
752       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
753 
754       detail::non_const_lvalue<ReadHandler> handler2(handler);
755       self_->impl_.get_service().async_receive_with_flags(
756           self_->impl_.get_implementation(), buffers, in_flags,
757           *out_flags, handler2.value, self_->impl_.get_executor());
758     }
759 
760   private:
761     basic_seq_packet_socket* self_;
762   };
763 };
764 
765 } // namespace asio
766 } // namespace boost
767 
768 #include <boost/asio/detail/pop_options.hpp>
769 
770 #endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
771