diff options
author | Vincent Richard <[email protected]> | 2014-01-03 20:54:32 +0000 |
---|---|---|
committer | Vincent Richard <[email protected]> | 2014-01-03 20:54:32 +0000 |
commit | 696e3ff902c6601fd706fa21021e711e9993e0a6 (patch) | |
tree | e9ae52833c6032d2b2b428ae2f32a242089608e6 | |
parent | Added support for SPECIAL-USE extension (IMAP). (diff) | |
download | vmime-696e3ff902c6601fd706fa21021e711e9993e0a6.tar.gz vmime-696e3ff902c6601fd706fa21021e711e9993e0a6.zip |
Loop on SSL_write/gnutls_record_send in blocking send.
OpenSSL reports SSL3_WRITE_PENDING on slow network connections, this
patch fixes it (and is the correct way to do).
-rw-r--r-- | src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp | 34 | ||||
-rw-r--r-- | src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp | 26 |
2 files changed, 47 insertions, 13 deletions
diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp index 5a90565b..18ea352d 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp @@ -179,22 +179,32 @@ size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) { - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast <size_t>(count)); - - if (m_ex) - internalThrow(); + m_status &= ~STATUS_WOULDBLOCK; - if (ret < 0) + for (size_t size = count ; size > 0 ; ) { - if (ret == GNUTLS_E_AGAIN) + ssize_t ret = gnutls_record_send + (*m_session->m_gnutlsSession, + buffer, static_cast <size_t>(size)); + + if (m_ex) + internalThrow(); + + if (ret < 0) { - m_status |= STATUS_WOULDBLOCK; - return; - } + if (ret == GNUTLS_E_AGAIN) + { + platform::getHandler()->wait(); + continue; + } - TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast <int>(ret)); + TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast <int>(ret)); + } + else + { + buffer += ret; + size -= ret; + } } } diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp index ef6647d6..9857b8fb 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp @@ -119,6 +119,7 @@ void TLSSocket_OpenSSL::createSSLHandle() SSL_set_bio(m_ssl, sockBio, sockBio); SSL_set_connect_state(m_ssl); + SSL_set_mode(m_ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); } else { @@ -234,7 +235,30 @@ size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) { - sendRawNonBlocking(buffer, count); + m_status &= ~STATUS_WOULDBLOCK; + + for (size_t size = count ; size > 0 ; ) + { + int rc = SSL_write(m_ssl, buffer, static_cast <int>(size)); + + if (rc <= 0) + { + int error = SSL_get_error(m_ssl, rc); + + if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) + { + platform::getHandler()->wait(); + continue; + } + + handleError(rc); + } + else + { + buffer += rc; + size -= rc; + } + } } |