A boost-asio
SSL/TLS TCP socket is implemented as an ssl::stream
over a tcp::socket
:
boost::asio::ssl::stream
To securely disconnect, perform a shutdown operation and then close the underlying transport once shutdown has complete. Hence, the method you are currently using will perform a secure disconnect:
boost::system::error_code ec;
ssl_socket.cancel(ec);
ssl_socket.async_shutdown([](...) { ssl_socket.close(); };
Be aware that the current async_shutdown
operation will be considered complete when either:
close_notify
has been received by the remote peer.Hence, if resources are bound to the lifetime of the socket or connection, then these resources will remain alive waiting for the remote peer to take action or until the operation is cancelled locally. However, waiting for a close_notify
response is not required for a secure shutdown. If resources are bound to the connection, and locally the connection is considered dead upon sending a shutdown, then it may be worthwhile to not wait for the remote peer to take action:
ssl_socket.async_shutdown(...);
const char buffer[] = "";
async_write(ssl_socket, boost::asio::buffer(buffer),
[](...) { ssl_socket.close(); })
When a client sends a close_notify
message, the client guarantees that the client will not send additional data across the secure connection. In essence, the async_write()
is being used to detect when the client has sent a close_notify
, and within the completion handler, will close the underlying transport, causing the async_shutdown()
to complete with boost::asio::error::operation_aborted
. As noted in the linked answer, the async_write()
operation is expected to fail.
... as the write side of PartyA's SSL stream has closed, the
async_write()
operation will fail with an SSL error indicating the protocol has been shutdown.if ((error.category() == boost::asio::error::get_ssl_category()) && (SSL_R_PROTOCOL_IS_SHUTDOWN == ERR_GET_REASON(error.value()))) { ssl_stream.lowest_layer().close(); }
The failed
async_write()
operation will then explicitly close the underlying transport, causing theasync_shutdown()
operation that is waiting for PartyB'sclose_notify
to be cancelled.