One way to resolve the 'decryption failed or bad record mac' error code from the 2nd context is:
a) from inside the stdin handler call:
ssl::stream<tcp_socket>::lowest_layer()::shutdown(tcp::socket::shutdown_receive)
b) this results in the async_read_some()
callback getting executed with a 'short read' 'error' code
c) in that callback under that 'error' condition async_shutdown()
is called:
// 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:
do_ssl_async_shutdown();
}
d) the async_shutdown()
callback is executed with a 'short read' error code, from where we finally call:
ssl::stream::lowest_layer()::close()
These steps result in a connection shutdown without any weird error messages on the client or server side.
For example, when using openssl s_server -state ...
as server it reports on sutdown:
SSL3 alert read:warning:close notify
DONE
shutting down SSL
CONNECTION CLOSED
ACCEPT
(the last line is because the command accepts new connections)
Alternative
Instead of lowest_layer()::shutdown(tcp::socket::shutdown_receive)
we can also call
ssl::stream<tcp_socket>::lowest_layer()::cancel()
to initiate a proper shutdown. It has the same effect, i.e. it yields the execution of the scheduled async_read_some()
callback (but with operation_aborted
error code). Thus, one can call async_shutdown()
from there:
if (ec.value() == asio::error::operation_aborted) {
cout << "(not really an error)
";
do_async_ssl_shutdown();
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…