Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // ssl/stream.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_SSL_STREAM_HPP
0012 #define BOOST_ASIO_SSL_STREAM_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 
0020 #include <boost/asio/async_result.hpp>
0021 #include <boost/asio/buffer.hpp>
0022 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0023 #include <boost/asio/detail/handler_type_requirements.hpp>
0024 #include <boost/asio/detail/non_const_lvalue.hpp>
0025 #include <boost/asio/detail/noncopyable.hpp>
0026 #include <boost/asio/detail/type_traits.hpp>
0027 #include <boost/asio/ssl/context.hpp>
0028 #include <boost/asio/ssl/detail/buffered_handshake_op.hpp>
0029 #include <boost/asio/ssl/detail/handshake_op.hpp>
0030 #include <boost/asio/ssl/detail/io.hpp>
0031 #include <boost/asio/ssl/detail/read_op.hpp>
0032 #include <boost/asio/ssl/detail/shutdown_op.hpp>
0033 #include <boost/asio/ssl/detail/stream_core.hpp>
0034 #include <boost/asio/ssl/detail/write_op.hpp>
0035 #include <boost/asio/ssl/stream_base.hpp>
0036 
0037 #include <boost/asio/detail/push_options.hpp>
0038 
0039 namespace boost {
0040 namespace asio {
0041 namespace ssl {
0042 
0043 /// Provides stream-oriented functionality using SSL.
0044 /**
0045  * The stream class template provides asynchronous and blocking stream-oriented
0046  * functionality using SSL.
0047  *
0048  * @par Thread Safety
0049  * @e Distinct @e objects: Safe.@n
0050  * @e Shared @e objects: Unsafe. The application must also ensure that all
0051  * asynchronous operations are performed within the same implicit or explicit
0052  * strand.
0053  *
0054  * @par Example
0055  * To use the SSL stream template with an ip::tcp::socket, you would write:
0056  * @code
0057  * boost::asio::io_context my_context;
0058  * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
0059  * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx);
0060  * @endcode
0061  *
0062  * @par Concepts:
0063  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
0064  */
0065 template <typename Stream>
0066 class stream :
0067   public stream_base,
0068   private noncopyable
0069 {
0070 private:
0071   class initiate_async_handshake;
0072   class initiate_async_buffered_handshake;
0073   class initiate_async_shutdown;
0074   class initiate_async_write_some;
0075   class initiate_async_read_some;
0076 
0077 public:
0078   /// The native handle type of the SSL stream.
0079   typedef SSL* native_handle_type;
0080 
0081   /// Structure for use with deprecated impl_type.
0082   struct impl_struct
0083   {
0084     SSL* ssl;
0085   };
0086 
0087   /// The type of the next layer.
0088   typedef remove_reference_t<Stream> next_layer_type;
0089 
0090   /// The type of the lowest layer.
0091   typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
0092 
0093   /// The type of the executor associated with the object.
0094   typedef typename lowest_layer_type::executor_type executor_type;
0095 
0096   /// Construct a stream.
0097   /**
0098    * This constructor creates a stream and initialises the underlying stream
0099    * object.
0100    *
0101    * @param arg The argument to be passed to initialise the underlying stream.
0102    *
0103    * @param ctx The SSL context to be used for the stream.
0104    */
0105   template <typename Arg>
0106   stream(Arg&& arg, context& ctx)
0107     : next_layer_(static_cast<Arg&&>(arg)),
0108       core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())
0109   {
0110   }
0111 
0112   /// Construct a stream from an existing native implementation.
0113   /**
0114    * This constructor creates a stream and initialises the underlying stream
0115    * object. On success, ownership of the native implementation is transferred
0116    * to the stream, and it will be cleaned up when the stream is destroyed.
0117    *
0118    * @param arg The argument to be passed to initialise the underlying stream.
0119    *
0120    * @param handle An existing native SSL implementation.
0121    */
0122   template <typename Arg>
0123   stream(Arg&& arg, native_handle_type handle)
0124     : next_layer_(static_cast<Arg&&>(arg)),
0125       core_(handle, next_layer_.lowest_layer().get_executor())
0126   {
0127   }
0128 
0129   /// Move-construct a stream from another.
0130   /**
0131    * @param other The other stream object from which the move will occur. Must
0132    * have no outstanding asynchronous operations associated with it. Following
0133    * the move, @c other has a valid but unspecified state where the only safe
0134    * operation is destruction, or use as the target of a move assignment.
0135    */
0136   stream(stream&& other)
0137     : next_layer_(static_cast<Stream&&>(other.next_layer_)),
0138       core_(static_cast<detail::stream_core&&>(other.core_))
0139   {
0140   }
0141 
0142   /// Move-assign a stream from another.
0143   /**
0144    * @param other The other stream object from which the move will occur. Must
0145    * have no outstanding asynchronous operations associated with it. Following
0146    * the move, @c other has a valid but unspecified state where the only safe
0147    * operation is destruction, or use as the target of a move assignment.
0148    */
0149   stream& operator=(stream&& other)
0150   {
0151     if (this != &other)
0152     {
0153       next_layer_ = static_cast<Stream&&>(other.next_layer_);
0154       core_ = static_cast<detail::stream_core&&>(other.core_);
0155     }
0156     return *this;
0157   }
0158 
0159   /// Destructor.
0160   /**
0161    * @note A @c stream object must not be destroyed while there are pending
0162    * asynchronous operations associated with it.
0163    */
0164   ~stream()
0165   {
0166   }
0167 
0168   /// Get the executor associated with the object.
0169   /**
0170    * This function may be used to obtain the executor object that the stream
0171    * uses to dispatch handlers for asynchronous operations.
0172    *
0173    * @return A copy of the executor that stream will use to dispatch handlers.
0174    */
0175   executor_type get_executor() noexcept
0176   {
0177     return next_layer_.lowest_layer().get_executor();
0178   }
0179 
0180   /// Get the underlying implementation in the native type.
0181   /**
0182    * This function may be used to obtain the underlying implementation of the
0183    * context. This is intended to allow access to context functionality that is
0184    * not otherwise provided.
0185    *
0186    * @par Example
0187    * The native_handle() function returns a pointer of type @c SSL* that is
0188    * suitable for passing to functions such as @c SSL_get_verify_result and
0189    * @c SSL_get_peer_certificate:
0190    * @code
0191    * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx);
0192    *
0193    * // ... establish connection and perform handshake ...
0194    *
0195    * if (X509* cert = SSL_get_peer_certificate(sock.native_handle()))
0196    * {
0197    *   if (SSL_get_verify_result(sock.native_handle()) == X509_V_OK)
0198    *   {
0199    *     // ...
0200    *   }
0201    * }
0202    * @endcode
0203    */
0204   native_handle_type native_handle()
0205   {
0206     return core_.engine_.native_handle();
0207   }
0208 
0209   /// Get a reference to the next layer.
0210   /**
0211    * This function returns a reference to the next layer in a stack of stream
0212    * layers.
0213    *
0214    * @return A reference to the next layer in the stack of stream layers.
0215    * Ownership is not transferred to the caller.
0216    */
0217   const next_layer_type& next_layer() const
0218   {
0219     return next_layer_;
0220   }
0221 
0222   /// Get a reference to the next layer.
0223   /**
0224    * This function returns a reference to the next layer in a stack of stream
0225    * layers.
0226    *
0227    * @return A reference to the next layer in the stack of stream layers.
0228    * Ownership is not transferred to the caller.
0229    */
0230   next_layer_type& next_layer()
0231   {
0232     return next_layer_;
0233   }
0234 
0235   /// Get a reference to the lowest layer.
0236   /**
0237    * This function returns a reference to the lowest layer in a stack of
0238    * stream layers.
0239    *
0240    * @return A reference to the lowest layer in the stack of stream layers.
0241    * Ownership is not transferred to the caller.
0242    */
0243   lowest_layer_type& lowest_layer()
0244   {
0245     return next_layer_.lowest_layer();
0246   }
0247 
0248   /// Get a reference to the lowest layer.
0249   /**
0250    * This function returns a reference to the lowest layer in a stack of
0251    * stream layers.
0252    *
0253    * @return A reference to the lowest layer in the stack of stream layers.
0254    * Ownership is not transferred to the caller.
0255    */
0256   const lowest_layer_type& lowest_layer() const
0257   {
0258     return next_layer_.lowest_layer();
0259   }
0260 
0261   /// Set the peer verification mode.
0262   /**
0263    * This function may be used to configure the peer verification mode used by
0264    * the stream. The new mode will override the mode inherited from the context.
0265    *
0266    * @param v A bitmask of peer verification modes. See @ref verify_mode for
0267    * available values.
0268    *
0269    * @throws boost::system::system_error Thrown on failure.
0270    *
0271    * @note Calls @c SSL_set_verify.
0272    */
0273   void set_verify_mode(verify_mode v)
0274   {
0275     boost::system::error_code ec;
0276     set_verify_mode(v, ec);
0277     boost::asio::detail::throw_error(ec, "set_verify_mode");
0278   }
0279 
0280   /// Set the peer verification mode.
0281   /**
0282    * This function may be used to configure the peer verification mode used by
0283    * the stream. The new mode will override the mode inherited from the context.
0284    *
0285    * @param v A bitmask of peer verification modes. See @ref verify_mode for
0286    * available values.
0287    *
0288    * @param ec Set to indicate what error occurred, if any.
0289    *
0290    * @note Calls @c SSL_set_verify.
0291    */
0292   BOOST_ASIO_SYNC_OP_VOID set_verify_mode(
0293       verify_mode v, boost::system::error_code& ec)
0294   {
0295     core_.engine_.set_verify_mode(v, ec);
0296     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0297   }
0298 
0299   /// Set the peer verification depth.
0300   /**
0301    * This function may be used to configure the maximum verification depth
0302    * allowed by the stream.
0303    *
0304    * @param depth Maximum depth for the certificate chain verification that
0305    * shall be allowed.
0306    *
0307    * @throws boost::system::system_error Thrown on failure.
0308    *
0309    * @note Calls @c SSL_set_verify_depth.
0310    */
0311   void set_verify_depth(int depth)
0312   {
0313     boost::system::error_code ec;
0314     set_verify_depth(depth, ec);
0315     boost::asio::detail::throw_error(ec, "set_verify_depth");
0316   }
0317 
0318   /// Set the peer verification depth.
0319   /**
0320    * This function may be used to configure the maximum verification depth
0321    * allowed by the stream.
0322    *
0323    * @param depth Maximum depth for the certificate chain verification that
0324    * shall be allowed.
0325    *
0326    * @param ec Set to indicate what error occurred, if any.
0327    *
0328    * @note Calls @c SSL_set_verify_depth.
0329    */
0330   BOOST_ASIO_SYNC_OP_VOID set_verify_depth(
0331       int depth, boost::system::error_code& ec)
0332   {
0333     core_.engine_.set_verify_depth(depth, ec);
0334     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0335   }
0336 
0337   /// Set the callback used to verify peer certificates.
0338   /**
0339    * This function is used to specify a callback function that will be called
0340    * by the implementation when it needs to verify a peer certificate.
0341    *
0342    * @param callback The function object to be used for verifying a certificate.
0343    * The function signature of the handler must be:
0344    * @code bool verify_callback(
0345    *   bool preverified, // True if the certificate passed pre-verification.
0346    *   verify_context& ctx // The peer certificate and other context.
0347    * ); @endcode
0348    * The return value of the callback is true if the certificate has passed
0349    * verification, false otherwise.
0350    *
0351    * @throws boost::system::system_error Thrown on failure.
0352    *
0353    * @note Calls @c SSL_set_verify.
0354    */
0355   template <typename VerifyCallback>
0356   void set_verify_callback(VerifyCallback callback)
0357   {
0358     boost::system::error_code ec;
0359     this->set_verify_callback(callback, ec);
0360     boost::asio::detail::throw_error(ec, "set_verify_callback");
0361   }
0362 
0363   /// Set the callback used to verify peer certificates.
0364   /**
0365    * This function is used to specify a callback function that will be called
0366    * by the implementation when it needs to verify a peer certificate.
0367    *
0368    * @param callback The function object to be used for verifying a certificate.
0369    * The function signature of the handler must be:
0370    * @code bool verify_callback(
0371    *   bool preverified, // True if the certificate passed pre-verification.
0372    *   verify_context& ctx // The peer certificate and other context.
0373    * ); @endcode
0374    * The return value of the callback is true if the certificate has passed
0375    * verification, false otherwise.
0376    *
0377    * @param ec Set to indicate what error occurred, if any.
0378    *
0379    * @note Calls @c SSL_set_verify.
0380    */
0381   template <typename VerifyCallback>
0382   BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,
0383       boost::system::error_code& ec)
0384   {
0385     core_.engine_.set_verify_callback(
0386         new detail::verify_callback<VerifyCallback>(callback), ec);
0387     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0388   }
0389 
0390   /// Perform SSL handshaking.
0391   /**
0392    * This function is used to perform SSL handshaking on the stream. The
0393    * function call will block until handshaking is complete or an error occurs.
0394    *
0395    * @param type The type of handshaking to be performed, i.e. as a client or as
0396    * a server.
0397    *
0398    * @throws boost::system::system_error Thrown on failure.
0399    */
0400   void handshake(handshake_type type)
0401   {
0402     boost::system::error_code ec;
0403     handshake(type, ec);
0404     boost::asio::detail::throw_error(ec, "handshake");
0405   }
0406 
0407   /// Perform SSL handshaking.
0408   /**
0409    * This function is used to perform SSL handshaking on the stream. The
0410    * function call will block until handshaking is complete or an error occurs.
0411    *
0412    * @param type The type of handshaking to be performed, i.e. as a client or as
0413    * a server.
0414    *
0415    * @param ec Set to indicate what error occurred, if any.
0416    */
0417   BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
0418       boost::system::error_code& ec)
0419   {
0420     detail::io(next_layer_, core_, detail::handshake_op(type), ec);
0421     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0422   }
0423 
0424   /// Perform SSL handshaking.
0425   /**
0426    * This function is used to perform SSL handshaking on the stream. The
0427    * function call will block until handshaking is complete or an error occurs.
0428    *
0429    * @param type The type of handshaking to be performed, i.e. as a client or as
0430    * a server.
0431    *
0432    * @param buffers The buffered data to be reused for the handshake.
0433    *
0434    * @throws boost::system::system_error Thrown on failure.
0435    */
0436   template <typename ConstBufferSequence>
0437   void handshake(handshake_type type, const ConstBufferSequence& buffers)
0438   {
0439     boost::system::error_code ec;
0440     handshake(type, buffers, ec);
0441     boost::asio::detail::throw_error(ec, "handshake");
0442   }
0443 
0444   /// Perform SSL handshaking.
0445   /**
0446    * This function is used to perform SSL handshaking on the stream. The
0447    * function call will block until handshaking is complete or an error occurs.
0448    *
0449    * @param type The type of handshaking to be performed, i.e. as a client or as
0450    * a server.
0451    *
0452    * @param buffers The buffered data to be reused for the handshake.
0453    *
0454    * @param ec Set to indicate what error occurred, if any.
0455    */
0456   template <typename ConstBufferSequence>
0457   BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
0458       const ConstBufferSequence& buffers, boost::system::error_code& ec)
0459   {
0460     detail::io(next_layer_, core_,
0461         detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec);
0462     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0463   }
0464 
0465   /// Start an asynchronous SSL handshake.
0466   /**
0467    * This function is used to asynchronously perform an SSL handshake on the
0468    * stream. It is an initiating function for an @ref asynchronous_operation,
0469    * and always returns immediately.
0470    *
0471    * @param type The type of handshaking to be performed, i.e. as a client or as
0472    * a server.
0473    *
0474    * @param token The @ref completion_token that will be used to produce a
0475    * completion handler, which will be called when the handshake completes.
0476    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0477    * @ref yield_context, or a function object with the correct completion
0478    * signature. The function signature of the completion handler must be:
0479    * @code void handler(
0480    *   const boost::system::error_code& error // Result of operation.
0481    * ); @endcode
0482    * Regardless of whether the asynchronous operation completes immediately or
0483    * not, the completion handler will not be invoked from within this function.
0484    * On immediate completion, invocation of the handler will be performed in a
0485    * manner equivalent to using boost::asio::post().
0486    *
0487    * @par Completion Signature
0488    * @code void(boost::system::error_code) @endcode
0489    *
0490    * @par Per-Operation Cancellation
0491    * This asynchronous operation supports cancellation for the following
0492    * boost::asio::cancellation_type values:
0493    *
0494    * @li @c cancellation_type::terminal
0495    *
0496    * @li @c cancellation_type::partial
0497    *
0498    * if they are also supported by the @c Stream type's @c async_read_some and
0499    * @c async_write_some operations.
0500    */
0501   template <
0502       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
0503         HandshakeToken = default_completion_token_t<executor_type>>
0504   auto async_handshake(handshake_type type,
0505       HandshakeToken&& token = default_completion_token_t<executor_type>())
0506     -> decltype(
0507       async_initiate<HandshakeToken,
0508         void (boost::system::error_code)>(
0509           declval<initiate_async_handshake>(), token, type))
0510   {
0511     return async_initiate<HandshakeToken,
0512       void (boost::system::error_code)>(
0513         initiate_async_handshake(this), token, type);
0514   }
0515 
0516   /// Start an asynchronous SSL handshake.
0517   /**
0518    * This function is used to asynchronously perform an SSL handshake on the
0519    * stream. It is an initiating function for an @ref asynchronous_operation,
0520    * and always returns immediately.
0521    *
0522    * @param type The type of handshaking to be performed, i.e. as a client or as
0523    * a server.
0524    *
0525    * @param buffers The buffered data to be reused for the handshake. Although
0526    * the buffers object may be copied as necessary, ownership of the underlying
0527    * buffers is retained by the caller, which must guarantee that they remain
0528    * valid until the completion handler is called.
0529    *
0530    * @param token The @ref completion_token that will be used to produce a
0531    * completion handler, which will be called when the handshake completes.
0532    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0533    * @ref yield_context, or a function object with the correct completion
0534    * signature. The function signature of the completion handler must be:
0535    * @code void handler(
0536    *   const boost::system::error_code& error, // Result of operation.
0537    *   std::size_t bytes_transferred // Amount of buffers used in handshake.
0538    * ); @endcode
0539    * Regardless of whether the asynchronous operation completes immediately or
0540    * not, the completion handler will not be invoked from within this function.
0541    * On immediate completion, invocation of the handler will be performed in a
0542    * manner equivalent to using boost::asio::post().
0543    *
0544    * @par Completion Signature
0545    * @code void(boost::system::error_code, std::size_t) @endcode
0546    *
0547    * @par Per-Operation Cancellation
0548    * This asynchronous operation supports cancellation for the following
0549    * boost::asio::cancellation_type values:
0550    *
0551    * @li @c cancellation_type::terminal
0552    *
0553    * @li @c cancellation_type::partial
0554    *
0555    * if they are also supported by the @c Stream type's @c async_read_some and
0556    * @c async_write_some operations.
0557    */
0558   template <typename ConstBufferSequence,
0559       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0560         std::size_t)) BufferedHandshakeToken
0561           = default_completion_token_t<executor_type>>
0562   auto async_handshake(handshake_type type, const ConstBufferSequence& buffers,
0563       BufferedHandshakeToken&& token
0564         = default_completion_token_t<executor_type>(),
0565       constraint_t<
0566         is_const_buffer_sequence<ConstBufferSequence>::value
0567       > = 0)
0568     -> decltype(
0569       async_initiate<BufferedHandshakeToken,
0570         void (boost::system::error_code, std::size_t)>(
0571           declval<initiate_async_buffered_handshake>(), token, type, buffers))
0572   {
0573     return async_initiate<BufferedHandshakeToken,
0574       void (boost::system::error_code, std::size_t)>(
0575         initiate_async_buffered_handshake(this), token, type, buffers);
0576   }
0577 
0578   /// Shut down SSL on the stream.
0579   /**
0580    * This function is used to shut down SSL on the stream. The function call
0581    * will block until SSL has been shut down or an error occurs.
0582    *
0583    * @throws boost::system::system_error Thrown on failure.
0584    */
0585   void shutdown()
0586   {
0587     boost::system::error_code ec;
0588     shutdown(ec);
0589     boost::asio::detail::throw_error(ec, "shutdown");
0590   }
0591 
0592   /// Shut down SSL on the stream.
0593   /**
0594    * This function is used to shut down SSL on the stream. The function call
0595    * will block until SSL has been shut down or an error occurs.
0596    *
0597    * @param ec Set to indicate what error occurred, if any.
0598    */
0599   BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec)
0600   {
0601     detail::io(next_layer_, core_, detail::shutdown_op(), ec);
0602     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0603   }
0604 
0605   /// Asynchronously shut down SSL on the stream.
0606   /**
0607    * This function is used to asynchronously shut down SSL on the stream. It is
0608    * an initiating function for an @ref asynchronous_operation, and always
0609    * returns immediately.
0610    *
0611    * @param token The @ref completion_token that will be used to produce a
0612    * completion handler, which will be called when the shutdown completes.
0613    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0614    * @ref yield_context, or a function object with the correct completion
0615    * signature. The function signature of the completion handler must be:
0616    * @code void handler(
0617    *   const boost::system::error_code& error // Result of operation.
0618    * ); @endcode
0619    * Regardless of whether the asynchronous operation completes immediately or
0620    * not, the completion handler will not be invoked from within this function.
0621    * On immediate completion, invocation of the handler will be performed in a
0622    * manner equivalent to using boost::asio::post().
0623    *
0624    * @par Completion Signature
0625    * @code void(boost::system::error_code) @endcode
0626    *
0627    * @par Per-Operation Cancellation
0628    * This asynchronous operation supports cancellation for the following
0629    * boost::asio::cancellation_type values:
0630    *
0631    * @li @c cancellation_type::terminal
0632    *
0633    * @li @c cancellation_type::partial
0634    *
0635    * if they are also supported by the @c Stream type's @c async_read_some and
0636    * @c async_write_some operations.
0637    */
0638   template <
0639       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
0640         ShutdownToken
0641           = default_completion_token_t<executor_type>>
0642   auto async_shutdown(
0643       ShutdownToken&& token = default_completion_token_t<executor_type>())
0644     -> decltype(
0645       async_initiate<ShutdownToken,
0646         void (boost::system::error_code)>(
0647           declval<initiate_async_shutdown>(), token))
0648   {
0649     return async_initiate<ShutdownToken,
0650       void (boost::system::error_code)>(
0651         initiate_async_shutdown(this), token);
0652   }
0653 
0654   /// Write some data to the stream.
0655   /**
0656    * This function is used to write data on the stream. The function call will
0657    * block until one or more bytes of data has been written successfully, or
0658    * until an error occurs.
0659    *
0660    * @param buffers The data to be written.
0661    *
0662    * @returns The number of bytes written.
0663    *
0664    * @throws boost::system::system_error Thrown on failure.
0665    *
0666    * @note The write_some operation may not transmit all of the data to the
0667    * peer. Consider using the @ref write function if you need to ensure that all
0668    * data is written before the blocking operation completes.
0669    */
0670   template <typename ConstBufferSequence>
0671   std::size_t write_some(const ConstBufferSequence& buffers)
0672   {
0673     boost::system::error_code ec;
0674     std::size_t n = write_some(buffers, ec);
0675     boost::asio::detail::throw_error(ec, "write_some");
0676     return n;
0677   }
0678 
0679   /// Write some data to the stream.
0680   /**
0681    * This function is used to write data on the stream. The function call will
0682    * block until one or more bytes of data has been written successfully, or
0683    * until an error occurs.
0684    *
0685    * @param buffers The data to be written to the stream.
0686    *
0687    * @param ec Set to indicate what error occurred, if any.
0688    *
0689    * @returns The number of bytes written. Returns 0 if an error occurred.
0690    *
0691    * @note The write_some operation may not transmit all of the data to the
0692    * peer. Consider using the @ref write function if you need to ensure that all
0693    * data is written before the blocking operation completes.
0694    */
0695   template <typename ConstBufferSequence>
0696   std::size_t write_some(const ConstBufferSequence& buffers,
0697       boost::system::error_code& ec)
0698   {
0699     return detail::io(next_layer_, core_,
0700         detail::write_op<ConstBufferSequence>(buffers), ec);
0701   }
0702 
0703   /// Start an asynchronous write.
0704   /**
0705    * This function is used to asynchronously write one or more bytes of data to
0706    * the stream. It is an initiating function for an @ref
0707    * asynchronous_operation, and always returns immediately.
0708    *
0709    * @param buffers The data to be written to the stream. Although the buffers
0710    * object may be copied as necessary, ownership of the underlying buffers is
0711    * retained by the caller, which must guarantee that they remain valid until
0712    * the completion handler is called.
0713    *
0714    * @param token The @ref completion_token that will be used to produce a
0715    * completion handler, which will be called when the write completes.
0716    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0717    * @ref yield_context, or a function object with the correct completion
0718    * signature. The function signature of the completion handler must be:
0719    * @code void handler(
0720    *   const boost::system::error_code& error, // Result of operation.
0721    *   std::size_t bytes_transferred // Number of bytes written.
0722    * ); @endcode
0723    * Regardless of whether the asynchronous operation completes immediately or
0724    * not, the completion handler will not be invoked from within this function.
0725    * On immediate completion, invocation of the handler will be performed in a
0726    * manner equivalent to using boost::asio::post().
0727    *
0728    * @par Completion Signature
0729    * @code void(boost::system::error_code, std::size_t) @endcode
0730    *
0731    * @note The async_write_some operation may not transmit all of the data to
0732    * the peer. Consider using the @ref async_write function if you need to
0733    * ensure that all data is written before the asynchronous operation
0734    * completes.
0735    *
0736    * @par Per-Operation Cancellation
0737    * This asynchronous operation supports cancellation for the following
0738    * boost::asio::cancellation_type values:
0739    *
0740    * @li @c cancellation_type::terminal
0741    *
0742    * @li @c cancellation_type::partial
0743    *
0744    * if they are also supported by the @c Stream type's @c async_read_some and
0745    * @c async_write_some operations.
0746    */
0747   template <typename ConstBufferSequence,
0748       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0749         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0750   auto async_write_some(const ConstBufferSequence& buffers,
0751       WriteToken&& token = default_completion_token_t<executor_type>())
0752     -> decltype(
0753       async_initiate<WriteToken,
0754         void (boost::system::error_code, std::size_t)>(
0755           declval<initiate_async_write_some>(), token, buffers))
0756   {
0757     return async_initiate<WriteToken,
0758       void (boost::system::error_code, std::size_t)>(
0759         initiate_async_write_some(this), token, buffers);
0760   }
0761 
0762   /// Read some data from the stream.
0763   /**
0764    * This function is used to read data from the stream. The function call will
0765    * block until one or more bytes of data has been read successfully, or until
0766    * an error occurs.
0767    *
0768    * @param buffers The buffers into which the data will be read.
0769    *
0770    * @returns The number of bytes read.
0771    *
0772    * @throws boost::system::system_error Thrown on failure.
0773    *
0774    * @note The read_some operation may not read all of the requested number of
0775    * bytes. Consider using the @ref read function if you need to ensure that the
0776    * requested amount of data is read before the blocking operation completes.
0777    */
0778   template <typename MutableBufferSequence>
0779   std::size_t read_some(const MutableBufferSequence& buffers)
0780   {
0781     boost::system::error_code ec;
0782     std::size_t n = read_some(buffers, ec);
0783     boost::asio::detail::throw_error(ec, "read_some");
0784     return n;
0785   }
0786 
0787   /// Read some data from the stream.
0788   /**
0789    * This function is used to read data from the stream. The function call will
0790    * block until one or more bytes of data has been read successfully, or until
0791    * an error occurs.
0792    *
0793    * @param buffers The buffers into which the data will be read.
0794    *
0795    * @param ec Set to indicate what error occurred, if any.
0796    *
0797    * @returns The number of bytes read. Returns 0 if an error occurred.
0798    *
0799    * @note The read_some operation may not read all of the requested number of
0800    * bytes. Consider using the @ref read function if you need to ensure that the
0801    * requested amount of data is read before the blocking operation completes.
0802    */
0803   template <typename MutableBufferSequence>
0804   std::size_t read_some(const MutableBufferSequence& buffers,
0805       boost::system::error_code& ec)
0806   {
0807     return detail::io(next_layer_, core_,
0808         detail::read_op<MutableBufferSequence>(buffers), ec);
0809   }
0810 
0811   /// Start an asynchronous read.
0812   /**
0813    * This function is used to asynchronously read one or more bytes of data from
0814    * the stream. It is an initiating function for an @ref
0815    * asynchronous_operation, and always returns immediately.
0816    *
0817    * @param buffers The buffers into which the data will be read. Although the
0818    * buffers object may be copied as necessary, ownership of the underlying
0819    * buffers is retained by the caller, which must guarantee that they remain
0820    * valid until the completion handler is called.
0821    *
0822    * @param token The @ref completion_token that will be used to produce a
0823    * completion handler, which will be called when the read completes.
0824    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0825    * @ref yield_context, or a function object with the correct completion
0826    * signature. The function signature of the completion handler must be:
0827    * @code void handler(
0828    *   const boost::system::error_code& error, // Result of operation.
0829    *   std::size_t bytes_transferred // Number of bytes read.
0830    * ); @endcode
0831    * Regardless of whether the asynchronous operation completes immediately or
0832    * not, the completion handler will not be invoked from within this function.
0833    * On immediate completion, invocation of the handler will be performed in a
0834    * manner equivalent to using boost::asio::post().
0835    *
0836    * @par Completion Signature
0837    * @code void(boost::system::error_code, std::size_t) @endcode
0838    *
0839    * @note The async_read_some operation may not read all of the requested
0840    * number of bytes. Consider using the @ref async_read function if you need to
0841    * ensure that the requested amount of data is read before the asynchronous
0842    * operation completes.
0843    *
0844    * @par Per-Operation Cancellation
0845    * This asynchronous operation supports cancellation for the following
0846    * boost::asio::cancellation_type values:
0847    *
0848    * @li @c cancellation_type::terminal
0849    *
0850    * @li @c cancellation_type::partial
0851    *
0852    * if they are also supported by the @c Stream type's @c async_read_some and
0853    * @c async_write_some operations.
0854    */
0855   template <typename MutableBufferSequence,
0856       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0857         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0858   auto async_read_some(const MutableBufferSequence& buffers,
0859       ReadToken&& token = default_completion_token_t<executor_type>())
0860     -> decltype(
0861       async_initiate<ReadToken,
0862         void (boost::system::error_code, std::size_t)>(
0863           declval<initiate_async_read_some>(), token, buffers))
0864   {
0865     return async_initiate<ReadToken,
0866       void (boost::system::error_code, std::size_t)>(
0867         initiate_async_read_some(this), token, buffers);
0868   }
0869 
0870 private:
0871   class initiate_async_handshake
0872   {
0873   public:
0874     typedef typename stream::executor_type executor_type;
0875 
0876     explicit initiate_async_handshake(stream* self)
0877       : self_(self)
0878     {
0879     }
0880 
0881     executor_type get_executor() const noexcept
0882     {
0883       return self_->get_executor();
0884     }
0885 
0886     template <typename HandshakeHandler>
0887     void operator()(HandshakeHandler&& handler,
0888         handshake_type type) const
0889     {
0890       // If you get an error on the following line it means that your handler
0891       // does not meet the documented type requirements for a HandshakeHandler.
0892       BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
0893 
0894       boost::asio::detail::non_const_lvalue<HandshakeHandler> handler2(handler);
0895       detail::async_io(self_->next_layer_, self_->core_,
0896           detail::handshake_op(type), handler2.value);
0897     }
0898 
0899   private:
0900     stream* self_;
0901   };
0902 
0903   class initiate_async_buffered_handshake
0904   {
0905   public:
0906     typedef typename stream::executor_type executor_type;
0907 
0908     explicit initiate_async_buffered_handshake(stream* self)
0909       : self_(self)
0910     {
0911     }
0912 
0913     executor_type get_executor() const noexcept
0914     {
0915       return self_->get_executor();
0916     }
0917 
0918     template <typename BufferedHandshakeHandler, typename ConstBufferSequence>
0919     void operator()(BufferedHandshakeHandler&& handler,
0920         handshake_type type, const ConstBufferSequence& buffers) const
0921     {
0922       // If you get an error on the following line it means that your
0923       // handler does not meet the documented type requirements for a
0924       // BufferedHandshakeHandler.
0925       BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
0926           BufferedHandshakeHandler, handler) type_check;
0927 
0928       boost::asio::detail::non_const_lvalue<
0929           BufferedHandshakeHandler> handler2(handler);
0930       detail::async_io(self_->next_layer_, self_->core_,
0931           detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
0932           handler2.value);
0933     }
0934 
0935   private:
0936     stream* self_;
0937   };
0938 
0939   class initiate_async_shutdown
0940   {
0941   public:
0942     typedef typename stream::executor_type executor_type;
0943 
0944     explicit initiate_async_shutdown(stream* self)
0945       : self_(self)
0946     {
0947     }
0948 
0949     executor_type get_executor() const noexcept
0950     {
0951       return self_->get_executor();
0952     }
0953 
0954     template <typename ShutdownHandler>
0955     void operator()(ShutdownHandler&& handler) const
0956     {
0957       // If you get an error on the following line it means that your handler
0958       // does not meet the documented type requirements for a ShutdownHandler.
0959       BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check;
0960 
0961       boost::asio::detail::non_const_lvalue<ShutdownHandler> handler2(handler);
0962       detail::async_io(self_->next_layer_, self_->core_,
0963           detail::shutdown_op(), handler2.value);
0964     }
0965 
0966   private:
0967     stream* self_;
0968   };
0969 
0970   class initiate_async_write_some
0971   {
0972   public:
0973     typedef typename stream::executor_type executor_type;
0974 
0975     explicit initiate_async_write_some(stream* self)
0976       : self_(self)
0977     {
0978     }
0979 
0980     executor_type get_executor() const noexcept
0981     {
0982       return self_->get_executor();
0983     }
0984 
0985     template <typename WriteHandler, typename ConstBufferSequence>
0986     void operator()(WriteHandler&& handler,
0987         const ConstBufferSequence& buffers) const
0988     {
0989       // If you get an error on the following line it means that your handler
0990       // does not meet the documented type requirements for a WriteHandler.
0991       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0992 
0993       boost::asio::detail::non_const_lvalue<WriteHandler> handler2(handler);
0994       detail::async_io(self_->next_layer_, self_->core_,
0995           detail::write_op<ConstBufferSequence>(buffers), handler2.value);
0996     }
0997 
0998   private:
0999     stream* self_;
1000   };
1001 
1002   class initiate_async_read_some
1003   {
1004   public:
1005     typedef typename stream::executor_type executor_type;
1006 
1007     explicit initiate_async_read_some(stream* self)
1008       : self_(self)
1009     {
1010     }
1011 
1012     executor_type get_executor() const noexcept
1013     {
1014       return self_->get_executor();
1015     }
1016 
1017     template <typename ReadHandler, typename MutableBufferSequence>
1018     void operator()(ReadHandler&& handler,
1019         const MutableBufferSequence& buffers) const
1020     {
1021       // If you get an error on the following line it means that your handler
1022       // does not meet the documented type requirements for a ReadHandler.
1023       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1024 
1025       boost::asio::detail::non_const_lvalue<ReadHandler> handler2(handler);
1026       detail::async_io(self_->next_layer_, self_->core_,
1027           detail::read_op<MutableBufferSequence>(buffers), handler2.value);
1028     }
1029 
1030   private:
1031     stream* self_;
1032   };
1033 
1034   Stream next_layer_;
1035   detail::stream_core core_;
1036 };
1037 
1038 } // namespace ssl
1039 } // namespace asio
1040 } // namespace boost
1041 
1042 #include <boost/asio/detail/pop_options.hpp>
1043 
1044 #endif // BOOST_ASIO_SSL_STREAM_HPP