Bug 1622384: Implement stable indexing for JSEP transceivers. r=mjf

JSEP transceivers were previously held in a vector, in the order that they were
created. However, these could be removed, which meant that the indexing was not
stable. Under most circumstances this did not matter, however there was a
wrinkle with implicit rollback in repeated sRD. Re-applying a remote offer that
had created a transceiver would destroy that transceiver, and create a new one
to replace it. However, JS was not informed, because to PeerConnectionImpl it
looked like nothing had changed. Now, transceivers are indexed in a stable way,
which allows this bug to be fixed, and makes things a little less confusing.

Differential Revision: https://phabricator.services.mozilla.com/D70400
This commit is contained in:
Byron Campen [:bwc] 2020-04-29 02:48:07 +00:00
parent a82fa5316d
commit d2457e5246
6 changed files with 206 additions and 188 deletions

View File

@ -101,12 +101,12 @@ class JsepSessionTest : public JsepSessionTestBase,
}
void CheckTransceiverInvariants(
const std::vector<RefPtr<JsepTransceiver>>& oldTransceivers,
const std::vector<RefPtr<JsepTransceiver>>& newTransceivers) {
const std::map<size_t, RefPtr<JsepTransceiver>>& oldTransceivers,
const std::map<size_t, RefPtr<JsepTransceiver>>& newTransceivers) {
ASSERT_LE(oldTransceivers.size(), newTransceivers.size());
std::set<size_t> levels;
for (const RefPtr<JsepTransceiver>& newTransceiver : newTransceivers) {
for (const auto& [id, newTransceiver] : newTransceivers) {
if (newTransceiver->HasLevel()) {
ASSERT_FALSE(levels.count(newTransceiver->GetLevel()))
<< "Two new transceivers are mapped to level "
@ -124,7 +124,7 @@ class JsepSessionTest : public JsepSessionTestBase,
"transceivers.";
}
for (const RefPtr<JsepTransceiver>& oldTransceiver : oldTransceivers) {
for (const auto& [id, oldTransceiver] : oldTransceivers) {
if (oldTransceiver->HasLevel()) {
ASSERT_TRUE(levels.count(oldTransceiver->GetLevel()))
<< "Level " << oldTransceiver->GetLevel()
@ -136,18 +136,17 @@ class JsepSessionTest : public JsepSessionTestBase,
}
}
std::vector<RefPtr<JsepTransceiver>> DeepCopy(
const std::vector<RefPtr<JsepTransceiver>>& transceivers) {
std::vector<RefPtr<JsepTransceiver>> copy;
copy.reserve(transceivers.size());
for (const RefPtr<JsepTransceiver>& transceiver : transceivers) {
copy.push_back(new JsepTransceiver(*transceiver));
std::map<size_t, RefPtr<JsepTransceiver>> DeepCopy(
const std::map<size_t, RefPtr<JsepTransceiver>>& transceivers) {
std::map<size_t, RefPtr<JsepTransceiver>> copy;
for (const auto& [id, transceiver] : transceivers) {
copy[id] = new JsepTransceiver(*transceiver);
}
return copy;
}
std::string CreateOffer(const Maybe<JsepOfferOptions>& options = Nothing()) {
std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionOff->GetTransceivers());
JsepOfferOptions defaultOptions;
const JsepOfferOptions& optionsRef = options ? *options : defaultOptions;
@ -302,35 +301,36 @@ class JsepSessionTest : public JsepSessionTestBase,
for (auto type : mediatypes) {
ASSERT_TRUE(uuid_gen.Generate(&track_id));
std::vector<RefPtr<JsepTransceiver>>& transceivers(
side.GetTransceivers());
size_t i = transceivers.size();
RefPtr<JsepTransceiver> suitableTransceiver;
size_t i;
if (magic == ADDTRACK_MAGIC) {
for (i = 0; i < transceivers.size(); ++i) {
if (transceivers[i]->mSendTrack.GetMediaType() != type) {
for (auto& [id, transceiver] : side.GetTransceivers()) {
if (transceiver->mSendTrack.GetMediaType() != type) {
continue;
}
if (IsNull(transceivers[i]->mSendTrack) ||
transceivers[i]->GetMediaType() ==
SdpMediaSection::kApplication) {
if (IsNull(transceiver->mSendTrack) ||
transceiver->GetMediaType() == SdpMediaSection::kApplication) {
suitableTransceiver = transceiver;
i = id;
break;
}
}
}
if (i == transceivers.size()) {
side.AddTransceiver(new JsepTransceiver(type));
MOZ_ASSERT(i < transceivers.size());
if (!suitableTransceiver) {
suitableTransceiver = new JsepTransceiver(type);
side.AddTransceiver(suitableTransceiver);
i = side.GetTransceivers().rbegin()->first;
}
std::cerr << "Updating send track for transceiver " << i << std::endl;
if (magic == ADDTRACK_MAGIC) {
transceivers[i]->SetAddTrackMagic();
suitableTransceiver->SetAddTrackMagic();
}
transceivers[i]->mJsDirection |=
suitableTransceiver->mJsDirection |=
SdpDirectionAttribute::Direction::kSendonly;
transceivers[i]->mSendTrack.UpdateStreamIds(
suitableTransceiver->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, stream_id));
}
}
@ -351,7 +351,7 @@ class JsepSessionTest : public JsepSessionTestBase,
std::vector<JsepTrack> GetLocalTracks(const JsepSession& session) const {
std::vector<JsepTrack> result;
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
if (!IsNull(transceiver->mSendTrack)) {
result.push_back(transceiver->mSendTrack);
}
@ -361,7 +361,7 @@ class JsepSessionTest : public JsepSessionTestBase,
std::vector<JsepTrack> GetRemoteTracks(const JsepSession& session) const {
std::vector<JsepTrack> result;
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
if (!IsNull(transceiver->mRecvTrack)) {
result.push_back(transceiver->mRecvTrack);
}
@ -370,7 +370,7 @@ class JsepSessionTest : public JsepSessionTestBase,
}
JsepTransceiver* GetDatachannelTransceiver(JsepSession& side) {
for (const auto& transceiver : side.GetTransceivers()) {
for (const auto& [id, transceiver] : side.GetTransceivers()) {
if (transceiver->mSendTrack.GetMediaType() ==
SdpMediaSection::MediaType::kApplication) {
return transceiver.get();
@ -381,7 +381,7 @@ class JsepSessionTest : public JsepSessionTestBase,
}
JsepTransceiver* GetNegotiatedTransceiver(JsepSession& side, size_t index) {
for (RefPtr<JsepTransceiver>& transceiver : side.GetTransceivers()) {
for (const auto& [id, transceiver] : side.GetTransceivers()) {
if (transceiver->mSendTrack.GetNegotiatedDetails() ||
transceiver->mRecvTrack.GetNegotiatedDetails()) {
if (index) {
@ -397,8 +397,9 @@ class JsepSessionTest : public JsepSessionTestBase,
}
JsepTransceiver* GetTransceiverByLevel(
const std::vector<RefPtr<JsepTransceiver>>& transceivers, size_t level) {
for (auto& transceiver : transceivers) {
const std::map<size_t, RefPtr<JsepTransceiver>>& transceivers,
size_t level) {
for (const auto& [id, transceiver] : transceivers) {
if (transceiver->HasLevel() && transceiver->GetLevel() == level) {
return transceiver.get();
}
@ -454,7 +455,7 @@ class JsepSessionTest : public JsepSessionTestBase,
JsepTrack GetTrack(JsepSessionImpl& side, SdpMediaSection::MediaType type,
size_t index) const {
for (const auto& transceiver : side.GetTransceivers()) {
for (const auto& [id, transceiver] : side.GetTransceivers()) {
if (IsNull(transceiver->mSendTrack) ||
transceiver->mSendTrack.GetMediaType() != type) {
continue;
@ -647,16 +648,19 @@ class JsepSessionTest : public JsepSessionTestBase,
return true;
}
bool Equals(const std::vector<RefPtr<JsepTransceiver>>& t1,
const std::vector<RefPtr<JsepTransceiver>>& t2) const {
bool Equals(const std::map<size_t, RefPtr<JsepTransceiver>>& t1,
const std::map<size_t, RefPtr<JsepTransceiver>>& t2) const {
if (t1.size() != t2.size()) {
std::cerr << "Size differs: t1.size = " << t1.size()
<< ", t2.size = " << t2.size() << std::endl;
return false;
}
for (size_t i = 0; i < t1.size(); ++i) {
if (!Equals(*t1[i], *t2[i])) {
for (const auto& [id, transceiver] : t1) {
if (!t2.count(id)) {
return false;
}
if (!Equals(*transceiver, *t2.at(id))) {
return false;
}
}
@ -732,7 +736,7 @@ class JsepSessionTest : public JsepSessionTestBase,
}
std::string CreateAnswer() {
std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionAns->GetTransceivers());
JsepAnswerOptions options;
@ -768,7 +772,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetLocalOffer(const std::string& offer,
uint32_t checkFlags = ALL_CHECKS) {
std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionOff->GetTransceivers());
JsepSession::Result result =
@ -784,7 +788,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) {
// This assumes no recvonly or inactive transceivers.
ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size());
for (const auto& transceiver : mSessionOff->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) {
if (!transceiver->HasLevel()) {
continue;
}
@ -808,7 +812,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetRemoteOffer(const std::string& offer,
uint32_t checkFlags = ALL_CHECKS) {
std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionAns->GetTransceivers());
JsepSession::Result result =
@ -824,7 +828,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) {
// This assumes no recvonly or inactive transceivers.
ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size());
for (const auto& transceiver : mSessionAns->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) {
if (!transceiver->HasLevel()) {
continue;
}
@ -845,7 +849,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetLocalAnswer(const std::string& answer,
uint32_t checkFlags = ALL_CHECKS) {
std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionAns->GetTransceivers());
JsepSession::Result result =
@ -860,7 +864,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) {
// Verify that the right stuff is in the tracks.
ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size());
for (const auto& transceiver : mSessionAns->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) {
if (!transceiver->HasLevel()) {
continue;
}
@ -892,7 +896,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetRemoteAnswer(const std::string& answer,
uint32_t checkFlags = ALL_CHECKS) {
std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionOff->GetTransceivers());
JsepSession::Result result =
@ -907,7 +911,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) {
// Verify that the right stuff is in the tracks.
ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size());
for (const auto& transceiver : mSessionOff->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) {
if (!transceiver->HasLevel()) {
continue;
}
@ -935,7 +939,7 @@ class JsepSessionTest : public JsepSessionTestBase,
}
std::string GetTransportId(const JsepSession& session, size_t level) {
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
if (transceiver->HasLevel() && transceiver->GetLevel() == level) {
return transceiver->mTransport.mTransportId;
}
@ -950,7 +954,7 @@ class JsepSessionTest : public JsepSessionTestBase,
CandidateSet() {}
void Gather(JsepSession& session, ComponentType maxComponent = RTCP) {
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
if (transceiver->HasOwnTransport()) {
Gather(session, transceiver->mTransport.mTransportId, RTP);
if (transceiver->mTransport.mComponents > 1) {
@ -1182,7 +1186,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void CheckTransceiversAreBundled(const JsepSession& session,
const std::string& context) {
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
ASSERT_TRUE(transceiver->HasBundleLevel())
<< context;
ASSERT_EQ(0U, transceiver->BundleLevel()) << context;
@ -1330,7 +1334,7 @@ class JsepSessionTest : public JsepSessionTestBase,
}
void DumpTransceivers(const JsepSessionImpl& session) {
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
std::cerr << "Transceiver ";
if (transceiver->HasLevel()) {
std::cerr << transceiver->GetLevel() << std::endl;
@ -1567,9 +1571,9 @@ TEST_P(JsepSessionTest, RenegotiationNoChange) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
std::string reoffer = CreateOffer();
@ -1628,6 +1632,14 @@ TEST_P(JsepSessionTest, DISABLED_RenegotiationSwappedRolesNoChange) {
ASSERT_TRUE(Equals(answererTransceivers, newOffererTransceivers));
}
static void RemoveLastN(
std::map<size_t, RefPtr<JsepTransceiver>>& aTransceivers, size_t aNum) {
while (aNum--) {
// erase doesn't take reverse_iterator :(
aTransceivers.erase(--aTransceivers.end());
}
}
TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) {
AddTracks(*mSessionOff);
AddTracks(*mSessionAns);
@ -1637,9 +1649,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes;
@ -1657,11 +1669,11 @@ TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) {
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_LE(2U, newOffererTransceivers.size());
newOffererTransceivers.resize(newOffererTransceivers.size() - 2);
RemoveLastN(newOffererTransceivers, 2);
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_LE(2U, newAnswererTransceivers.size());
newAnswererTransceivers.resize(newAnswererTransceivers.size() - 2);
RemoveLastN(newAnswererTransceivers, 2);
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
}
@ -1674,9 +1686,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererAddsTrack) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes;
@ -1706,11 +1718,11 @@ TEST_P(JsepSessionTest, RenegotiationAnswererAddsTrack) {
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_LE(2U, newOffererTransceivers.size());
newOffererTransceivers.resize(newOffererTransceivers.size() - 2);
RemoveLastN(newOffererTransceivers, 2);
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_LE(2U, newAnswererTransceivers.size());
newAnswererTransceivers.resize(newAnswererTransceivers.size() - 2);
RemoveLastN(newAnswererTransceivers, 2);
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
}
@ -1723,9 +1735,9 @@ TEST_P(JsepSessionTest, RenegotiationBothAddTrack) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes;
@ -1744,11 +1756,11 @@ TEST_P(JsepSessionTest, RenegotiationBothAddTrack) {
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_LE(2U, newOffererTransceivers.size());
newOffererTransceivers.resize(newOffererTransceivers.size() - 2);
RemoveLastN(newOffererTransceivers, 2);
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_LE(2U, newAnswererTransceivers.size());
newAnswererTransceivers.resize(newAnswererTransceivers.size() - 2);
RemoveLastN(newAnswererTransceivers, 2);
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
}
@ -1886,14 +1898,15 @@ TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver) {
OfferAnswer();
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
auto lastTransceiver = mSessionOff->GetTransceivers().rbegin()->second;
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().back()->Stop();
JsepTrack removedTrack(mSessionOff->GetTransceivers().back()->mSendTrack);
lastTransceiver->Stop();
JsepTrack removedTrack(lastTransceiver->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
@ -1915,17 +1928,15 @@ TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver) {
ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size());
ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped());
ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped());
ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped());
origOffererTransceivers.pop_back(); // Ignore this one
newOffererTransceivers.pop_back(); // Ignore this one
origAnswererTransceivers.pop_back(); // Ignore this one
newAnswererTransceivers.pop_back(); // Ignore this one
ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped());
RemoveLastN(origOffererTransceivers, 1); // Ignore this one
RemoveLastN(newOffererTransceivers, 1); // Ignore this one
RemoveLastN(origAnswererTransceivers, 1); // Ignore this one
RemoveLastN(newAnswererTransceivers, 1); // Ignore this one
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
@ -1940,14 +1951,15 @@ TEST_P(JsepSessionTest, RenegotiationAnswererStopsTransceiver) {
OfferAnswer();
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionAns->GetTransceivers().back()->Stop();
JsepTrack removedTrack(mSessionAns->GetTransceivers().back()->mSendTrack);
mSessionAns->GetTransceivers().rbegin()->second->Stop();
JsepTrack removedTrack(
mSessionAns->GetTransceivers().rbegin()->second->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
@ -1970,14 +1982,14 @@ TEST_P(JsepSessionTest, RenegotiationAnswererStopsTransceiver) {
ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size());
ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped());
origOffererTransceivers.pop_back(); // Ignore this one
newOffererTransceivers.pop_back(); // Ignore this one
origAnswererTransceivers.pop_back(); // Ignore this one
newAnswererTransceivers.pop_back(); // Ignore this one
ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped());
ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped());
RemoveLastN(origOffererTransceivers, 1); // Ignore this one
RemoveLastN(newOffererTransceivers, 1); // Ignore this one
RemoveLastN(origAnswererTransceivers, 1); // Ignore this one
RemoveLastN(newAnswererTransceivers, 1); // Ignore this one
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
@ -1992,18 +2004,18 @@ TEST_P(JsepSessionTest, RenegotiationBothStopSameTransceiver) {
OfferAnswer();
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().back()->Stop();
mSessionOff->GetTransceivers().rbegin()->second->Stop();
JsepTrack removedTrackOffer(
mSessionOff->GetTransceivers().back()->mSendTrack);
mSessionAns->GetTransceivers().back()->Stop();
mSessionOff->GetTransceivers().rbegin()->second->mSendTrack);
mSessionAns->GetTransceivers().rbegin()->second->Stop();
JsepTrack removedTrackAnswer(
mSessionAns->GetTransceivers().back()->mSendTrack);
mSessionAns->GetTransceivers().rbegin()->second->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
@ -2025,14 +2037,14 @@ TEST_P(JsepSessionTest, RenegotiationBothStopSameTransceiver) {
ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size());
ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped());
origOffererTransceivers.pop_back(); // Ignore this one
newOffererTransceivers.pop_back(); // Ignore this one
origAnswererTransceivers.pop_back(); // Ignore this one
newAnswererTransceivers.pop_back(); // Ignore this one
ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped());
ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped());
RemoveLastN(origOffererTransceivers, 1); // Ignore this one
RemoveLastN(newOffererTransceivers, 1); // Ignore this one
RemoveLastN(origAnswererTransceivers, 1); // Ignore this one
RemoveLastN(newAnswererTransceivers, 1); // Ignore this one
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
@ -2050,18 +2062,18 @@ TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverThenAddTrack) {
OfferAnswer();
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().back()->Stop();
mSessionOff->GetTransceivers().rbegin()->second->Stop();
JsepTrack removedTrackOffer(
mSessionOff->GetTransceivers().back()->mSendTrack);
mSessionOff->GetTransceivers().back()->Stop();
mSessionOff->GetTransceivers().rbegin()->second->mSendTrack);
mSessionOff->GetTransceivers().rbegin()->second->Stop();
JsepTrack removedTrackAnswer(
mSessionOff->GetTransceivers().back()->mSendTrack);
mSessionOff->GetTransceivers().rbegin()->second->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes;
@ -2080,11 +2092,11 @@ TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverThenAddTrack) {
newAnswererTransceivers.size());
// Ensure that the m-section was re-used; no gaps
ASSERT_EQ(origOffererTransceivers.back()->GetLevel(),
newOffererTransceivers.back()->GetLevel());
ASSERT_EQ(origOffererTransceivers.rbegin()->second->GetLevel(),
newOffererTransceivers.rbegin()->second->GetLevel());
ASSERT_EQ(origAnswererTransceivers.back()->GetLevel(),
newAnswererTransceivers.back()->GetLevel());
ASSERT_EQ(origAnswererTransceivers.rbegin()->second->GetLevel(),
newAnswererTransceivers.rbegin()->second->GetLevel());
}
TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverDifferentMsection) {
@ -2167,9 +2179,9 @@ TEST_P(JsepSessionTest, RenegotiationAutoAssignedMsidIsStable) {
SetRemoteAnswer(answer, CHECK_SUCCESS);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
ASSERT_EQ(origOffererTransceivers.size(), origAnswererTransceivers.size());
@ -2204,7 +2216,7 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) {
// check all the audio tracks to make sure they have 2 codecs (109 and 101),
// and dtmf is enabled on all audio tracks
std::vector<JsepTrack> tracks;
for (const auto& transceiver : mSessionOff->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) {
tracks.push_back(transceiver->mSendTrack);
tracks.push_back(transceiver->mRecvTrack);
}
@ -2243,7 +2255,7 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) {
// check all the audio tracks to make sure they have 1 codec (109),
// and dtmf is disabled on all audio tracks
tracks.clear();
for (const auto& transceiver : mSessionOff->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) {
tracks.push_back(transceiver->mSendTrack);
tracks.push_back(transceiver->mRecvTrack);
}
@ -2281,9 +2293,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererEnablesMsid) {
SetRemoteAnswer(answer, CHECK_SUCCESS);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
offer = CreateOffer();
@ -2327,9 +2339,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererDisablesMsid) {
SetLocalAnswer(answer);
SetRemoteAnswer(answer, CHECK_SUCCESS);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
offer = CreateOffer();
@ -2387,9 +2399,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererEnablesBundle) {
SetLocalAnswer(answer);
SetRemoteAnswer(answer);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
OfferAnswer();
@ -2434,9 +2446,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesBundleTransport) {
GetTransceiverByLevel(*mSessionOff, 0)->Stop();
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
OfferAnswer(CHECK_SUCCESS);
@ -2485,9 +2497,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererDisablesBundleTransport) {
OfferAnswer();
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers());
GetTransceiverByLevel(*mSessionAns, 0)->Stop();
@ -3038,10 +3050,10 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines) {
SetLocalAnswer(answer, CHECK_SUCCESS);
SetRemoteAnswer(answer, CHECK_SUCCESS);
std::vector<RefPtr<JsepTransceiver>> transceivers(
std::map<size_t, RefPtr<JsepTransceiver>> transceivers(
mSessionOff->GetTransceivers());
ASSERT_EQ(3U, transceivers.size());
for (const auto& transceiver : transceivers) {
for (const auto& [id, transceiver] : transceivers) {
auto ssrcs = parsedOffer->GetMediaSection(transceiver->GetLevel())
.GetAttributeList()
.GetSsrc()
@ -4799,7 +4811,7 @@ TEST_P(JsepSessionTest, TestRejectOfferRollback) {
ASSERT_FALSE(
mSessionAns->SetRemoteDescription(kJsepSdpRollback, "").mError.isSome());
ASSERT_EQ(kJsepStateStable, mSessionAns->GetState());
for (const auto& transceiver : mSessionAns->GetTransceivers()) {
for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) {
ASSERT_EQ(0U, transceiver->mRecvTrack.GetStreamIds().size());
}
@ -4852,7 +4864,7 @@ TEST_P(JsepSessionTest, TestInvalidRollback) {
size_t GetActiveTransportCount(const JsepSession& session) {
size_t activeTransportCount = 0;
for (const auto& transceiver : session.GetTransceivers()) {
for (const auto& [id, transceiver] : session.GetTransceivers()) {
if (!transceiver->HasBundleLevel() ||
(transceiver->BundleLevel() == transceiver->GetLevel())) {
activeTransportCount += transceiver->mTransport.mComponents;
@ -6529,12 +6541,12 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) {
// Third audio transceiver should also be gone.
// Fourth audio transceiver, created after SetRemote
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->HasLevel());
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->IsStopped());
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->IsAssociated());
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->HasAddTrackMagic());
ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->HasLevel());
ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->IsStopped());
ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->IsAssociated());
ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->HasAddTrackMagic());
ASSERT_TRUE(
mSessionAns->GetTransceivers()[3]->mSendTrack.GetStreamIds().empty());
mSessionAns->GetTransceivers()[5]->mSendTrack.GetStreamIds().empty());
}
TEST_F(JsepSessionTest, LocalRollback) {

View File

@ -5,6 +5,7 @@
#ifndef _JSEPSESSION_H_
#define _JSEPSESSION_H_
#include <map>
#include <string>
#include <vector>
#include "mozilla/Attributes.h"
@ -106,7 +107,7 @@ class JsepSession {
template <class UnaryFunction>
void ForEachCodec(UnaryFunction& function) {
std::for_each(Codecs().begin(), Codecs().end(), function);
for (auto& transceiver : GetTransceivers()) {
for (auto& [id, transceiver] : GetTransceivers()) {
transceiver->mSendTrack.ForEachCodec(function);
transceiver->mRecvTrack.ForEachCodec(function);
}
@ -115,15 +116,15 @@ class JsepSession {
template <class BinaryPredicate>
void SortCodecs(BinaryPredicate& sorter) {
std::stable_sort(Codecs().begin(), Codecs().end(), sorter);
for (auto& transceiver : GetTransceivers()) {
for (auto& [id, transceiver] : GetTransceivers()) {
transceiver->mSendTrack.SortCodecs(sorter);
transceiver->mRecvTrack.SortCodecs(sorter);
}
}
virtual const std::vector<RefPtr<JsepTransceiver>>& GetTransceivers()
virtual const std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers()
const = 0;
virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() = 0;
virtual std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers() = 0;
virtual nsresult AddTransceiver(RefPtr<JsepTransceiver> transceiver) = 0;
class Result {
@ -190,7 +191,7 @@ class JsepSession {
memset(receiving, 0, sizeof(receiving));
memset(sending, 0, sizeof(sending));
for (const auto& transceiver : GetTransceivers()) {
for (const auto& [id, transceiver] : GetTransceivers()) {
if (transceiver->mRecvTrack.GetActive() ||
transceiver->GetMediaType() == SdpMediaSection::kApplication) {
receiving[transceiver->mRecvTrack.GetMediaType()]++;

View File

@ -113,7 +113,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) {
// of asserting.
transceiver->mJsDirection = SdpDirectionAttribute::kSendrecv;
#ifdef DEBUG
for (auto& transceiver : mTransceivers) {
for (const auto& [id, transceiver] : mTransceivers) {
MOZ_ASSERT(transceiver->GetMediaType() != SdpMediaSection::kApplication);
}
#endif
@ -123,7 +123,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) {
transceiver->mRecvTrack.PopulateCodecs(mSupportedCodecs);
// We do not set mLevel yet, we do that either on createOffer, or setRemote
mTransceivers.push_back(transceiver);
mTransceivers[mTransceiverIdCounter++] = transceiver;
return NS_OK;
}
@ -690,8 +690,8 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
if (type == kJsepSdpOffer) {
// Save in case we need to rollback
mOldTransceivers.clear();
for (const auto& transceiver : mTransceivers) {
mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
for (const auto& [id, transceiver] : mTransceivers) {
mOldTransceivers[id] = new JsepTransceiver(*transceiver);
}
}
@ -862,8 +862,8 @@ JsepSession::Result JsepSessionImpl::SetRemoteDescription(
// Save in case we need to rollback.
if (type == kJsepSdpOffer) {
mOldTransceivers.clear();
for (const auto& transceiver : mTransceivers) {
mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
for (const auto& [id, transceiver] : mTransceivers) {
mOldTransceivers[id] = new JsepTransceiver(*transceiver);
if (!transceiver->IsNegotiated()) {
// We chose a level for this transceiver, but never negotiated it.
// Discard this state.
@ -958,7 +958,7 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(
}
std::vector<JsepTrack*> remoteTracks;
for (const RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
for (const auto& [id, transceiver] : mTransceivers) {
remoteTracks.push_back(&transceiver->mRecvTrack);
}
JsepTrack::SetUniquePayloadTypes(remoteTracks);
@ -1331,7 +1331,7 @@ nsresult JsepSessionImpl::SetRemoteDescriptionAnswer(JsepSdpType type,
}
JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) {
for (RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
for (auto& [id, transceiver] : mTransceivers) {
if (transceiver->HasLevel() && (transceiver->GetLevel() == level)) {
return transceiver.get();
}
@ -1341,7 +1341,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) {
}
JsepTransceiver* JsepSessionImpl::GetTransceiverForMid(const std::string& mid) {
for (RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
for (auto& [id, transceiver] : mTransceivers) {
if (transceiver->IsAssociated() && (transceiver->GetMid() == mid)) {
return transceiver.get();
}
@ -1371,7 +1371,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) {
// There is no transceiver for |level| right now.
// Look for an RTP transceiver
for (RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
for (auto& [id, transceiver] : mTransceivers) {
if (transceiver->GetMediaType() != SdpMediaSection::kApplication &&
!transceiver->IsStopped() && !transceiver->HasLevel()) {
transceiver->SetLevel(level);
@ -1380,7 +1380,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) {
}
// Ok, look for a datachannel
for (RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
for (auto& [id, transceiver] : mTransceivers) {
if (!transceiver->IsStopped() && !transceiver->HasLevel()) {
transceiver->SetLevel(level);
return transceiver.get();
@ -1417,12 +1417,12 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForRemote(
newTransceiver->SetCreatedBySetRemote();
nsresult rv = AddTransceiver(newTransceiver);
NS_ENSURE_SUCCESS(rv, nullptr);
return mTransceivers.back().get();
return newTransceiver.get();
}
JsepTransceiver* JsepSessionImpl::GetTransceiverWithTransport(
const std::string& transportId) {
for (const auto& transceiver : mTransceivers) {
for (const auto& [id, transceiver] : mTransceivers) {
if (transceiver->HasOwnTransport() &&
(transceiver->mTransport.mTransportId == transportId)) {
MOZ_ASSERT(transceiver->HasLevel(),
@ -1485,7 +1485,7 @@ nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription(
JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver(
SdpMediaSection::MediaType type, bool magic) {
// Look through transceivers that are not mapped to an m-section
for (RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
for (auto& [id, transceiver] : mTransceivers) {
if (type == SdpMediaSection::kApplication &&
type == transceiver->GetMediaType()) {
transceiver->RestartDatachannelTransceiver();
@ -1502,10 +1502,10 @@ JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver(
}
void JsepSessionImpl::RollbackLocalOffer() {
for (size_t i = 0; i < mTransceivers.size(); ++i) {
RefPtr<JsepTransceiver>& transceiver(mTransceivers[i]);
if (i < mOldTransceivers.size()) {
transceiver->Rollback(*mOldTransceivers[i], false);
for (auto& [id, transceiver] : mTransceivers) {
if (mOldTransceivers.count(id)) {
transceiver->Rollback(*mOldTransceivers[id], false);
mOldTransceivers[id] = transceiver;
continue;
}
@ -1514,16 +1514,18 @@ void JsepSessionImpl::RollbackLocalOffer() {
temp->mSendTrack.PopulateCodecs(mSupportedCodecs);
temp->mRecvTrack.PopulateCodecs(mSupportedCodecs);
transceiver->Rollback(*temp, false);
mOldTransceivers[id] = transceiver;
}
mOldTransceivers.clear();
mTransceivers = std::move(mOldTransceivers);
}
void JsepSessionImpl::RollbackRemoteOffer() {
for (size_t i = 0; i < mTransceivers.size(); ++i) {
RefPtr<JsepTransceiver>& transceiver(mTransceivers[i]);
if (i < mOldTransceivers.size()) {
transceiver->Rollback(*mOldTransceivers[i], true);
for (auto& [id, transceiver] : mTransceivers) {
if (mOldTransceivers.count(id)) {
// Some stuff cannot be rolled back. Save this information.
transceiver->Rollback(*mOldTransceivers[id], true);
mOldTransceivers[id] = transceiver;
continue;
}
@ -1542,12 +1544,12 @@ void JsepSessionImpl::RollbackRemoteOffer() {
if (shouldRemove) {
transceiver->Stop();
transceiver->SetRemoved();
mTransceivers.erase(mTransceivers.begin() + i);
--i;
} else {
mOldTransceivers[id] = transceiver;
}
}
mOldTransceivers.clear();
mTransceivers = std::move(mOldTransceivers);
}
nsresult JsepSessionImpl::ValidateLocalDescription(const Sdp& description,
@ -2133,7 +2135,7 @@ nsresult JsepSessionImpl::UpdateDefaultCandidate(
return NS_ERROR_UNEXPECTED;
}
for (const auto& transceiver : mTransceivers) {
for (const auto& [id, transceiver] : mTransceivers) {
// We set the default address for bundled m-sections, but not candidate
// attributes. Ugh.
if (transceiver->mTransport.mTransportId == transportId) {
@ -2236,7 +2238,7 @@ const std::string JsepSessionImpl::GetLastError() const { return mLastError; }
bool JsepSessionImpl::CheckNegotiationNeeded() const {
MOZ_ASSERT(mState == kJsepStateStable);
for (const auto& transceiver : mTransceivers) {
for (const auto& [id, transceiver] : mTransceivers) {
if (transceiver->IsStopped()) {
if (transceiver->IsAssociated()) {
MOZ_MTLOG(ML_DEBUG, "[" << mName

View File

@ -5,6 +5,7 @@
#ifndef _JSEPSESSIONIMPL_H_
#define _JSEPSESSIONIMPL_H_
#include <map>
#include <set>
#include <string>
#include <vector>
@ -131,12 +132,13 @@ class JsepSessionImpl : public JsepSession {
return !mOldIceUfrag.empty();
}
virtual const std::vector<RefPtr<JsepTransceiver>>& GetTransceivers()
virtual const std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers()
const override {
return mTransceivers;
}
virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() override {
virtual std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers()
override {
return mTransceivers;
}
@ -225,11 +227,12 @@ class JsepSessionImpl : public JsepSession {
const Sdp* GetAnswer() const;
void SetIceRestarting(bool restarting);
// !!!NOT INDEXED BY LEVEL!!! These are in the order they were created in. The
// level mapping is done with JsepTransceiver::mLevel.
std::vector<RefPtr<JsepTransceiver>> mTransceivers;
// !!!NOT INDEXED BY LEVEL!!! The level mapping is done with
// JsepTransceiver::mLevel. The keys are opaque, stable identifiers that are
// unique within the JsepSession.
std::map<size_t, RefPtr<JsepTransceiver>> mTransceivers;
// So we can rollback. Not as simple as just going back to the old, though...
std::vector<RefPtr<JsepTransceiver>> mOldTransceivers;
std::map<size_t, RefPtr<JsepTransceiver>> mOldTransceivers;
Maybe<bool> mIsPendingOfferer;
Maybe<bool> mIsCurrentOfferer;
@ -247,6 +250,7 @@ class JsepSessionImpl : public JsepSession {
size_t mMidCounter;
std::set<std::string> mUsedMids;
size_t mTransportIdCounter;
size_t mTransceiverIdCounter = 0;
std::vector<JsepExtmapMediaType> mRtpExtensions;
UniquePtr<JsepUuidGenerator> mUuidGen;
std::string mDefaultRemoteStreamId;

View File

@ -878,7 +878,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
transportId->clear();
RefPtr<JsepTransceiver> datachannelTransceiver;
for (const auto& transceiver : mJsepSession->GetTransceivers()) {
for (const auto& [id, transceiver] : mJsepSession->GetTransceivers()) {
if ((transceiver->GetMediaType() == SdpMediaSection::kApplication) &&
transceiver->mSendTrack.GetNegotiatedDetails()) {
datachannelTransceiver = transceiver;
@ -895,7 +895,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
transportTransceiver = datachannelTransceiver;
} else if (datachannelTransceiver->HasBundleLevel()) {
// Find the actual transport.
for (const auto& transceiver : mJsepSession->GetTransceivers()) {
for (const auto& [id, transceiver] : mJsepSession->GetTransceivers()) {
if (transceiver->HasLevel() &&
transceiver->GetLevel() == datachannelTransceiver->BundleLevel() &&
transceiver->HasOwnTransport()) {
@ -1118,7 +1118,7 @@ PeerConnectionImpl::CreateDataChannel(
CSFLogDebug(LOGTAG, "%s: making DOMDataChannel", __FUNCTION__);
RefPtr<JsepTransceiver> dcTransceiver;
for (auto& transceiver : mJsepSession->GetTransceivers()) {
for (auto& [id, transceiver] : mJsepSession->GetTransceivers()) {
if (transceiver->GetMediaType() == SdpMediaSection::kApplication) {
dcTransceiver = transceiver;
break;
@ -1403,7 +1403,7 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) {
return NS_ERROR_FAILURE;
}
size_t originalTransceiverCount = mJsepSession->GetTransceivers().size();
auto originalTransceivers = mJsepSession->GetTransceivers();
JsepSession::Result result =
mJsepSession->SetRemoteDescription(sdpType, mRemoteRequestedSDP);
if (result.mError.isSome()) {
@ -1413,18 +1413,17 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) {
mPCObserver->OnSetDescriptionError(*buildJSErrorData(result, errorString),
jrv);
} else {
// Iterate over the JSEP transceivers that were just created
for (size_t i = originalTransceiverCount;
i < mJsepSession->GetTransceivers().size(); ++i) {
RefPtr<JsepTransceiver> jsepTransceiver =
mJsepSession->GetTransceivers()[i];
for (const auto& [id, jsepTransceiver] : mJsepSession->GetTransceivers()) {
if (jsepTransceiver->GetMediaType() ==
SdpMediaSection::MediaType::kApplication) {
continue;
}
// Audio or video transceiver, need to tell JS about it.
if (originalTransceivers.count(id)) {
continue;
}
// New audio or video transceiver, need to tell JS about it.
RefPtr<TransceiverImpl> transceiverImpl =
CreateTransceiverImpl(jsepTransceiver, nullptr, jrv);
if (jrv.Failed()) {

View File

@ -165,7 +165,7 @@ nsresult PeerConnectionMedia::Init() {
}
void PeerConnectionMedia::EnsureTransports(const JsepSession& aSession) {
for (const auto& transceiver : aSession.GetTransceivers()) {
for (const auto& [id, transceiver] : aSession.GetTransceivers()) {
if (transceiver->HasOwnTransport()) {
mTransportHandler->EnsureProvisionalTransport(
transceiver->mTransport.mTransportId,
@ -181,7 +181,7 @@ void PeerConnectionMedia::EnsureTransports(const JsepSession& aSession) {
nsresult PeerConnectionMedia::UpdateTransports(const JsepSession& aSession,
const bool forceIceTcp) {
std::set<std::string> finalTransports;
for (const auto& transceiver : aSession.GetTransceivers()) {
for (const auto& [id, transceiver] : aSession.GetTransceivers()) {
if (transceiver->HasOwnTransport()) {
finalTransports.insert(transceiver->mTransport.mTransportId);
UpdateTransport(*transceiver, forceIceTcp);