8353407c1f939c1b776febc9c5867a601b7dd69a — Kevin McCarthy 4 months ago fdfda1b
Add checks for buffered OpenSSL or GnuTLS data when polling.

I don't believe this has had an actual effect, because Mutt doesn't
support renegotiation, and we are only polling immediately after
sending NOOP.

However, it looks like checking is technically the correct thing to do
to avoid polling waiting for data that is already buffered.
2 files changed, 29 insertions(+), 2 deletions(-)

M mutt_ssl.c
M mutt_ssl_gnutls.c
M mutt_ssl.c => mutt_ssl.c +15 -1
@@ 38,6 38,7 @@
 #define X509_getm_notBefore X509_get_notBefore
 #define X509_getm_notAfter X509_get_notAfter
 #define X509_STORE_CTX_get0_chain X509_STORE_CTX_get_chain
+#define SSL_has_pending SSL_pending
 #endif
 
 #undef _


@@ 94,6 95,7 @@ static int ssl_init (void);
 static int add_entropy (const char *file);
 static int ssl_socket_read (CONNECTION* conn, char* buf, size_t len);
 static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len);
+static int ssl_socket_poll (CONNECTION* conn, time_t wait_secs);
 static int ssl_socket_open (CONNECTION * conn);
 static int ssl_socket_close (CONNECTION * conn);
 static int tls_close (CONNECTION* conn);


@@ 284,6 286,7 @@ int mutt_ssl_starttls (CONNECTION* conn)
   conn->conn_read = ssl_socket_read;
   conn->conn_write = ssl_socket_write;
   conn->conn_close = tls_close;
+  conn->conn_poll = ssl_socket_poll;
 
   conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (ssldata->ssl),
                                    &maxbits);


@@ 413,7 416,7 @@ int mutt_ssl_socket_setup (CONNECTION * conn)
   conn->conn_read	= ssl_socket_read;
   conn->conn_write	= ssl_socket_write;
   conn->conn_close	= ssl_socket_close;
-  conn->conn_poll       = raw_socket_poll;
+  conn->conn_poll       = ssl_socket_poll;
 
   return 0;
 }


@@ 445,6 448,16 @@ static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len)
   return rc;
 }
 
+static int ssl_socket_poll (CONNECTION* conn, time_t wait_secs)
+{
+  sslsockdata *data = conn->sockdata;
+
+  if (SSL_has_pending (data->ssl))
+    return 1;
+  else
+    return raw_socket_poll (conn, wait_secs);
+}
+
 static int ssl_socket_open (CONNECTION * conn)
 {
   sslsockdata *data;


@@ 647,6 660,7 @@ static int tls_close (CONNECTION* conn)
   conn->conn_read = raw_socket_read;
   conn->conn_write = raw_socket_write;
   conn->conn_close = raw_socket_close;
+  conn->conn_poll = raw_socket_poll;
 
   return rc;
 }

M mutt_ssl_gnutls.c => mutt_ssl_gnutls.c +14 -1
@@ 85,6 85,7 @@ tlssockdata;
 /* local prototypes */
 static int tls_socket_read (CONNECTION* conn, char* buf, size_t len);
 static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len);
+static int tls_socket_poll (CONNECTION* conn, time_t wait_secs);
 static int tls_socket_open (CONNECTION* conn);
 static int tls_socket_close (CONNECTION* conn);
 static int tls_starttls_close (CONNECTION* conn);


@@ 123,7 124,7 @@ int mutt_ssl_socket_setup (CONNECTION* conn)
   conn->conn_read	= tls_socket_read;
   conn->conn_write	= tls_socket_write;
   conn->conn_close	= tls_socket_close;
-  conn->conn_poll       = raw_socket_poll;
+  conn->conn_poll       = tls_socket_poll;
 
   return 0;
 }


@@ 188,6 189,16 @@ static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len)
   return sent;
 }
 
+static int tls_socket_poll (CONNECTION* conn, time_t wait_secs)
+{
+  tlssockdata *data = conn->sockdata;
+
+  if (gnutls_record_check_pending (data->state))
+    return 1;
+  else
+    return raw_socket_poll (conn, wait_secs);
+}
+
 static int tls_socket_open (CONNECTION* conn)
 {
   if (raw_socket_open (conn) < 0)


@@ 213,6 224,7 @@ int mutt_ssl_starttls (CONNECTION* conn)
   conn->conn_read	= tls_socket_read;
   conn->conn_write	= tls_socket_write;
   conn->conn_close	= tls_starttls_close;
+  conn->conn_poll       = tls_socket_poll;
 
   return 0;
 }


@@ 523,6 535,7 @@ static int tls_starttls_close (CONNECTION* conn)
   conn->conn_read = raw_socket_read;
   conn->conn_write = raw_socket_write;
   conn->conn_close = raw_socket_close;
+  conn->conn_poll = raw_socket_poll;
 
   return rc;
 }