From 3029f74ad5b8f989e26673a31c257fa2aa8d7304 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 3 Aug 2016 01:54:20 -0700 Subject: [PATCH 2/2] 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 . */ + 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); -- 2.5.5