From 0d762b4e5062c4407712fef74f473dbc5a16cfac Mon Sep 17 00:00:00 2001 From: lukasIO Date: Mon, 2 Nov 2026 17:20:11 +0100 Subject: [PATCH] rtc: match publisher m-sections by mid, not by position (#5122) * rtc: match publisher m-sections by mid, not by position A client that stops a transceiver lets the next one recycle its m-line (JSEP 5.2.2), so a new m-section can come before negotiated ones. GetUnmatchMediaForOffer stopped at the last answered mid and missed it, so its codec preferences were never applied. Bump the protocol so clients know they can stop transceivers. Co-Authored-By: Claude Opus 5.5 * Update protocol_version.go * Remove comments from GetUnmatchMediaForOffer function Removed comments explaining the GetUnmatchMediaForOffer function. --------- Co-authored-by: Claude Opus 5.5 --- pkg/rtc/transportmanager.go | 20 +++++++++----------- pkg/rtc/types/protocol_version.go | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/rtc/transportmanager.go b/pkg/rtc/transportmanager.go index 2aac96fe2..ad31468d9 100644 --- a/pkg/rtc/transportmanager.go +++ b/pkg/rtc/transportmanager.go @@ -538,7 +538,7 @@ func (t *TransportManager) createDataChannelsForSubscriber(pendingDataChannels [ } func (t *TransportManager) GetUnmatchMediaForOffer(parsedOffer *sdp.SessionDescription, mediaType string) (unmatched []*sdp.MediaDescription, err error) { - var lastMatchedMid string + matchedMids := make(map[string]struct{}) if lastAnswer := t.publisher.CurrentLocalDescription(); lastAnswer != nil { parsedAnswer, err1 := lastAnswer.Unmarshal() if err1 != nil { @@ -547,22 +547,20 @@ func (t *TransportManager) GetUnmatchMediaForOffer(parsedOffer *sdp.SessionDescr return unmatched, err1 } - for i := len(parsedAnswer.MediaDescriptions) - 1; i >= 0; i-- { - media := parsedAnswer.MediaDescriptions[i] - if media.MediaName.Media == mediaType { - lastMatchedMid, _ = media.Attribute(sdp.AttrKeyMID) - break + for _, media := range parsedAnswer.MediaDescriptions { + if mid, ok := media.Attribute(sdp.AttrKeyMID); ok { + matchedMids[mid] = struct{}{} } } } for i := len(parsedOffer.MediaDescriptions) - 1; i >= 0; i-- { media := parsedOffer.MediaDescriptions[i] - if media.MediaName.Media == mediaType { - mid, _ := media.Attribute(sdp.AttrKeyMID) - if mid == lastMatchedMid { - break - } + if media.MediaName.Media != mediaType { + continue + } + mid, _ := media.Attribute(sdp.AttrKeyMID) + if _, ok := matchedMids[mid]; !ok { unmatched = append(unmatched, media) } } diff --git a/pkg/rtc/types/protocol_version.go b/pkg/rtc/types/protocol_version.go index 9b8d05be1..f85b65f21 100644 --- a/pkg/rtc/types/protocol_version.go +++ b/pkg/rtc/types/protocol_version.go @@ -16,7 +16,7 @@ package types type ProtocolVersion int -const CurrentProtocol = 18 +const CurrentProtocol = 19 func (v ProtocolVersion) SupportsPackedStreamId() bool { return v > 0