aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Rantzsch <[email protected]>2021-03-29 13:51:01 +0200
committerHannes Rantzsch <[email protected]>2021-03-30 13:41:16 +0200
commit9e702ccbbb6f62424d81ce8ecc3e8f5c1e0f130b (patch)
tree5b2f4c6f31993f4d75e743a1c9999e711c6b8423
parentebf264977d52b6bd2da1614b97f88d796d07a1e4 (diff)
TLS::Stream Asio extensible model compatibility
Async functions can now handle generic completion tokens rather than callback functions only. Fixes #2648
-rw-r--r--src/lib/tls/asio/asio_stream.h152
1 files changed, 81 insertions, 71 deletions
diff --git a/src/lib/tls/asio/asio_stream.h b/src/lib/tls/asio/asio_stream.h
index ab1c20959..2591408f6 100644
--- a/src/lib/tls/asio/asio_stream.h
+++ b/src/lib/tls/asio/asio_stream.h
@@ -1,7 +1,7 @@
/*
* TLS ASIO Stream
-* (C) 2018-2020 Jack Lloyd
-* 2018-2020 Hannes Rantzsch, Tim Oesterreich, Rene Meusel
+* (C) 2018-2021 Jack Lloyd
+* 2018-2021 Hannes Rantzsch, Tim Oesterreich, Rene Meusel
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -255,26 +255,29 @@ class Stream
* This function call always returns immediately.
*
* @param side 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.
- * The equivalent function signature of the handler must be: void(boost::system::error_code)
+ * @param completion_token The completion handler to be called when the handshake operation completes.
+ * The completion signature of the handler must be: void(boost::system::error_code).
*/
- template <typename HandshakeHandler>
- auto async_handshake(Connection_Side side, HandshakeHandler&& handler) ->
- BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code))
+ template <typename CompletionToken>
+ auto async_handshake(Botan::TLS::Connection_Side side, CompletionToken&& completion_token)
{
- BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
-
- boost::system::error_code ec;
- setup_native_handle(side, ec);
- // If ec is set by setup_native_handle, the AsyncHandshakeOperation created below will do nothing but call the
- // handler with the error_code set appropriately - no need to early return here.
+ return boost::asio::async_initiate<CompletionToken, void(boost::system::error_code)>(
+ [this](auto&& completion_handler, Botan::TLS::Connection_Side connection_side)
+ {
+ using completion_handler_t = std::decay_t<decltype(completion_handler)>;
- boost::asio::async_completion<HandshakeHandler, void(boost::system::error_code)> init(handler);
+ BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(completion_handler_t, completion_handler) type_check;
- detail::AsyncHandshakeOperation<typename std::decay<HandshakeHandler>::type, Stream>
- op{std::move(init.completion_handler), *this, ec};
+ boost::system::error_code ec;
+ setup_native_handle(connection_side, ec);
- return init.result.get();
+ detail::AsyncHandshakeOperation<completion_handler_t, Stream> op
+ {
+ std::forward<completion_handler_t>(completion_handler),
+ *this,
+ ec
+ };
+ }, completion_token, side);
}
//! @throws Not_Implemented
@@ -372,32 +375,32 @@ class Stream
*
* Note that this can be used in reaction of a received shutdown alert from the peer.
*
- * @param handler The handler to be called when the shutdown operation completes.
- * The equivalent function signature of the handler must be: void(boost::system::error_code)
+ * @param completion_token The completion handler to be called when the shutdown operation completes.
+ * The completion signature of the handler must be: void(boost::system::error_code).
*/
- template <typename ShutdownHandler>
- void async_shutdown(ShutdownHandler&& handler)
+ template <typename CompletionToken>
+ auto async_shutdown(CompletionToken&& completion_token)
{
- boost::system::error_code ec;
- try_with_error_code([&]
+ return boost::asio::async_initiate<CompletionToken, void(boost::system::error_code)>(
+ [this](auto&& completion_handler)
{
- native_handle()->close();
- }, ec);
- // If ec is set by native_handle->close(), the AsyncWriteOperation created below will do nothing but call the
- // handler with the error_code set appropriately - no need to early return here.
-
- using ShutdownHandlerWrapper = Wrapper<ShutdownHandler>;
+ using completion_handler_t = std::decay_t<decltype(completion_handler)>;
- ShutdownHandlerWrapper w(std::forward<ShutdownHandler>(handler));
- BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, w) type_check;
+ BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(completion_handler_t, completion_handler) type_check;
- boost::asio::async_completion<ShutdownHandlerWrapper, void(boost::system::error_code, std::size_t)>
- init(w);
+ boost::system::error_code ec;
+ try_with_error_code([&] { native_handle()->close(); }, ec);
- detail::AsyncWriteOperation<typename std::decay<ShutdownHandlerWrapper>::type, Stream>
- op{std::move(init.completion_handler), *this, boost::asio::buffer_size(send_buffer())};
+ using write_handler_t = Wrapper<completion_handler_t, typename Stream::executor_type>;
- return init.result.get();
+ Botan::TLS::detail::AsyncWriteOperation<write_handler_t, Stream> op
+ {
+ write_handler_t{std::forward<completion_handler_t>(completion_handler), get_executor()},
+ *this,
+ boost::asio::buffer_size(send_buffer()),
+ ec
+ };
+ }, completion_token);
}
//! @}
@@ -506,35 +509,38 @@ class Stream
* @brief Start an asynchronous write. The function call always returns immediately.
*
* @param buffers The data to be written.
- * @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:
- * void(boost::system::error_code, std::size_t)
+ * @param completion_token The completion handler to be called when the write operation completes. Copies of the
+ * handler will be made as required. The completion signature of the handler must be:
+ * void(boost::system::error_code, std::size_t).
*/
- template <typename ConstBufferSequence, typename WriteHandler>
- auto async_write_some(const ConstBufferSequence& buffers, WriteHandler&& handler) ->
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void(boost::system::error_code, std::size_t))
+ template <typename ConstBufferSequence, typename CompletionToken>
+ auto async_write_some(const ConstBufferSequence& buffers, CompletionToken&& completion_token)
{
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+ return boost::asio::async_initiate<CompletionToken, void(boost::system::error_code, std::size_t)>(
+ [this](auto&& completion_handler, const auto& bufs)
+ {
+ using completion_handler_t = std::decay_t<decltype(completion_handler)>;
- boost::asio::async_completion<WriteHandler, void(boost::system::error_code, std::size_t)> init(handler);
+ BOOST_ASIO_WRITE_HANDLER_CHECK(completion_handler_t, completion_handler) type_check;
- boost::system::error_code ec;
- tls_encrypt(buffers, ec);
- if(ec)
- {
- // we cannot be sure how many bytes were committed here so clear the send_buffer and let the
- // AsyncWriteOperation call the handler with the error_code set
- consume_send_buffer(m_core.send_buffer.size());
- detail::AsyncWriteOperation<typename std::decay<WriteHandler>::type, Stream>
- op{std::move(init.completion_handler), *this, std::size_t(0), ec};
- return init.result.get();
- }
+ boost::system::error_code ec;
+ tls_encrypt(bufs, ec);
- detail::AsyncWriteOperation<typename std::decay<WriteHandler>::type, Stream>
- op{std::move(init.completion_handler), *this, boost::asio::buffer_size(buffers)};
+ if(ec)
+ {
+ // we cannot be sure how many bytes were committed here so clear the send_buffer and let the
+ // AsyncWriteOperation call the handler with the error_code set
+ consume_send_buffer(m_core.send_buffer.size());
+ }
- return init.result.get();
+ detail::AsyncWriteOperation<completion_handler_t, Stream> op
+ {
+ std::forward<completion_handler_t>(completion_handler),
+ *this,
+ ec ? 0 : boost::asio::buffer_size(bufs),
+ ec
+ };
+ }, completion_token, buffers);
}
/**
@@ -543,22 +549,26 @@ class Stream
* @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.
- * @param handler The handler to be called when the read operation completes. The equivalent function signature of
- * the handler must be:
- * void(boost::system::error_code, std::size_t)
+ * @param completion_token The completion handler to be called when the read operation completes. The completion
+ * signature of the handler must be: void(boost::system::error_code, std::size_t).
*/
- template <typename MutableBufferSequence, typename ReadHandler>
- auto async_read_some(const MutableBufferSequence& buffers, ReadHandler&& handler) ->
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void(boost::system::error_code, std::size_t))
+ template <typename MutableBufferSequence, typename CompletionToken>
+ auto async_read_some(const MutableBufferSequence& buffers, CompletionToken&& completion_token)
{
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+ return boost::asio::async_initiate<CompletionToken, void(boost::system::error_code, std::size_t)>(
+ [this](auto&& completion_handler, const auto& bufs)
+ {
+ using completion_handler_t = std::decay_t<decltype(completion_handler)>;
- boost::asio::async_completion<ReadHandler, void(boost::system::error_code, std::size_t)> init(handler);
+ BOOST_ASIO_READ_HANDLER_CHECK(completion_handler_t, completion_handler) type_check;
- detail::AsyncReadOperation<typename std::decay<ReadHandler>::type, Stream, MutableBufferSequence>
- op{std::move(init.completion_handler), *this, buffers};
- return init.result.get();
+ detail::AsyncReadOperation<completion_handler_t, Stream, MutableBufferSequence> op
+ {
+ std::forward<completion_handler_t>(completion_handler),
+ *this,
+ bufs
+ };
+ }, completion_token, buffers);
}
//! @}