Skip to content

fix(mqtt): full-size TLS receive buffer on boards with PSRAM - #3303

Open
csutcliff wants to merge 1 commit into
emsesp:devfrom
csutcliff:pr/mqtt-tls-rx-buffer
Open

csutcliff wants to merge 1 commit into
emsesp:devfrom
csutcliff:pr/mqtt-tls-rx-buffer

Conversation

@csutcliff

Copy link
Copy Markdown
Contributor

Problem

The MQTT TLS client uses a 1440 byte receive buffer (plus BearSSL's 325 bytes of overhead). That only works because BearSSL then asks the broker, through the TLS max fragment length extension, to keep records small. mosquitto (OpenSSL) honours it. A broker that ignores it can send records of up to 16 KB, and the first one that doesn't fit ends the connection.

Reproduced with ghostunnel (Go's crypto/tls, which doesn't implement max fragment length) in front of mosquitto, and an RSA-4096 chain. The handshake works. Go's crypto/tls keeps records small at the start of a connection, and once it stops, EMS-ESP drops the connection (MQTT connection failure: TCP) and reconnects. In the test that happened after 61 KiB of a burst of 300 x 1 KB messages.

Fix

ESP_SSLClient already allocates its buffers in PSRAM when the build has BOARD_HAS_PSRAM and ENABLE_PSRAM (both set for PSRAM builds). On those boards ClientSecureSync now asks for a 16 KB receive buffer, the TLS maximum. Boards without PSRAM keep 1440 bytes, so their internal heap is untouched.

Testing

Same ghostunnel setup and flood (300 x 1 KB, then 20 x 8 KB):

Receive buffer Result
1440 bytes Connection dropped mid-flood after 61.2 KiB
16 KB (PSRAM) All 477 KB delivered and acknowledged, no reconnect
  • Cost: free PSRAM 4051 KB to 4026 KB at connect. Free internal heap unchanged (195 KB, all-time low 191 KB).
  • Normal operation against mosquitto with Let's Encrypt X2 unchanged.
  • Builds for s_16M_P, clang-format clean.

The test broker ran on port 18883, which needs #3302 to get TLS at all. On a port from ESP_SSLClient's list this fix stands alone. Other MQTT TLS fixes: #3300, #3301.

Checklist

  • Against the dev branch
  • Formatted per .clang-format
  • New logic is commented
  • One fix only, only relevant files touched
  • CHANGELOG_LATEST.md updated
  • I accept the CLA in CONTRIBUTING.md

@proddy

proddy commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

this looks like a valid fix, but should be fixed upstream in the owner's project at https://github.com/bertmelis/espMqttClient . Please do a PR there.

@proddy proddy closed this Oct 19, 2026
@csutcliff

Copy link
Copy Markdown
Contributor Author

This one is only a setting in EMS-ESP's ClientSecureSync: the receive buffer size passed to ESP_SSLClient's setBufferSizes(). Upstream espMqttClient doesn't use ESP_SSLClient, so there's nothing to change there. 1440 bytes works with mosquitto, but drops the connection to brokers that ignore the TLS max fragment length extension.

@proddy proddy reopened this Oct 19, 2026
The 1440 byte receive buffer only works when the broker honours the TLS
max fragment length extension the client asks for. A broker that
ignores it (Go crypto/tls, for example) sends records of up to 16 KB and
the connection fails on the first one that does not fit. Behind
ghostunnel this happened mid-stream once the broker had sent a few
hundred messages.

ESP_SSLClient allocates its buffers in PSRAM (ENABLE_PSRAM), so on boards
that have it use a 16 KB receive buffer. Boards without PSRAM keep the
small buffer.
@csutcliff
csutcliff force-pushed the pr/mqtt-tls-rx-buffer branch from 16efaf8 to aee80ab Compare October 20, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants