Клиент выполняет несколько вызовов ssl::stream<tcp_socket>::async_read_some()
/ssl::stream<tcp_socket>::async_write()
и в какой-то момент должен выйти, т.е. ему нужно отключить соединение.
Вызов ssl::stream<tcp_socket>::lowest_layer().close()
работает, но (как и ожидалось) сервер (команда openssl s_server -state ...
) сообщает об ошибке при закрытии соединения.
Посмотрев на API, правильным способом является вызов ssl::stream<tcp_socket>::async_shutdown()
.
Теперь есть в основном 2 ситуации, когда требуется выключение:
1) Клиент находится в обратном вызове async_read_some()
и реагирует на команду "quit" с сервера. Вызов оттуда async_shutdown()
дает ошибку "короткого чтения" в обратном вызове выключения.
Это удивительно, но после того, как googling вокруг этого, похоже, является нормальным поведением - кажется, нужно проверить, является ли это реальной ошибкой или нет:
// 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, кажется, счастлив, хотя - он сообщает:
DONE
shutting down SSL
CONNECTION CLOSED
2) A async_read_some()
активен, но пользователь решает выйти из клиента (например, с помощью команды из stdin). При вызове async_shutdown()
из этого контекста происходит следующее:
- обратный вызов
async_read_some()
выполняется с кодом ошибки "короткого чтения" - вид ожидаемого сейчас - Обратный вызов
async_shutdown()
выполняется с кодом ошибки дешифрования или неудачной записью mac - это неожиданно.
Серверная сторона не сообщает об ошибке.
Таким образом, мой вопрос, как правильно закрыть клиент TLS с boost asio.