summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/ssl/stream.hpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/include/asio/ssl/stream.hpp')
-rw-r--r--3rdparty/asio/include/asio/ssl/stream.hpp565
1 files changed, 423 insertions, 142 deletions
diff --git a/3rdparty/asio/include/asio/ssl/stream.hpp b/3rdparty/asio/include/asio/ssl/stream.hpp
index bc259b59ca7..befcc287e7f 100644
--- a/3rdparty/asio/include/asio/ssl/stream.hpp
+++ b/3rdparty/asio/include/asio/ssl/stream.hpp
@@ -2,7 +2,7 @@
// ssl/stream.hpp
// ~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -18,8 +18,10 @@
#include "asio/detail/config.hpp"
#include "asio/async_result.hpp"
+#include "asio/buffer.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/handler_type_requirements.hpp"
+#include "asio/detail/non_const_lvalue.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/ssl/context.hpp"
@@ -51,9 +53,9 @@ namespace ssl {
* @par Example
* To use the SSL stream template with an ip::tcp::socket, you would write:
* @code
- * asio::io_context io_context;
+ * asio::io_context my_context;
* asio::ssl::context ctx(asio::ssl::context::sslv23);
- * asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
+ * asio::ssl::stream<asio::ip::tcp::socket> sock(my_context, ctx);
* @endcode
*
* @par Concepts:
@@ -64,6 +66,13 @@ class stream :
public stream_base,
private noncopyable
{
+private:
+ class initiate_async_handshake;
+ class initiate_async_buffered_handshake;
+ class initiate_async_shutdown;
+ class initiate_async_write_some;
+ class initiate_async_read_some;
+
public:
/// The native handle type of the SSL stream.
typedef SSL* native_handle_type;
@@ -75,7 +84,7 @@ public:
};
/// The type of the next layer.
- typedef typename remove_reference<Stream>::type next_layer_type;
+ typedef remove_reference_t<Stream> next_layer_type;
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
@@ -83,7 +92,6 @@ public:
/// The type of the executor associated with the object.
typedef typename lowest_layer_type::executor_type executor_type;
-#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Construct a stream.
/**
* This constructor creates a stream and initialises the underlying stream
@@ -95,20 +103,57 @@ public:
*/
template <typename Arg>
stream(Arg&& arg, context& ctx)
- : next_layer_(ASIO_MOVE_CAST(Arg)(arg)),
- core_(ctx.native_handle(),
- next_layer_.lowest_layer().get_executor().context())
+ : next_layer_(static_cast<Arg&&>(arg)),
+ core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())
{
}
-#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Construct a stream from an existing native implementation.
+ /**
+ * This constructor creates a stream and initialises the underlying stream
+ * object. On success, ownership of the native implementation is transferred
+ * to the stream, and it will be cleaned up when the stream is destroyed.
+ *
+ * @param arg The argument to be passed to initialise the underlying stream.
+ *
+ * @param handle An existing native SSL implementation.
+ */
template <typename Arg>
- stream(Arg& arg, context& ctx)
- : next_layer_(arg),
- core_(ctx.native_handle(),
- next_layer_.lowest_layer().get_executor().context())
+ stream(Arg&& arg, native_handle_type handle)
+ : next_layer_(static_cast<Arg&&>(arg)),
+ core_(handle, next_layer_.lowest_layer().get_executor())
+ {
+ }
+
+ /// Move-construct a stream from another.
+ /**
+ * @param other The other stream object from which the move will occur. Must
+ * have no outstanding asynchronous operations associated with it. Following
+ * the move, @c other has a valid but unspecified state where the only safe
+ * operation is destruction, or use as the target of a move assignment.
+ */
+ stream(stream&& other)
+ : next_layer_(static_cast<Stream&&>(other.next_layer_)),
+ core_(static_cast<detail::stream_core&&>(other.core_))
{
}
-#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Move-assign a stream from another.
+ /**
+ * @param other The other stream object from which the move will occur. Must
+ * have no outstanding asynchronous operations associated with it. Following
+ * the move, @c other has a valid but unspecified state where the only safe
+ * operation is destruction, or use as the target of a move assignment.
+ */
+ stream& operator=(stream&& other)
+ {
+ if (this != &other)
+ {
+ next_layer_ = static_cast<Stream&&>(other.next_layer_);
+ core_ = static_cast<detail::stream_core&&>(other.core_);
+ }
+ return *this;
+ }
/// Destructor.
/**
@@ -126,27 +171,11 @@ public:
*
* @return A copy of the executor that stream will use to dispatch handlers.
*/
- executor_type get_executor() ASIO_NOEXCEPT
+ executor_type get_executor() noexcept
{
return next_layer_.lowest_layer().get_executor();
}
-#if !defined(ASIO_NO_DEPRECATED)
- /// (Deprecated: Use get_executor().) Get the io_context associated with the
- /// object.
- asio::io_context& get_io_context()
- {
- return next_layer_.lowest_layer().get_io_context();
- }
-
- /// (Deprecated: Use get_executor().) Get the io_context associated with the
- /// object.
- asio::io_context& get_io_service()
- {
- return next_layer_.lowest_layer().get_io_service();
- }
-#endif // !defined(ASIO_NO_DEPRECATED)
-
/// Get the underlying implementation in the native type.
/**
* This function may be used to obtain the underlying implementation of the
@@ -158,7 +187,7 @@ public:
* suitable for passing to functions such as @c SSL_get_verify_result and
* @c SSL_get_peer_certificate:
* @code
- * asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
+ * asio::ssl::stream<asio::ip::tcp::socket> sock(io_ctx, ctx);
*
* // ... establish connection and perform handshake ...
*
@@ -435,41 +464,59 @@ public:
/// Start an asynchronous SSL handshake.
/**
* This function is used to asynchronously perform an SSL handshake on the
- * stream. This function call always returns immediately.
+ * stream. It is an initiating function for an @ref asynchronous_operation,
+ * and always returns immediately.
*
* @param type The type of handshaking to be performed, i.e. as a client or as
* a server.
*
- * @param handler The handler to be called when the handshake operation
- * completes. Copies will be made of the handler as required. The equivalent
- * function signature of the handler must be:
+ * @param token The @ref completion_token that will be used to produce a
+ * completion handler, which will be called when the handshake completes.
+ * Potential completion tokens include @ref use_future, @ref use_awaitable,
+ * @ref yield_context, or a function object with the correct completion
+ * signature. The function signature of the completion handler must be:
* @code void handler(
* const asio::error_code& error // Result of operation.
* ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the completion handler will not be invoked from within this function.
+ * On immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using asio::post().
+ *
+ * @par Completion Signature
+ * @code void(asio::error_code) @endcode
+ *
+ * @par Per-Operation Cancellation
+ * This asynchronous operation supports cancellation for the following
+ * asio::cancellation_type values:
+ *
+ * @li @c cancellation_type::terminal
+ *
+ * @li @c cancellation_type::partial
+ *
+ * if they are also supported by the @c Stream type's @c async_read_some and
+ * @c async_write_some operations.
*/
- template <typename HandshakeHandler>
- ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
- void (asio::error_code))
- async_handshake(handshake_type type,
- ASIO_MOVE_ARG(HandshakeHandler) handler)
+ template <
+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))
+ HandshakeToken = default_completion_token_t<executor_type>>
+ auto async_handshake(handshake_type type,
+ HandshakeToken&& token = default_completion_token_t<executor_type>())
+ -> decltype(
+ async_initiate<HandshakeToken,
+ void (asio::error_code)>(
+ declval<initiate_async_handshake>(), token, type))
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a HandshakeHandler.
- ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
-
- asio::async_completion<HandshakeHandler,
- void (asio::error_code)> init(handler);
-
- detail::async_io(next_layer_, core_,
- detail::handshake_op(type), init.completion_handler);
-
- return init.result.get();
+ return async_initiate<HandshakeToken,
+ void (asio::error_code)>(
+ initiate_async_handshake(this), token, type);
}
/// Start an asynchronous SSL handshake.
/**
* This function is used to asynchronously perform an SSL handshake on the
- * stream. This function call always returns immediately.
+ * stream. It is an initiating function for an @ref asynchronous_operation,
+ * and always returns immediately.
*
* @param type The type of handshaking to be performed, i.e. as a client or as
* a server.
@@ -477,35 +524,54 @@ public:
* @param buffers The buffered data to be reused for the handshake. Although
* the buffers object may be copied as necessary, ownership of the underlying
* buffers is retained by the caller, which must guarantee that they remain
- * valid until the handler is called.
+ * valid until the completion handler is called.
*
- * @param handler The handler to be called when the handshake operation
- * completes. Copies will be made of the handler as required. The equivalent
- * function signature of the handler must be:
+ * @param token The @ref completion_token that will be used to produce a
+ * completion handler, which will be called when the handshake completes.
+ * Potential completion tokens include @ref use_future, @ref use_awaitable,
+ * @ref yield_context, or a function object with the correct completion
+ * signature. The function signature of the completion handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Amount of buffers used in handshake.
* ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the completion handler will not be invoked from within this function.
+ * On immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using asio::post().
+ *
+ * @par Completion Signature
+ * @code void(asio::error_code, std::size_t) @endcode
+ *
+ * @par Per-Operation Cancellation
+ * This asynchronous operation supports cancellation for the following
+ * asio::cancellation_type values:
+ *
+ * @li @c cancellation_type::terminal
+ *
+ * @li @c cancellation_type::partial
+ *
+ * if they are also supported by the @c Stream type's @c async_read_some and
+ * @c async_write_some operations.
*/
- template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
- ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
- void (asio::error_code, std::size_t))
- async_handshake(handshake_type type, const ConstBufferSequence& buffers,
- ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
+ template <typename ConstBufferSequence,
+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
+ std::size_t)) BufferedHandshakeToken
+ = default_completion_token_t<executor_type>>
+ auto async_handshake(handshake_type type, const ConstBufferSequence& buffers,
+ BufferedHandshakeToken&& token
+ = default_completion_token_t<executor_type>(),
+ constraint_t<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ > = 0)
+ -> decltype(
+ async_initiate<BufferedHandshakeToken,
+ void (asio::error_code, std::size_t)>(
+ declval<initiate_async_buffered_handshake>(), token, type, buffers))
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a BufferedHandshakeHandler.
- ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
- BufferedHandshakeHandler, handler) type_check;
-
- asio::async_completion<BufferedHandshakeHandler,
- void (asio::error_code, std::size_t)> init(handler);
-
- detail::async_io(next_layer_, core_,
- detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<BufferedHandshakeToken,
+ void (asio::error_code, std::size_t)>(
+ initiate_async_buffered_handshake(this), token, type, buffers);
}
/// Shut down SSL on the stream.
@@ -537,32 +603,51 @@ public:
/// Asynchronously shut down SSL on the stream.
/**
- * This function is used to asynchronously shut down SSL on the stream. This
- * function call always returns immediately.
- *
- * @param handler The handler to be called when the handshake operation
- * completes. Copies will be made of the handler as required. The equivalent
- * function signature of the handler must be:
+ * This function is used to asynchronously shut down SSL on the stream. It is
+ * an initiating function for an @ref asynchronous_operation, and always
+ * returns immediately.
+ *
+ * @param token The @ref completion_token that will be used to produce a
+ * completion handler, which will be called when the shutdown completes.
+ * Potential completion tokens include @ref use_future, @ref use_awaitable,
+ * @ref yield_context, or a function object with the correct completion
+ * signature. The function signature of the completion handler must be:
* @code void handler(
* const asio::error_code& error // Result of operation.
* ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the completion handler will not be invoked from within this function.
+ * On immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using asio::post().
+ *
+ * @par Completion Signature
+ * @code void(asio::error_code) @endcode
+ *
+ * @par Per-Operation Cancellation
+ * This asynchronous operation supports cancellation for the following
+ * asio::cancellation_type values:
+ *
+ * @li @c cancellation_type::terminal
+ *
+ * @li @c cancellation_type::partial
+ *
+ * if they are also supported by the @c Stream type's @c async_read_some and
+ * @c async_write_some operations.
*/
- template <typename ShutdownHandler>
- ASIO_INITFN_RESULT_TYPE(ShutdownHandler,
- void (asio::error_code))
- async_shutdown(ASIO_MOVE_ARG(ShutdownHandler) handler)
+ template <
+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))
+ ShutdownToken
+ = default_completion_token_t<executor_type>>
+ auto async_shutdown(
+ ShutdownToken&& token = default_completion_token_t<executor_type>())
+ -> decltype(
+ async_initiate<ShutdownToken,
+ void (asio::error_code)>(
+ declval<initiate_async_shutdown>(), token))
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ShutdownHandler.
- ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, handler) type_check;
-
- asio::async_completion<ShutdownHandler,
- void (asio::error_code)> init(handler);
-
- detail::async_io(next_layer_, core_, detail::shutdown_op(),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<ShutdownToken,
+ void (asio::error_code)>(
+ initiate_async_shutdown(this), token);
}
/// Write some data to the stream.
@@ -617,43 +702,60 @@ public:
/// Start an asynchronous write.
/**
* This function is used to asynchronously write one or more bytes of data to
- * the stream. The function call always returns immediately.
+ * the stream. It is an initiating function for an @ref
+ * asynchronous_operation, and always returns immediately.
*
* @param buffers The data to be written to the stream. Although the buffers
* object may be copied as necessary, ownership of the underlying buffers is
* retained by the caller, which must guarantee that they remain valid until
- * the handler is called.
+ * the completion handler is called.
*
- * @param handler The handler to be called when the write operation completes.
- * Copies will be made of the handler as required. The equivalent function
- * signature of the handler must be:
+ * @param token The @ref completion_token that will be used to produce a
+ * completion handler, which will be called when the write completes.
+ * Potential completion tokens include @ref use_future, @ref use_awaitable,
+ * @ref yield_context, or a function object with the correct completion
+ * signature. The function signature of the completion handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes written.
+ * std::size_t bytes_transferred // Number of bytes written.
* ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the completion handler will not be invoked from within this function.
+ * On immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using asio::post().
+ *
+ * @par Completion Signature
+ * @code void(asio::error_code, std::size_t) @endcode
*
* @note The async_write_some operation may not transmit all of the data to
* the peer. Consider using the @ref async_write function if you need to
- * ensure that all data is written before the blocking operation completes.
+ * ensure that all data is written before the asynchronous operation
+ * completes.
+ *
+ * @par Per-Operation Cancellation
+ * This asynchronous operation supports cancellation for the following
+ * asio::cancellation_type values:
+ *
+ * @li @c cancellation_type::terminal
+ *
+ * @li @c cancellation_type::partial
+ *
+ * if they are also supported by the @c Stream type's @c async_read_some and
+ * @c async_write_some operations.
*/
- template <typename ConstBufferSequence, typename WriteHandler>
- ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (asio::error_code, std::size_t))
- async_write_some(const ConstBufferSequence& buffers,
- ASIO_MOVE_ARG(WriteHandler) handler)
+ template <typename ConstBufferSequence,
+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
+ std::size_t)) WriteToken = default_completion_token_t<executor_type>>
+ auto async_write_some(const ConstBufferSequence& buffers,
+ WriteToken&& token = default_completion_token_t<executor_type>())
+ -> decltype(
+ async_initiate<WriteToken,
+ void (asio::error_code, std::size_t)>(
+ declval<initiate_async_write_some>(), token, buffers))
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- asio::async_completion<WriteHandler,
- void (asio::error_code, std::size_t)> init(handler);
-
- detail::async_io(next_layer_, core_,
- detail::write_op<ConstBufferSequence>(buffers),
- init.completion_handler);
-
- return init.result.get();
+ return async_initiate<WriteToken,
+ void (asio::error_code, std::size_t)>(
+ initiate_async_write_some(this), token, buffers);
}
/// Read some data from the stream.
@@ -708,47 +810,226 @@ public:
/// Start an asynchronous read.
/**
* This function is used to asynchronously read one or more bytes of data from
- * the stream. The function call always returns immediately.
+ * the stream. It is an initiating function for an @ref
+ * asynchronous_operation, and always returns immediately.
*
* @param buffers The buffers into which the data will be read. Although the
* buffers object may be copied as necessary, ownership of the underlying
* buffers is retained by the caller, which must guarantee that they remain
- * valid until the handler is called.
+ * valid until the completion handler is called.
*
- * @param handler The handler to be called when the read operation completes.
- * Copies will be made of the handler as required. The equivalent function
- * signature of the handler must be:
+ * @param token The @ref completion_token that will be used to produce a
+ * completion handler, which will be called when the read completes.
+ * Potential completion tokens include @ref use_future, @ref use_awaitable,
+ * @ref yield_context, or a function object with the correct completion
+ * signature. The function signature of the completion handler must be:
* @code void handler(
* const asio::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes read.
+ * std::size_t bytes_transferred // Number of bytes read.
* ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the completion handler will not be invoked from within this function.
+ * On immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using asio::post().
+ *
+ * @par Completion Signature
+ * @code void(asio::error_code, std::size_t) @endcode
*
* @note The async_read_some operation may not read all of the requested
* number of bytes. Consider using the @ref async_read function if you need to
* ensure that the requested amount of data is read before the asynchronous
* operation completes.
+ *
+ * @par Per-Operation Cancellation
+ * This asynchronous operation supports cancellation for the following
+ * asio::cancellation_type values:
+ *
+ * @li @c cancellation_type::terminal
+ *
+ * @li @c cancellation_type::partial
+ *
+ * if they are also supported by the @c Stream type's @c async_read_some and
+ * @c async_write_some operations.
*/
- template <typename MutableBufferSequence, typename ReadHandler>
- ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (asio::error_code, std::size_t))
- async_read_some(const MutableBufferSequence& buffers,
- ASIO_MOVE_ARG(ReadHandler) handler)
+ template <typename MutableBufferSequence,
+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
+ std::size_t)) ReadToken = default_completion_token_t<executor_type>>
+ auto async_read_some(const MutableBufferSequence& buffers,
+ ReadToken&& token = default_completion_token_t<executor_type>())
+ -> decltype(
+ async_initiate<ReadToken,
+ void (asio::error_code, std::size_t)>(
+ declval<initiate_async_read_some>(), token, buffers))
+ {
+ return async_initiate<ReadToken,
+ void (asio::error_code, std::size_t)>(
+ initiate_async_read_some(this), token, buffers);
+ }
+
+private:
+ class initiate_async_handshake
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+ public:
+ typedef typename stream::executor_type executor_type;
- asio::async_completion<ReadHandler,
- void (asio::error_code, std::size_t)> init(handler);
+ explicit initiate_async_handshake(stream* self)
+ : self_(self)
+ {
+ }
- detail::async_io(next_layer_, core_,
- detail::read_op<MutableBufferSequence>(buffers),
- init.completion_handler);
+ executor_type get_executor() const noexcept
+ {
+ return self_->get_executor();
+ }
- return init.result.get();
- }
+ template <typename HandshakeHandler>
+ void operator()(HandshakeHandler&& handler,
+ handshake_type type) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a HandshakeHandler.
+ ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
+
+ asio::detail::non_const_lvalue<HandshakeHandler> handler2(handler);
+ detail::async_io(self_->next_layer_, self_->core_,
+ detail::handshake_op(type), handler2.value);
+ }
+
+ private:
+ stream* self_;
+ };
+
+ class initiate_async_buffered_handshake
+ {
+ public:
+ typedef typename stream::executor_type executor_type;
+
+ explicit initiate_async_buffered_handshake(stream* self)
+ : self_(self)
+ {
+ }
+
+ executor_type get_executor() const noexcept
+ {
+ return self_->get_executor();
+ }
+
+ template <typename BufferedHandshakeHandler, typename ConstBufferSequence>
+ void operator()(BufferedHandshakeHandler&& handler,
+ handshake_type type, const ConstBufferSequence& buffers) const
+ {
+ // If you get an error on the following line it means that your
+ // handler does not meet the documented type requirements for a
+ // BufferedHandshakeHandler.
+ ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
+ BufferedHandshakeHandler, handler) type_check;
+
+ asio::detail::non_const_lvalue<
+ BufferedHandshakeHandler> handler2(handler);
+ detail::async_io(self_->next_layer_, self_->core_,
+ detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
+ handler2.value);
+ }
+
+ private:
+ stream* self_;
+ };
+
+ class initiate_async_shutdown
+ {
+ public:
+ typedef typename stream::executor_type executor_type;
+
+ explicit initiate_async_shutdown(stream* self)
+ : self_(self)
+ {
+ }
+
+ executor_type get_executor() const noexcept
+ {
+ return self_->get_executor();
+ }
+
+ template <typename ShutdownHandler>
+ void operator()(ShutdownHandler&& handler) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ShutdownHandler.
+ ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check;
+
+ asio::detail::non_const_lvalue<ShutdownHandler> handler2(handler);
+ detail::async_io(self_->next_layer_, self_->core_,
+ detail::shutdown_op(), handler2.value);
+ }
+
+ private:
+ stream* self_;
+ };
+
+ class initiate_async_write_some
+ {
+ public:
+ typedef typename stream::executor_type executor_type;
+
+ explicit initiate_async_write_some(stream* self)
+ : self_(self)
+ {
+ }
+
+ executor_type get_executor() const noexcept
+ {
+ return self_->get_executor();
+ }
+
+ template <typename WriteHandler, typename ConstBufferSequence>
+ void operator()(WriteHandler&& handler,
+ const ConstBufferSequence& buffers) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ asio::detail::non_const_lvalue<WriteHandler> handler2(handler);
+ detail::async_io(self_->next_layer_, self_->core_,
+ detail::write_op<ConstBufferSequence>(buffers), handler2.value);
+ }
+
+ private:
+ stream* self_;
+ };
+
+ class initiate_async_read_some
+ {
+ public:
+ typedef typename stream::executor_type executor_type;
+
+ explicit initiate_async_read_some(stream* self)
+ : self_(self)
+ {
+ }
+
+ executor_type get_executor() const noexcept
+ {
+ return self_->get_executor();
+ }
+
+ template <typename ReadHandler, typename MutableBufferSequence>
+ void operator()(ReadHandler&& handler,
+ const MutableBufferSequence& buffers) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ asio::detail::non_const_lvalue<ReadHandler> handler2(handler);
+ detail::async_io(self_->next_layer_, self_->core_,
+ detail::read_op<MutableBufferSequence>(buffers), handler2.value);
+ }
+
+ private:
+ stream* self_;
+ };
-private:
Stream next_layer_;
detail::stream_core core_;
};