aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2016-08-03 01:54:20 -0700
committerPaul Eggert2016-08-03 01:55:49 -0700
commit1a8d31123698ccf6f165e49fcfe16631d07a7aea (patch)
treeb8570bf5d4ea0f92f8c516f3ffc70d2beb61783d
parent64edd14ca9cf6d1b957316a9a547e482c9ba811b (diff)
downloademacs-1a8d31123698ccf6f165e49fcfe16631d07a7aea.tar.gz
emacs-1a8d31123698ccf6f165e49fcfe16631d07a7aea.zip
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.
-rw-r--r--src/gnutls.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/gnutls.c b/src/gnutls.c
index 681e2989071..e3e9311c48d 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -411,6 +411,31 @@ gnutls_try_handshake (struct Lisp_Process *proc)
411 return ret; 411 return ret;
412} 412}
413 413
414#ifndef WINDOWSNT
415static int
416emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
417{
418 int err = errno;
419
420 switch (err)
421 {
422# ifdef _AIX
423 /* This is taken from the GnuTLS system_errno function circa 2016;
424 see <http://savannah.gnu.org/support/?107464>. */
425 case 0:
426 errno = EAGAIN;
427 /* Fall through. */
428# endif
429 case EINPROGRESS:
430 case ENOTCONN:
431 return EAGAIN;
432
433 default:
434 return err;
435 }
436}
437#endif
438
414static int 439static int
415emacs_gnutls_handshake (struct Lisp_Process *proc) 440emacs_gnutls_handshake (struct Lisp_Process *proc)
416{ 441{
@@ -437,6 +462,9 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
437 gnutls_transport_set_ptr2 (state, 462 gnutls_transport_set_ptr2 (state,
438 (void *) (intptr_t) proc->infd, 463 (void *) (intptr_t) proc->infd,
439 (void *) (intptr_t) proc->outfd); 464 (void *) (intptr_t) proc->outfd);
465 if (proc->is_non_blocking_client)
466 gnutls_transport_set_errno_function (state,
467 emacs_gnutls_nonblock_errno);
440#endif 468#endif
441 469
442 proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; 470 proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
@@ -1574,7 +1602,8 @@ one trustfile (usually a CA bundle). */)
1574 /* Call gnutls_init here: */ 1602 /* Call gnutls_init here: */
1575 1603
1576 GNUTLS_LOG (1, max_log_level, "gnutls_init"); 1604 GNUTLS_LOG (1, max_log_level, "gnutls_init");
1577 ret = gnutls_init (&state, GNUTLS_CLIENT); 1605 int nonblock = XPROCESS (proc)->is_non_blocking_client ? GNUTLS_NONBLOCK : 0;
1606 ret = gnutls_init (&state, GNUTLS_CLIENT | nonblock);
1578 XPROCESS (proc)->gnutls_state = state; 1607 XPROCESS (proc)->gnutls_state = state;
1579 if (ret < GNUTLS_E_SUCCESS) 1608 if (ret < GNUTLS_E_SUCCESS)
1580 return gnutls_make_error (ret); 1609 return gnutls_make_error (ret);