Reputation: 28659
I have a boost::beast
ssl stream data member:
class HttpsClient
{
...
asio::ssl::context _ssl_ctx;
beast::ssl_stream<beast::tcp_stream> _stream;
};
At construction I initialise the stream with an asio::io_context
and an ssl context as follows:
namespace ssl = boost::asio::ssl;
ssl::context sslContext()
{
ssl::context ssl_ctx {ssl::context::tlsv12_client};
ssl_ctx.set_verify_mode(ssl::context::verify_peer | ssl::context::verify_fail_if_no_peer_cert);
ssl_ctx.set_default_verify_paths();
boost::certify::enable_native_https_server_verification(ssl_ctx);
return ssl_ctx;
}
HttpsClient::HttpsClient(asio::io_context& ctx)
: _ssl_ctx(sslContext())
, _stream(ctx, _ssl_ctx)
{}
My connect function synchronously resolves the endpoint, connects to it, and performs the SSL handshake.
void HttpsClient::connect(const std::string& host, std::uint16_t port, const std::string& path)
{
tcp::resolver resolver {_stream.get_executor()};
tcp::resolver::results_type end_point = resolver.resolve(host, std::to_string(port));
beast::get_lowest_layer(_stream).connect(end_point);
beast::get_lowest_layer(_stream).socket().set_option(tcp::no_delay {true});
SSL_set_tlsext_host_name(_stream.native_handle(), host.c_str());
_stream.handshake(ssl::stream_base::client);
}
Once connected, I start an async_read
, and when I want to send a request, I use the synchronously version:
void HttpsClient::write(beast::http::request<beast::http::string_body>& request)
{
request.prepare_payload();
http::write(_stream, request);
}
This is all works as expected.
The problem I'm coming up against is that I would like to disconnect and then reconnect the stream.
I have tried several different ways to close the connection:
Cancel outstanding async_read and shutdown the stream:
_stream.next_layer().cancel();
_stream.shutdown();
Once the shutdown
completes I am seemingly able to connect again, but attempts to write to the stream fail with "protocol is shutdown"
.
After receiving "protocol is shutdown"
any attempts to reconnect receive "Operation canceled"
Cancel outstanding async_read and close the underlying TCP stream:
_stream.next_layer().cancel();
_stream.next_layer().close();
Once the close
completes I am still seemingly able to connect again, but now attempts to write to the stream fail with "wrong version number"
.
After receiving "wrong version number"
any attempts to reconnect receive "unspecified system error"
Questions:
Upvotes: 3
Views: 1526
Reputation: 28659
This issue relating to websocket, but possibly the ssl stream has similar requirements, says to recreate the entire stream... suggests reusing a disconnected stream is not possible.
Certainly recreating the stream does work, which suggests this is indeed the case
Upvotes: 2