[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 1a8d311 2/2: Fix non-blocking GnuTLS with slow conn
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] master 1a8d311 2/2: Fix non-blocking GnuTLS with slow connection |
Date: |
Wed, 3 Aug 2016 08:55:53 +0000 (UTC) |
branch: master
commit 1a8d31123698ccf6f165e49fcfe16631d07a7aea
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>
Fix non-blocking GnuTLS with slow connection
Although the problem is reported for OS X (Bug#23982), it seems to
be possible on other POSIXish platforms.
* src/gnutls.c (emacs_gnutls_nonblock_errno) [!WINDOWSNT]:
New function.
(emacs_gnutls_handshake) [!WINDOWSNT]:
Use it as the errno function, if non-blocking.
(Fgnutls_boot): Use GNUTLS_NONBLOCK if non-blocking.
---
src/gnutls.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/gnutls.c b/src/gnutls.c
index 681e298..e3e9311 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -411,6 +411,31 @@ gnutls_try_handshake (struct Lisp_Process *proc)
return ret;
}
+#ifndef WINDOWSNT
+static int
+emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
+{
+ int err = errno;
+
+ switch (err)
+ {
+# ifdef _AIX
+ /* This is taken from the GnuTLS system_errno function circa 2016;
+ see <http://savannah.gnu.org/support/?107464>. */
+ case 0:
+ errno = EAGAIN;
+ /* Fall through. */
+# endif
+ case EINPROGRESS:
+ case ENOTCONN:
+ return EAGAIN;
+
+ default:
+ return err;
+ }
+}
+#endif
+
static int
emacs_gnutls_handshake (struct Lisp_Process *proc)
{
@@ -437,6 +462,9 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
gnutls_transport_set_ptr2 (state,
(void *) (intptr_t) proc->infd,
(void *) (intptr_t) proc->outfd);
+ if (proc->is_non_blocking_client)
+ gnutls_transport_set_errno_function (state,
+ emacs_gnutls_nonblock_errno);
#endif
proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
@@ -1574,7 +1602,8 @@ one trustfile (usually a CA bundle). */)
/* Call gnutls_init here: */
GNUTLS_LOG (1, max_log_level, "gnutls_init");
- ret = gnutls_init (&state, GNUTLS_CLIENT);
+ int nonblock = XPROCESS (proc)->is_non_blocking_client ? GNUTLS_NONBLOCK : 0;
+ ret = gnutls_init (&state, GNUTLS_CLIENT | nonblock);
XPROCESS (proc)->gnutls_state = state;
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);