Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:05

0001 //
0002 // basic_seq_packet_socket.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
0012 #define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cstddef>
0020 #include <boost/asio/basic_socket.hpp>
0021 #include <boost/asio/detail/handler_type_requirements.hpp>
0022 #include <boost/asio/detail/throw_error.hpp>
0023 #include <boost/asio/error.hpp>
0024 
0025 #include <boost/asio/detail/push_options.hpp>
0026 
0027 namespace boost {
0028 namespace asio {
0029 
0030 #if !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
0031 #define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
0032 
0033 // Forward declaration with defaulted arguments.
0034 template <typename Protocol, typename Executor = any_io_executor>
0035 class basic_seq_packet_socket;
0036 
0037 #endif // !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
0038 
0039 /// Provides sequenced packet socket functionality.
0040 /**
0041  * The basic_seq_packet_socket class template provides asynchronous and blocking
0042  * sequenced packet socket functionality.
0043  *
0044  * @par Thread Safety
0045  * @e Distinct @e objects: Safe.@n
0046  * @e Shared @e objects: Unsafe.
0047  *
0048  * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are
0049  * thread safe with respect to each other, if the underlying operating system
0050  * calls are also thread safe. This means that it is permitted to perform
0051  * concurrent calls to these synchronous operations on a single socket object.
0052  * Other synchronous operations, such as @c open or @c close, are not thread
0053  * safe.
0054  */
0055 template <typename Protocol, typename Executor>
0056 class basic_seq_packet_socket
0057   : public basic_socket<Protocol, Executor>
0058 {
0059 private:
0060   class initiate_async_send;
0061   class initiate_async_receive_with_flags;
0062 
0063 public:
0064   /// The type of the executor associated with the object.
0065   typedef Executor executor_type;
0066 
0067   /// Rebinds the socket type to another executor.
0068   template <typename Executor1>
0069   struct rebind_executor
0070   {
0071     /// The socket type when rebound to the specified executor.
0072     typedef basic_seq_packet_socket<Protocol, Executor1> other;
0073   };
0074 
0075   /// The native representation of a socket.
0076 #if defined(GENERATING_DOCUMENTATION)
0077   typedef implementation_defined native_handle_type;
0078 #else
0079   typedef typename basic_socket<Protocol,
0080     Executor>::native_handle_type native_handle_type;
0081 #endif
0082 
0083   /// The protocol type.
0084   typedef Protocol protocol_type;
0085 
0086   /// The endpoint type.
0087   typedef typename Protocol::endpoint endpoint_type;
0088 
0089   /// Construct a basic_seq_packet_socket without opening it.
0090   /**
0091    * This constructor creates a sequenced packet socket without opening it. The
0092    * socket needs to be opened and then connected or accepted before data can
0093    * be sent or received on it.
0094    *
0095    * @param ex The I/O executor that the socket will use, by default, to
0096    * dispatch handlers for any asynchronous operations performed on the socket.
0097    */
0098   explicit basic_seq_packet_socket(const executor_type& ex)
0099     : basic_socket<Protocol, Executor>(ex)
0100   {
0101   }
0102 
0103   /// Construct a basic_seq_packet_socket without opening it.
0104   /**
0105    * This constructor creates a sequenced packet socket without opening it. The
0106    * socket needs to be opened and then connected or accepted before data can
0107    * be sent or received on it.
0108    *
0109    * @param context An execution context which provides the I/O executor that
0110    * the socket will use, by default, to dispatch handlers for any asynchronous
0111    * operations performed on the socket.
0112    */
0113   template <typename ExecutionContext>
0114   explicit basic_seq_packet_socket(ExecutionContext& context,
0115       constraint_t<
0116         is_convertible<ExecutionContext&, execution_context&>::value
0117       > = 0)
0118     : basic_socket<Protocol, Executor>(context)
0119   {
0120   }
0121 
0122   /// Construct and open a basic_seq_packet_socket.
0123   /**
0124    * This constructor creates and opens a sequenced_packet socket. The socket
0125    * needs to be connected or accepted before data can be sent or received on
0126    * it.
0127    *
0128    * @param ex The I/O executor that the socket will use, by default, to
0129    * dispatch handlers for any asynchronous operations performed on the socket.
0130    *
0131    * @param protocol An object specifying protocol parameters to be used.
0132    *
0133    * @throws boost::system::system_error Thrown on failure.
0134    */
0135   basic_seq_packet_socket(const executor_type& ex,
0136       const protocol_type& protocol)
0137     : basic_socket<Protocol, Executor>(ex, protocol)
0138   {
0139   }
0140 
0141   /// Construct and open a basic_seq_packet_socket.
0142   /**
0143    * This constructor creates and opens a sequenced_packet socket. The socket
0144    * needs to be connected or accepted before data can be sent or received on
0145    * it.
0146    *
0147    * @param context An execution context which provides the I/O executor that
0148    * the socket will use, by default, to dispatch handlers for any asynchronous
0149    * operations performed on the socket.
0150    *
0151    * @param protocol An object specifying protocol parameters to be used.
0152    *
0153    * @throws boost::system::system_error Thrown on failure.
0154    */
0155   template <typename ExecutionContext>
0156   basic_seq_packet_socket(ExecutionContext& context,
0157       const protocol_type& protocol,
0158       constraint_t<
0159         is_convertible<ExecutionContext&, execution_context&>::value,
0160         defaulted_constraint
0161       > = defaulted_constraint())
0162     : basic_socket<Protocol, Executor>(context, protocol)
0163   {
0164   }
0165 
0166   /// Construct a basic_seq_packet_socket, opening it and binding it to the
0167   /// given local endpoint.
0168   /**
0169    * This constructor creates a sequenced packet socket and automatically opens
0170    * it bound to the specified endpoint on the local machine. The protocol used
0171    * is the protocol associated with the given endpoint.
0172    *
0173    * @param ex The I/O executor that the socket will use, by default, to
0174    * dispatch handlers for any asynchronous operations performed on the socket.
0175    *
0176    * @param endpoint An endpoint on the local machine to which the sequenced
0177    * packet socket will be bound.
0178    *
0179    * @throws boost::system::system_error Thrown on failure.
0180    */
0181   basic_seq_packet_socket(const executor_type& ex,
0182       const endpoint_type& endpoint)
0183     : basic_socket<Protocol, Executor>(ex, endpoint)
0184   {
0185   }
0186 
0187   /// Construct a basic_seq_packet_socket, opening it and binding it to the
0188   /// given local endpoint.
0189   /**
0190    * This constructor creates a sequenced packet socket and automatically opens
0191    * it bound to the specified endpoint on the local machine. The protocol used
0192    * is the protocol associated with the given endpoint.
0193    *
0194    * @param context An execution context which provides the I/O executor that
0195    * the socket will use, by default, to dispatch handlers for any asynchronous
0196    * operations performed on the socket.
0197    *
0198    * @param endpoint An endpoint on the local machine to which the sequenced
0199    * packet socket will be bound.
0200    *
0201    * @throws boost::system::system_error Thrown on failure.
0202    */
0203   template <typename ExecutionContext>
0204   basic_seq_packet_socket(ExecutionContext& context,
0205       const endpoint_type& endpoint,
0206       constraint_t<
0207         is_convertible<ExecutionContext&, execution_context&>::value
0208       > = 0)
0209     : basic_socket<Protocol, Executor>(context, endpoint)
0210   {
0211   }
0212 
0213   /// Construct a basic_seq_packet_socket on an existing native socket.
0214   /**
0215    * This constructor creates a sequenced packet socket object to hold an
0216    * existing native socket.
0217    *
0218    * @param ex The I/O executor that the socket will use, by default, to
0219    * dispatch handlers for any asynchronous operations performed on the socket.
0220    *
0221    * @param protocol An object specifying protocol parameters to be used.
0222    *
0223    * @param native_socket The new underlying socket implementation.
0224    *
0225    * @throws boost::system::system_error Thrown on failure.
0226    */
0227   basic_seq_packet_socket(const executor_type& ex,
0228       const protocol_type& protocol, const native_handle_type& native_socket)
0229     : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
0230   {
0231   }
0232 
0233   /// Construct a basic_seq_packet_socket on an existing native socket.
0234   /**
0235    * This constructor creates a sequenced packet socket object to hold an
0236    * existing native socket.
0237    *
0238    * @param context An execution context which provides the I/O executor that
0239    * the socket will use, by default, to dispatch handlers for any asynchronous
0240    * operations performed on the socket.
0241    *
0242    * @param protocol An object specifying protocol parameters to be used.
0243    *
0244    * @param native_socket The new underlying socket implementation.
0245    *
0246    * @throws boost::system::system_error Thrown on failure.
0247    */
0248   template <typename ExecutionContext>
0249   basic_seq_packet_socket(ExecutionContext& context,
0250       const protocol_type& protocol, const native_handle_type& native_socket,
0251       constraint_t<
0252         is_convertible<ExecutionContext&, execution_context&>::value
0253       > = 0)
0254     : basic_socket<Protocol, Executor>(context, protocol, native_socket)
0255   {
0256   }
0257 
0258   /// Move-construct a basic_seq_packet_socket from another.
0259   /**
0260    * This constructor moves a sequenced packet socket from one object to
0261    * another.
0262    *
0263    * @param other The other basic_seq_packet_socket object from which the move
0264    * will occur.
0265    *
0266    * @note Following the move, the moved-from object is in the same state as if
0267    * constructed using the @c basic_seq_packet_socket(const executor_type&)
0268    * constructor.
0269    */
0270   basic_seq_packet_socket(basic_seq_packet_socket&& other) noexcept
0271     : basic_socket<Protocol, Executor>(std::move(other))
0272   {
0273   }
0274 
0275   /// Move-assign a basic_seq_packet_socket from another.
0276   /**
0277    * This assignment operator moves a sequenced packet socket from one object to
0278    * another.
0279    *
0280    * @param other The other basic_seq_packet_socket object from which the move
0281    * will occur.
0282    *
0283    * @note Following the move, the moved-from object is in the same state as if
0284    * constructed using the @c basic_seq_packet_socket(const executor_type&)
0285    * constructor.
0286    */
0287   basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
0288   {
0289     basic_socket<Protocol, Executor>::operator=(std::move(other));
0290     return *this;
0291   }
0292 
0293   /// Move-construct a basic_seq_packet_socket from a socket of another protocol
0294   /// type.
0295   /**
0296    * This constructor moves a sequenced packet socket from one object to
0297    * another.
0298    *
0299    * @param other The other basic_seq_packet_socket object from which the move
0300    * will occur.
0301    *
0302    * @note Following the move, the moved-from object is in the same state as if
0303    * constructed using the @c basic_seq_packet_socket(const executor_type&)
0304    * constructor.
0305    */
0306   template <typename Protocol1, typename Executor1>
0307   basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
0308       constraint_t<
0309         is_convertible<Protocol1, Protocol>::value
0310           && is_convertible<Executor1, Executor>::value
0311       > = 0)
0312     : basic_socket<Protocol, Executor>(std::move(other))
0313   {
0314   }
0315 
0316   /// Move-assign a basic_seq_packet_socket from a socket of another protocol
0317   /// type.
0318   /**
0319    * This assignment operator moves a sequenced packet socket from one object to
0320    * another.
0321    *
0322    * @param other The other basic_seq_packet_socket object from which the move
0323    * will occur.
0324    *
0325    * @note Following the move, the moved-from object is in the same state as if
0326    * constructed using the @c basic_seq_packet_socket(const executor_type&)
0327    * constructor.
0328    */
0329   template <typename Protocol1, typename Executor1>
0330   constraint_t<
0331     is_convertible<Protocol1, Protocol>::value
0332       && is_convertible<Executor1, Executor>::value,
0333     basic_seq_packet_socket&
0334   > operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
0335   {
0336     basic_socket<Protocol, Executor>::operator=(std::move(other));
0337     return *this;
0338   }
0339 
0340   /// Destroys the socket.
0341   /**
0342    * This function destroys the socket, cancelling any outstanding asynchronous
0343    * operations associated with the socket as if by calling @c cancel.
0344    */
0345   ~basic_seq_packet_socket()
0346   {
0347   }
0348 
0349   /// Send some data on the socket.
0350   /**
0351    * This function is used to send data on the sequenced packet socket. The
0352    * function call will block until the data has been sent successfully, or an
0353    * until error occurs.
0354    *
0355    * @param buffers One or more data buffers to be sent on the socket.
0356    *
0357    * @param flags Flags specifying how the send call is to be made.
0358    *
0359    * @returns The number of bytes sent.
0360    *
0361    * @throws boost::system::system_error Thrown on failure.
0362    *
0363    * @par Example
0364    * To send a single data buffer use the @ref buffer function as follows:
0365    * @code
0366    * socket.send(boost::asio::buffer(data, size), 0);
0367    * @endcode
0368    * See the @ref buffer documentation for information on sending multiple
0369    * buffers in one go, and how to use it with arrays, boost::array or
0370    * std::vector.
0371    */
0372   template <typename ConstBufferSequence>
0373   std::size_t send(const ConstBufferSequence& buffers,
0374       socket_base::message_flags flags)
0375   {
0376     boost::system::error_code ec;
0377     std::size_t s = this->impl_.get_service().send(
0378         this->impl_.get_implementation(), buffers, flags, ec);
0379     boost::asio::detail::throw_error(ec, "send");
0380     return s;
0381   }
0382 
0383   /// Send some data on the socket.
0384   /**
0385    * This function is used to send data on the sequenced packet socket. The
0386    * function call will block the data has been sent successfully, or an until
0387    * error occurs.
0388    *
0389    * @param buffers One or more data buffers to be sent on the socket.
0390    *
0391    * @param flags Flags specifying how the send call is to be made.
0392    *
0393    * @param ec Set to indicate what error occurred, if any.
0394    *
0395    * @returns The number of bytes sent. Returns 0 if an error occurred.
0396    *
0397    * @note The send operation may not transmit all of the data to the peer.
0398    * Consider using the @ref write function if you need to ensure that all data
0399    * is written before the blocking operation completes.
0400    */
0401   template <typename ConstBufferSequence>
0402   std::size_t send(const ConstBufferSequence& buffers,
0403       socket_base::message_flags flags, boost::system::error_code& ec)
0404   {
0405     return this->impl_.get_service().send(
0406         this->impl_.get_implementation(), buffers, flags, ec);
0407   }
0408 
0409   /// Start an asynchronous send.
0410   /**
0411    * This function is used to asynchronously send data on the sequenced packet
0412    * socket. It is an initiating function for an @ref asynchronous_operation,
0413    * and always returns immediately.
0414    *
0415    * @param buffers One or more data buffers to be sent on the socket. Although
0416    * the buffers object may be copied as necessary, ownership of the underlying
0417    * memory blocks is retained by the caller, which must guarantee that they
0418    * remain valid until the completion handler is called.
0419    *
0420    * @param flags Flags specifying how the send call is to be made.
0421    *
0422    * @param token The @ref completion_token that will be used to produce a
0423    * completion handler, which will be called when the send completes.
0424    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0425    * @ref yield_context, or a function object with the correct completion
0426    * signature. The function signature of the completion handler must be:
0427    * @code void handler(
0428    *   const boost::system::error_code& error, // Result of operation.
0429    *   std::size_t bytes_transferred // Number of bytes sent.
0430    * ); @endcode
0431    * Regardless of whether the asynchronous operation completes immediately or
0432    * not, the completion handler will not be invoked from within this function.
0433    * On immediate completion, invocation of the handler will be performed in a
0434    * manner equivalent to using boost::asio::post().
0435    *
0436    * @par Completion Signature
0437    * @code void(boost::system::error_code, std::size_t) @endcode
0438    *
0439    * @par Example
0440    * To send a single data buffer use the @ref buffer function as follows:
0441    * @code
0442    * socket.async_send(boost::asio::buffer(data, size), 0, handler);
0443    * @endcode
0444    * See the @ref buffer documentation for information on sending multiple
0445    * buffers in one go, and how to use it with arrays, boost::array or
0446    * std::vector.
0447    *
0448    * @par Per-Operation Cancellation
0449    * On POSIX or Windows operating systems, this asynchronous operation supports
0450    * cancellation for the following boost::asio::cancellation_type values:
0451    *
0452    * @li @c cancellation_type::terminal
0453    *
0454    * @li @c cancellation_type::partial
0455    *
0456    * @li @c cancellation_type::total
0457    */
0458   template <typename ConstBufferSequence,
0459       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0460         std::size_t)) WriteToken
0461           = default_completion_token_t<executor_type>>
0462   auto async_send(const ConstBufferSequence& buffers,
0463       socket_base::message_flags flags,
0464       WriteToken&& token
0465         = default_completion_token_t<executor_type>())
0466     -> decltype(
0467       async_initiate<WriteToken,
0468         void (boost::system::error_code, std::size_t)>(
0469           declval<initiate_async_send>(), token, buffers, flags))
0470   {
0471     return async_initiate<WriteToken,
0472       void (boost::system::error_code, std::size_t)>(
0473         initiate_async_send(this), token, buffers, flags);
0474   }
0475 
0476   /// Receive some data on the socket.
0477   /**
0478    * This function is used to receive data on the sequenced packet socket. The
0479    * function call will block until data has been received successfully, or
0480    * until an error occurs.
0481    *
0482    * @param buffers One or more buffers into which the data will be received.
0483    *
0484    * @param out_flags After the receive call completes, contains flags
0485    * associated with the received data. For example, if the
0486    * socket_base::message_end_of_record bit is set then the received data marks
0487    * the end of a record.
0488    *
0489    * @returns The number of bytes received.
0490    *
0491    * @throws boost::system::system_error Thrown on failure. An error code of
0492    * boost::asio::error::eof indicates that the connection was closed by the
0493    * peer.
0494    *
0495    * @par Example
0496    * To receive into a single data buffer use the @ref buffer function as
0497    * follows:
0498    * @code
0499    * socket.receive(boost::asio::buffer(data, size), out_flags);
0500    * @endcode
0501    * See the @ref buffer documentation for information on receiving into
0502    * multiple buffers in one go, and how to use it with arrays, boost::array or
0503    * std::vector.
0504    */
0505   template <typename MutableBufferSequence>
0506   std::size_t receive(const MutableBufferSequence& buffers,
0507       socket_base::message_flags& out_flags)
0508   {
0509     boost::system::error_code ec;
0510     std::size_t s = this->impl_.get_service().receive_with_flags(
0511         this->impl_.get_implementation(), buffers, 0, out_flags, ec);
0512     boost::asio::detail::throw_error(ec, "receive");
0513     return s;
0514   }
0515 
0516   /// Receive some data on the socket.
0517   /**
0518    * This function is used to receive data on the sequenced packet socket. The
0519    * function call will block until data has been received successfully, or
0520    * until an error occurs.
0521    *
0522    * @param buffers One or more buffers into which the data will be received.
0523    *
0524    * @param in_flags Flags specifying how the receive call is to be made.
0525    *
0526    * @param out_flags After the receive call completes, contains flags
0527    * associated with the received data. For example, if the
0528    * socket_base::message_end_of_record bit is set then the received data marks
0529    * the end of a record.
0530    *
0531    * @returns The number of bytes received.
0532    *
0533    * @throws boost::system::system_error Thrown on failure. An error code of
0534    * boost::asio::error::eof indicates that the connection was closed by the
0535    * peer.
0536    *
0537    * @note The receive operation may not receive all of the requested number of
0538    * bytes. Consider using the @ref read function if you need to ensure that the
0539    * requested amount of data is read before the blocking operation completes.
0540    *
0541    * @par Example
0542    * To receive into a single data buffer use the @ref buffer function as
0543    * follows:
0544    * @code
0545    * socket.receive(boost::asio::buffer(data, size), 0, out_flags);
0546    * @endcode
0547    * See the @ref buffer documentation for information on receiving into
0548    * multiple buffers in one go, and how to use it with arrays, boost::array or
0549    * std::vector.
0550    */
0551   template <typename MutableBufferSequence>
0552   std::size_t receive(const MutableBufferSequence& buffers,
0553       socket_base::message_flags in_flags,
0554       socket_base::message_flags& out_flags)
0555   {
0556     boost::system::error_code ec;
0557     std::size_t s = this->impl_.get_service().receive_with_flags(
0558         this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
0559     boost::asio::detail::throw_error(ec, "receive");
0560     return s;
0561   }
0562 
0563   /// Receive some data on a connected socket.
0564   /**
0565    * This function is used to receive data on the sequenced packet socket. The
0566    * function call will block until data has been received successfully, or
0567    * until an error occurs.
0568    *
0569    * @param buffers One or more buffers into which the data will be received.
0570    *
0571    * @param in_flags Flags specifying how the receive call is to be made.
0572    *
0573    * @param out_flags After the receive call completes, contains flags
0574    * associated with the received data. For example, if the
0575    * socket_base::message_end_of_record bit is set then the received data marks
0576    * the end of a record.
0577    *
0578    * @param ec Set to indicate what error occurred, if any.
0579    *
0580    * @returns The number of bytes received. Returns 0 if an error occurred.
0581    *
0582    * @note The receive operation may not receive all of the requested number of
0583    * bytes. Consider using the @ref read function if you need to ensure that the
0584    * requested amount of data is read before the blocking operation completes.
0585    */
0586   template <typename MutableBufferSequence>
0587   std::size_t receive(const MutableBufferSequence& buffers,
0588       socket_base::message_flags in_flags,
0589       socket_base::message_flags& out_flags, boost::system::error_code& ec)
0590   {
0591     return this->impl_.get_service().receive_with_flags(
0592         this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
0593   }
0594 
0595   /// Start an asynchronous receive.
0596   /**
0597    * This function is used to asynchronously receive data from the sequenced
0598    * packet socket. It is an initiating function for an @ref
0599    * asynchronous_operation, and always returns immediately.
0600    *
0601    * @param buffers One or more buffers into which the data will be received.
0602    * Although the buffers object may be copied as necessary, ownership of the
0603    * underlying memory blocks is retained by the caller, which must guarantee
0604    * that they remain valid until the completion handler is called.
0605    *
0606    * @param out_flags Once the asynchronous operation completes, contains flags
0607    * associated with the received data. For example, if the
0608    * socket_base::message_end_of_record bit is set then the received data marks
0609    * the end of a record. The caller must guarantee that the referenced
0610    * variable remains valid until the completion handler is called.
0611    *
0612    * @param token The @ref completion_token that will be used to produce a
0613    * completion handler, which will be called when the receive completes.
0614    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0615    * @ref yield_context, or a function object with the correct completion
0616    * signature. The function signature of the completion handler must be:
0617    * @code void handler(
0618    *   const boost::system::error_code& error, // Result of operation.
0619    *   std::size_t bytes_transferred // Number of bytes received.
0620    * ); @endcode
0621    * Regardless of whether the asynchronous operation completes immediately or
0622    * not, the completion handler will not be invoked from within this function.
0623    * On immediate completion, invocation of the handler will be performed in a
0624    * manner equivalent to using boost::asio::post().
0625    *
0626    * @par Completion Signature
0627    * @code void(boost::system::error_code, std::size_t) @endcode
0628    *
0629    * @par Example
0630    * To receive into a single data buffer use the @ref buffer function as
0631    * follows:
0632    * @code
0633    * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler);
0634    * @endcode
0635    * See the @ref buffer documentation for information on receiving into
0636    * multiple buffers in one go, and how to use it with arrays, boost::array or
0637    * std::vector.
0638    *
0639    * @par Per-Operation Cancellation
0640    * On POSIX or Windows operating systems, this asynchronous operation supports
0641    * cancellation for the following boost::asio::cancellation_type values:
0642    *
0643    * @li @c cancellation_type::terminal
0644    *
0645    * @li @c cancellation_type::partial
0646    *
0647    * @li @c cancellation_type::total
0648    */
0649   template <typename MutableBufferSequence,
0650       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0651         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0652   auto async_receive(const MutableBufferSequence& buffers,
0653       socket_base::message_flags& out_flags,
0654       ReadToken&& token = default_completion_token_t<executor_type>())
0655     -> decltype(
0656       async_initiate<ReadToken,
0657         void (boost::system::error_code, std::size_t)>(
0658           declval<initiate_async_receive_with_flags>(), token,
0659           buffers, socket_base::message_flags(0), &out_flags))
0660   {
0661     return async_initiate<ReadToken,
0662       void (boost::system::error_code, std::size_t)>(
0663         initiate_async_receive_with_flags(this), token,
0664         buffers, socket_base::message_flags(0), &out_flags);
0665   }
0666 
0667   /// Start an asynchronous receive.
0668   /**
0669    * This function is used to asynchronously receive data from the sequenced
0670    * data socket. It is an initiating function for an @ref
0671    * asynchronous_operation, and always returns immediately.
0672    *
0673    * @param buffers One or more buffers into which the data will be received.
0674    * Although the buffers object may be copied as necessary, ownership of the
0675    * underlying memory blocks is retained by the caller, which must guarantee
0676    * that they remain valid until the completion handler is called.
0677    *
0678    * @param in_flags Flags specifying how the receive call is to be made.
0679    *
0680    * @param out_flags Once the asynchronous operation completes, contains flags
0681    * associated with the received data. For example, if the
0682    * socket_base::message_end_of_record bit is set then the received data marks
0683    * the end of a record. The caller must guarantee that the referenced
0684    * variable remains valid until the completion handler is called.
0685    *
0686    * @param token The @ref completion_token that will be used to produce a
0687    * completion handler, which will be called when the receive completes.
0688    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0689    * @ref yield_context, or a function object with the correct completion
0690    * signature. The function signature of the completion handler must be:
0691    * @code void handler(
0692    *   const boost::system::error_code& error, // Result of operation.
0693    *   std::size_t bytes_transferred // Number of bytes received.
0694    * ); @endcode
0695    * Regardless of whether the asynchronous operation completes immediately or
0696    * not, the completion handler will not be invoked from within this function.
0697    * On immediate completion, invocation of the handler will be performed in a
0698    * manner equivalent to using boost::asio::post().
0699    *
0700    * @par Completion Signature
0701    * @code void(boost::system::error_code, std::size_t) @endcode
0702    *
0703    * @par Example
0704    * To receive into a single data buffer use the @ref buffer function as
0705    * follows:
0706    * @code
0707    * socket.async_receive(
0708    *     boost::asio::buffer(data, size),
0709    *     0, out_flags, handler);
0710    * @endcode
0711    * See the @ref buffer documentation for information on receiving into
0712    * multiple buffers in one go, and how to use it with arrays, boost::array or
0713    * std::vector.
0714    *
0715    * @par Per-Operation Cancellation
0716    * On POSIX or Windows operating systems, this asynchronous operation supports
0717    * cancellation for the following boost::asio::cancellation_type values:
0718    *
0719    * @li @c cancellation_type::terminal
0720    *
0721    * @li @c cancellation_type::partial
0722    *
0723    * @li @c cancellation_type::total
0724    */
0725   template <typename MutableBufferSequence,
0726       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0727         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0728   auto async_receive(const MutableBufferSequence& buffers,
0729       socket_base::message_flags in_flags,
0730       socket_base::message_flags& out_flags,
0731       ReadToken&& token = default_completion_token_t<executor_type>())
0732     -> decltype(
0733       async_initiate<ReadToken,
0734         void (boost::system::error_code, std::size_t)>(
0735           declval<initiate_async_receive_with_flags>(),
0736           token, buffers, in_flags, &out_flags))
0737   {
0738     return async_initiate<ReadToken,
0739       void (boost::system::error_code, std::size_t)>(
0740         initiate_async_receive_with_flags(this),
0741         token, buffers, in_flags, &out_flags);
0742   }
0743 
0744 private:
0745   // Disallow copying and assignment.
0746   basic_seq_packet_socket(const basic_seq_packet_socket&) = delete;
0747   basic_seq_packet_socket& operator=(
0748       const basic_seq_packet_socket&) = delete;
0749 
0750   class initiate_async_send
0751   {
0752   public:
0753     typedef Executor executor_type;
0754 
0755     explicit initiate_async_send(basic_seq_packet_socket* self)
0756       : self_(self)
0757     {
0758     }
0759 
0760     const executor_type& get_executor() const noexcept
0761     {
0762       return self_->get_executor();
0763     }
0764 
0765     template <typename WriteHandler, typename ConstBufferSequence>
0766     void operator()(WriteHandler&& handler,
0767         const ConstBufferSequence& buffers,
0768         socket_base::message_flags flags) const
0769     {
0770       // If you get an error on the following line it means that your handler
0771       // does not meet the documented type requirements for a WriteHandler.
0772       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0773 
0774       detail::non_const_lvalue<WriteHandler> handler2(handler);
0775       self_->impl_.get_service().async_send(
0776           self_->impl_.get_implementation(), buffers, flags,
0777           handler2.value, self_->impl_.get_executor());
0778     }
0779 
0780   private:
0781     basic_seq_packet_socket* self_;
0782   };
0783 
0784   class initiate_async_receive_with_flags
0785   {
0786   public:
0787     typedef Executor executor_type;
0788 
0789     explicit initiate_async_receive_with_flags(basic_seq_packet_socket* self)
0790       : self_(self)
0791     {
0792     }
0793 
0794     const executor_type& get_executor() const noexcept
0795     {
0796       return self_->get_executor();
0797     }
0798 
0799     template <typename ReadHandler, typename MutableBufferSequence>
0800     void operator()(ReadHandler&& handler,
0801         const MutableBufferSequence& buffers,
0802         socket_base::message_flags in_flags,
0803         socket_base::message_flags* out_flags) const
0804     {
0805       // If you get an error on the following line it means that your handler
0806       // does not meet the documented type requirements for a ReadHandler.
0807       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0808 
0809       detail::non_const_lvalue<ReadHandler> handler2(handler);
0810       self_->impl_.get_service().async_receive_with_flags(
0811           self_->impl_.get_implementation(), buffers, in_flags,
0812           *out_flags, handler2.value, self_->impl_.get_executor());
0813     }
0814 
0815   private:
0816     basic_seq_packet_socket* self_;
0817   };
0818 };
0819 
0820 } // namespace asio
0821 } // namespace boost
0822 
0823 #include <boost/asio/detail/pop_options.hpp>
0824 
0825 #endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP