-
-
Notifications
You must be signed in to change notification settings - Fork 443
Description
webrtc-rs fails to properly handle track receivers during SDP renegotiation when the same tracks (SSRCs) appear in multiple negotiation rounds. This causes receivers that are already active to be marked as "NOT HANDLED", breaking media flow in mesh topology scenarios with renegotiation.
Problem Description
Symptoms
During WebRTC renegotiation in mesh topology:
- Peers establish initial connections successfully
- Tracks flow correctly after initial negotiation
- When renegotiation occurs (e.g., adding new tracks, ICE restart)
- Existing tracks stop being handled properly
- Logs show: "Track NOT HANDLED: mid=X, kind=video, ssrcs=[...]"
- Media flow is disrupted despite receivers being active
Root Cause
The start_rtp_receivers() function in peer_connection_internal.rs has logic to check if a receiver has already started receiving:
let receiver = t.receiver().await;
let already_receiving = receiver.have_received().await;
if already_receiving {
continue; // SKIP this transceiver
}The Bug: This check does NOT distinguish between:
- Initial negotiation: Receiver already receiving → skip it (CORRECT)
- Renegotiation: Receiver already receiving → should mark as handled (WRONG - currently skips)
During renegotiation, the same tracks appear in the new SDP offer. The receiver is already active and receiving data. The code incorrectly skips these receivers, marking them as "NOT HANDLED" instead of recognizing they are already properly established.
Why This Happens
Mesh Topology Context:
- In mesh topology, each peer maintains multiple P2P connections
- When a new peer joins or leaves, renegotiation occurs
- The SDP for existing connections includes the same tracks again
- These tracks have the same SSRCs as before
The Logic Flaw:
// Current behavior (BROKEN):
if receiver.have_received() {
continue; // Skip - causes track to be unhandled
}
// Start receiver here (never reached for active receivers)This means active receivers are skipped during renegotiation, never reaching the "track_handled = true" logic.
How to Identify This Issue
Log Signatures
Without Fix:
WARN: Track NOT HANDLED: mid=0, kind=video, ssrcs=[12345]
WARN: Track NOT HANDLED: mid=1, kind=audio, ssrcs=[67890]
These warnings appear during renegotiation for tracks that are actually flowing correctly.
Debugging Steps
- Enable verbose logging in
start_rtp_receivers() - Trigger renegotiation (add track, ICE restart, etc.)
- Check if
have_received()returnstruefor unhandled tracks - Verify the tracks are actually flowing despite "NOT HANDLED" warning
Test Scenario
Setup:
- Create mesh topology with 3+ peers (A, B, C)
- Establish initial connections with tracks flowing
- Trigger renegotiation (e.g., peer A adds a new track)
Without Fix:
- Existing tracks from B and C marked as "NOT HANDLED"
- Media flow may be disrupted
- Renegotiation may fail
With Fix:
- Existing tracks properly marked as "HANDLED"
- New tracks started correctly
- Media flow continues uninterrupted
Testing
Test Cases
-
Initial negotiation with multiple tracks
- Verify all tracks marked as HANDLED
- Verify no duplicate receiver starts
-
Renegotiation with existing tracks
- Verify existing tracks marked as HANDLED (not restarted)
- Verify new tracks properly started
- Verify media continues flowing for existing tracks
-
Renegotiation without new tracks (ICE restart)
- Verify all existing tracks marked as HANDLED
- Verify no receiver restarts
- Verify media continues flowing
-
Mesh topology with 3+ peers
- Verify initial connections work
- Add new peer → trigger renegotiation
- Verify existing peer connections unaffected
- Verify new peer properly connected
Related Issues
- Mesh topology connection failures during peer addition/removal
- "Incoming unhandled RTCP ssrc" warnings (may be related)
- Media flow interruption during renegotiation
- Transceiver state management during renegotiation
References
WebRTC Specification
- RFC 3264 - Offer/Answer Model
- RFC 8829 - JavaScript Session Establishment Protocol (JSEP)
- Section 3.7: Subsequent Offers and Answers
Key Insight from RFC 8829
"When createOffer is called after the session has been established, the
generated description will reflect the current state of the session. The
created offer may reuse existing media descriptions."
This confirms that existing tracks appearing in renegotiation SDPs is expected behavior per the WebRTC specification.