Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // basic_stream_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_STREAM_SOCKET_HPP
0012 #define BOOST_ASIO_BASIC_STREAM_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/async_result.hpp>
0021 #include <boost/asio/basic_socket.hpp>
0022 #include <boost/asio/detail/handler_type_requirements.hpp>
0023 #include <boost/asio/detail/non_const_lvalue.hpp>
0024 #include <boost/asio/detail/throw_error.hpp>
0025 #include <boost/asio/error.hpp>
0026 
0027 #include <boost/asio/detail/push_options.hpp>
0028 
0029 namespace boost {
0030 namespace asio {
0031 
0032 #if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL)
0033 #define BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL
0034 
0035 // Forward declaration with defaulted arguments.
0036 template <typename Protocol, typename Executor = any_io_executor>
0037 class basic_stream_socket;
0038 
0039 #endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_FWD_DECL)
0040 
0041 /// Provides stream-oriented socket functionality.
0042 /**
0043  * The basic_stream_socket class template provides asynchronous and blocking
0044  * stream-oriented socket functionality.
0045  *
0046  * @par Thread Safety
0047  * @e Distinct @e objects: Safe.@n
0048  * @e Shared @e objects: Unsafe.
0049  *
0050  * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are
0051  * thread safe with respect to each other, if the underlying operating system
0052  * calls are also thread safe. This means that it is permitted to perform
0053  * concurrent calls to these synchronous operations on a single socket object.
0054  * Other synchronous operations, such as @c open or @c close, are not thread
0055  * safe.
0056  *
0057  * @par Concepts:
0058  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
0059  */
0060 template <typename Protocol, typename Executor>
0061 class basic_stream_socket
0062   : public basic_socket<Protocol, Executor>
0063 {
0064 private:
0065   class initiate_async_send;
0066   class initiate_async_receive;
0067 
0068 public:
0069   /// The type of the executor associated with the object.
0070   typedef Executor executor_type;
0071 
0072   /// Rebinds the socket type to another executor.
0073   template <typename Executor1>
0074   struct rebind_executor
0075   {
0076     /// The socket type when rebound to the specified executor.
0077     typedef basic_stream_socket<Protocol, Executor1> other;
0078   };
0079 
0080   /// The native representation of a socket.
0081 #if defined(GENERATING_DOCUMENTATION)
0082   typedef implementation_defined native_handle_type;
0083 #else
0084   typedef typename basic_socket<Protocol,
0085     Executor>::native_handle_type native_handle_type;
0086 #endif
0087 
0088   /// The protocol type.
0089   typedef Protocol protocol_type;
0090 
0091   /// The endpoint type.
0092   typedef typename Protocol::endpoint endpoint_type;
0093 
0094   /// Construct a basic_stream_socket without opening it.
0095   /**
0096    * This constructor creates a stream socket without opening it. The socket
0097    * needs to be opened and then connected or accepted before data can be sent
0098    * or received on it.
0099    *
0100    * @param ex The I/O executor that the socket will use, by default, to
0101    * dispatch handlers for any asynchronous operations performed on the socket.
0102    */
0103   explicit basic_stream_socket(const executor_type& ex)
0104     : basic_socket<Protocol, Executor>(ex)
0105   {
0106   }
0107 
0108   /// Construct a basic_stream_socket without opening it.
0109   /**
0110    * This constructor creates a stream socket without opening it. The socket
0111    * needs to be opened and then connected or accepted before data can be sent
0112    * or received on it.
0113    *
0114    * @param context An execution context which provides the I/O executor that
0115    * the socket will use, by default, to dispatch handlers for any asynchronous
0116    * operations performed on the socket.
0117    */
0118   template <typename ExecutionContext>
0119   explicit basic_stream_socket(ExecutionContext& context,
0120       constraint_t<
0121         is_convertible<ExecutionContext&, execution_context&>::value
0122       > = 0)
0123     : basic_socket<Protocol, Executor>(context)
0124   {
0125   }
0126 
0127   /// Construct and open a basic_stream_socket.
0128   /**
0129    * This constructor creates and opens a stream socket. The socket needs to be
0130    * connected or accepted before data can be sent or received on it.
0131    *
0132    * @param ex The I/O executor that the socket will use, by default, to
0133    * dispatch handlers for any asynchronous operations performed on the socket.
0134    *
0135    * @param protocol An object specifying protocol parameters to be used.
0136    *
0137    * @throws boost::system::system_error Thrown on failure.
0138    */
0139   basic_stream_socket(const executor_type& ex, const protocol_type& protocol)
0140     : basic_socket<Protocol, Executor>(ex, protocol)
0141   {
0142   }
0143 
0144   /// Construct and open a basic_stream_socket.
0145   /**
0146    * This constructor creates and opens a stream socket. The socket needs to be
0147    * connected or accepted before data can be sent or received on it.
0148    *
0149    * @param context An execution context which provides the I/O executor that
0150    * the socket will use, by default, to dispatch handlers for any asynchronous
0151    * operations performed on the socket.
0152    *
0153    * @param protocol An object specifying protocol parameters to be used.
0154    *
0155    * @throws boost::system::system_error Thrown on failure.
0156    */
0157   template <typename ExecutionContext>
0158   basic_stream_socket(ExecutionContext& context, const protocol_type& protocol,
0159       constraint_t<
0160         is_convertible<ExecutionContext&, execution_context&>::value,
0161         defaulted_constraint
0162       > = defaulted_constraint())
0163     : basic_socket<Protocol, Executor>(context, protocol)
0164   {
0165   }
0166 
0167   /// Construct a basic_stream_socket, opening it and binding it to the given
0168   /// local endpoint.
0169   /**
0170    * This constructor creates a stream socket and automatically opens it bound
0171    * to the specified endpoint on the local machine. The protocol used is the
0172    * protocol associated with the given endpoint.
0173    *
0174    * @param ex The I/O executor that the socket will use, by default, to
0175    * dispatch handlers for any asynchronous operations performed on the socket.
0176    *
0177    * @param endpoint An endpoint on the local machine to which the stream
0178    * socket will be bound.
0179    *
0180    * @throws boost::system::system_error Thrown on failure.
0181    */
0182   basic_stream_socket(const executor_type& ex, const endpoint_type& endpoint)
0183     : basic_socket<Protocol, Executor>(ex, endpoint)
0184   {
0185   }
0186 
0187   /// Construct a basic_stream_socket, opening it and binding it to the given
0188   /// local endpoint.
0189   /**
0190    * This constructor creates a stream socket and automatically opens it bound
0191    * to the specified endpoint on the local machine. The protocol used is the
0192    * 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 stream
0199    * socket will be bound.
0200    *
0201    * @throws boost::system::system_error Thrown on failure.
0202    */
0203   template <typename ExecutionContext>
0204   basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,
0205       constraint_t<
0206         is_convertible<ExecutionContext&, execution_context&>::value
0207       > = 0)
0208     : basic_socket<Protocol, Executor>(context, endpoint)
0209   {
0210   }
0211 
0212   /// Construct a basic_stream_socket on an existing native socket.
0213   /**
0214    * This constructor creates a stream socket object to hold an existing native
0215    * socket.
0216    *
0217    * @param ex The I/O executor that the socket will use, by default, to
0218    * dispatch handlers for any asynchronous operations performed on the socket.
0219    *
0220    * @param protocol An object specifying protocol parameters to be used.
0221    *
0222    * @param native_socket The new underlying socket implementation.
0223    *
0224    * @throws boost::system::system_error Thrown on failure.
0225    */
0226   basic_stream_socket(const executor_type& ex,
0227       const protocol_type& protocol, const native_handle_type& native_socket)
0228     : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
0229   {
0230   }
0231 
0232   /// Construct a basic_stream_socket on an existing native socket.
0233   /**
0234    * This constructor creates a stream socket object to hold an existing native
0235    * socket.
0236    *
0237    * @param context An execution context which provides the I/O executor that
0238    * the socket will use, by default, to dispatch handlers for any asynchronous
0239    * operations performed on the socket.
0240    *
0241    * @param protocol An object specifying protocol parameters to be used.
0242    *
0243    * @param native_socket The new underlying socket implementation.
0244    *
0245    * @throws boost::system::system_error Thrown on failure.
0246    */
0247   template <typename ExecutionContext>
0248   basic_stream_socket(ExecutionContext& context,
0249       const protocol_type& protocol, const native_handle_type& native_socket,
0250       constraint_t<
0251         is_convertible<ExecutionContext&, execution_context&>::value
0252       > = 0)
0253     : basic_socket<Protocol, Executor>(context, protocol, native_socket)
0254   {
0255   }
0256 
0257   /// Move-construct a basic_stream_socket from another.
0258   /**
0259    * This constructor moves a stream socket from one object to another.
0260    *
0261    * @param other The other basic_stream_socket object from which the move
0262    * will occur.
0263    *
0264    * @note Following the move, the moved-from object is in the same state as if
0265    * constructed using the @c basic_stream_socket(const executor_type&)
0266    * constructor.
0267    */
0268   basic_stream_socket(basic_stream_socket&& other) noexcept
0269     : basic_socket<Protocol, Executor>(std::move(other))
0270   {
0271   }
0272 
0273   /// Move-assign a basic_stream_socket from another.
0274   /**
0275    * This assignment operator moves a stream socket from one object to another.
0276    *
0277    * @param other The other basic_stream_socket object from which the move
0278    * will occur.
0279    *
0280    * @note Following the move, the moved-from object is in the same state as if
0281    * constructed using the @c basic_stream_socket(const executor_type&)
0282    * constructor.
0283    */
0284   basic_stream_socket& operator=(basic_stream_socket&& other)
0285   {
0286     basic_socket<Protocol, Executor>::operator=(std::move(other));
0287     return *this;
0288   }
0289 
0290   /// Move-construct a basic_stream_socket from a socket of another protocol
0291   /// type.
0292   /**
0293    * This constructor moves a stream socket from one object to another.
0294    *
0295    * @param other The other basic_stream_socket object from which the move
0296    * will occur.
0297    *
0298    * @note Following the move, the moved-from object is in the same state as if
0299    * constructed using the @c basic_stream_socket(const executor_type&)
0300    * constructor.
0301    */
0302   template <typename Protocol1, typename Executor1>
0303   basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,
0304       constraint_t<
0305         is_convertible<Protocol1, Protocol>::value
0306           && is_convertible<Executor1, Executor>::value
0307       > = 0)
0308     : basic_socket<Protocol, Executor>(std::move(other))
0309   {
0310   }
0311 
0312   /// Move-assign a basic_stream_socket from a socket of another protocol type.
0313   /**
0314    * This assignment operator moves a stream socket from one object to another.
0315    *
0316    * @param other The other basic_stream_socket object from which the move
0317    * will occur.
0318    *
0319    * @note Following the move, the moved-from object is in the same state as if
0320    * constructed using the @c basic_stream_socket(const executor_type&)
0321    * constructor.
0322    */
0323   template <typename Protocol1, typename Executor1>
0324   constraint_t<
0325     is_convertible<Protocol1, Protocol>::value
0326       && is_convertible<Executor1, Executor>::value,
0327     basic_stream_socket&
0328   > operator=(basic_stream_socket<Protocol1, Executor1>&& other)
0329   {
0330     basic_socket<Protocol, Executor>::operator=(std::move(other));
0331     return *this;
0332   }
0333 
0334   /// Destroys the socket.
0335   /**
0336    * This function destroys the socket, cancelling any outstanding asynchronous
0337    * operations associated with the socket as if by calling @c cancel.
0338    */
0339   ~basic_stream_socket()
0340   {
0341   }
0342 
0343   /// Send some data on the socket.
0344   /**
0345    * This function is used to send data on the stream socket. The function
0346    * call will block until one or more bytes of the data has been sent
0347    * successfully, or an until error occurs.
0348    *
0349    * @param buffers One or more data buffers to be sent on the socket.
0350    *
0351    * @returns The number of bytes sent.
0352    *
0353    * @throws boost::system::system_error Thrown on failure.
0354    *
0355    * @note The send operation may not transmit all of the data to the peer.
0356    * Consider using the @ref write function if you need to ensure that all data
0357    * is written before the blocking operation completes.
0358    *
0359    * @par Example
0360    * To send a single data buffer use the @ref buffer function as follows:
0361    * @code
0362    * socket.send(boost::asio::buffer(data, size));
0363    * @endcode
0364    * See the @ref buffer documentation for information on sending multiple
0365    * buffers in one go, and how to use it with arrays, boost::array or
0366    * std::vector.
0367    */
0368   template <typename ConstBufferSequence>
0369   std::size_t send(const ConstBufferSequence& buffers)
0370   {
0371     boost::system::error_code ec;
0372     std::size_t s = this->impl_.get_service().send(
0373         this->impl_.get_implementation(), buffers, 0, ec);
0374     boost::asio::detail::throw_error(ec, "send");
0375     return s;
0376   }
0377 
0378   /// Send some data on the socket.
0379   /**
0380    * This function is used to send data on the stream socket. The function
0381    * call will block until one or more bytes of the data has been sent
0382    * successfully, or an until error occurs.
0383    *
0384    * @param buffers One or more data buffers to be sent on the socket.
0385    *
0386    * @param flags Flags specifying how the send call is to be made.
0387    *
0388    * @returns The number of bytes sent.
0389    *
0390    * @throws boost::system::system_error Thrown on failure.
0391    *
0392    * @note The send operation may not transmit all of the data to the peer.
0393    * Consider using the @ref write function if you need to ensure that all data
0394    * is written before the blocking operation completes.
0395    *
0396    * @par Example
0397    * To send a single data buffer use the @ref buffer function as follows:
0398    * @code
0399    * socket.send(boost::asio::buffer(data, size), 0);
0400    * @endcode
0401    * See the @ref buffer documentation for information on sending multiple
0402    * buffers in one go, and how to use it with arrays, boost::array or
0403    * std::vector.
0404    */
0405   template <typename ConstBufferSequence>
0406   std::size_t send(const ConstBufferSequence& buffers,
0407       socket_base::message_flags flags)
0408   {
0409     boost::system::error_code ec;
0410     std::size_t s = this->impl_.get_service().send(
0411         this->impl_.get_implementation(), buffers, flags, ec);
0412     boost::asio::detail::throw_error(ec, "send");
0413     return s;
0414   }
0415 
0416   /// Send some data on the socket.
0417   /**
0418    * This function is used to send data on the stream socket. The function
0419    * call will block until one or more bytes of the data has been sent
0420    * successfully, or an until error occurs.
0421    *
0422    * @param buffers One or more data buffers to be sent on the socket.
0423    *
0424    * @param flags Flags specifying how the send call is to be made.
0425    *
0426    * @param ec Set to indicate what error occurred, if any.
0427    *
0428    * @returns The number of bytes sent. Returns 0 if an error occurred.
0429    *
0430    * @note The send operation may not transmit all of the data to the peer.
0431    * Consider using the @ref write function if you need to ensure that all data
0432    * is written before the blocking operation completes.
0433    */
0434   template <typename ConstBufferSequence>
0435   std::size_t send(const ConstBufferSequence& buffers,
0436       socket_base::message_flags flags, boost::system::error_code& ec)
0437   {
0438     return this->impl_.get_service().send(
0439         this->impl_.get_implementation(), buffers, flags, ec);
0440   }
0441 
0442   /// Start an asynchronous send.
0443   /**
0444    * This function is used to asynchronously send data on the stream socket.
0445    * It is an initiating function for an @ref asynchronous_operation, and always
0446    * returns immediately.
0447    *
0448    * @param buffers One or more data buffers to be sent on the socket. Although
0449    * the buffers object may be copied as necessary, ownership of the underlying
0450    * memory blocks is retained by the caller, which must guarantee that they
0451    * remain valid until the completion handler is called.
0452    *
0453    * @param token The @ref completion_token that will be used to produce a
0454    * completion handler, which will be called when the send completes.
0455    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0456    * @ref yield_context, or a function object with the correct completion
0457    * signature. The function signature of the completion handler must be:
0458    * @code void handler(
0459    *   const boost::system::error_code& error, // Result of operation.
0460    *   std::size_t bytes_transferred // Number of bytes sent.
0461    * ); @endcode
0462    * Regardless of whether the asynchronous operation completes immediately or
0463    * not, the completion handler will not be invoked from within this function.
0464    * On immediate completion, invocation of the handler will be performed in a
0465    * manner equivalent to using boost::asio::post().
0466    *
0467    * @par Completion Signature
0468    * @code void(boost::system::error_code, std::size_t) @endcode
0469    *
0470    * @note The send operation may not transmit all of the data to the peer.
0471    * Consider using the @ref async_write function if you need to ensure that all
0472    * data is written before the asynchronous operation completes.
0473    *
0474    * @par Example
0475    * To send a single data buffer use the @ref buffer function as follows:
0476    * @code
0477    * socket.async_send(boost::asio::buffer(data, size), handler);
0478    * @endcode
0479    * See the @ref buffer documentation for information on sending multiple
0480    * buffers in one go, and how to use it with arrays, boost::array or
0481    * std::vector.
0482    *
0483    * @par Per-Operation Cancellation
0484    * On POSIX or Windows operating systems, this asynchronous operation supports
0485    * cancellation for the following boost::asio::cancellation_type values:
0486    *
0487    * @li @c cancellation_type::terminal
0488    *
0489    * @li @c cancellation_type::partial
0490    *
0491    * @li @c cancellation_type::total
0492    */
0493   template <typename ConstBufferSequence,
0494       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0495         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0496   auto async_send(const ConstBufferSequence& buffers,
0497       WriteToken&& token = default_completion_token_t<executor_type>())
0498     -> decltype(
0499       async_initiate<WriteToken,
0500         void (boost::system::error_code, std::size_t)>(
0501           declval<initiate_async_send>(), token,
0502           buffers, socket_base::message_flags(0)))
0503   {
0504     return async_initiate<WriteToken,
0505       void (boost::system::error_code, std::size_t)>(
0506         initiate_async_send(this), token,
0507         buffers, socket_base::message_flags(0));
0508   }
0509 
0510   /// Start an asynchronous send.
0511   /**
0512    * This function is used to asynchronously send data on the stream socket.
0513    * It is an initiating function for an @ref asynchronous_operation, and always
0514    * returns immediately.
0515    *
0516    * @param buffers One or more data buffers to be sent on the socket. Although
0517    * the buffers object may be copied as necessary, ownership of the underlying
0518    * memory blocks is retained by the caller, which must guarantee that they
0519    * remain valid until the completion handler is called.
0520    *
0521    * @param flags Flags specifying how the send call is to be made.
0522    *
0523    * @param token The @ref completion_token that will be used to produce a
0524    * completion handler, which will be called when the send completes.
0525    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0526    * @ref yield_context, or a function object with the correct completion
0527    * signature. The function signature of the completion handler must be:
0528    * @code void handler(
0529    *   const boost::system::error_code& error, // Result of operation.
0530    *   std::size_t bytes_transferred // Number of bytes sent.
0531    * ); @endcode
0532    * Regardless of whether the asynchronous operation completes immediately or
0533    * not, the completion handler will not be invoked from within this function.
0534    * On immediate completion, invocation of the handler will be performed in a
0535    * manner equivalent to using boost::asio::post().
0536    *
0537    * @par Completion Signature
0538    * @code void(boost::system::error_code, std::size_t) @endcode
0539    *
0540    * @note The send operation may not transmit all of the data to the peer.
0541    * Consider using the @ref async_write function if you need to ensure that all
0542    * data is written before the asynchronous operation completes.
0543    *
0544    * @par Example
0545    * To send a single data buffer use the @ref buffer function as follows:
0546    * @code
0547    * socket.async_send(boost::asio::buffer(data, size), 0, handler);
0548    * @endcode
0549    * See the @ref buffer documentation for information on sending multiple
0550    * buffers in one go, and how to use it with arrays, boost::array or
0551    * std::vector.
0552    *
0553    * @par Per-Operation Cancellation
0554    * On POSIX or Windows operating systems, this asynchronous operation supports
0555    * cancellation for the following boost::asio::cancellation_type values:
0556    *
0557    * @li @c cancellation_type::terminal
0558    *
0559    * @li @c cancellation_type::partial
0560    *
0561    * @li @c cancellation_type::total
0562    */
0563   template <typename ConstBufferSequence,
0564       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0565         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0566   auto async_send(const ConstBufferSequence& buffers,
0567       socket_base::message_flags flags,
0568       WriteToken&& token = default_completion_token_t<executor_type>())
0569     -> decltype(
0570       async_initiate<WriteToken,
0571         void (boost::system::error_code, std::size_t)>(
0572           declval<initiate_async_send>(), token, buffers, flags))
0573   {
0574     return async_initiate<WriteToken,
0575       void (boost::system::error_code, std::size_t)>(
0576         initiate_async_send(this), token, buffers, flags);
0577   }
0578 
0579   /// Receive some data on the socket.
0580   /**
0581    * This function is used to receive data on the stream socket. The function
0582    * call will block until one or more bytes of data has been received
0583    * successfully, or until an error occurs.
0584    *
0585    * @param buffers One or more buffers into which the data will be received.
0586    *
0587    * @returns The number of bytes received.
0588    *
0589    * @throws boost::system::system_error Thrown on failure. An error code of
0590    * boost::asio::error::eof indicates that the connection was closed by the
0591    * peer.
0592    *
0593    * @note The receive operation may not receive all of the requested number of
0594    * bytes. Consider using the @ref read function if you need to ensure that the
0595    * requested amount of data is read before the blocking operation completes.
0596    *
0597    * @par Example
0598    * To receive into a single data buffer use the @ref buffer function as
0599    * follows:
0600    * @code
0601    * socket.receive(boost::asio::buffer(data, size));
0602    * @endcode
0603    * See the @ref buffer documentation for information on receiving into
0604    * multiple buffers in one go, and how to use it with arrays, boost::array or
0605    * std::vector.
0606    */
0607   template <typename MutableBufferSequence>
0608   std::size_t receive(const MutableBufferSequence& buffers)
0609   {
0610     boost::system::error_code ec;
0611     std::size_t s = this->impl_.get_service().receive(
0612         this->impl_.get_implementation(), buffers, 0, ec);
0613     boost::asio::detail::throw_error(ec, "receive");
0614     return s;
0615   }
0616 
0617   /// Receive some data on the socket.
0618   /**
0619    * This function is used to receive data on the stream socket. The function
0620    * call will block until one or more bytes of data has been received
0621    * successfully, or until an error occurs.
0622    *
0623    * @param buffers One or more buffers into which the data will be received.
0624    *
0625    * @param flags Flags specifying how the receive call is to be made.
0626    *
0627    * @returns The number of bytes received.
0628    *
0629    * @throws boost::system::system_error Thrown on failure. An error code of
0630    * boost::asio::error::eof indicates that the connection was closed by the
0631    * peer.
0632    *
0633    * @note The receive operation may not receive all of the requested number of
0634    * bytes. Consider using the @ref read function if you need to ensure that the
0635    * requested amount of data is read before the blocking operation completes.
0636    *
0637    * @par Example
0638    * To receive into a single data buffer use the @ref buffer function as
0639    * follows:
0640    * @code
0641    * socket.receive(boost::asio::buffer(data, size), 0);
0642    * @endcode
0643    * See the @ref buffer documentation for information on receiving into
0644    * multiple buffers in one go, and how to use it with arrays, boost::array or
0645    * std::vector.
0646    */
0647   template <typename MutableBufferSequence>
0648   std::size_t receive(const MutableBufferSequence& buffers,
0649       socket_base::message_flags flags)
0650   {
0651     boost::system::error_code ec;
0652     std::size_t s = this->impl_.get_service().receive(
0653         this->impl_.get_implementation(), buffers, flags, ec);
0654     boost::asio::detail::throw_error(ec, "receive");
0655     return s;
0656   }
0657 
0658   /// Receive some data on a connected socket.
0659   /**
0660    * This function is used to receive data on the stream socket. The function
0661    * call will block until one or more bytes of data has been received
0662    * successfully, or until an error occurs.
0663    *
0664    * @param buffers One or more buffers into which the data will be received.
0665    *
0666    * @param flags Flags specifying how the receive call is to be made.
0667    *
0668    * @param ec Set to indicate what error occurred, if any.
0669    *
0670    * @returns The number of bytes received. Returns 0 if an error occurred.
0671    *
0672    * @note The receive operation may not receive all of the requested number of
0673    * bytes. Consider using the @ref read function if you need to ensure that the
0674    * requested amount of data is read before the blocking operation completes.
0675    */
0676   template <typename MutableBufferSequence>
0677   std::size_t receive(const MutableBufferSequence& buffers,
0678       socket_base::message_flags flags, boost::system::error_code& ec)
0679   {
0680     return this->impl_.get_service().receive(
0681         this->impl_.get_implementation(), buffers, flags, ec);
0682   }
0683 
0684   /// Start an asynchronous receive.
0685   /**
0686    * This function is used to asynchronously receive data from the stream
0687    * socket. It is an initiating function for an @ref asynchronous_operation,
0688    * and always returns immediately.
0689    *
0690    * @param buffers One or more buffers into which the data will be received.
0691    * Although the buffers object may be copied as necessary, ownership of the
0692    * underlying memory blocks is retained by the caller, which must guarantee
0693    * that they remain valid until the completion handler is called.
0694    *
0695    * @param token The @ref completion_token that will be used to produce a
0696    * completion handler, which will be called when the receive completes.
0697    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0698    * @ref yield_context, or a function object with the correct completion
0699    * signature. The function signature of the completion handler must be:
0700    * @code void handler(
0701    *   const boost::system::error_code& error, // Result of operation.
0702    *   std::size_t bytes_transferred // Number of bytes received.
0703    * ); @endcode
0704    * Regardless of whether the asynchronous operation completes immediately or
0705    * not, the completion handler will not be invoked from within this function.
0706    * On immediate completion, invocation of the handler will be performed in a
0707    * manner equivalent to using boost::asio::post().
0708    *
0709    * @par Completion Signature
0710    * @code void(boost::system::error_code, std::size_t) @endcode
0711    *
0712    * @note The receive operation may not receive all of the requested number of
0713    * bytes. Consider using the @ref async_read function if you need to ensure
0714    * that the requested amount of data is received before the asynchronous
0715    * operation completes.
0716    *
0717    * @par Example
0718    * To receive into a single data buffer use the @ref buffer function as
0719    * follows:
0720    * @code
0721    * socket.async_receive(boost::asio::buffer(data, size), handler);
0722    * @endcode
0723    * See the @ref buffer documentation for information on receiving into
0724    * multiple buffers in one go, and how to use it with arrays, boost::array or
0725    * std::vector.
0726    *
0727    * @par Per-Operation Cancellation
0728    * On POSIX or Windows operating systems, this asynchronous operation supports
0729    * cancellation for the following boost::asio::cancellation_type values:
0730    *
0731    * @li @c cancellation_type::terminal
0732    *
0733    * @li @c cancellation_type::partial
0734    *
0735    * @li @c cancellation_type::total
0736    */
0737   template <typename MutableBufferSequence,
0738       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0739         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0740   auto async_receive(const MutableBufferSequence& buffers,
0741       ReadToken&& token = default_completion_token_t<executor_type>())
0742     -> decltype(
0743       async_initiate<ReadToken,
0744         void (boost::system::error_code, std::size_t)>(
0745           declval<initiate_async_receive>(), token,
0746           buffers, socket_base::message_flags(0)))
0747   {
0748     return async_initiate<ReadToken,
0749       void (boost::system::error_code, std::size_t)>(
0750         initiate_async_receive(this), token,
0751         buffers, socket_base::message_flags(0));
0752   }
0753 
0754   /// Start an asynchronous receive.
0755   /**
0756    * This function is used to asynchronously receive data from the stream
0757    * socket. It is an initiating function for an @ref asynchronous_operation,
0758    * and always returns immediately.
0759    *
0760    * @param buffers One or more buffers into which the data will be received.
0761    * Although the buffers object may be copied as necessary, ownership of the
0762    * underlying memory blocks is retained by the caller, which must guarantee
0763    * that they remain valid until the completion handler is called.
0764    *
0765    * @param flags Flags specifying how the receive call is to be made.
0766    *
0767    * @param token The @ref completion_token that will be used to produce a
0768    * completion handler, which will be called when the receive completes.
0769    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0770    * @ref yield_context, or a function object with the correct completion
0771    * signature. The function signature of the completion handler must be:
0772    * @code void handler(
0773    *   const boost::system::error_code& error, // Result of operation.
0774    *   std::size_t bytes_transferred // Number of bytes received.
0775    * ); @endcode
0776    * Regardless of whether the asynchronous operation completes immediately or
0777    * not, the completion handler will not be invoked from within this function.
0778    * On immediate completion, invocation of the handler will be performed in a
0779    * manner equivalent to using boost::asio::post().
0780    *
0781    * @par Completion Signature
0782    * @code void(boost::system::error_code, std::size_t) @endcode
0783    *
0784    * @note The receive operation may not receive all of the requested number of
0785    * bytes. Consider using the @ref async_read function if you need to ensure
0786    * that the requested amount of data is received before the asynchronous
0787    * operation completes.
0788    *
0789    * @par Example
0790    * To receive into a single data buffer use the @ref buffer function as
0791    * follows:
0792    * @code
0793    * socket.async_receive(boost::asio::buffer(data, size), 0, handler);
0794    * @endcode
0795    * See the @ref buffer documentation for information on receiving into
0796    * multiple buffers in one go, and how to use it with arrays, boost::array or
0797    * std::vector.
0798    *
0799    * @par Per-Operation Cancellation
0800    * On POSIX or Windows operating systems, this asynchronous operation supports
0801    * cancellation for the following boost::asio::cancellation_type values:
0802    *
0803    * @li @c cancellation_type::terminal
0804    *
0805    * @li @c cancellation_type::partial
0806    *
0807    * @li @c cancellation_type::total
0808    */
0809   template <typename MutableBufferSequence,
0810       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0811         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0812   auto async_receive(const MutableBufferSequence& buffers,
0813       socket_base::message_flags flags,
0814       ReadToken&& token = default_completion_token_t<executor_type>())
0815     -> decltype(
0816       async_initiate<ReadToken,
0817         void (boost::system::error_code, std::size_t)>(
0818           declval<initiate_async_receive>(), token, buffers, flags))
0819   {
0820     return async_initiate<ReadToken,
0821       void (boost::system::error_code, std::size_t)>(
0822         initiate_async_receive(this), token, buffers, flags);
0823   }
0824 
0825   /// Write some data to the socket.
0826   /**
0827    * This function is used to write data to the stream socket. The function call
0828    * will block until one or more bytes of the data has been written
0829    * successfully, or until an error occurs.
0830    *
0831    * @param buffers One or more data buffers to be written to the socket.
0832    *
0833    * @returns The number of bytes written.
0834    *
0835    * @throws boost::system::system_error Thrown on failure. An error code of
0836    * boost::asio::error::eof indicates that the connection was closed by the
0837    * peer.
0838    *
0839    * @note The write_some operation may not transmit all of the data to the
0840    * peer. Consider using the @ref write function if you need to ensure that
0841    * all data is written before the blocking operation completes.
0842    *
0843    * @par Example
0844    * To write a single data buffer use the @ref buffer function as follows:
0845    * @code
0846    * socket.write_some(boost::asio::buffer(data, size));
0847    * @endcode
0848    * See the @ref buffer documentation for information on writing multiple
0849    * buffers in one go, and how to use it with arrays, boost::array or
0850    * std::vector.
0851    */
0852   template <typename ConstBufferSequence>
0853   std::size_t write_some(const ConstBufferSequence& buffers)
0854   {
0855     boost::system::error_code ec;
0856     std::size_t s = this->impl_.get_service().send(
0857         this->impl_.get_implementation(), buffers, 0, ec);
0858     boost::asio::detail::throw_error(ec, "write_some");
0859     return s;
0860   }
0861 
0862   /// Write some data to the socket.
0863   /**
0864    * This function is used to write data to the stream socket. The function call
0865    * will block until one or more bytes of the data has been written
0866    * successfully, or until an error occurs.
0867    *
0868    * @param buffers One or more data buffers to be written to the socket.
0869    *
0870    * @param ec Set to indicate what error occurred, if any.
0871    *
0872    * @returns The number of bytes written. Returns 0 if an error occurred.
0873    *
0874    * @note The write_some operation may not transmit all of the data to the
0875    * peer. Consider using the @ref write function if you need to ensure that
0876    * all data is written before the blocking operation completes.
0877    */
0878   template <typename ConstBufferSequence>
0879   std::size_t write_some(const ConstBufferSequence& buffers,
0880       boost::system::error_code& ec)
0881   {
0882     return this->impl_.get_service().send(
0883         this->impl_.get_implementation(), buffers, 0, ec);
0884   }
0885 
0886   /// Start an asynchronous write.
0887   /**
0888    * This function is used to asynchronously write data to the stream socket.
0889    * It is an initiating function for an @ref asynchronous_operation, and always
0890    * returns immediately.
0891    *
0892    * @param buffers One or more data buffers to be written to the socket.
0893    * Although the buffers object may be copied as necessary, ownership of the
0894    * underlying memory blocks is retained by the caller, which must guarantee
0895    * that they remain valid until the completion handler is called.
0896    *
0897    * @param token The @ref completion_token that will be used to produce a
0898    * completion handler, which will be called when the write completes.
0899    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0900    * @ref yield_context, or a function object with the correct completion
0901    * signature. The function signature of the completion handler must be:
0902    * @code void handler(
0903    *   const boost::system::error_code& error, // Result of operation.
0904    *   std::size_t bytes_transferred // Number of bytes written.
0905    * ); @endcode
0906    * Regardless of whether the asynchronous operation completes immediately or
0907    * not, the completion handler will not be invoked from within this function.
0908    * On immediate completion, invocation of the handler will be performed in a
0909    * manner equivalent to using boost::asio::post().
0910    *
0911    * @par Completion Signature
0912    * @code void(boost::system::error_code, std::size_t) @endcode
0913    *
0914    * @note The write operation may not transmit all of the data to the peer.
0915    * Consider using the @ref async_write function if you need to ensure that all
0916    * data is written before the asynchronous operation completes.
0917    *
0918    * @par Example
0919    * To write a single data buffer use the @ref buffer function as follows:
0920    * @code
0921    * socket.async_write_some(boost::asio::buffer(data, size), handler);
0922    * @endcode
0923    * See the @ref buffer documentation for information on writing multiple
0924    * buffers in one go, and how to use it with arrays, boost::array or
0925    * std::vector.
0926    *
0927    * @par Per-Operation Cancellation
0928    * On POSIX or Windows operating systems, this asynchronous operation supports
0929    * cancellation for the following boost::asio::cancellation_type values:
0930    *
0931    * @li @c cancellation_type::terminal
0932    *
0933    * @li @c cancellation_type::partial
0934    *
0935    * @li @c cancellation_type::total
0936    */
0937   template <typename ConstBufferSequence,
0938       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0939         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0940   auto async_write_some(const ConstBufferSequence& buffers,
0941       WriteToken&& token = default_completion_token_t<executor_type>())
0942     -> decltype(
0943       async_initiate<WriteToken,
0944         void (boost::system::error_code, std::size_t)>(
0945           declval<initiate_async_send>(), token,
0946           buffers, socket_base::message_flags(0)))
0947   {
0948     return async_initiate<WriteToken,
0949       void (boost::system::error_code, std::size_t)>(
0950         initiate_async_send(this), token,
0951         buffers, socket_base::message_flags(0));
0952   }
0953 
0954   /// Read some data from the socket.
0955   /**
0956    * This function is used to read data from the stream socket. The function
0957    * call will block until one or more bytes of data has been read successfully,
0958    * or until an error occurs.
0959    *
0960    * @param buffers One or more buffers into which the data will be read.
0961    *
0962    * @returns The number of bytes read.
0963    *
0964    * @throws boost::system::system_error Thrown on failure. An error code of
0965    * boost::asio::error::eof indicates that the connection was closed by the
0966    * peer.
0967    *
0968    * @note The read_some operation may not read all of the requested number of
0969    * bytes. Consider using the @ref read function if you need to ensure that
0970    * the requested amount of data is read before the blocking operation
0971    * completes.
0972    *
0973    * @par Example
0974    * To read into a single data buffer use the @ref buffer function as follows:
0975    * @code
0976    * socket.read_some(boost::asio::buffer(data, size));
0977    * @endcode
0978    * See the @ref buffer documentation for information on reading into multiple
0979    * buffers in one go, and how to use it with arrays, boost::array or
0980    * std::vector.
0981    */
0982   template <typename MutableBufferSequence>
0983   std::size_t read_some(const MutableBufferSequence& buffers)
0984   {
0985     boost::system::error_code ec;
0986     std::size_t s = this->impl_.get_service().receive(
0987         this->impl_.get_implementation(), buffers, 0, ec);
0988     boost::asio::detail::throw_error(ec, "read_some");
0989     return s;
0990   }
0991 
0992   /// Read some data from the socket.
0993   /**
0994    * This function is used to read data from the stream socket. The function
0995    * call will block until one or more bytes of data has been read successfully,
0996    * or until an error occurs.
0997    *
0998    * @param buffers One or more buffers into which the data will be read.
0999    *
1000    * @param ec Set to indicate what error occurred, if any.
1001    *
1002    * @returns The number of bytes read. Returns 0 if an error occurred.
1003    *
1004    * @note The read_some operation may not read all of the requested number of
1005    * bytes. Consider using the @ref read function if you need to ensure that
1006    * the requested amount of data is read before the blocking operation
1007    * completes.
1008    */
1009   template <typename MutableBufferSequence>
1010   std::size_t read_some(const MutableBufferSequence& buffers,
1011       boost::system::error_code& ec)
1012   {
1013     return this->impl_.get_service().receive(
1014         this->impl_.get_implementation(), buffers, 0, ec);
1015   }
1016 
1017   /// Start an asynchronous read.
1018   /**
1019    * This function is used to asynchronously read data from the stream socket.
1020    * socket. It is an initiating function for an @ref asynchronous_operation,
1021    * and always returns immediately.
1022    *
1023    * @param buffers One or more buffers into which the data will be read.
1024    * Although the buffers object may be copied as necessary, ownership of the
1025    * underlying memory blocks is retained by the caller, which must guarantee
1026    * that they remain valid until the completion handler is called.
1027    *
1028    * @param token The @ref completion_token that will be used to produce a
1029    * completion handler, which will be called when the read completes.
1030    * Potential completion tokens include @ref use_future, @ref use_awaitable,
1031    * @ref yield_context, or a function object with the correct completion
1032    * signature. The function signature of the completion handler must be:
1033    * @code void handler(
1034    *   const boost::system::error_code& error, // Result of operation.
1035    *   std::size_t bytes_transferred // Number of bytes read.
1036    * ); @endcode
1037    * Regardless of whether the asynchronous operation completes immediately or
1038    * not, the completion handler will not be invoked from within this function.
1039    * On immediate completion, invocation of the handler will be performed in a
1040    * manner equivalent to using boost::asio::post().
1041    *
1042    * @par Completion Signature
1043    * @code void(boost::system::error_code, std::size_t) @endcode
1044    *
1045    * @note The read operation may not read all of the requested number of bytes.
1046    * Consider using the @ref async_read function if you need to ensure that the
1047    * requested amount of data is read before the asynchronous operation
1048    * completes.
1049    *
1050    * @par Example
1051    * To read into a single data buffer use the @ref buffer function as follows:
1052    * @code
1053    * socket.async_read_some(boost::asio::buffer(data, size), handler);
1054    * @endcode
1055    * See the @ref buffer documentation for information on reading into multiple
1056    * buffers in one go, and how to use it with arrays, boost::array or
1057    * std::vector.
1058    *
1059    * @par Per-Operation Cancellation
1060    * On POSIX or Windows operating systems, this asynchronous operation supports
1061    * cancellation for the following boost::asio::cancellation_type values:
1062    *
1063    * @li @c cancellation_type::terminal
1064    *
1065    * @li @c cancellation_type::partial
1066    *
1067    * @li @c cancellation_type::total
1068    */
1069   template <typename MutableBufferSequence,
1070       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1071         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
1072   auto async_read_some(const MutableBufferSequence& buffers,
1073       ReadToken&& token = default_completion_token_t<executor_type>())
1074     -> decltype(
1075       async_initiate<ReadToken,
1076         void (boost::system::error_code, std::size_t)>(
1077           declval<initiate_async_receive>(), token,
1078           buffers, socket_base::message_flags(0)))
1079   {
1080     return async_initiate<ReadToken,
1081       void (boost::system::error_code, std::size_t)>(
1082         initiate_async_receive(this), token,
1083         buffers, socket_base::message_flags(0));
1084   }
1085 
1086 private:
1087   // Disallow copying and assignment.
1088   basic_stream_socket(const basic_stream_socket&) = delete;
1089   basic_stream_socket& operator=(const basic_stream_socket&) = delete;
1090 
1091   class initiate_async_send
1092   {
1093   public:
1094     typedef Executor executor_type;
1095 
1096     explicit initiate_async_send(basic_stream_socket* self)
1097       : self_(self)
1098     {
1099     }
1100 
1101     const executor_type& get_executor() const noexcept
1102     {
1103       return self_->get_executor();
1104     }
1105 
1106     template <typename WriteHandler, typename ConstBufferSequence>
1107     void operator()(WriteHandler&& handler,
1108         const ConstBufferSequence& buffers,
1109         socket_base::message_flags flags) const
1110     {
1111       // If you get an error on the following line it means that your handler
1112       // does not meet the documented type requirements for a WriteHandler.
1113       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
1114 
1115       detail::non_const_lvalue<WriteHandler> handler2(handler);
1116       self_->impl_.get_service().async_send(
1117           self_->impl_.get_implementation(), buffers, flags,
1118           handler2.value, self_->impl_.get_executor());
1119     }
1120 
1121   private:
1122     basic_stream_socket* self_;
1123   };
1124 
1125   class initiate_async_receive
1126   {
1127   public:
1128     typedef Executor executor_type;
1129 
1130     explicit initiate_async_receive(basic_stream_socket* self)
1131       : self_(self)
1132     {
1133     }
1134 
1135     const executor_type& get_executor() const noexcept
1136     {
1137       return self_->get_executor();
1138     }
1139 
1140     template <typename ReadHandler, typename MutableBufferSequence>
1141     void operator()(ReadHandler&& handler,
1142         const MutableBufferSequence& buffers,
1143         socket_base::message_flags flags) const
1144     {
1145       // If you get an error on the following line it means that your handler
1146       // does not meet the documented type requirements for a ReadHandler.
1147       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1148 
1149       detail::non_const_lvalue<ReadHandler> handler2(handler);
1150       self_->impl_.get_service().async_receive(
1151           self_->impl_.get_implementation(), buffers, flags,
1152           handler2.value, self_->impl_.get_executor());
1153     }
1154 
1155   private:
1156     basic_stream_socket* self_;
1157   };
1158 };
1159 
1160 } // namespace asio
1161 } // namespace boost
1162 
1163 #include <boost/asio/detail/pop_options.hpp>
1164 
1165 #endif // BOOST_ASIO_BASIC_STREAM_SOCKET_HPP