Summary
In rtc/src/peer_connection/internal.rs, generate_matched_sdp silently drops rejected m-lines (m=video 0 …) from the SDP answer instead of reflecting them as rejected.
Root cause
// internal.rs ~line 243
let kind = RtpCodecKind::from(media.media_name.media.as_str());
let direction = get_peer_direction(media);
if kind == RtpCodecKind::Unspecified
|| direction == RTCRtpTransceiverDirection::Unspecified // <-- hits here for rejected m-lines
{
continue; // m-line is silently skipped
}
A rejected m-line in an offer has port 0 and carries no a=sendrecv/sendonly/recvonly/inactive attribute, so get_peer_direction returns Unspecified. The continue causes the m-line to be omitted from the answer entirely.
Expected behaviour (RFC 8829 §5.3.1)
If the answerer has no media format in common for a given m= section, the answerer MUST reject that m= section by setting the port to zero.
More broadly, the answer MUST contain the same number of m-lines as the offer, in the same order, to preserve m-line indexing. A rejected offer m-line must produce a rejected (port=0) answer m-line.
Impact
- Any peer that receives an offer containing a rejected video/audio m-line and tries to create an answer will produce a malformed answer (wrong m-line count).
- Breaks interoperability with browsers, which routinely emit rejected m-lines during renegotiation.
Fix
Detect rejected m-lines (direction == Unspecified AND port == 0) and push a rejected MediaSection instead of skipping:
if kind == RtpCodecKind::Unspecified {
continue;
}
if direction == RTCRtpTransceiverDirection::Unspecified {
// Rejected m-line — reflect as rejected in the answer (RFC 8829 §5.3.1)
media_sections.push(MediaSection {
mid: mid_value.to_owned(),
rejected: true,
..Default::default()
});
continue;
}
This requires adding a rejected: bool field to MediaSection and handling it in the SDP writer (sdp/mod.rs) to emit m=<kind> 0 … with no attributes.
Discovered while investigating webrtc-rs/webrtc#787.
Summary
In
rtc/src/peer_connection/internal.rs,generate_matched_sdpsilently drops rejected m-lines (m=video 0 …) from the SDP answer instead of reflecting them as rejected.Root cause
A rejected m-line in an offer has port 0 and carries no
a=sendrecv/sendonly/recvonly/inactiveattribute, soget_peer_directionreturnsUnspecified. Thecontinuecauses the m-line to be omitted from the answer entirely.Expected behaviour (RFC 8829 §5.3.1)
More broadly, the answer MUST contain the same number of m-lines as the offer, in the same order, to preserve m-line indexing. A rejected offer m-line must produce a rejected (
port=0) answer m-line.Impact
Fix
Detect rejected m-lines (direction == Unspecified AND port == 0) and push a rejected
MediaSectioninstead of skipping:This requires adding a
rejected: boolfield toMediaSectionand handling it in the SDP writer (sdp/mod.rs) to emitm=<kind> 0 …with no attributes.Discovered while investigating webrtc-rs/webrtc#787.