ssl-write-retry-3.patch
text/x-patch
Filename: ssl-write-retry-3.patch
Type: text/x-patch
Part: 0
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index 17dde4a..977e37c 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -793,20 +793,26 @@ pqSendSome(PGconn *conn, int len)
while (len > 0)
{
int sent;
+ int write_size = len;
char sebuf[256];
-#ifndef WIN32
- sent = pqsecure_write(conn, ptr, len);
-#else
-
+#ifdef WIN32
/*
* Windows can fail on large sends, per KB article Q201213. The
* failure-point appears to be different in different versions of
* Windows, but 64k should always be safe.
*/
- sent = pqsecure_write(conn, ptr, Min(len, 65536));
+ write_size = Min(len, 65536);
+#endif
+
+#ifdef USE_SSL
+ /* We have leftovers from previous SSL write, send these first. */
+ if (conn->ssl_retry_bytes)
+ write_size = conn->ssl_retry_bytes;
#endif
+ sent = pqsecure_write(conn, ptr, write_size);
+
if (sent < 0)
{
/*
@@ -857,11 +863,30 @@ pqSendSome(PGconn *conn, int len)
return -1;
}
}
+#ifdef USE_SSL
+ else if (sent == 0)
+ {
+ /*
+ * We are in non-blocking mode, set up for retrying a SSL write
+ * operation. OpenSSL requires the same buffer to be passed to the
+ * write retry, so we must remember the write size. However, we
+ * don't need to keep the original buffer address as the
+ * SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER mode ought to be set.
+ */
+ if (!conn->ssl_retry_bytes)
+ conn->ssl_retry_bytes = write_size;
+ }
+#endif
else
{
ptr += sent;
len -= sent;
remaining -= sent;
+#ifdef USE_SSL
+ /* Forget the retry buffer size if all the data has been sent */
+ if (conn->ssl_retry_bytes)
+ conn->ssl_retry_bytes = 0;
+#endif
}
if (len > 0)
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index cd1292c..540561d 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -757,6 +757,9 @@ init_ssl_system(PGconn *conn)
#endif
return -1;
}
+
+ /* Enable moving write buffer to simplify write retry handling. */
+ SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
}
#ifdef ENABLE_THREAD_SAFETY
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index d56ef5d..ae212a6 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -407,6 +407,8 @@ struct pg_conn
X509 *peer; /* X509 cert of server */
char peer_dn[256 + 1]; /* peer distinguished name */
char peer_cn[SM_USER + 1]; /* peer common name */
+
+ int ssl_retry_bytes; /* buffer size for SSL write retry */
#ifdef USE_SSL_ENGINE
ENGINE *engine; /* SSL engine, if any */
#else