The client does some ssl::stream<tcp_socket>::async_read_some()
/ssl::stream<tcp_socket>::async_write()
calls and at some point needs to exit, i.e. it needs to shutdown the connection.
Calling ssl::stream<tcp_socket>::lowest_layer().close()
works, but (as it is expected) the server (a openssl s_server -state ...
command) reports an error on closing the connection.
Looking at the API the right way seems to be to call ssl::stream<tcp_socket>::async_shutdown()
.
Now there are basically 2 situation where a shutdown is needed:
1) Client is in the async_read_some()
callback and reacts on a 'quit' command from the server. Calling from there async_shutdown()
yields a 'short read' error in the shutdown callback.
This is surprising but after googling around this seems to be normal behaviour - one seem to have to check if it is a real error or not like this:
// const boost::system::error_code &ec
if (ec.category() == asio::error::get_ssl_category() &&
ec.value() == ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ)) {
// -> not a real error, just a normal TLS shutdown
}
The TLS server seems to be happy, though - it reports:
DONE
shutting down SSL
CONNECTION CLOSED
2) A async_read_some()
is active - but a user decides to exit the client (e.g. via a command from stdin). When calling async_shutdown()
from that context following happens:
- the
async_read_some()
callback is executed with a 'short read' error code - kind of expected now - the
async_shutdown()
callback is executed with a decryption failed or bad record mac error code - this is unexpected
The server side does not report an error.
Thus my question how to properly shutdown a TLS client with boost asio.
See Question&Answers more detail:os