В моем приложении C ++ я использую OpenSSL для подключения к серверу с использованием неблокирующего BIO. Я занимаюсь разработкой для Mac OS X и iOS.
Первый звонок SSL_shutdown()
возвращает 0. Что означает, что я должен позвонить SSL_shutdown()
снова:
Могут возникнуть следующие возвращаемые значения:
0 Завершение работы еще не завершено. Вызовите SSL_shutdown () во второй раз, если необходимо выполнить двунаправленное отключение. Вывод SSL_get_error может вводить в заблуждение, так как ошибочный SSL_ERROR_SYSCALL может быть помечен, даже если не было ошибок.
<0
Завершение работы не было успешным, потому что произошла неустранимая ошибка на уровне протокола или произошла ошибка соединения. Это также может произойти, если необходимо продолжить действие для неблокирующих BIO. Вызовите SSL_get_error с возвращаемым значением ret, чтобы выяснить причину.
https://www.openssl.org/docs/ssl/SSL_shutdown.html
Пока что бог. Проблема возникает при втором вызове SSL_shutdown()
, Это возвращает -1, что означает, что произошла ошибка (см. Выше). Теперь, если я проверю с SSL_get_error()
Я получаю ошибку SSL_ERROR_SYSCALL
что в свою очередь означает, что произошла системная ошибка. Но теперь подвох. Если я проверю errno
возвращает 0 -> неизвестная ошибка. То, что я до сих пор читал об этой проблеме, это то, что это может означать, что сервер просто «завис», но, честно говоря, меня это не удовлетворяет.
Вот моя реализация выключения:
int result = 0;
int shutdownResult;
while ((shutdownResult = SSL_shutdown(sslHandle)) != 1) { //close connection 1 means everything is shut down ok
if (shutdownResult == 0) { //we are supposed to call shutdown again
continue;
} else if (SSL_get_error(sslHandle, shutdownResult) == SSL_ERROR_WANT_READ) {
[...] //omitted want read code, in this case the application never reaches this point
} else if (SSL_get_error(sslHandle, shutdownResult) == SSL_ERROR_WANT_WRITE) {
[...] //omitted want write code, in this case the application never reaches this point
} else {
logError("Error in ssl shutdown, ssl error: " + std::to_string(SSL_get_error(sslHandle, shutdownResult)) + ", system error: " + std::string(strerror(errno))); //something went wrong
break;
}
}
Когда запускаются журналы приложений:
ОШИБКА :: Ошибка в завершении работы ssl, ошибка ssl: 5, системная ошибка: неопределенная ошибка: 0
Так вот, просто сервер закрывает соединение или есть более важная проблема? Я просто упускаю что-то действительно очевидное?
Полное отключение SSL состоит из двух частей:
Первый SSL_shutdown возвратил 0, что означает, что он отправил «уведомление о закрытии» одноранговому узлу, но еще ничего не получил обратно. Второй вызов SSL_shutdown завершается неудачно, поскольку одноранговый узел не выполнил надлежащее отключение SSL и не отправил обратно уведомление о закрытии, а просто закрыл базовое TCP-соединение.
Такое поведение на самом деле очень распространено, и вы можете просто игнорировать ошибку. Не имеет большого значения, должно ли базовое TCP-соединение быть закрыто в любом случае. Но правильное отключение SSL обычно требуется, когда вы хотите продолжить в простом тексте на том же TCP-соединении, как это необходимо для команды CCC в соединениях FTPS (но даже там, где различные реализации не справляются с этим делом должным образом).