aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Rantzsch <[email protected]>2019-03-27 17:24:53 +0100
committerHannes Rantzsch <[email protected]>2019-04-16 10:48:16 +0200
commit287a4ba2ad02392d11dbcb6c18c5f7776ead79c4 (patch)
tree51aff7b987b8c6ba19753db0dbe2332db854ba1d
parentb5a3a91a763b49840b03e05c6043ee4add9ca931 (diff)
improve constructor interface of Stream
-rw-r--r--src/lib/tls/asio/asio_context.h40
-rw-r--r--src/lib/tls/asio/asio_includes.h12
-rw-r--r--src/lib/tls/asio/asio_stream.h29
-rw-r--r--src/lib/tls/asio/asio_stream_base.h20
-rw-r--r--src/lib/tls/asio/info.txt1
-rw-r--r--src/tests/unit_asio_stream.cpp196
6 files changed, 165 insertions, 133 deletions
diff --git a/src/lib/tls/asio/asio_context.h b/src/lib/tls/asio/asio_context.h
new file mode 100644
index 000000000..387d201c0
--- /dev/null
+++ b/src/lib/tls/asio/asio_context.h
@@ -0,0 +1,40 @@
+/*
+ * TLS Context
+ * (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_TLS_CONTEXT_H_
+#define BOTAN_ASIO_TLS_CONTEXT_H_
+
+#if defined(BOTAN_HAS_TLS) && defined(BOTAN_HAS_BOOST_ASIO)
+
+#include <boost/version.hpp>
+#if BOOST_VERSION > 106600
+
+#include <botan/credentials_manager.h>
+#include <botan/rng.h>
+#include <botan/tls_policy.h>
+#include <botan/tls_server_info.h>
+#include <botan/tls_session_manager.h>
+
+namespace Botan {
+namespace TLS {
+
+struct Context
+ {
+ Credentials_Manager* credentialsManager;
+ RandomNumberGenerator* randomNumberGenerator;
+ Session_Manager* sessionManager;
+ Policy* policy;
+ Server_Information serverInfo;
+ };
+
+} // namespace TLS
+} // namespace Botan
+
+#endif // BOOST_VERSION
+#endif // BOTAN_HAS_TLS && BOTAN_HAS_BOOST_ASIO
+#endif // BOTAN_ASIO_TLS_CONTEXT_H_
diff --git a/src/lib/tls/asio/asio_includes.h b/src/lib/tls/asio/asio_includes.h
index 5f67db148..dfbd24474 100644
--- a/src/lib/tls/asio/asio_includes.h
+++ b/src/lib/tls/asio/asio_includes.h
@@ -11,12 +11,12 @@
#ifdef BOTAN_HAS_BOOST_ASIO
-// We need to define BOOST_ASIO_DISABLE_SERIAL_PORT before any asio imports. Otherwise asio will include <termios.h>,
-// which interferes with Botan's amalgamation by defining macros like 'B0' and 'FF1'.
-#define BOOST_ASIO_DISABLE_SERIAL_PORT
-#include <boost/asio.hpp>
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/ip/tcp.hpp>
+ // We need to define BOOST_ASIO_DISABLE_SERIAL_PORT before any asio imports. Otherwise asio will include <termios.h>,
+ // which interferes with Botan's amalgamation by defining macros like 'B0' and 'FF1'.
+ #define BOOST_ASIO_DISABLE_SERIAL_PORT
+ #include <boost/asio.hpp>
+ #include <boost/asio/buffer.hpp>
+ #include <boost/asio/ip/tcp.hpp>
#endif // BOTAN_HAS_BOOST_ASIO
#endif // BOTAN_ASIO_INCLUDES_H_
diff --git a/src/lib/tls/asio/asio_stream.h b/src/lib/tls/asio/asio_stream.h
index 4988338ea..1926eadf9 100644
--- a/src/lib/tls/asio/asio_stream.h
+++ b/src/lib/tls/asio/asio_stream.h
@@ -21,6 +21,7 @@
#include <botan/internal/asio_includes.h>
#include <botan/internal/asio_stream_base.h>
#include <botan/internal/asio_stream_core.h>
+#include <botan/asio_context.h>
#include <algorithm>
#include <memory>
@@ -40,7 +41,9 @@ namespace Botan {
namespace TLS {
/**
- * boost::asio compatible SSL/TLS stream based on TLS::Client or TLS::Server.
+ * boost::asio compatible SSL/TLS stream
+ *
+ * Currently only the TLS::Client specialization is implemented.
*/
template <class StreamLayer, class Channel>
class Stream : public StreamBase<Channel>
@@ -55,25 +58,13 @@ class Stream : public StreamBase<Channel>
public:
template <typename... Args>
- explicit Stream(StreamLayer&& nextLayer, Args&& ... args)
- : StreamBase<Channel>(std::forward<Args>(args)...),
- m_nextLayer(std::forward<StreamLayer>(nextLayer)) {}
+ explicit Stream(Context& context, Args&& ... args)
+ : StreamBase<Channel>(context), m_nextLayer(std::forward<Args>(args)...) {}
- Stream(StreamLayer&& nextLayer, boost::asio::ssl::context&)
- : StreamBase<Channel>(Botan::TLS::Session_Manager_Noop(), Botan::Credentials_Manager()),
- m_nextLayer(std::forward<StreamLayer>(nextLayer))
- {
- // Configuring a TLS stream via asio::ssl::context is not supported.
- // The corresponding configuration objects for Botan are:
- // * TLS::Session_Manager
- // * Credentials_Manager
- // * TLS::Policy
- // * TLS::Server_Information
- // It would be nice to have a masquarading wrapper that exposes an API
- // compatible with asio::ssl::context for convenient drop-in replacement.
- // For now, base your TLS configurations on the above mentioned classes.
- throw Not_Implemented("cannot handle an asio::ssl::context");
- }
+ // overload for boost::asio::ssl::stream compatibility
+ template <typename Arg>
+ explicit Stream(Arg&& arg, Context& context)
+ : StreamBase<Channel>(context), m_nextLayer(std::forward<Arg>(arg)) {}
Stream(Stream&& other) = default;
Stream& operator=(Stream&& other) = default;
diff --git a/src/lib/tls/asio/asio_stream_base.h b/src/lib/tls/asio/asio_stream_base.h
index 949f76bef..4832b2f8f 100644
--- a/src/lib/tls/asio/asio_stream_base.h
+++ b/src/lib/tls/asio/asio_stream_base.h
@@ -14,9 +14,8 @@
#include <boost/version.hpp>
#if BOOST_VERSION > 106600
-#include <botan/auto_rng.h>
#include <botan/tls_client.h>
-#include <botan/tls_server.h>
+#include <botan/asio_context.h>
#include <botan/asio_error.h>
#include <botan/internal/asio_stream_core.h>
@@ -48,17 +47,13 @@ template <>
class StreamBase<Botan::TLS::Client>
{
public:
- StreamBase(Botan::TLS::Session_Manager& sessionManager,
- Botan::Credentials_Manager& credentialsManager,
- const Botan::TLS::Policy& policy,
- const Botan::TLS::Server_Information& serverInfo =
- Botan::TLS::Server_Information{})
+ StreamBase(Context& context)
: m_channel(m_core,
- sessionManager,
- credentialsManager,
- policy,
- m_rng,
- serverInfo)
+ *context.sessionManager,
+ *context.credentialsManager,
+ *context.policy,
+ *context.randomNumberGenerator,
+ context.serverInfo)
{
}
@@ -90,7 +85,6 @@ class StreamBase<Botan::TLS::Client>
}
Botan::TLS::StreamCore m_core;
- Botan::AutoSeeded_RNG m_rng;
Botan::TLS::Client m_channel;
};
diff --git a/src/lib/tls/asio/info.txt b/src/lib/tls/asio/info.txt
index cfca189a7..73afbb960 100644
--- a/src/lib/tls/asio/info.txt
+++ b/src/lib/tls/asio/info.txt
@@ -3,6 +3,7 @@ TLS_ASIO_STREAM -> 20181218
</defines>
<header:public>
+asio_context.h
asio_stream.h
asio_error.h
</header:public>
diff --git a/src/tests/unit_asio_stream.cpp b/src/tests/unit_asio_stream.cpp
index dcb0783de..1cc1ee7c1 100644
--- a/src/tests/unit_asio_stream.cpp
+++ b/src/tests/unit_asio_stream.cpp
@@ -72,18 +72,18 @@ class ThrowingMockChannel : public MockChannel
{
public:
ThrowingMockChannel(Botan::TLS::StreamCore& core) : MockChannel(core)
- {
- }
-
- std::size_t received_data(const uint8_t[], std::size_t)
- {
- throw Botan::TLS::Unexpected_Message("test_error");
- }
-
- void send(const uint8_t[], std::size_t)
- {
- throw Botan::TLS::Unexpected_Message("test_error");
- }
+ {
+ }
+
+ std::size_t received_data(const uint8_t[], std::size_t)
+ {
+ throw Botan::TLS::Unexpected_Message("test_error");
+ }
+
+ void send(const uint8_t[], std::size_t)
+ {
+ throw Botan::TLS::Unexpected_Message("test_error");
+ }
};
}
@@ -101,7 +101,7 @@ template <>
class StreamBase<Botan_Tests::MockChannel>
{
public:
- StreamBase()
+ StreamBase(Context& /*ignored*/)
: m_channel(m_core)
{
}
@@ -113,7 +113,6 @@ class StreamBase<Botan_Tests::MockChannel>
protected:
StreamCore m_core;
- Botan::AutoSeeded_RNG m_rng;
Botan_Tests::MockChannel m_channel;
void validate_handshake_type(handshake_type) {}
@@ -125,8 +124,8 @@ template <>
class StreamBase<Botan_Tests::ThrowingMockChannel> : public StreamBase<Botan_Tests::MockChannel>
{
public:
- StreamBase()
- : m_channel(m_core)
+ StreamBase(Context& c)
+ : StreamBase<Botan_Tests::MockChannel>(c), m_channel(m_core)
{
}
@@ -157,17 +156,16 @@ class Asio_Stream_Tests final : public Test
{
using TestStream = boost::beast::test::stream;
using FailCount = boost::beast::test::fail_count;
- using AsioStream = Botan::TLS::Stream<TestStream&, MockChannel>;
- using ThrowingAsioStream = Botan::TLS::Stream<TestStream&, ThrowingMockChannel>;
+ using AsioStream = Botan::TLS::Stream<TestStream, MockChannel>;
+ using ThrowingAsioStream = Botan::TLS::Stream<TestStream, ThrowingMockChannel>;
boost::string_view test_data() const { return boost::string_view((const char*)TEST_DATA, TEST_DATA_SIZE); }
void test_sync_handshake(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()};
-
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, test_data());
ssl.handshake(AsioStream::handshake_type::client);
@@ -181,11 +179,12 @@ class Asio_Stream_Tests final : public Test
net::io_context ioc;
// fail right away
FailCount fc{0, net::error::eof};
- TestStream socket{ioc, fc}, remote{ioc};
+ TestStream remote{ioc};
- socket.connect(remote);
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, fc);
+ ssl.next_layer().connect(remote);
- AsioStream ssl{socket};
// mimic handshake initialization
ssl.native_handle()->send(TEST_DATA, TEST_DATA_SIZE);
@@ -201,11 +200,11 @@ class Asio_Stream_Tests final : public Test
void test_sync_handshake_throw(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()}, remote{ioc};
-
- socket.connect(remote);
+ TestStream remote{ioc};
- ThrowingAsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ ThrowingAsioStream ssl(ctx, ioc, test_data());
+ ssl.next_layer().connect(remote);
error_code ec;
ssl.handshake(AsioStream::handshake_type::client, ec);
@@ -219,11 +218,12 @@ class Asio_Stream_Tests final : public Test
void test_async_handshake(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()}, remote{ioc};
+ TestStream remote{ioc};
- socket.connect(remote);
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, test_data());
+ ssl.next_layer().connect(remote);
- AsioStream ssl{socket};
// mimic handshake initialization
ssl.native_handle()->send(TEST_DATA, TEST_DATA_SIZE);
@@ -231,14 +231,14 @@ class Asio_Stream_Tests final : public Test
auto handler = [&](const error_code&)
{
- result.confirm("reads from socket", socket.nread() > 0);
- result.confirm("writes from socket", socket.nwrite() > 0);
+ result.confirm("reads from socket", ssl.next_layer().nread() > 0);
+ result.confirm("writes from socket", ssl.next_layer().nwrite() > 0);
result.test_eq("feeds data into channel until active", ssl.native_handle()->is_active(), true);
};
ssl.async_handshake(AsioStream::handshake_type::client, handler);
- socket.close_remote();
+ ssl.next_layer().close_remote();
ioc.run();
results.push_back(result);
}
@@ -248,11 +248,12 @@ class Asio_Stream_Tests final : public Test
net::io_context ioc;
// fail right away
FailCount fc{0, net::error::eof};
- TestStream socket{ioc, fc}, remote{ioc};
+ TestStream remote{ioc};
- socket.connect(remote);
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, fc);
+ ssl.next_layer().connect(remote);
- AsioStream ssl{socket};
// mimic handshake initialization
ssl.native_handle()->send(TEST_DATA, TEST_DATA_SIZE);
@@ -273,11 +274,11 @@ class Asio_Stream_Tests final : public Test
void test_async_handshake_throw(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()}, remote{ioc};
-
- socket.connect(remote);
+ TestStream remote{ioc};
- ThrowingAsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ ThrowingAsioStream ssl(ctx, ioc, test_data());
+ ssl.next_layer().connect(remote);
Test::Result result("async TLS handshake throw");
@@ -296,9 +297,9 @@ class Asio_Stream_Tests final : public Test
void test_sync_read_some_success(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, test_data());
const std::size_t buf_size = 128;
uint8_t buf[buf_size];
@@ -317,9 +318,9 @@ class Asio_Stream_Tests final : public Test
void test_sync_read_some_buffer_sequence(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, test_data());
error_code ec;
std::vector<net::mutable_buffer> data;
@@ -346,11 +347,11 @@ class Asio_Stream_Tests final : public Test
net::io_context ioc;
// fail right away
FailCount fc{0, net::error::eof};
- TestStream socket{ioc, fc}, remote{ioc};
+ TestStream remote{ioc};
- socket.connect(remote);
-
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, fc);
+ ssl.next_layer().connect(remote);
uint8_t buf[128];
error_code ec;
@@ -367,11 +368,11 @@ class Asio_Stream_Tests final : public Test
void test_sync_read_some_throw(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()}, remote{ioc};
-
- socket.connect(remote);
+ TestStream remote{ioc};
- ThrowingAsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ ThrowingAsioStream ssl(ctx, ioc, test_data());
+ ssl.next_layer().connect(remote);
uint8_t buf[128];
error_code ec;
@@ -388,9 +389,10 @@ class Asio_Stream_Tests final : public Test
void test_async_read_some_success(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()};
+ TestStream remote{ioc};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, test_data());
uint8_t data[TEST_DATA_SIZE];
error_code ec;
@@ -406,7 +408,7 @@ class Asio_Stream_Tests final : public Test
net::mutable_buffer buf {data, TEST_DATA_SIZE};
net::async_read(ssl, buf, read_handler);
- socket.close_remote();
+ ssl.next_layer().close_remote();
ioc.run();
results.push_back(result);
}
@@ -414,9 +416,8 @@ class Asio_Stream_Tests final : public Test
void test_async_read_some_buffer_sequence(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()};
-
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, test_data());
error_code ec;
std::vector<net::mutable_buffer> data;
@@ -438,7 +439,7 @@ class Asio_Stream_Tests final : public Test
net::async_read(ssl, data, read_handler);
- socket.close_remote();
+ ssl.next_layer().close_remote();
ioc.run();
results.push_back(result);
}
@@ -448,9 +449,8 @@ class Asio_Stream_Tests final : public Test
net::io_context ioc;
// fail right away
FailCount fc{0, net::error::eof};
- TestStream socket{ioc, fc};
-
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, fc);
uint8_t data[TEST_DATA_SIZE];
error_code ec;
@@ -465,7 +465,7 @@ class Asio_Stream_Tests final : public Test
net::mutable_buffer buf {data, TEST_DATA_SIZE};
net::async_read(ssl, buf, read_handler);
- socket.close_remote();
+ ssl.next_layer().close_remote();
ioc.run();
results.push_back(result);
}
@@ -473,9 +473,8 @@ class Asio_Stream_Tests final : public Test
void test_async_read_some_throw(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc, test_data()};
-
- ThrowingAsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ ThrowingAsioStream ssl(ctx, ioc, test_data());
uint8_t data[TEST_DATA_SIZE];
error_code ec;
@@ -490,7 +489,7 @@ class Asio_Stream_Tests final : public Test
net::mutable_buffer buf {data, TEST_DATA_SIZE};
net::async_read(ssl, buf, read_handler);
- socket.close_remote();
+ ssl.next_layer().close_remote();
ioc.run();
results.push_back(result);
}
@@ -498,10 +497,11 @@ class Asio_Stream_Tests final : public Test
void test_sync_write_some_success(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc}, remote{ioc};
- socket.connect(remote);
+ TestStream remote{ioc};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc);
+ ssl.next_layer().connect(remote);
error_code ec;
auto bytes_transferred = net::write(ssl, net::const_buffer(TEST_DATA, TEST_DATA_SIZE), ec);
@@ -517,10 +517,11 @@ class Asio_Stream_Tests final : public Test
void test_sync_write_some_buffer_sequence(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc}, remote{ioc};
- socket.connect(remote);
+ TestStream remote{ioc};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc);
+ ssl.next_layer().connect(remote);
error_code ec;
// this should be Botan::TLS::MAX_PLAINTEXT_SIZE + 1024 + 1
@@ -545,7 +546,7 @@ class Asio_Stream_Tests final : public Test
result.confirm("writes the correct data",
contains(remote.buffer().data().data(), random_data.data(), random_data.size()));
result.test_eq("writes the correct amount of data", bytes_transferred, random_data.size());
- result.test_eq("correct number of writes", socket.nwrite(), 2);
+ result.test_eq("correct number of writes", ssl.next_layer().nwrite(), 2);
result.confirm("does not report an error", !ec);
results.push_back(result);
@@ -556,11 +557,12 @@ class Asio_Stream_Tests final : public Test
net::io_context ioc;
// fail right away
FailCount fc{0, net::error::eof};
- TestStream socket{ioc, fc}, remote{ioc};
+ TestStream remote{ioc};
- socket.connect(remote);
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, fc);
+ ssl.next_layer().connect(remote);
- AsioStream ssl{socket};
error_code ec;
auto bytes_transferred = net::write(ssl, net::const_buffer(TEST_DATA, TEST_DATA_SIZE), ec);
@@ -575,11 +577,11 @@ class Asio_Stream_Tests final : public Test
void test_sync_write_some_throw(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc}, remote{ioc};
-
- socket.connect(remote);
+ TestStream remote{ioc};
- ThrowingAsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ ThrowingAsioStream ssl(ctx, ioc);
+ ssl.next_layer().connect(remote);
error_code ec;
auto bytes_transferred = net::write(ssl, net::const_buffer(TEST_DATA, TEST_DATA_SIZE), ec);
@@ -594,10 +596,11 @@ class Asio_Stream_Tests final : public Test
void test_async_write_some_success(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc}, remote{ioc};
- socket.connect(remote);
+ TestStream remote{ioc};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc);
+ ssl.next_layer().connect(remote);
error_code ec;
Test::Result result("async write_some success");
@@ -618,10 +621,11 @@ class Asio_Stream_Tests final : public Test
void test_async_write_some_buffer_sequence(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc}, remote{ioc};
- socket.connect(remote);
+ TestStream remote{ioc};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc);
+ ssl.next_layer().connect(remote);
error_code ec;
// this should be Botan::TLS::MAX_PLAINTEXT_SIZE + 1024 + 1
@@ -646,7 +650,7 @@ class Asio_Stream_Tests final : public Test
result.confirm("writes the correct data",
contains(remote.buffer().data().data(), random_data.data(), random_data.size()));
result.test_eq("writes the correct amount of data", bytes_transferred, random_data.size());
- result.test_eq("correct number of writes", socket.nwrite(), 2);
+ result.test_eq("correct number of writes", ssl.next_layer().nwrite(), 2);
result.confirm("does not report an error", !ec);
};
@@ -661,10 +665,11 @@ class Asio_Stream_Tests final : public Test
net::io_context ioc;
// fail right away
FailCount fc{0, net::error::eof};
- TestStream socket{ioc, fc}, remote{ioc};
- socket.connect(remote);
+ TestStream remote{ioc};
- AsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ AsioStream ssl(ctx, ioc, fc);
+ ssl.next_layer().connect(remote);
error_code ec;
Test::Result result("async write_some error");
@@ -684,10 +689,11 @@ class Asio_Stream_Tests final : public Test
void test_async_write_throw(std::vector<Test::Result>& results)
{
net::io_context ioc;
- TestStream socket{ioc}, remote{ioc};
- socket.connect(remote);
+ TestStream remote{ioc};
- ThrowingAsioStream ssl{socket};
+ Botan::TLS::Context ctx;
+ ThrowingAsioStream ssl(ctx, ioc);
+ ssl.next_layer().connect(remote);
error_code ec;
Test::Result result("async write_some throw");