Improve ssrc-group validation

disallowing more than one ssrc-group with the same semantic
and primary ssrc.

BUG=chromium:1477075

Change-Id: I4bce0555cd49834725d9b97693d26c971bc5d5c2
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/318822
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40694}
This commit is contained in:
Philipp Hancke 2023-09-04 17:47:34 +02:00 committed by WebRTC LUCI CQ
parent cbaf91bcf0
commit 7cc1ca26c8
2 changed files with 57 additions and 0 deletions

View file

@ -305,6 +305,23 @@ static bool ValidateStreamParams(const StreamParams& sp) {
return false; return false;
} }
// Validate that a primary SSRC can only have one ssrc-group per semantics.
std::map<uint32_t, std::set<std::string>> primary_ssrc_to_semantics;
for (const auto& group : sp.ssrc_groups) {
auto result = primary_ssrc_to_semantics.try_emplace(
group.ssrcs[0], std::set<std::string>({group.semantics}));
if (!result.second) {
// A duplicate SSRC was found, check for duplicate semantics.
auto semantics_it = result.first->second.insert(group.semantics);
if (!semantics_it.second) {
RTC_LOG(LS_ERROR) << "Duplicate ssrc-group '" << group.semantics
<< " for primary SSRC " << group.ssrcs[0] << " "
<< sp.ToString();
return false;
}
}
}
std::vector<uint32_t> primary_ssrcs; std::vector<uint32_t> primary_ssrcs;
sp.GetPrimarySsrcs(&primary_ssrcs); sp.GetPrimarySsrcs(&primary_ssrcs);
for (const auto& semantic : for (const auto& semantic :

View file

@ -890,4 +890,44 @@ TEST_F(SdpOfferAnswerTest,
EXPECT_FALSE(pc->SetLocalDescription(std::move(modified_offer))); EXPECT_FALSE(pc->SetLocalDescription(std::move(modified_offer)));
} }
TEST_F(SdpOfferAnswerTest, AllowOnlyOneSsrcGroupPerSemanticAndPrimarySsrc) {
auto pc = CreatePeerConnection();
pc->AddAudioTrack("audio_track", {});
pc->AddVideoTrack("video_track", {});
auto offer = pc->CreateOffer();
auto& offer_contents = offer->description()->contents();
ASSERT_EQ(offer_contents.size(), 2u);
uint32_t audio_ssrc = offer_contents[0].media_description()->first_ssrc();
ASSERT_EQ(offer_contents[1].media_description()->streams().size(), 1u);
auto& video_stream = offer->description()
->contents()[1]
.media_description()
->mutable_streams()[0];
ASSERT_EQ(video_stream.ssrcs.size(), 2u);
ASSERT_EQ(video_stream.ssrc_groups.size(), 1u);
video_stream.ssrcs.push_back(audio_ssrc);
video_stream.ssrc_groups.push_back(
{cricket::kFidSsrcGroupSemantics, {video_stream.ssrcs[0], audio_ssrc}});
std::string sdp;
offer->ToString(&sdp);
// Trim the last two lines which contain ssrc-specific attributes
// that we change/munge above. Guarded with expectation about what
// should be removed in case the SDP generation changes.
size_t end = sdp.rfind("\r\n");
end = sdp.rfind("\r\n", end - 2);
end = sdp.rfind("\r\n", end - 2);
EXPECT_EQ(sdp.substr(end + 2), "a=ssrc:" + rtc::ToString(audio_ssrc) +
" cname:" + video_stream.cname +
"\r\n"
"a=ssrc:" +
rtc::ToString(audio_ssrc) +
" msid:- video_track\r\n");
auto modified_offer =
CreateSessionDescription(SdpType::kOffer, sdp.substr(0, end + 2));
EXPECT_FALSE(pc->SetLocalDescription(std::move(modified_offer)));
}
} // namespace webrtc } // namespace webrtc