Commit | Line | Data |
---|---|---|
0c0c20aa AM |
1 | From 783cb0301d9ceef2748956c3f91762275b7b45e5 Mon Sep 17 00:00:00 2001 |
2 | From: "Heiko Schlittermann (HS12-RIPE)" <hs@schlittermann.de> | |
3 | Date: Tue, 18 Feb 2020 18:59:49 +0100 | |
4 | Subject: [PATCH 5/6] GnuTLS: tls_write(): wait after uncorking the session | |
5 | ||
6 | (cherry picked from commit 8f9adfd36222d4e9e730734e00dffe874073e5b4) | |
7 | --- | |
8 | src/tls-gnu.c | 34 ++++++++++++++++++++++++++++------ | |
9 | 1 file changed, 28 insertions(+), 6 deletions(-) | |
10 | ||
11 | diff --git a/src/tls-gnu.c b/src/tls-gnu.c | |
12 | index 822ad89c6..94a718673 100644 | |
13 | --- a/src/tls-gnu.c | |
14 | +++ b/src/tls-gnu.c | |
15 | @@ -2835,9 +2835,14 @@ tls_write(void * ct_ctx, const uschar * buff, size_t len, BOOL more) | |
16 | ssize_t outbytes; | |
17 | size_t left = len; | |
18 | exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server; | |
19 | -#ifdef SUPPORT_CORK | |
20 | ||
21 | -if (more && !state->corked) gnutls_record_cork(state->session); | |
22 | +#ifdef SUPPORT_CORK | |
23 | +if (more && !state->corked) | |
24 | + { | |
25 | + DEBUG(D_tls) debug_printf("gnutls_record_cork(session=%p)\n", state->session); | |
26 | + gnutls_record_cork(state->session); | |
27 | + state->corked = TRUE; | |
28 | + } | |
29 | #endif | |
30 | ||
31 | DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__, | |
32 | @@ -2853,6 +2858,7 @@ while (left > 0) | |
33 | while (outbytes == GNUTLS_E_AGAIN); | |
34 | ||
35 | DEBUG(D_tls) debug_printf("outbytes=" SSIZE_T_FMT "\n", outbytes); | |
36 | + | |
37 | if (outbytes < 0) | |
38 | { | |
39 | DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__); | |
40 | @@ -2878,10 +2884,26 @@ if (len > INT_MAX) | |
41 | } | |
42 | ||
43 | #ifdef SUPPORT_CORK | |
44 | -if (more != state->corked) | |
45 | - { | |
46 | - if (!more) (void) gnutls_record_uncork(state->session, 0); | |
47 | - state->corked = more; | |
48 | +if (!more && state->corked) | |
49 | + { | |
50 | + DEBUG(D_tls) debug_printf("gnutls_record_uncork(session=%p)\n", state->session); | |
51 | + do { | |
52 | + do | |
53 | + /* We can't use GNUTLS_RECORD_WAIT here, as it retries on | |
54 | + GNUTLS_E_AGAIN || GNUTLS_E_INTR, which would break our timeout set by alarm(). | |
55 | + The GNUTLS_E_AGAIN should not happen ever, as our sockets are blocking anyway. | |
56 | + But who knows. (That all relies on the fact that GNUTLS_E_INTR and GNUTLS_E_AGAIN | |
57 | + match the EINTR and EAGAIN errno values.) */ | |
58 | + outbytes = gnutls_record_uncork(state->session, 0); | |
59 | + while (outbytes == GNUTLS_E_AGAIN); | |
60 | + | |
61 | + if (outbytes < 0) | |
62 | + { | |
63 | + record_io_error(state, len, US"uncork", NULL); | |
64 | + return -1; | |
65 | + } | |
66 | + } while (gnutls_record_check_corked(state->session) > 0); | |
67 | + state->corked = FALSE; | |
68 | } | |
69 | #endif | |
70 | ||
71 | -- | |
72 | 2.28.0 | |
73 |