I'm using OpenSSL Bio interface with a blocking socket to create a TCP SSL connection.
After many successful send/reads...
BIO_write()
succeeds. Immediately I progress to wait for the response but BIO_read()
fails. I process the return value using OpenSSL enums but it maps to SSL_ERROR_NONE
?
Given it's a blocking socket, is the only explanation the client MUST have closed the connection? It doesn't make much sense for the client to close the connection in this case. Are there any other possibilities, or ways to determine the exact reason?
This is how the code looks:
std::optional<Response> sendThenRecv()
{
// .....
if(BIO_write(bio_, write_buf, strlen(write_buf)) <= 0)
{
return std::nullopt;
}
const int res = BIO_read(bio_, read_buf, read_size);
if(res <= 0)
{
LOG("BIO_read() failed. errno details: " << GetSSLError(res));
return std::nullopt;
}
//.....
}
static inline std::string GetSSLError(const int reason)
{
switch(reason)
{
case 0:
return "SSL_ERROR_NONE";
case 1:
return "SSL_ERROR_SSL";
case 2:
return "SSL_ERROR_WANT_READ";
case 3:
return "SSL_ERROR_WANT_WRITE";
case 4:
return "SSL_ERROR_WANT_X509_LOOKUP";
case 5:
return "SSL_ERROR_SYSCALL: " + std::string(strerror(errno));
case 6:
return "SSL_ERROR_ZERO_RETURN";
case 7:
return "SSL_ERROR_WANT_CONNECT";
case 8:
return "SSL_ERROR_WANT_ACCEPT";
case 9:
return "SSL_ERROR_WANT_ASYNC";
case 10:
return "SSL_ERROR_WANT_ASYNC_JOB";
case 11:
return "SSL_ERROR_WANT_CLIENT_HELLO_CB";
case 12:
return "SSL_ERROR_WANT_RETRY_VERIFY";
default:
MY_ASSERT(false);
}
return std::to_string(reason);
}