Skip to content
File

Blob: ERRATA.md

Markdown147 lines

Integration notes

Known issues and workarounds that matter when changing or upgrading the project.

RustCrypto certificate generation

The upstream str0m-rust-crypto certificate generator pulls in AWS-LC, whose native headers reject Xtensa. The firmware uses a small provider patch, disables that generator, and supplies a fresh mbedTLS-generated certificate from the S3. Explicitly select the configured crypto provider for DTLS; allowing default selection can activate an unintended backend through Cargo feature unification.

Install only P-256 key exchange in the S3 provider before dimpl validates the configured groups. Allowing its software P-384 exchange test can starve the idle watchdog. Keep P-384 signature verification on mbedTLS; the corresponding RustCrypto startup check also adds substantial startup time. Provider, signature and fingerprint checks remain enabled.

Crypto adapter boundaries

The SHA value-snapshot adapter is specific to the pinned S3 port, whose contexts contain no pointers and release the peripheral lock between calls. Review both properties before changing the SDK or target; checking struct size is insufficient. In-place AES-GCM arguments must derive from the same exclusive Rust pointer. Independent shared/mutable slice reborrows can violate Rust aliasing rules.

The native provider uses mbedTLS for both EC curves. In the pinned build, hardware-assisted P-256 takes longer than software; using one EC backend is a simplicity tradeoff. Recheck matching build options and full connection startup before changing that policy. EC timings do not represent per-audio-packet costs.

Use scripts/build_firmware.py --crypto-self-test for adapter changes, then run the image on the device and verify live audio/data. The extended tests include altered signatures, malformed certificates and output bounds. Normal builds omit their public signature fixtures.

str0m task stack

Keep Rtc behind a Box in the transport. Storing and returning it inline created large nested stack frames that overflowed a 48 KiB radio task during initialization. Measure the low-water mark on the S3 after transport upgrades; host compilation cannot establish the device stack requirement.

The radio task runs on core 0. Full-catalog validation must yield between cache fills so that core's idle task can service its watchdog.

Keep the configured 1 KiB malloc threshold so larger allocations prefer PSRAM. The SDK's 16 KiB setting filled internal RAM with transport allocations. Task stacks, Wi-Fi and the FFT scratch buffer retain their internal memory.

Negotiated data channels

Create application channels using the IDs returned by the SFU. The two endpoints have separate SCTP associations and can receive different IDs. Stream 0 carries SFU server events and establishes SCTP before application registration. Reliable commands use ordered robot; spectrum is unordered with zero retransmits.

The SFU can return only a channel's ID and name, without echoing ordered or maxRetransmits. Normalize omitted settings from the shared channel profiles; reject explicit settings that conflict with the requested reliability.

The command queue's 512-byte limit applies after SCTP reassembly. The local str0m/sctp-proto patches enforce earlier receive budgets and align advertised credit with retained DATA. Keep fragment, stream-state and byte bounds together; an SDP message-size attribute alone cannot bound receive memory. Tests cover fragmentation, TSN gaps, stream reset deferral and high negotiated IDs.

N32R16V memory configuration

This board uses 32 MiB octal flash and 16 MiB octal PSRAM at 1.8 V. Retain its OPI/DTR bootloader settings and partition layout. A generic S3 configuration may not boot this module. C6 and C61 are different chips; a C61 transport archive does not establish C6 support.

Rust and ESP-IDF linking

The build supplies espidf_time64 for ESP-IDF 5's time ABI. The C adapter component is linked with WHOLE_ARCHIVE so references introduced by the Rust archive resolve correctly. The pinned Xtensa compiler does not support the compiler-builtins-weak-intrinsics feature; leave it disabled.

The HAL uses the existing CMake SDK through CARGO_CMAKE_BUILD_* metadata. The pinned bindings generator does not track those inputs for Cargo, so the build fingerprints its SDK configuration and header context in Rust flags. Configuration changes then regenerate the bindings instead of reusing stale ones. Keep the HAL's binstart and libstart features disabled because entry.c owns app_main. Binding generation uses libclang from the pinned esp-radio toolchain; make setup-firmware supplies it. Host checks compile the application with a stub that returns an error if task configuration is called. They do not run the firmware or compile its HAL path; make build-firmware compiles that path against the SDK, and device checks validate its behavior.

Worker session cleanup and leases

Publisher replacement and expiry use the application's disposable-session policy. An SFU close failure on an obsolete generation must not block a replacement boot.

For cleanup within the current generation, treat responses 404/410 and an HTTP 200 close_track_error as already closed. The latter can appear at the top level or on a track or DataChannel item. Keep other failures pending; an internal_error does not establish absence. See the SFU error-code clarification. Keep the earliest pending Durable Object alarm: ordinary status polling must not postpone controller-lease expiration. The isolated signaling tests cover both behaviors.

SFU allocation responses can contain successful IDs beside failed items. Save those IDs before checking the complete response. Optional pendingChannels and pendingMids fields hold cleanup receipts, separate from usable media. They survive eviction within the current generation and remain until cleanup succeeds or that generation is discarded. Before rolling back to a Worker version without receipt handling, close listeners and replace the board session under the current version.

Music pack compatibility

Preparation creates a v4 playlist catalog for the 16 MiB music partition. The firmware also reads v1/v2/v3 single-song packs. V4 contains bounded v3 song packs; firmware limited to single-song formats cannot read it. When upgrading an installation with a 4 MiB music partition, flash the partition table that allocates 16 MiB to music together with the firmware before using make flash-music. The helper checks the installed partition before writing.

The browser accepts 48-byte spectrum v2 packets, which include a playback revision, and archived 44-byte v1 packets. Deploy compatible Worker/browser code before firmware changes that alter the protocol, and refresh open pages.

The archived C radio and FFT harness require v1 music packs and a partition table that allocates 4 MiB to music. Restore these together with the firmware when rolling back. The archive flash helper supplies the matching layout and v1 music independently of the main catalog.

Runtime metrics

CPU metrics require ESP-IDF's timer-backed U64 runtime counters. Idle runtime is committed when a task switches out. Keep the sampler on core 1 so its wake-up refreshes that core's counters during paused playback.

Temperature conversion uses floating point. Keep it on the pinned sampler task to prevent ESP-IDF's lazy FPU handling from implicitly pinning the radio task.

The browser's telemetry schema accepts an optional hardware object. Missing hardware measurements display as unavailable.