feat(webrtc): negotiate data channel message limits - #6560
Conversation
# Conflicts: # transports/webrtc-websys/src/stream/poll_data_channel.rs
|
Follow-up from browser-to-browser relay transfer testing: the negotiated With an 8 KiB negotiated frame limit, multiple individually valid This update adds I added focused tests for consecutive valid 8 KiB messages, the configured bound, and a negotiated message larger than the default. Validation also passed with:
This keeps the message-size API and the local resource-limit API separate, rather than making an application-layer workaround (such as skipping |
Description
Add a connection-level WebRTC data-channel message limit and negotiate an effective limit after the existing Noise authentication handshake.
Both native
libp2p-webrtcand browserlibp2p-webrtc-websysexposewith_max_message_size. The selected effective value is used consistently by the libp2p frame codec, write high-water mark, browser buffered-amount accounting, and the native WebRTC read buffer.Fixes #6557.
Why
The WebRTC DataChannel stack has a message-size limit below the libp2p stream abstraction. The current fixed 16 KiB libp2p frame limit follows RFC 8831's guidance for SCTP without message interleaving, but deployments can have a smaller effective limit. In a browser-to-browser relay path, this led to an underlying SCTP implementation rejecting a frame and closing the data channel.
W3C WebRTC specifies that the maximum size accepted by
RTCDataChannel.send()is derived from the remotemax-message-sizeSDP attribute and local sending capability, using the smaller applicable value. See WebRTC §6.1.1.2 and theRTCSctpTransport.maxMessageSizedefinition. RFC 8831 also recommends a 16 KiB maximum when SCTP message interleaving is unavailable: RFC 8831 §6.7.WebRTC Direct does not exchange arbitrary application SDP between libp2p peers: each endpoint synthesizes the remote SDP needed to establish the direct connection. Consequently, putting a local configuration value in that SDP would not negotiate the remote capability and could make the two framing layers disagree.
Design
min(local, remote)as the connection's effective limit.StreamConfiginto the framing and transport implementations.This avoids a global conservative limit while preserving compatibility with existing WebRTC Direct peers. The capability value is exchanged only after Noise has authenticated the peer and bound the DTLS fingerprints into its prologue.
Validation
cargo test -p libp2p-webrtc-utils— 26 tests, including smaller-limit selection and legacy/invalid-peer fallback.cargo test -p libp2p-webrtc --features tokio --test smoke smoke— real two-node UDP WebRTC Direct connection.cargo check -p libp2p-webrtc --features tokiocargo check -p libp2p-webrtc-websys --target wasm32-unknown-unknowngit diff --checkThe existing multi-node WebRTC smoke test was also run. It completes successfully, but its detached background tasks log cleanup-time
NoListeners/SendError(Disconnected)panics, so I do not present it as a clean regression signal in this PR.AI Assistance Disclosure
Tools used (required — write
noneif no AI was used): Codex 5.6Attestation (required):
Notes & open questions
The post-Noise exchange deliberately uses the existing reserved handshake data channel rather than introducing a new SDP extension or a second negotiated data channel. It adds no new public wire format to application substreams.
Change checklist