Skip to content

Commit f4f4bc6

Browse files
authored
WiFiClientSecure: robust TLS writes (loop & chunk), avoid zero-length write -> fixes sporadic MBEDTLS_ERR_NET_CONN_RESET (#11865)
* fix(ssl_client,wifi): Write full TLS buffer and avoid zero-length writes Loop in send_ssl_data() until the entire buffer is written; handle MBEDTLS_ERR_SSL_WANT_{READ,WRITE} and respect socket timeouts. Return 0 for len==0 to prevent zero-length TLS writes. Add a size==0 guard in WiFiClientSecure::write() for symmetry. No API changes. * fix(ssl_client): Chunk TLS writes and reset timeout after progress Chunk TLS writes and reset timeout after progress to reduce mid-body resets Send large TLS payloads in moderate chunks (4 KiB) instead of a single large write, and measure the write timeout from the last successful progress. This significantly reduces sporadic MBEDTLS_ERR_NET_CONN_RESET (-0x0050) observed during long HTTP bodies (e.g., multipart uploads). - write loop remains intact; now caps per-call size to 4096 bytes - updates timeout window after each positive write to avoid false timeouts on slow links - no API changes; handshake/verification paths unaffected Sources Ask ChatGPT * refactor(ssl_client): Constexpr chunk size; rename max_write_chunk_size
1 parent f49eb06 commit f4f4bc6

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

libraries/NetworkClientSecure/src/NetworkClientSecure.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ size_t NetworkClientSecure::write(const uint8_t *buf, size_t size) {
227227
return 0;
228228
}
229229

230+
if (size == 0) {
231+
return 0;
232+
}
233+
230234
if (_stillinPlainStart) {
231235
return send_net_data(sslclient.get(), buf, size);
232236
}

libraries/NetworkClientSecure/src/ssl_client.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -409,25 +409,41 @@ int data_to_read(sslclient_context *ssl_client) {
409409
}
410410

411411
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len) {
412-
unsigned long write_start_time = millis();
413-
int ret = -1;
412+
if (len == 0) {
413+
return 0; // Skipping zero-length write
414+
}
415+
416+
static constexpr size_t max_write_chunk_size = 4096;
417+
unsigned long last_progress = millis(); // Timeout since last progress
418+
size_t sent = 0;
419+
420+
while (sent < len) {
421+
size_t to_send = len - sent;
422+
if (to_send > max_write_chunk_size) {
423+
to_send = max_write_chunk_size;
424+
}
414425

415-
while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) {
416-
if ((millis() - write_start_time) > ssl_client->socket_timeout) {
426+
int ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data + sent, to_send);
427+
if (ret > 0) {
428+
sent += ret;
429+
last_progress = millis(); // refresh timeout window
430+
continue;
431+
}
432+
433+
if ((millis() - last_progress) > ssl_client->socket_timeout) {
417434
log_v("SSL write timed out.");
418435
return -1;
419436
}
420437

421438
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) {
422-
log_v("Handling error %d", ret); //for low level debug
439+
log_v("Handling error %d", ret);
423440
return handle_error(ret);
424441
}
425442

426-
//wait for space to become available
427443
vTaskDelay(2);
428444
}
429445

430-
return ret;
446+
return (int)sent;
431447
}
432448

433449
// Some protocols, such as SMTP, XMPP, MySQL/Posgress and various others

0 commit comments

Comments
 (0)