aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/asio
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tls/asio')
-rw-r--r--src/lib/tls/asio/asio_async_base.h68
-rw-r--r--src/lib/tls/asio/asio_async_handshake_op.h63
-rw-r--r--src/lib/tls/asio/asio_async_read_op.h40
-rw-r--r--src/lib/tls/asio/asio_async_write_op.h26
-rw-r--r--src/lib/tls/asio/asio_stream.h17
-rw-r--r--src/lib/tls/asio/info.txt1
6 files changed, 149 insertions, 66 deletions
diff --git a/src/lib/tls/asio/asio_async_base.h b/src/lib/tls/asio/asio_async_base.h
new file mode 100644
index 000000000..af9199288
--- /dev/null
+++ b/src/lib/tls/asio/asio_async_base.h
@@ -0,0 +1,68 @@
+/*
+* TLS ASIO Stream Helper
+* (C) 2018-2019 Jack Lloyd
+* 2018-2019 Hannes Rantzsch, Tim Oesterreich, Rene Meusel
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ASIO_ASYNC_BASE_H_
+#define BOTAN_ASIO_ASYNC_BASE_H_
+
+#include <boost/beast/core/bind_handler.hpp>
+
+#include <botan/internal/asio_includes.h>
+
+namespace Botan {
+
+namespace TLS {
+
+template <class Handler, class Executor, class Allocator>
+struct AsyncBase
+ {
+ using allocator_type = boost::asio::associated_allocator_t<Handler, Allocator>;
+ using executor_type = boost::asio::associated_executor_t<Handler, Executor>;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(m_handler);
+ }
+
+ executor_type get_executor() const noexcept
+ {
+ return boost::asio::get_associated_executor(m_handler, m_work.get_executor());
+ }
+
+ protected:
+ template <class HandlerT>
+ AsyncBase(HandlerT&& handler, const Executor& executor)
+ : m_handler(std::forward<HandlerT>(handler))
+ , m_work(executor)
+ {
+ }
+
+ template<class... Args>
+ void invoke(bool isContinuation, Args&& ... args)
+ {
+ if(!isContinuation)
+ {
+ boost::asio::post(boost::asio::bind_executor(
+ m_work.get_executor(), boost::beast::bind_handler(std::move(m_handler), args...))
+ );
+
+ m_work.reset();
+ }
+ else
+ {
+ m_handler(std::forward<Args>(args)...);
+ m_work.reset();
+ }
+ }
+
+ Handler m_handler;
+ boost::asio::executor_work_guard<executor_type> m_work;
+ };
+}
+}
+
+#endif
diff --git a/src/lib/tls/asio/asio_async_handshake_op.h b/src/lib/tls/asio/asio_async_handshake_op.h
index c9a8b8058..1a93ab78b 100644
--- a/src/lib/tls/asio/asio_async_handshake_op.h
+++ b/src/lib/tls/asio/asio_async_handshake_op.h
@@ -18,24 +18,28 @@ namespace Botan {
namespace TLS {
-template <class Handler, class StreamLayer, class Channel>
-struct AsyncHandshakeOperation
+template <class Handler, class Stream, class Allocator = std::allocator<void>>
+struct AsyncHandshakeOperation : public AsyncBase<Handler, typename Stream::executor_type, Allocator>
{
template<class HandlerT>
AsyncHandshakeOperation(
HandlerT&& handler,
- StreamLayer& nextLayer,
- Channel* channel,
+ Stream& stream,
StreamCore& core)
- : m_handler(std::forward<HandlerT>(handler))
- , m_nextLayer(nextLayer)
- , m_channel(channel)
- , m_core(core) {}
+ : AsyncBase<Handler, typename Stream::executor_type, Allocator>(
+ std::forward<HandlerT>(handler),
+ stream.get_executor())
+ , m_stream(stream)
+ , m_core(core)
+ {
+ }
AsyncHandshakeOperation(AsyncHandshakeOperation&&) = default;
- void operator()(boost::system::error_code ec,
- std::size_t bytesTransferred = 0, int start = 0)
+ using typename AsyncBase<Handler, typename Stream::executor_type, Allocator>::allocator_type;
+ using typename AsyncBase<Handler, typename Stream::executor_type, Allocator>::executor_type;
+
+ void operator()(boost::system::error_code ec, std::size_t bytesTransferred, bool isContinuation = true)
{
// process tls packets from socket first
if(bytesTransferred > 0)
@@ -43,14 +47,12 @@ struct AsyncHandshakeOperation
boost::asio::const_buffer read_buffer {m_core.input_buffer.data(), bytesTransferred};
try
{
- m_channel->received_data(
- static_cast<const uint8_t*>(read_buffer.data()),
- read_buffer.size());
+ m_stream.native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), read_buffer.size());
}
catch(const std::exception&)
{
ec = convertException();
- m_handler(ec);
+ this->invoke(isContinuation, ec);
return;
}
}
@@ -58,33 +60,32 @@ struct AsyncHandshakeOperation
// send tls packets
if(m_core.hasDataToSend())
{
- AsyncWriteOperation<AsyncHandshakeOperation<typename std::decay<Handler>::type, StreamLayer, Channel>>
- op{std::move(*this), m_core, 0};
- boost::asio::async_write(m_nextLayer, m_core.sendBuffer(), std::move(op));
+ // TODO comment: plainBytesTransferred is 0 here because... we construct a write operation to use it only
+ // as a handler for our async_write call, not for actually calling it. However, once
+ // AsyncWriteOperation::operator() is called as the handler, it will consume the send buffer and call (this)
+ // as it's own handler. Now we know that AsyncHandshakeOperation::operator() checks bytesTransferred first.
+ // We want it to NOT receive data into the channel, hence we set plainBytesTransferred to 0 here.
+ AsyncWriteOperation<
+ AsyncHandshakeOperation<typename std::decay<Handler>::type, Stream, Allocator>,
+ Stream,
+ Allocator>
+ op{std::move(*this), m_stream, m_core, 0};
+ boost::asio::async_write(m_stream.next_layer(), m_core.sendBuffer(), std::move(op));
return;
}
- if(!m_channel->is_active() && !ec)
+ // we need more tls data from the socket
+ if(!m_stream.native_handle()->is_active() && !ec)
{
- // we need more tls data from the socket
- m_nextLayer.async_read_some(m_core.input_buffer, std::move(*this));
+ m_stream.next_layer().async_read_some(m_core.input_buffer, std::move(*this));
return;
}
- if(start)
- {
- // don't call the handler directly, similar to io_context.post
- m_nextLayer.async_read_some(
- boost::asio::mutable_buffer(m_core.input_buffer.data(), 0), std::move(*this));
- return;
- }
- m_handler(ec);
+ this->invoke(isContinuation, ec);
}
private:
- Handler m_handler;
- StreamLayer& m_nextLayer;
- Channel* m_channel;
+ Stream& m_stream;
StreamCore& m_core;
};
diff --git a/src/lib/tls/asio/asio_async_read_op.h b/src/lib/tls/asio/asio_async_read_op.h
index 241f9ae5c..ed66df07d 100644
--- a/src/lib/tls/asio/asio_async_read_op.h
+++ b/src/lib/tls/asio/asio_async_read_op.h
@@ -9,6 +9,7 @@
#ifndef BOTAN_ASIO_ASYNC_READ_OP_H_
#define BOTAN_ASIO_ASYNC_READ_OP_H_
+#include <botan/internal/asio_async_base.h>
#include <botan/internal/asio_convert_exceptions.h>
#include <botan/internal/asio_includes.h>
#include <botan/internal/asio_stream_core.h>
@@ -17,34 +18,39 @@ namespace Botan {
namespace TLS {
-template <class Handler, class StreamLayer, class Channel, class MutableBufferSequence>
-struct AsyncReadOperation
+template <class Handler, class Stream, class MutableBufferSequence, class Allocator = std::allocator<void>>
+struct AsyncReadOperation : public AsyncBase<Handler, typename Stream::executor_type, Allocator>
{
template <class HandlerT>
AsyncReadOperation(HandlerT&& handler,
- StreamLayer& nextLayer,
- Channel* channel,
+ Stream& stream,
StreamCore& core,
const MutableBufferSequence& buffers)
- : m_handler(std::forward<HandlerT>(handler))
- , m_nextLayer(nextLayer)
- , m_channel(channel)
+ : AsyncBase<Handler, typename Stream::executor_type, Allocator>(
+ std::forward<HandlerT>(handler),
+ stream.get_executor())
+ , m_stream(stream)
, m_core(core)
- , m_buffers(buffers) {}
+ , m_buffers(buffers)
+ {
+ }
AsyncReadOperation(AsyncReadOperation&&) = default;
- void operator()(boost::system::error_code ec, std::size_t bytes_transferred)
+ using typename AsyncBase<Handler, typename Stream::executor_type, Allocator>::allocator_type;
+ using typename AsyncBase<Handler, typename Stream::executor_type, Allocator>::executor_type;
+
+ void operator()(boost::system::error_code ec, std::size_t bytes_transferred, bool isContinuation = true)
{
std::size_t decodedBytes = 0;
if(bytes_transferred > 0 && !ec)
{
- boost::asio::const_buffer read_buffer {m_core.input_buffer.data(), bytes_transferred};
+ boost::asio::const_buffer read_buffer{m_core.input_buffer.data(), bytes_transferred};
try
{
- m_channel->received_data(static_cast<const uint8_t*>(read_buffer.data()),
- read_buffer.size());
+ m_stream.native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()),
+ read_buffer.size());
}
catch(const std::exception&)
{
@@ -55,23 +61,21 @@ struct AsyncReadOperation
if(!m_core.hasReceivedData() && !ec)
{
// we need more tls packets from the socket
- m_nextLayer.async_read_some(m_core.input_buffer, std::move(*this));
+ m_stream.next_layer().async_read_some(m_core.input_buffer, std::move(*this));
return;
}
if(m_core.hasReceivedData() && !ec)
{
decodedBytes = m_core.copyReceivedData(m_buffers);
- ec = boost::system::error_code{};
+ ec = {};
}
- m_handler(ec, decodedBytes);
+ this->invoke(isContinuation, ec, decodedBytes);
}
private:
- Handler m_handler;
- StreamLayer& m_nextLayer;
- Channel* m_channel;
+ Stream& m_stream;
StreamCore& m_core;
MutableBufferSequence m_buffers;
};
diff --git a/src/lib/tls/asio/asio_async_write_op.h b/src/lib/tls/asio/asio_async_write_op.h
index 3af7d7fee..4103987ae 100644
--- a/src/lib/tls/asio/asio_async_write_op.h
+++ b/src/lib/tls/asio/asio_async_write_op.h
@@ -11,32 +11,42 @@
#include <botan/internal/asio_stream_core.h>
#include <botan/internal/asio_includes.h>
+#include <botan/internal/asio_async_base.h>
namespace Botan {
namespace TLS {
-template <typename Handler>
-struct AsyncWriteOperation
+template <typename Handler, class Stream, class Allocator = std::allocator<void>>
+struct AsyncWriteOperation : public AsyncBase<Handler, typename Stream::executor_type, Allocator>
{
template <class HandlerT>
AsyncWriteOperation(HandlerT&& handler,
+ Stream& stream,
StreamCore& core,
std::size_t plainBytesTransferred)
- : m_handler(std::forward<HandlerT>(handler))
+ : AsyncBase<Handler, typename Stream::executor_type, Allocator>(
+ std::forward<HandlerT>(handler),
+ stream.get_executor())
+ , m_stream(stream)
, m_core(core)
- , m_plainBytesTransferred(plainBytesTransferred) {}
+ , m_plainBytesTransferred(plainBytesTransferred)
+ {
+ }
AsyncWriteOperation(AsyncWriteOperation&&) = default;
- void operator()(boost::system::error_code ec, std::size_t bytes_transferred)
+ using typename AsyncBase<Handler, typename Stream::executor_type, Allocator>::allocator_type;
+ using typename AsyncBase<Handler, typename Stream::executor_type, Allocator>::executor_type;
+
+ void operator()(boost::system::error_code ec, std::size_t bytes_transferred, bool isContinuation = true)
{
m_core.consumeSendBuffer(bytes_transferred);
- m_handler(ec, ec ? 0 : m_plainBytesTransferred);
+ this->invoke(isContinuation, ec, ec ? 0 : m_plainBytesTransferred);
}
- Handler m_handler;
- StreamCore& m_core;
+ Stream& m_stream;
+ StreamCore& m_core;
std::size_t m_plainBytesTransferred;
};
diff --git a/src/lib/tls/asio/asio_stream.h b/src/lib/tls/asio/asio_stream.h
index 1abad507a..8a28fc68e 100644
--- a/src/lib/tls/asio/asio_stream.h
+++ b/src/lib/tls/asio/asio_stream.h
@@ -191,10 +191,9 @@ class Stream final : public StreamBase<Channel>
boost::asio::async_completion<HandshakeHandler, void(boost::system::error_code)> init(handler);
- AsyncHandshakeOperation<typename std::decay<HandshakeHandler>::type, StreamLayer, Channel>
- op{std::move(init.completion_handler), m_nextLayer, native_handle(), this->m_core};
-
- op(boost::system::error_code{}, 0, 1);
+ AsyncHandshakeOperation<typename std::decay<HandshakeHandler>::type, Stream>
+ op{std::move(init.completion_handler), *this, this->m_core};
+ op({}, 0, false);
return init.result.get();
}
@@ -407,8 +406,9 @@ class Stream final : public StreamBase<Channel>
return init.result.get();
}
- Botan::TLS::AsyncWriteOperation<typename std::decay<WriteHandler>::type>
+ Botan::TLS::AsyncWriteOperation<typename std::decay<WriteHandler>::type, Stream>
op{std::move(init.completion_handler),
+ *this,
this->m_core,
sent};
boost::asio::async_write(m_nextLayer, this->m_core.sendBuffer(), std::move(op));
@@ -425,13 +425,12 @@ class Stream final : public StreamBase<Channel>
boost::asio::async_completion<ReadHandler, void(boost::system::error_code, std::size_t)> init(handler);
- AsyncReadOperation<typename std::decay<ReadHandler>::type, StreamLayer, Channel, MutableBufferSequence>
+ AsyncReadOperation<typename std::decay<ReadHandler>::type, Stream, MutableBufferSequence>
op{std::move(init.completion_handler),
- m_nextLayer,
- native_handle(),
+ *this,
this->m_core,
buffers};
- op(boost::system::error_code{}, 0);
+ op({}, 0, false);
return init.result.get();
}
diff --git a/src/lib/tls/asio/info.txt b/src/lib/tls/asio/info.txt
index 2b303c89e..cfca189a7 100644
--- a/src/lib/tls/asio/info.txt
+++ b/src/lib/tls/asio/info.txt
@@ -8,6 +8,7 @@ asio_error.h
</header:public>
<header:internal>
+asio_async_base.h
asio_async_handshake_op.h
asio_async_read_op.h
asio_async_write_op.h