aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2014-01-03 20:54:32 +0000
committerVincent Richard <[email protected]>2014-01-03 20:54:32 +0000
commit696e3ff902c6601fd706fa21021e711e9993e0a6 (patch)
treee9ae52833c6032d2b2b428ae2f32a242089608e6
parentAdded support for SPECIAL-USE extension (IMAP). (diff)
downloadvmime-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.cpp34
-rw-r--r--src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp26
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;
+ }
+ }
}