Commit 1a8d3112 authored by Paul Eggert's avatar Paul Eggert
Browse files

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.
parent 64edd14c
...@@ -411,6 +411,31 @@ gnutls_try_handshake (struct Lisp_Process *proc) ...@@ -411,6 +411,31 @@ gnutls_try_handshake (struct Lisp_Process *proc)
return ret; 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 static int
emacs_gnutls_handshake (struct Lisp_Process *proc) emacs_gnutls_handshake (struct Lisp_Process *proc)
{ {
...@@ -437,6 +462,9 @@ emacs_gnutls_handshake (struct Lisp_Process *proc) ...@@ -437,6 +462,9 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
gnutls_transport_set_ptr2 (state, gnutls_transport_set_ptr2 (state,
(void *) (intptr_t) proc->infd, (void *) (intptr_t) proc->infd,
(void *) (intptr_t) proc->outfd); (void *) (intptr_t) proc->outfd);
if (proc->is_non_blocking_client)
gnutls_transport_set_errno_function (state,
emacs_gnutls_nonblock_errno);
#endif #endif
proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
...@@ -1574,7 +1602,8 @@ one trustfile (usually a CA bundle). */) ...@@ -1574,7 +1602,8 @@ one trustfile (usually a CA bundle). */)
/* Call gnutls_init here: */ /* Call gnutls_init here: */
GNUTLS_LOG (1, max_log_level, "gnutls_init"); 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; XPROCESS (proc)->gnutls_state = state;
if (ret < GNUTLS_E_SUCCESS) if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret); return gnutls_make_error (ret);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment