diff options
| author | Lars Ingebrigtsen | 2016-02-16 15:56:56 +1100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2016-02-16 15:56:56 +1100 |
| commit | ac6e085cf6b26257cfe181f17828432d414cb3a6 (patch) | |
| tree | 9d382588ce869a2b816373e278b2805ffbb90f59 /src/gnutls.c | |
| parent | c43bb7f136ab9e9439a4b5c045040a12cbe8bda0 (diff) | |
| download | emacs-ac6e085cf6b26257cfe181f17828432d414cb3a6.tar.gz emacs-ac6e085cf6b26257cfe181f17828432d414cb3a6.zip | |
Implement asynch TLS negotiation
* src/gnutls.c (gnutls_try_handshake): Factor out into its own
function.
(emacs_gnutls_handshake): Use it.
(emacs_gnutls_read): Just return instead of retrying the handshake.
* src/process.c (finish_after_tls_connection): Factor out
into its own function.
(connect_network_socket): Use it.
(wait_reading_process_output): Retry TLS handshakes.
(wait_reading_process_output): Defer sentinel until TLS completes.
Diffstat (limited to 'src/gnutls.c')
| -rw-r--r-- | src/gnutls.c | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/src/gnutls.c b/src/gnutls.c index 948a0c56f14..6573c87cf78 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -397,11 +397,42 @@ gnutls_log_function2i (int level, const char *string, int extra) | |||
| 397 | message ("gnutls.c: [%d] %s %d", level, string, extra); | 397 | message ("gnutls.c: [%d] %s %d", level, string, extra); |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | int | ||
| 401 | gnutls_try_handshake (struct Lisp_Process *proc) | ||
| 402 | { | ||
| 403 | gnutls_session_t state = proc->gnutls_state; | ||
| 404 | int ret; | ||
| 405 | |||
| 406 | do | ||
| 407 | { | ||
| 408 | ret = gnutls_handshake (state); | ||
| 409 | emacs_gnutls_handle_error (state, ret); | ||
| 410 | QUIT; | ||
| 411 | } | ||
| 412 | while (ret < 0 && gnutls_error_is_fatal (ret) == 0 && | ||
| 413 | ! proc->is_non_blocking_client); | ||
| 414 | |||
| 415 | proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED; | ||
| 416 | |||
| 417 | if (proc->is_non_blocking_client) | ||
| 418 | proc->gnutls_p = 1; | ||
| 419 | |||
| 420 | if (ret == GNUTLS_E_SUCCESS) | ||
| 421 | { | ||
| 422 | /* Here we're finally done. */ | ||
| 423 | proc->gnutls_initstage = GNUTLS_STAGE_READY; | ||
| 424 | } | ||
| 425 | else | ||
| 426 | { | ||
| 427 | //check_memory_full (gnutls_alert_send_appropriate (state, ret)); | ||
| 428 | } | ||
| 429 | return ret; | ||
| 430 | } | ||
| 431 | |||
| 400 | static int | 432 | static int |
| 401 | emacs_gnutls_handshake (struct Lisp_Process *proc) | 433 | emacs_gnutls_handshake (struct Lisp_Process *proc) |
| 402 | { | 434 | { |
| 403 | gnutls_session_t state = proc->gnutls_state; | 435 | gnutls_session_t state = proc->gnutls_state; |
| 404 | int ret; | ||
| 405 | 436 | ||
| 406 | if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO) | 437 | if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO) |
| 407 | return -1; | 438 | return -1; |
| @@ -443,26 +474,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc) | |||
| 443 | proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; | 474 | proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; |
| 444 | } | 475 | } |
| 445 | 476 | ||
| 446 | do | 477 | return gnutls_try_handshake (proc); |
| 447 | { | ||
| 448 | ret = gnutls_handshake (state); | ||
| 449 | emacs_gnutls_handle_error (state, ret); | ||
| 450 | QUIT; | ||
| 451 | } | ||
| 452 | while (ret < 0 && gnutls_error_is_fatal (ret) == 0); | ||
| 453 | |||
| 454 | proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED; | ||
| 455 | |||
| 456 | if (ret == GNUTLS_E_SUCCESS) | ||
| 457 | { | ||
| 458 | /* Here we're finally done. */ | ||
| 459 | proc->gnutls_initstage = GNUTLS_STAGE_READY; | ||
| 460 | } | ||
| 461 | else | ||
| 462 | { | ||
| 463 | check_memory_full (gnutls_alert_send_appropriate (state, ret)); | ||
| 464 | } | ||
| 465 | return ret; | ||
| 466 | } | 478 | } |
| 467 | 479 | ||
| 468 | ptrdiff_t | 480 | ptrdiff_t |
| @@ -531,23 +543,8 @@ emacs_gnutls_read (struct Lisp_Process *proc, char *buf, ptrdiff_t nbyte) | |||
| 531 | int log_level = proc->gnutls_log_level; | 543 | int log_level = proc->gnutls_log_level; |
| 532 | 544 | ||
| 533 | if (proc->gnutls_initstage != GNUTLS_STAGE_READY) | 545 | if (proc->gnutls_initstage != GNUTLS_STAGE_READY) |
| 534 | { | 546 | return -1; |
| 535 | /* If the handshake count is under the limit, try the handshake | ||
| 536 | again and increment the handshake count. This count is kept | ||
| 537 | per process (connection), not globally. */ | ||
| 538 | if (proc->gnutls_handshakes_tried < GNUTLS_EMACS_HANDSHAKES_LIMIT) | ||
| 539 | { | ||
| 540 | proc->gnutls_handshakes_tried++; | ||
| 541 | emacs_gnutls_handshake (proc); | ||
| 542 | GNUTLS_LOG2i (5, log_level, "Retried handshake", | ||
| 543 | proc->gnutls_handshakes_tried); | ||
| 544 | return -1; | ||
| 545 | } | ||
| 546 | 547 | ||
| 547 | GNUTLS_LOG (2, log_level, "Giving up on handshake; resetting retries"); | ||
| 548 | proc->gnutls_handshakes_tried = 0; | ||
| 549 | return 0; | ||
| 550 | } | ||
| 551 | rtnval = gnutls_record_recv (state, buf, nbyte); | 548 | rtnval = gnutls_record_recv (state, buf, nbyte); |
| 552 | if (rtnval >= 0) | 549 | if (rtnval >= 0) |
| 553 | return rtnval; | 550 | return rtnval; |