diff options
| author | Lars Magne Ingebrigtsen | 2010-09-29 15:25:24 +0200 |
|---|---|---|
| committer | Lars Magne Ingebrigtsen | 2010-09-29 15:25:24 +0200 |
| commit | bac5cef8cc902c7332ef66f6731fa5be0866811c (patch) | |
| tree | 060d740fcae01d8b4c80c76a24d871c24006cdf1 /src | |
| parent | df7fcafff05c4002f35e507c65518f4b20ba5382 (diff) | |
| download | emacs-bac5cef8cc902c7332ef66f6731fa5be0866811c.tar.gz emacs-bac5cef8cc902c7332ef66f6731fa5be0866811c.zip | |
Do the gnutls handshake from the reader loop, instead of looping over
the handshake from Emacs Lisp.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 4 | ||||
| -rw-r--r-- | src/gnutls.c | 90 |
2 files changed, 38 insertions, 56 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index ee6e8f6ce90..9d9833f7e66 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,9 @@ | |||
| 1 | 2010-09-29 Lars Magne Ingebrigtsen <larsi@gnus.org> | 1 | 2010-09-29 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 2 | ||
| 3 | * gnutls.c (emacs_gnutls_handshake): Made into internal function. | ||
| 4 | (Fgnutls_boot): Start the handshake. | ||
| 5 | (emacs_gnutls_read): Perform the handshake from the reader loop. | ||
| 6 | |||
| 3 | * process.h (Lisp_Process): Add a gnutls_p field to Lisp_Process. | 7 | * process.h (Lisp_Process): Add a gnutls_p field to Lisp_Process. |
| 4 | 8 | ||
| 5 | * process.c (make_process): Set the gnutls_p field to zero by | 9 | * process.c (make_process): Set the gnutls_p field to zero by |
diff --git a/src/gnutls.c b/src/gnutls.c index 2d1aa3247f8..4be28016eac 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -32,6 +32,34 @@ Lisp_Object Qgnutls_e_interrupted, Qgnutls_e_again, | |||
| 32 | Qgnutls_e_invalid_session, Qgnutls_e_not_ready_for_handshake; | 32 | Qgnutls_e_invalid_session, Qgnutls_e_not_ready_for_handshake; |
| 33 | int global_initialized; | 33 | int global_initialized; |
| 34 | 34 | ||
| 35 | void | ||
| 36 | emacs_gnutls_handshake (struct Lisp_Process *proc) | ||
| 37 | { | ||
| 38 | gnutls_session_t state = proc->gnutls_state; | ||
| 39 | int ret; | ||
| 40 | |||
| 41 | if (proc->gnutls_initstage < GNUTLS_STAGE_HANDSHAKE_CANDO) | ||
| 42 | return; | ||
| 43 | |||
| 44 | if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET) | ||
| 45 | { | ||
| 46 | /* FIXME: This can't be right: infd and outfd are integers (file handles) | ||
| 47 | whereas the function expects args of type gnutls_transport_ptr_t. */ | ||
| 48 | gnutls_transport_set_ptr2 (state, proc->infd, proc->outfd); | ||
| 49 | |||
| 50 | proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; | ||
| 51 | } | ||
| 52 | |||
| 53 | ret = gnutls_handshake (state); | ||
| 54 | proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED; | ||
| 55 | |||
| 56 | if (ret == GNUTLS_E_SUCCESS) | ||
| 57 | { | ||
| 58 | /* here we're finally done. */ | ||
| 59 | proc->gnutls_initstage = GNUTLS_STAGE_READY; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 35 | int | 63 | int |
| 36 | emacs_gnutls_write (int fildes, struct Lisp_Process *proc, char *buf, | 64 | emacs_gnutls_write (int fildes, struct Lisp_Process *proc, char *buf, |
| 37 | unsigned int nbyte) | 65 | unsigned int nbyte) |
| @@ -72,8 +100,10 @@ emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf, | |||
| 72 | register int rtnval; | 100 | register int rtnval; |
| 73 | gnutls_session_t state = proc->gnutls_state; | 101 | gnutls_session_t state = proc->gnutls_state; |
| 74 | 102 | ||
| 75 | if (proc->gnutls_initstage != GNUTLS_STAGE_READY) | 103 | if (proc->gnutls_initstage != GNUTLS_STAGE_READY) { |
| 76 | return 0; | 104 | emacs_gnutls_handshake (proc); |
| 105 | return -1; | ||
| 106 | } | ||
| 77 | 107 | ||
| 78 | rtnval = gnutls_read (state, buf, nbyte); | 108 | rtnval = gnutls_read (state, buf, nbyte); |
| 79 | if (rtnval >= 0) | 109 | if (rtnval >= 0) |
| @@ -435,6 +465,8 @@ KEYFILE and optionally CALLBACK. */) | |||
| 435 | 465 | ||
| 436 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET; | 466 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET; |
| 437 | 467 | ||
| 468 | emacs_gnutls_handshake (XPROCESS (proc)); | ||
| 469 | |||
| 438 | return gnutls_make_error (GNUTLS_E_SUCCESS); | 470 | return gnutls_make_error (GNUTLS_E_SUCCESS); |
| 439 | } | 471 | } |
| 440 | 472 | ||
| @@ -467,59 +499,6 @@ This function may also return `gnutls-e-again', or | |||
| 467 | return gnutls_make_error (ret); | 499 | return gnutls_make_error (ret); |
| 468 | } | 500 | } |
| 469 | 501 | ||
| 470 | DEFUN ("gnutls-handshake", Fgnutls_handshake, | ||
| 471 | Sgnutls_handshake, 1, 1, 0, | ||
| 472 | doc: /* Perform GNU TLS handshake for PROCESS. | ||
| 473 | The identity of the peer is checked automatically. This function will | ||
| 474 | fail if any problem is encountered, and will return a negative error | ||
| 475 | code. In case of a client, if it has been asked to resume a session, | ||
| 476 | but the server didn't, then a full handshake will be performed. | ||
| 477 | |||
| 478 | If the error `gnutls-e-not-ready-for-handshake' is returned, you | ||
| 479 | didn't call `gnutls-boot' first. | ||
| 480 | |||
| 481 | This function may also return the non-fatal errors `gnutls-e-again', | ||
| 482 | or `gnutls-e-interrupted'. In that case you may resume the handshake | ||
| 483 | (by calling this function again). */) | ||
| 484 | (Lisp_Object proc) | ||
| 485 | { | ||
| 486 | gnutls_session_t state; | ||
| 487 | int ret; | ||
| 488 | |||
| 489 | CHECK_PROCESS (proc); | ||
| 490 | state = XPROCESS (proc)->gnutls_state; | ||
| 491 | |||
| 492 | if (GNUTLS_INITSTAGE (proc) < GNUTLS_STAGE_HANDSHAKE_CANDO) | ||
| 493 | return Qgnutls_e_not_ready_for_handshake; | ||
| 494 | |||
| 495 | |||
| 496 | if (GNUTLS_INITSTAGE (proc) < GNUTLS_STAGE_TRANSPORT_POINTERS_SET) | ||
| 497 | { | ||
| 498 | /* for a network process in Emacs infd and outfd are the same | ||
| 499 | but this shows our intent more clearly. */ | ||
| 500 | message ("gnutls: handshake: setting the transport pointers to %d/%d", | ||
| 501 | XPROCESS (proc)->infd, XPROCESS (proc)->outfd); | ||
| 502 | |||
| 503 | /* FIXME: This can't be right: infd and outfd are integers (file handles) | ||
| 504 | whereas the function expects args of type gnutls_transport_ptr_t. */ | ||
| 505 | gnutls_transport_set_ptr2 (state, XPROCESS (proc)->infd, | ||
| 506 | XPROCESS (proc)->outfd); | ||
| 507 | |||
| 508 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_TRANSPORT_POINTERS_SET; | ||
| 509 | } | ||
| 510 | |||
| 511 | ret = gnutls_handshake (state); | ||
| 512 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_HANDSHAKE_TRIED; | ||
| 513 | |||
| 514 | if (ret == GNUTLS_E_SUCCESS) | ||
| 515 | { | ||
| 516 | /* here we're finally done. */ | ||
| 517 | GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_READY; | ||
| 518 | } | ||
| 519 | |||
| 520 | return gnutls_make_error (ret); | ||
| 521 | } | ||
| 522 | |||
| 523 | void | 502 | void |
| 524 | syms_of_gnutls (void) | 503 | syms_of_gnutls (void) |
| 525 | { | 504 | { |
| @@ -561,7 +540,6 @@ syms_of_gnutls (void) | |||
| 561 | defsubr (&Sgnutls_error_string); | 540 | defsubr (&Sgnutls_error_string); |
| 562 | defsubr (&Sgnutls_boot); | 541 | defsubr (&Sgnutls_boot); |
| 563 | defsubr (&Sgnutls_deinit); | 542 | defsubr (&Sgnutls_deinit); |
| 564 | defsubr (&Sgnutls_handshake); | ||
| 565 | defsubr (&Sgnutls_bye); | 543 | defsubr (&Sgnutls_bye); |
| 566 | } | 544 | } |
| 567 | #endif | 545 | #endif |