Skip to content

Commit 407758d

Browse files
committed
fix IO_WAIT on send for builtin TLS and MbedTLS
1 parent b30cf65 commit 407758d

File tree

6 files changed

+74
-28
lines changed

6 files changed

+74
-28
lines changed

mongoose.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10720,7 +10720,7 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
1072010720
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
1072110721
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
1072210722
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
10723-
nonce[11] ^= (uint8_t) ((seq) & 255U);
10723+
nonce[11] ^= (uint8_t) ((seq) &255U);
1072410724

1072510725
mg_iobuf_add(wio, wio->len, hdr, sizeof(hdr));
1072610726
mg_iobuf_resize(wio, wio->len + encsz);
@@ -10799,7 +10799,7 @@ static int mg_tls_recv_record(struct mg_connection *c) {
1079910799
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
1080010800
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
1080110801
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
10802-
nonce[11] ^= (uint8_t) ((seq) & 255U);
10802+
nonce[11] ^= (uint8_t) ((seq) &255U);
1080310803
#if CHACHA20
1080410804
{
1080510805
uint8_t *dec = (uint8_t *) calloc(1, msgsz);
@@ -11557,7 +11557,7 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
1155711557
struct mg_tls_cert certs[8];
1155811558
int certnum = 0;
1155911559
uint8_t *p = recv_buf + 8;
11560-
//uint8_t *endp = recv_buf + tls->recv_len;
11560+
// uint8_t *endp = recv_buf + tls->recv_len;
1156111561
uint8_t *endp = recv_buf + cert_chain_len;
1156211562

1156311563
int found_ca = 0;
@@ -11666,7 +11666,8 @@ static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
1166611666
tls->recv_len - 8);
1166711667
return -1;
1166811668
}
11669-
MG_VERBOSE(("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
11669+
MG_VERBOSE(
11670+
("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
1167011671

1167111672
if (sigalg == 0x0804) { // rsa_pss_rsae_sha256
1167211673
uint8_t sig2[512]; // 2048 or 4096 bits
@@ -11819,7 +11820,9 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
1181911820
c->is_tls_hs = 0;
1182011821
mg_call(c, MG_EV_TLS_HS, NULL);
1182111822
break;
11822-
default: mg_error(c, "unexpected client state: %d", tls->state); break;
11823+
default:
11824+
mg_error(c, "unexpected client state: %d", tls->state);
11825+
break;
1182311826
}
1182411827
}
1182511828

@@ -11846,7 +11849,9 @@ static void mg_tls_server_handshake(struct mg_connection *c) {
1184611849
tls->state = MG_TLS_STATE_SERVER_CONNECTED;
1184711850
c->is_tls_hs = 0;
1184811851
return;
11849-
default: mg_error(c, "unexpected server state: %d", tls->state); break;
11852+
default:
11853+
mg_error(c, "unexpected server state: %d", tls->state);
11854+
break;
1185011855
}
1185111856
}
1185211857

@@ -11980,15 +11985,22 @@ void mg_tls_free(struct mg_connection *c) {
1198011985
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
1198111986
struct tls_data *tls = (struct tls_data *) c->tls;
1198211987
long n = MG_IO_WAIT;
11983-
if (len > MG_IO_SIZE) len = MG_IO_SIZE;
11984-
if (len > 16384) len = 16384;
11985-
mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA);
11988+
bool was_throttled = c->is_throttled; // see #3074
11989+
if (!was_throttled) { // encrypt new data
11990+
if (len > MG_IO_SIZE) len = MG_IO_SIZE;
11991+
if (len > 16384) len = 16384;
11992+
mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA);
11993+
} // else, resend outstanding encrypted data in tls->send
1198611994
while (tls->send.len > 0 &&
1198711995
(n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) {
1198811996
mg_iobuf_del(&tls->send, 0, (size_t) n);
1198911997
}
11990-
if (n == MG_IO_ERR || n == MG_IO_WAIT) return n;
11991-
return (long) len;
11998+
c->is_throttled = (tls->send.len > 0 && n == MG_IO_WAIT);
11999+
MG_VERBOSE(("%lu %ld %ld %ld %c %c", c->id, (long) len, (long) tls->send.len,
12000+
n, was_throttled ? 'T' : 't', c->is_throttled ? 'T' : 't'));
12001+
if (n == MG_IO_ERR) return MG_IO_ERR;
12002+
if (was_throttled) return MG_IO_WAIT; // sent throttled data instead
12003+
return (long) len; // return len even when throttled, already encripted that
1199212004
}
1199312005

1199412006
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
@@ -13609,9 +13621,16 @@ long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
1360913621

1361013622
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
1361113623
struct mg_tls *tls = (struct mg_tls *) c->tls;
13612-
long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
13613-
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
13614-
return MG_IO_WAIT;
13624+
long n;
13625+
bool was_throttled = c->is_throttled; // see #3074
13626+
n = was_throttled ? mbedtls_ssl_write(&tls->ssl, tls->throttled_buf,
13627+
tls->throttled_len) /* flush old data */
13628+
: mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf,
13629+
len); // encrypt current data
13630+
c->is_throttled =
13631+
(n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE);
13632+
if (was_throttled) return MG_IO_WAIT; // flushed throttled data instead
13633+
if (c->is_throttled) return len; // already encripted that when throttled
1361513634
if (n <= 0) return MG_IO_ERR;
1361613635
return n;
1361713636
}

