如何正常关闭升压ASIO SSL客户端? [英] How to gracefully shutdown a boost asio ssl client?
问题描述
客户端做了一些<$c$c>ssl::stream<tcp_socket>::async_read_some()$c$c>/<$c$c>ssl::stream<tcp_socket>::async_write()$c$c>电话和在一些点需要退出,即,它需要关闭该连接。
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.
调用 SSL ::流&LT; TCP_SOCKET方式&gt; :: lowest_layer()的close()
工作,但(如预期),服务器(A OpenSSL的s_server -state ...
命令)在关闭连接报告错误。
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.
看着正确的方式似乎是调用API SSL ::流&LT; TCP_SOCKET方式&gt; :: async_shutdown()
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)客户端是在 async_read_some()
回调,并反作用于来自服务器的退出命令。从那里调用 async_shutdown()
产生在关机回调短读的错误。
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
}
在TLS服务器似乎是幸福的,虽然 - 它报告:
The TLS server seems to be happy, though - it reports:
DONE
shutting down SSL
CONNECTION CLOSED
2) async_read_some()
活跃 - 但是一个用户决定(例如,通过从标准输入命令)退出客户端。打电话时 async_shutdown()
从上下文中发生以下情况:
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:
- 在
async_read_some()
回调与短读错误code执行的 - 种目前预计 - 在
async_shutdown()
回调与解密执行失败或不良记录MAC 错误code - 这是意外
- 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.
因此,我的问题如何正确关机TLS客户端升压ASIO。
Thus my question how to properly shutdown a TLS client with boost asio.
推荐答案
要解决的一种方式解密失败或不良记录MAC'从第二方面的错误code是:
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)这将导致 async_read_some()
回调得到一个短读执行错误code
b) this results in the async_read_some()
callback getting executed with a 'short read' 'error' code
c)如果回调'错误'的条件下 async_shutdown()
正所谓:
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();
}
四) async_shutdown()
回调与短读错误code,从那里我们最后调用执行:
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.
例如,当使用 OpenSSL的s_server -state ...
作为服务器它sutdown报道:
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)
而不是 lowest_layer()::关机(TCP ::插座:: shutdown_receive)的
我们也可以称之为
Instead of lowest_layer()::shutdown(tcp::socket::shutdown_receive)
we can also call
ssl::stream<tcp_socket>::lowest_layer()::cancel()
启动正常关机。它具有相同的效果,即它产生预定的 async_read_some的执行()
回调(但 operation_aborted
错误code)。因此,可以调用 async_shutdown()
从那里:
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)\n";
do_async_ssl_shutdown();
}
这篇关于如何正常关闭升压ASIO SSL客户端?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!