mirror of
https://github.com/pocoproject/poco.git
synced 2025-05-28 23:24:09 +02:00
fix for GH #1160: Poco::Net::NetException "SSL Exception: error:1409F07F:SSL routines:ssl3_write_pending:bad write retry
This commit is contained in:
parent
5076f60a5c
commit
f7ba58c80f
@ -196,7 +196,21 @@ protected:
|
|||||||
static bool isLocalHost(const std::string& hostName);
|
static bool isLocalHost(const std::string& hostName);
|
||||||
/// Returns true iff the given host name is the local host
|
/// Returns true iff the given host name is the local host
|
||||||
/// (either "localhost" or "127.0.0.1").
|
/// (either "localhost" or "127.0.0.1").
|
||||||
|
|
||||||
|
bool mustRetry(int rc);
|
||||||
|
/// Returns true if the last operation should be retried,
|
||||||
|
/// otherwise false.
|
||||||
|
///
|
||||||
|
/// In case of an SSL_ERROR_WANT_READ error, and if the socket is
|
||||||
|
/// blocking, waits for the underlying socket to become readable.
|
||||||
|
///
|
||||||
|
/// In case of an SSL_ERROR_WANT_WRITE error, and if the socket is
|
||||||
|
/// blocking, waits for the underlying socket to become writable.
|
||||||
|
///
|
||||||
|
/// Can also throw a Poco::TimeoutException if the socket does
|
||||||
|
/// not become readable or writable within the sockets
|
||||||
|
/// receive or send timeout.
|
||||||
|
|
||||||
int handleError(int rc);
|
int handleError(int rc);
|
||||||
/// Handles an SSL error by throwing an appropriate exception.
|
/// Handles an SSL error by throwing an appropriate exception.
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
|
|||||||
{
|
{
|
||||||
rc = SSL_write(_pSSL, buffer, length);
|
rc = SSL_write(_pSSL, buffer, length);
|
||||||
}
|
}
|
||||||
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
|
while (mustRetry(rc));
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
{
|
{
|
||||||
rc = handleError(rc);
|
rc = handleError(rc);
|
||||||
@ -298,7 +298,7 @@ int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
|
|||||||
{
|
{
|
||||||
rc = SSL_read(_pSSL, buffer, length);
|
rc = SSL_read(_pSSL, buffer, length);
|
||||||
}
|
}
|
||||||
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
|
while (mustRetry(rc));
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
{
|
{
|
||||||
return handleError(rc);
|
return handleError(rc);
|
||||||
@ -325,7 +325,7 @@ int SecureSocketImpl::completeHandshake()
|
|||||||
{
|
{
|
||||||
rc = SSL_do_handshake(_pSSL);
|
rc = SSL_do_handshake(_pSSL);
|
||||||
}
|
}
|
||||||
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
|
while (mustRetry(rc));
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
{
|
{
|
||||||
return handleError(rc);
|
return handleError(rc);
|
||||||
@ -390,6 +390,42 @@ X509* SecureSocketImpl::peerCertificate() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SecureSocketImpl::mustRetry(int rc)
|
||||||
|
{
|
||||||
|
if (rc <= 0)
|
||||||
|
{
|
||||||
|
int sslError = SSL_get_error(_pSSL, rc);
|
||||||
|
int socketError = _pSocket->lastError();
|
||||||
|
switch (sslError)
|
||||||
|
{
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
if (_pSocket->getBlocking())
|
||||||
|
{
|
||||||
|
if (_pSocket->poll(_pSocket->getReceiveTimeout(), Poco::Net::Socket::SELECT_READ))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
throw Poco::TimeoutException();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
if (_pSocket->getBlocking())
|
||||||
|
{
|
||||||
|
if (_pSocket->poll(_pSocket->getSendTimeout(), Poco::Net::Socket::SELECT_WRITE))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
throw Poco::TimeoutException();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
return socketError == POCO_EAGAIN || socketError == POCO_EINTR;
|
||||||
|
default:
|
||||||
|
return socketError == POCO_EINTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int SecureSocketImpl::handleError(int rc)
|
int SecureSocketImpl::handleError(int rc)
|
||||||
{
|
{
|
||||||
if (rc > 0) return rc;
|
if (rc > 0) return rc;
|
||||||
@ -402,13 +438,6 @@ int SecureSocketImpl::handleError(int rc)
|
|||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
return 0;
|
return 0;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
if (_pSocket->getBlocking() && error != 0)
|
|
||||||
{
|
|
||||||
if (error == POCO_EAGAIN)
|
|
||||||
throw TimeoutException(error);
|
|
||||||
else
|
|
||||||
SocketImpl::error(error);
|
|
||||||
}
|
|
||||||
return SecureStreamSocket::ERR_SSL_WANT_READ;
|
return SecureStreamSocket::ERR_SSL_WANT_READ;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
return SecureStreamSocket::ERR_SSL_WANT_WRITE;
|
return SecureStreamSocket::ERR_SSL_WANT_WRITE;
|
||||||
@ -421,11 +450,7 @@ int SecureSocketImpl::handleError(int rc)
|
|||||||
case SSL_ERROR_SYSCALL:
|
case SSL_ERROR_SYSCALL:
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
{
|
{
|
||||||
if (_pSocket->getBlocking() && error == POCO_EAGAIN)
|
SocketImpl::error(error);
|
||||||
throw TimeoutException(error);
|
|
||||||
else
|
|
||||||
SocketImpl::error(error);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
// fallthrough
|
// fallthrough
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user