mongoose.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,6 +2260,7 @@ struct mg_connection {
22602260
unsigned is_draining : 1; // Send remaining data, then close and free
22612261
unsigned is_closing : 1; // Close and free the connection immediately
22622262
unsigned is_full : 1; // Stop reads, until cleared
2263+
unsigned is_throttled : 1; // Last TLS write: MG_SOCK_PENDING() was true
22632264
unsigned is_resp : 1; // Response is still being generated
22642265
unsigned is_readable : 1; // Connection is ready to read
22652266
unsigned is_writable : 1; // Connection is ready to write
@@ -2430,6 +2431,9 @@ struct mg_tls {
24302431
#ifdef MBEDTLS_SSL_SESSION_TICKETS
24312432
mbedtls_ssl_ticket_context ticket; // Session tickets context
24322433
#endif
2434+
// https://github.com/Mbed-TLS/mbedtls/blob/3b3c652d/include/mbedtls/ssl.h#L5071C18-L5076C29
2435+
unsigned char *throttled_buf; // see #3074
2436+
size_t throttled_len;
24332437
};
24342438
#endif
24352439

src/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct mg_connection {
7474
unsigned is_draining : 1; // Send remaining data, then close and free
7575
unsigned is_closing : 1; // Close and free the connection immediately
7676
unsigned is_full : 1; // Stop reads, until cleared
77+
unsigned is_throttled : 1; // Last TLS write: MG_SOCK_PENDING() was true
7778
unsigned is_resp : 1; // Response is still being generated
7879
unsigned is_readable : 1; // Connection is ready to read
7980
unsigned is_writable : 1; // Connection is ready to write

src/tls_builtin.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
424424
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
425425
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
426426
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
427-
nonce[11] ^= (uint8_t) ((seq) & 255U);
427+
nonce[11] ^= (uint8_t) ((seq) &255U);
428428

429429
mg_iobuf_add(wio, wio->len, hdr, sizeof(hdr));
430430
mg_iobuf_resize(wio, wio->len + encsz);
@@ -503,7 +503,7 @@ static int mg_tls_recv_record(struct mg_connection *c) {
503503
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
504504
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
505505
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
506-
nonce[11] ^= (uint8_t) ((seq) & 255U);
506+
nonce[11] ^= (uint8_t) ((seq) &255U);
507507
#if CHACHA20
508508
{
509509
uint8_t *dec = (uint8_t *) calloc(1, msgsz);
@@ -1261,7 +1261,7 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
12611261
struct mg_tls_cert certs[8];
12621262
int certnum = 0;
12631263
uint8_t *p = recv_buf + 8;
1264-
//uint8_t *endp = recv_buf + tls->recv_len;
1264+
// uint8_t *endp = recv_buf + tls->recv_len;
12651265
uint8_t *endp = recv_buf + cert_chain_len;
12661266

12671267
int found_ca = 0;
@@ -1370,7 +1370,8 @@ static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
13701370
tls->recv_len - 8);
13711371
return -1;
13721372
}
1373-
MG_VERBOSE(("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
1373+
MG_VERBOSE(
1374+
("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
13741375

13751376
if (sigalg == 0x0804) { // rsa_pss_rsae_sha256
13761377
uint8_t sig2[512]; // 2048 or 4096 bits
@@ -1523,7 +1524,9 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
15231524
c->is_tls_hs = 0;
15241525
mg_call(c, MG_EV_TLS_HS, NULL);
15251526
break;
1526-
default: mg_error(c, "unexpected client state: %d", tls->state); break;
1527+
default:
1528+
mg_error(c, "unexpected client state: %d", tls->state);
1529+
break;
15271530
}
15281531
}
15291532

@@ -1550,7 +1553,9 @@ static void mg_tls_server_handshake(struct mg_connection *c) {
15501553
tls->state = MG_TLS_STATE_SERVER_CONNECTED;
15511554
c->is_tls_hs = 0;
15521555
return;
1553-
default: mg_error(c, "unexpected server state: %d", tls->state); break;
1556+
default:
1557+
mg_error(c, "unexpected server state: %d", tls->state);
1558+
break;
15541559
}
15551560
}
15561561

@@ -1684,15 +1689,22 @@ void mg_tls_free(struct mg_connection *c) {
16841689
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
16851690
struct tls_data *tls = (struct tls_data *) c->tls;
16861691
long n = MG_IO_WAIT;
1687-
if (len > MG_IO_SIZE) len = MG_IO_SIZE;
1688-
if (len > 16384) len = 16384;
1689-
mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA);
1692+
bool was_throttled = c->is_throttled; // see #3074
1693+
if (!was_throttled) { // encrypt new data
1694+
if (len > MG_IO_SIZE) len = MG_IO_SIZE;
1695+
if (len > 16384) len = 16384;
1696+
mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA);
1697+
} // else, resend outstanding encrypted data in tls->send
16901698
while (tls->send.len > 0 &&
16911699
(n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) {
16921700
mg_iobuf_del(&tls->send, 0, (size_t) n);
16931701
}
1694-
if (n == MG_IO_ERR || n == MG_IO_WAIT) return n;
1695-
return (long) len;
1702+
c->is_throttled = (tls->send.len > 0 && n == MG_IO_WAIT);
1703+
MG_VERBOSE(("%lu %ld %ld %ld %c %c", c->id, (long) len, (long) tls->send.len,
1704+
n, was_throttled ? 'T' : 't', c->is_throttled ? 'T' : 't'));
1705+
if (n == MG_IO_ERR) return MG_IO_ERR;
1706+
if (was_throttled) return MG_IO_WAIT; // sent throttled data instead
1707+
return (long) len; // return len even when throttled, already encripted that
16961708
}
16971709

16981710
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {

src/tls_mbed.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,16 @@ long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
190190

191191
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
192192
struct mg_tls *tls = (struct mg_tls *) c->tls;
193-
long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
194-
if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
195-
return MG_IO_WAIT;
193+
long n;
194+
bool was_throttled = c->is_throttled; // see #3074
195+
n = was_throttled ? mbedtls_ssl_write(&tls->ssl, tls->throttled_buf,
196+
tls->throttled_len) /* flush old data */
197+
: mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf,
198+
len); // encrypt current data
199+
c->is_throttled =
200+
(n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE);
201+
if (was_throttled) return MG_IO_WAIT; // flushed throttled data instead
202+
if (c->is_throttled) return len; // already encripted that when throttled
196203
if (n <= 0) return MG_IO_ERR;
197204
return n;
198205
}

src/tls_mbed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,8 @@ struct mg_tls {
2727
#ifdef MBEDTLS_SSL_SESSION_TICKETS
2828
mbedtls_ssl_ticket_context ticket; // Session tickets context
2929
#endif
30+
// https://github.com/Mbed-TLS/mbedtls/blob/3b3c652d/include/mbedtls/ssl.h#L5071C18-L5076C29
31+
unsigned char *throttled_buf; // see #3074
32+
size_t throttled_len;
3033
};
3134
#endif

0 commit comments

Comments
 (0)