diff options
| author | Paul Eggert | 2016-08-03 01:54:20 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-08-03 01:55:49 -0700 |
| commit | 1a8d31123698ccf6f165e49fcfe16631d07a7aea (patch) | |
| tree | b8570bf5d4ea0f92f8c516f3ffc70d2beb61783d | |
| parent | 64edd14ca9cf6d1b957316a9a547e482c9ba811b (diff) | |
| download | emacs-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.c | 31 |
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 | ||
| 415 | static int | ||
| 416 | emacs_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 | |||
| 414 | static int | 439 | static int |
| 415 | emacs_gnutls_handshake (struct Lisp_Process *proc) | 440 | emacs_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); |