Websocket SSL teardown also tears down underlying TCP

fixes #2023
This commit is contained in:
Richard Hodges
2020-07-20 12:38:46 +02:00
parent a35cd32005
commit ccd0f8822a
2 changed files with 66 additions and 6 deletions

View File

@ -1,5 +1,6 @@
Version XXX:
* Websocket SSL `teardown` also tears down underlying TCP.
* Update WebSocket examples to set TLS SNI.
* Add handler tracking locations to websocket.
* Add handler tracking locations to tcp teardown.
@ -10,6 +11,15 @@ Version XXX:
* Add handler tracking locations to basic_stream.
* Add handler tracking locations to http operations.
API Changes:
* Previously, `teardown` and `async_teardown` of a websocket connection over SSL
would only shut down the SSL layer, leaving the TCP layer connected. Now the
SSL teardown will tear down both the SSL and TCP layers, cleanly shutting down
the TCP connection and closing the socket.
Should the client expect the TCP socket to remain connected, users will need to
re-engineer their code.
--------------------------------------------------------------------------------
Version 300:

View File

@ -11,6 +11,9 @@
#define BOOST_BEAST_WEBSOCKET_IMPL_SSL_HPP
#include <utility>
#include <boost/beast/websocket/teardown.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp>
namespace boost {
namespace beast {
@ -33,24 +36,71 @@ namespace beast {
template<class AsyncStream>
void
teardown(
role_type,
net::ssl::stream<AsyncStream>& stream,
role_type role,
boost::asio::ssl::stream<AsyncStream>& stream,
error_code& ec)
{
stream.shutdown(ec);
using boost::beast::websocket::teardown;
error_code ec2;
teardown(role, stream.next_layer(), ec ? ec2 : ec);
}
namespace detail {
template<class AsyncStream>
struct ssl_shutdown_op
: boost::asio::coroutine
{
ssl_shutdown_op(
boost::asio::ssl::stream<AsyncStream>& s,
role_type role)
: s_(s)
, role_(role)
{
}
template<class Self>
void
operator()(Self& self, error_code ec = {}, std::size_t bytes_transferred = 0)
{
BOOST_ASIO_CORO_REENTER(*this)
{
BOOST_ASIO_CORO_YIELD
s_.async_shutdown(std::move(self));
ec_ = ec;
using boost::beast::websocket::async_teardown;
BOOST_ASIO_CORO_YIELD
async_teardown(role_, s_.next_layer(), std::move(self));
if (!ec_)
ec_ = ec;
self.complete(ec_);
}
}
private:
boost::asio::ssl::stream<AsyncStream>& s_;
role_type role_;
error_code ec_;
};
} // detail
template<
class AsyncStream,
class TeardownHandler>
void
async_teardown(
role_type,
net::ssl::stream<AsyncStream>& stream,
role_type role,
boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler)
{
stream.async_shutdown(
std::forward<TeardownHandler>(handler));
return boost::asio::async_compose<TeardownHandler, void(error_code)>(
detail::ssl_shutdown_op<AsyncStream>(stream, role),
handler,
stream);
}
} // beast