You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[C] az_mqtt adapter: static clients, no heap (AZ_IOT_AZ_MQTT_STATIC_CLIENTS) - #396
With AZ_IOT_AZ_MQTT_STATIC_CLIENTS=N (N > 0), the az_mqtt adapter allocates nothing. Each MQTT version has N clients in static storage, and its factory is static. The default, 0, is unchanged.
Macro (also a CMake option)
Default
Effect
AZ_IOT_AZ_MQTT_STATIC_CLIENTS
0
Clients per MQTT version. create() returns NULL when all are in use.
AZ_IOT_AZ_MQTT_TRANSPORT_SIZE
200 KiB on Windows, 8 KiB elsewhere
Bytes reserved for the transport. create() returns NULL when az_mqtt_transport_sizeof() is larger. Measured: OpenSSL 560 B, mbedTLS 4.2-4.6 KB, Schannel about 197 KB.
AZ_IOT_AZ_MQTT_CONNECT_STRINGS_SIZE
8 KiB
Copies of a connect's strings. A connect that does not fit returns AZ_IOT_ERR_NOT_ENOUGH_SPACE.
AZ_IOT_AZ_MQTT_MESSAGE_STORAGE_SIZE
send size + 18
Now may be 0: a connect whose session outlives the connection then returns AZ_IOT_ERR_NOT_SUPPORTED.
az_mqtt needs no change. Its transport size depends on the TLS library's version and configuration, so the adapter reserves an area of configurable size and checks it in create().
In static mode, create() and destroy() must not run concurrently.
The TLS library still allocates (OpenSSL, Schannel; mbedTLS unless given a static pool). This is documented.
Sizes: with CONSTRAINED and message storage 0, an MQTT 5 client takes about 290 KiB of .bss.
Verified on Linux (gcc, Debug):
ctest: 63/63 with OpenSSL, 62/62 with mbedTLS, and 62/62 for the whole SDK built with AZ_IOT_AZ_MQTT_STATIC_CLIENTS=4 (including the conformance suites against a broker).
nm: in the static build the adapter library references no malloc, calloc, realloc or free.
New tests: az_iot_tests_az_mqtt_adapter_static, _static_tiny, and az_iot_tests_az_mqtt_adapter_sizes_static.
Each fails when its corresponding check is removed: the string-area bound, slot release, string release, and the transport-size check.
They pass under ASan and UBSan.
MinGW -Wall -Wextra -Wpedantic -Werror syntax check of the static paths. MSVC is covered by CI.
Correct default descriptions for expanded CMake options
c/docs/client-configuration.md:25
The expanded option list makes the existing default description inaccurate: the new static-client, transport, connect-string, and message-storage options do not derive from AZ_IOT_AZ_MQTT_FOOTPRINT; they default respectively to 0, platform-specific storage, 8 KiB, and send size + 18. Describe these as each option's documented default so CMake users are not led to expect the footprint to control them.
Copilot "Correct default descriptions for expanded CMake options": fixed in 329332e. The table now gives each option's own default. The footprint sets only the send and receive sizes and the in-flight and user-property limits. The others default to send size + 18 (message store), 0 static clients, 200 KiB on Windows or 8 KiB elsewhere (transport) and 8 KiB (connect strings).
This validation accepts AZ_IOT_AZ_MQTT_MESSAGE_STORAGE_SIZE values above INT32_MAX, but _azm_connect() later passes the macro directly as the int32_t length to az_span_create(). A large CMake value can therefore convert to a negative span length and hit az_core's precondition handler instead of being rejected as an invalid build configuration. Cap this newly exposed setting at INT32_MAX.
Copilot "Reject MQTT storage sizes exceeding INT32_MAX": fixed in 0acffe1. AZ_IOT_AZ_MQTT_MESSAGE_STORAGE_SIZE above 2147483647 is now a compile error.
The documented credential-erasure behavior is not covered by the new tests: connect_strings_must_fit only proves that the cursor/capacity is released, so the earlier implementation that reset the cursor while leaving credentials in the static slot would still pass. Add a regression test that stores a recognizable password, destroys the client, and verifies that the reusable slot no longer contains those bytes.
Copilot "Add regression test to verify credentials are erased on client destruction": added in 5850620 as az_iot_tests_az_mqtt_adapter_static_wipe. After a second connect with a shorter password, the first password is no longer in the slot; after destroy(), the slot is all zeros. The test fails if either wipe is removed.
A rejected persistent-session reconnect returns before _azm_release_owned(). If this client previously disconnected, its copied password, proxy credentials, or TLS material therefore remains in the process-wide static slot until a later accepted connect or destroy, despite the new wipe-on-each-connect guarantee. Release the prior owned strings on this rejection path as well.
Copilot "Release owned credentials on rejected persistent-session reconnect": fixed in b91e009. connect() now releases and wipes the previous connect's strings right after the busy check, so a connect refused for invalid options or a persistent session is covered as well. The wipe test now checks the refused case, and fails without the change.
The reason will be displayed to describe this comment to others. Learn more.
Done in 8123f3b. With AZ_IOT_AZ_MQTT_STATIC_CLIENTS > 0, the adapter sources apply #pragma GCC poison malloc calloc realloc free (GCC and Clang) after their includes. The static test targets therefore fail to compile if the static path makes any heap call. Checked by adding malloc(1) to the static create(): both GCC and Clang rejected it, and the default build is unaffected.
…LIENTS)
- AZ_IOT_AZ_MQTT_STATIC_CLIENTS=N (> 0): each MQTT version has N clients in
static storage (buffers, transport, message store, connect strings) and a
static factory. The adapter references no malloc, calloc or free.
create() returns NULL when all are in use. 0, the default, is unchanged.
- AZ_IOT_AZ_MQTT_TRANSPORT_SIZE (200 KiB on Windows, 8 KiB elsewhere):
bytes reserved for the transport, checked against az_mqtt_transport_sizeof()
by create().
- AZ_IOT_AZ_MQTT_CONNECT_STRINGS_SIZE (8 KiB): copies of a connect's strings;
a connect that does not fit returns AZ_IOT_ERR_NOT_ENOUGH_SPACE.
- AZ_IOT_AZ_MQTT_MESSAGE_STORAGE_SIZE may be 0: a connect whose session
outlives the connection then returns AZ_IOT_ERR_NOT_SUPPORTED. It is now a
CMake option too.
- Tests: static clients (limits, reuse, string area, message store,
transport area too small) and the asymmetric-size test with static clients.
…sion rule; test sizes
- Copied connect strings are wiped when released; destroy() wipes the send buffer (heap) or the whole slot (static). Uses az_iot_crypto__wipe().
- Message storage 0 refuses clean_start false (MQTT 5: with session_expiry_seconds > 0); docs and log say so. Clean start with an expiry is accepted (tested).
- Adapter tests count the copied connect bytes exactly.
…on defaults documented
- The static factory is never written (no data race between concurrent factory_create calls); destroy is NULL.
- client-configuration.md: each option's default, not only the footprint's.
…strings
Released (and wiped) right after the busy check, so invalid options or a refused persistent session no longer leave them in place. Test extended.
…CC/Clang)
#pragma GCC poison malloc calloc realloc free in the adapter sources when AZ_IOT_AZ_MQTT_STATIC_CLIENTS > 0, so the static test targets enforce the no-heap contract in CI. CHANGELOG: > 0 enables it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With
AZ_IOT_AZ_MQTT_STATIC_CLIENTS=N(N > 0), the az_mqtt adapter allocates nothing. Each MQTT version has N clients in static storage, and its factory is static. The default, 0, is unchanged.AZ_IOT_AZ_MQTT_STATIC_CLIENTScreate()returns NULL when all are in use.AZ_IOT_AZ_MQTT_TRANSPORT_SIZEcreate()returns NULL whenaz_mqtt_transport_sizeof()is larger. Measured: OpenSSL 560 B, mbedTLS 4.2-4.6 KB, Schannel about 197 KB.AZ_IOT_AZ_MQTT_CONNECT_STRINGS_SIZEAZ_IOT_ERR_NOT_ENOUGH_SPACE.AZ_IOT_AZ_MQTT_MESSAGE_STORAGE_SIZEAZ_IOT_ERR_NOT_SUPPORTED.create().create()anddestroy()must not run concurrently.CONSTRAINEDand message storage 0, an MQTT 5 client takes about 290 KiB of.bss.Verified on Linux (gcc, Debug):
AZ_IOT_AZ_MQTT_STATIC_CLIENTS=4(including the conformance suites against a broker).nm: in the static build the adapter library references nomalloc,calloc,reallocorfree.az_iot_tests_az_mqtt_adapter_static,_static_tiny, andaz_iot_tests_az_mqtt_adapter_sizes_static.-Wall -Wextra -Wpedantic -Werrorsyntax check of the static paths. MSVC is covered by CI.