comparison src/gnutls.c @ 110649:2f0d755fa21b

Do the gnutls handshake from the reader loop, instead of looping over the handshake from Emacs Lisp.
author Lars Magne Ingebrigtsen <larsi@gnus.org>
date Wed, 29 Sep 2010 15:25:24 +0200
parents 256dd50b2a63
children 056ce44cedcd
comparison
equal deleted inserted replaced
110648:256dd50b2a63 110649:2f0d755fa21b
29 Lisp_Object Qgnutls_code; 29 Lisp_Object Qgnutls_code;
30 Lisp_Object Qgnutls_anon, Qgnutls_x509pki; 30 Lisp_Object Qgnutls_anon, Qgnutls_x509pki;
31 Lisp_Object Qgnutls_e_interrupted, Qgnutls_e_again, 31 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
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 }
34 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)
38 { 66 {
70 unsigned int nbyte) 98 unsigned int nbyte)
71 { 99 {
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)
80 return rtnval; 110 return rtnval;
81 else 111 else
433 XPROCESS (proc)->gnutls_x509_cred = x509_cred; 463 XPROCESS (proc)->gnutls_x509_cred = x509_cred;
434 XPROCESS (proc)->gnutls_cred_type = type; 464 XPROCESS (proc)->gnutls_cred_type = type;
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
441 DEFUN ("gnutls-bye", Fgnutls_bye, 473 DEFUN ("gnutls-bye", Fgnutls_bye,
442 Sgnutls_bye, 2, 2, 0, 474 Sgnutls_bye, 2, 2, 0,
465 NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR); 497 NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
466 498
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 {
526 global_initialized = 0; 505 global_initialized = 0;
527 506
559 defsubr (&Sgnutls_errorp); 538 defsubr (&Sgnutls_errorp);
560 defsubr (&Sgnutls_error_fatalp); 539 defsubr (&Sgnutls_error_fatalp);
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