]> granicus.if.org Git - neomutt/commitdiff
Fix gnutls tls_socket_write() to properly retry
authorKevin McCarthy <kevin@8t8.us>
Mon, 21 Jan 2019 19:56:04 +0000 (11:56 -0800)
committerRichard Russon <rich@flatcap.org>
Wed, 20 Feb 2019 00:55:01 +0000 (00:55 +0000)
Retry on GNUTLS_E_AGAIN and GNUTLS_E_INTERRUPTED.  This prevents an
aborted send due to a SIGWINCH, for instance.

Change tls_socket_read() to follow the same flow.  Don't bother
checking gnutls_error_is_fatal() because return codes besides AGAIN
and INTERRUPTED end up closing the connection regardless.  (We don't
handle handshakes and negotations during send/receive).

Co-authored-by: Richard Russon <rich@flatcap.org>
conn/ssl_gnutls.c

index eaea3e20428405c21959adfba962a8c9e7718511..fe3f5e5f40826103cc78b50923ada5e1cc8885fe 100644 (file)
@@ -1151,12 +1151,13 @@ static int tls_socket_read(struct Connection *conn, char *buf, size_t count)
   do
   {
     rc = gnutls_record_recv(data->state, buf, count);
-    if ((rc < 0 && gnutls_error_is_fatal(rc) == 1) || rc == GNUTLS_E_INTERRUPTED)
-    {
-      mutt_error("tls_socket_read (%s)", gnutls_strerror(rc));
-      return -1;
-    }
-  } while (rc == GNUTLS_E_AGAIN);
+  } while ((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED));
+
+  if (rc < 0)
+  {
+    mutt_error("tls_socket_read (%s)", gnutls_strerror(rc));
+    return -1;
+  }
 
   return rc;
 }
@@ -1177,16 +1178,18 @@ static int tls_socket_write(struct Connection *conn, const char *buf, size_t cou
 
   do
   {
-    const int ret = gnutls_record_send(data->state, buf + sent, count - sent);
+    int ret;
+    do
+    {
+      ret = gnutls_record_send(data->state, buf + sent, count - sent);
+    } while ((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED));
+
     if (ret < 0)
     {
-      if (gnutls_error_is_fatal(ret) == 1 || ret == GNUTLS_E_INTERRUPTED)
-      {
-        mutt_error("tls_socket_write (%s)", gnutls_strerror(ret));
-        return -1;
-      }
-      return ret;
+      mutt_error("tls_socket_write (%s)", gnutls_strerror(ret));
+      return -1;
     }
+
     sent += ret;
   } while (sent < count);