Bug 1769802: Key JsepTransceiver by UUID instead of a simple integer index. r=mjf

The integer index we're replacing here is based on the order in which
transceivers were added. If we clone the JSEP engine for an sRD that happens to
result in the creation of a transceiver, and at the same time JS calls
addTransceiver, we have a situation where the sRD transceiver is added first
to the cloned JSEP engine, but the addTransceiver transceiver is added first
to the old JSEP engine, resulting in them having the same index. So, let's just
use a proper key for this stuff.

Differential Revision: https://phabricator.services.mozilla.com/D150169
This commit is contained in:
Byron Campen 2022-08-05 14:03:43 +00:00
Родитель 118bbe616d
Коммит c2e51c8618
9 изменённых файлов: 293 добавлений и 273 удалений

Просмотреть файл

@ -851,8 +851,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
transportId->clear(); transportId->clear();
RefPtr<JsepTransceiver> datachannelTransceiver; RefPtr<JsepTransceiver> datachannelTransceiver;
for (const auto& [id, transceiver] : mJsepSession->GetTransceivers()) { for (const auto& transceiver : mJsepSession->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if ((transceiver->GetMediaType() == SdpMediaSection::kApplication) && if ((transceiver->GetMediaType() == SdpMediaSection::kApplication) &&
transceiver->mSendTrack.GetNegotiatedDetails()) { transceiver->mSendTrack.GetNegotiatedDetails()) {
datachannelTransceiver = transceiver; datachannelTransceiver = transceiver;
@ -958,18 +957,8 @@ already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
return nullptr; return nullptr;
} }
RefPtr<JsepTransceiver> jsepTransceiver = new JsepTransceiver(*type); RefPtr<JsepTransceiver> jsepTransceiver =
new JsepTransceiver(*type, *mUuidGen);
RefPtr<RTCRtpTransceiver> transceiver =
CreateTransceiver(jsepTransceiver, aInit, aSendTrack, aRv);
if (aRv.Failed()) {
// Would be nice if we could peek at the rv without stealing it, so we
// could log...
CSFLogError(LOGTAG, "%s: failed", __FUNCTION__);
return nullptr;
}
jsepTransceiver->SetRtxIsAllowed(mRtxIsAllowed); jsepTransceiver->SetRtxIsAllowed(mRtxIsAllowed);
// Do this last, since it is not possible to roll back. // Do this last, since it is not possible to roll back.
@ -981,6 +970,18 @@ already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
return nullptr; return nullptr;
} }
RefPtr<RTCRtpTransceiver> transceiver = CreateTransceiver(
jsepTransceiver->GetUuid(),
jsepTransceiver->GetMediaType() == SdpMediaSection::kVideo, aInit,
aSendTrack, aRv);
if (aRv.Failed()) {
// Would be nice if we could peek at the rv without stealing it, so we
// could log...
CSFLogError(LOGTAG, "%s: failed", __FUNCTION__);
return nullptr;
}
mTransceivers.AppendElement(transceiver); mTransceivers.AppendElement(transceiver);
return transceiver.forget(); return transceiver.forget();
} }
@ -1073,8 +1074,7 @@ PeerConnectionImpl::CreateDataChannel(
CSFLogDebug(LOGTAG, "%s: making DOMDataChannel", __FUNCTION__); CSFLogDebug(LOGTAG, "%s: making DOMDataChannel", __FUNCTION__);
RefPtr<JsepTransceiver> dcTransceiver; RefPtr<JsepTransceiver> dcTransceiver;
for (auto& [id, transceiver] : mJsepSession->GetTransceivers()) { for (auto& transceiver : mJsepSession->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->GetMediaType() == SdpMediaSection::kApplication) { if (transceiver->GetMediaType() == SdpMediaSection::kApplication) {
dcTransceiver = transceiver; dcTransceiver = transceiver;
break; break;
@ -1082,8 +1082,8 @@ PeerConnectionImpl::CreateDataChannel(
} }
if (!dcTransceiver) { if (!dcTransceiver) {
dcTransceiver = dcTransceiver = new JsepTransceiver(
new JsepTransceiver(SdpMediaSection::MediaType::kApplication); SdpMediaSection::MediaType::kApplication, *mUuidGen);
mJsepSession->AddTransceiver(dcTransceiver); mJsepSession->AddTransceiver(dcTransceiver);
} }
@ -1609,25 +1609,37 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) {
mPCObserver->OnSetDescriptionError(*buildJSErrorData(result, errorString), mPCObserver->OnSetDescriptionError(*buildJSErrorData(result, errorString),
jrv); jrv);
} else { } else {
for (const auto& [id, jsepTransceiver] : mJsepSession->GetTransceivers()) { for (const auto& jsepTransceiver : mJsepSession->GetTransceivers()) {
if (jsepTransceiver->GetMediaType() == if (jsepTransceiver->GetMediaType() ==
SdpMediaSection::MediaType::kApplication) { SdpMediaSection::MediaType::kApplication) {
continue; continue;
} }
if (originalTransceivers.count(id)) { CSFLogDebug(LOGTAG, "%s: Looking for match", __FUNCTION__);
continue; RefPtr<RTCRtpTransceiver> transceiver;
for (auto& temp : mTransceivers) {
if (temp->GetJsepTransceiverId() == jsepTransceiver->GetUuid()) {
CSFLogDebug(LOGTAG, "%s: Found match", __FUNCTION__);
transceiver = temp;
break;
}
} }
dom::RTCRtpTransceiverInit init; if (!transceiver) {
init.mDirection = RTCRtpTransceiverDirection::Recvonly; CSFLogDebug(LOGTAG, "%s: No match, making new", __FUNCTION__);
RefPtr<RTCRtpTransceiver> transceiver = dom::RTCRtpTransceiverInit init;
CreateTransceiver(jsepTransceiver, init, nullptr, jrv); init.mDirection = RTCRtpTransceiverDirection::Recvonly;
if (jrv.Failed()) { IgnoredErrorResult rv;
appendHistory(); transceiver = CreateTransceiver(
return NS_ERROR_FAILURE; jsepTransceiver->GetUuid(),
jsepTransceiver->GetMediaType() == SdpMediaSection::kVideo, init,
nullptr, rv);
if (NS_WARN_IF(rv.Failed())) {
MOZ_ASSERT(false);
break;
}
mTransceivers.AppendElement(transceiver);
} }
mTransceivers.AppendElement(transceiver);
} }
if (wasRestartingIce) { if (wasRestartingIce) {
@ -3213,8 +3225,7 @@ bool PeerConnectionImpl::ShouldForceProxy() const {
} }
void PeerConnectionImpl::EnsureTransports(const JsepSession& aSession) { void PeerConnectionImpl::EnsureTransports(const JsepSession& aSession) {
for (const auto& [id, transceiver] : aSession.GetTransceivers()) { for (const auto& transceiver : aSession.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasOwnTransport()) { if (transceiver->HasOwnTransport()) {
mTransportHandler->EnsureProvisionalTransport( mTransportHandler->EnsureProvisionalTransport(
transceiver->mTransport.mTransportId, transceiver->mTransport.mTransportId,
@ -3264,8 +3275,7 @@ void PeerConnectionImpl::RemoveRTCDtlsTransportsExcept(
nsresult PeerConnectionImpl::UpdateTransports(const JsepSession& aSession, nsresult PeerConnectionImpl::UpdateTransports(const JsepSession& aSession,
const bool forceIceTcp) { const bool forceIceTcp) {
std::set<std::string> finalTransports; std::set<std::string> finalTransports;
for (const auto& [id, transceiver] : aSession.GetTransceivers()) { for (const auto& transceiver : aSession.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasOwnTransport()) { if (transceiver->HasOwnTransport()) {
finalTransports.insert(transceiver->mTransport.mTransportId); finalTransports.insert(transceiver->mTransport.mTransportId);
UpdateTransport(*transceiver, forceIceTcp); UpdateTransport(*transceiver, forceIceTcp);
@ -3636,7 +3646,7 @@ void PeerConnectionImpl::EnsureIceGathering(bool aDefaultRouteOnly,
} }
already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver( already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
JsepTransceiver* aJsepTransceiver, const RTCRtpTransceiverInit& aInit, const std::string& aId, bool aIsVideo, const RTCRtpTransceiverInit& aInit,
dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv) { dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv) {
PeerConnectionCtx* ctx = PeerConnectionCtx::GetInstance(); PeerConnectionCtx* ctx = PeerConnectionCtx::GetInstance();
if (!mCall) { if (!mCall) {
@ -3649,8 +3659,8 @@ already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
} }
RefPtr<RTCRtpTransceiver> transceiver = new RTCRtpTransceiver( RefPtr<RTCRtpTransceiver> transceiver = new RTCRtpTransceiver(
mWindow, PrivacyNeeded(), this, mTransportHandler, aJsepTransceiver, mWindow, PrivacyNeeded(), this, mTransportHandler, mJsepSession.get(),
mSTSThread.get(), aSendTrack, mCall.get(), mIdGenerator); aId, aIsVideo, mSTSThread.get(), aSendTrack, mCall.get(), mIdGenerator);
transceiver->Init(aInit, aRv); transceiver->Init(aInit, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {

Просмотреть файл

@ -126,6 +126,9 @@ class RemoteSourceStreamInfo;
class PCUuidGenerator : public mozilla::JsepUuidGenerator { class PCUuidGenerator : public mozilla::JsepUuidGenerator {
public: public:
virtual bool Generate(std::string* idp) override; virtual bool Generate(std::string* idp) override;
virtual mozilla::JsepUuidGenerator* Clone() const override {
return new PCUuidGenerator(*this);
}
private: private:
nsCOMPtr<nsIUUIDGenerator> mGenerator; nsCOMPtr<nsIUUIDGenerator> mGenerator;
@ -725,7 +728,7 @@ class PeerConnectionImpl final
nsresult UpdateMediaPipelines(); nsresult UpdateMediaPipelines();
already_AddRefed<dom::RTCRtpTransceiver> CreateTransceiver( already_AddRefed<dom::RTCRtpTransceiver> CreateTransceiver(
JsepTransceiver* aJsepTransceiver, const std::string& aId, bool aIsVideo,
const dom::RTCRtpTransceiverInit& aInit, const dom::RTCRtpTransceiverInit& aInit,
dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv); dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv);

Просмотреть файл

@ -156,13 +156,15 @@ NS_INTERFACE_MAP_END
RTCRtpTransceiver::RTCRtpTransceiver( RTCRtpTransceiver::RTCRtpTransceiver(
nsPIDOMWindowInner* aWindow, bool aPrivacyNeeded, PeerConnectionImpl* aPc, nsPIDOMWindowInner* aWindow, bool aPrivacyNeeded, PeerConnectionImpl* aPc,
MediaTransportHandler* aTransportHandler, JsepTransceiver* aJsepTransceiver, MediaTransportHandler* aTransportHandler, JsepSession* aJsepSession,
const std::string& aTransceiverId, bool aIsVideo,
nsISerialEventTarget* aStsThread, dom::MediaStreamTrack* aSendTrack, nsISerialEventTarget* aStsThread, dom::MediaStreamTrack* aSendTrack,
WebrtcCallWrapper* aCallWrapper, RTCStatsIdGenerator* aIdGenerator) WebrtcCallWrapper* aCallWrapper, RTCStatsIdGenerator* aIdGenerator)
: mWindow(aWindow), : mWindow(aWindow),
mPc(aPc), mPc(aPc),
mTransportHandler(aTransportHandler), mTransportHandler(aTransportHandler),
mJsepTransceiver(aJsepTransceiver), mTransceiverId(aTransceiverId),
mJsepTransceiver(aJsepSession->GetTransceiver(mTransceiverId)),
mStsThread(aStsThread), mStsThread(aStsThread),
mCallWrapper(aCallWrapper), mCallWrapper(aCallWrapper),
mSendTrack(aSendTrack), mSendTrack(aSendTrack),

Просмотреть файл

@ -12,7 +12,7 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "mozilla/dom/MediaStreamTrack.h" #include "mozilla/dom/MediaStreamTrack.h"
#include "ErrorList.h" #include "ErrorList.h"
#include "jsep/JsepTransceiver.h" #include "jsep/JsepSession.h"
#include "transport/transportlayer.h" // For TransportLayer::State #include "transport/transportlayer.h" // For TransportLayer::State
#include "mozilla/dom/RTCRtpTransceiverBinding.h" #include "mozilla/dom/RTCRtpTransceiverBinding.h"
@ -20,7 +20,6 @@ class nsIPrincipal;
namespace mozilla { namespace mozilla {
class PeerIdentity; class PeerIdentity;
class JsepTransceiver;
class MediaSessionConduit; class MediaSessionConduit;
class VideoSessionConduit; class VideoSessionConduit;
class AudioSessionConduit; class AudioSessionConduit;
@ -58,14 +57,12 @@ class RTCRtpTransceiver : public nsISupports,
/** /**
* |aSendTrack| might or might not be set. * |aSendTrack| might or might not be set.
*/ */
RTCRtpTransceiver(nsPIDOMWindowInner* aWindow, bool aPrivacyNeeded, RTCRtpTransceiver(
PeerConnectionImpl* aPc, nsPIDOMWindowInner* aWindow, bool aPrivacyNeeded, PeerConnectionImpl* aPc,
MediaTransportHandler* aTransportHandler, MediaTransportHandler* aTransportHandler, JsepSession* aJsepSession,
JsepTransceiver* aJsepTransceiver, const std::string& aTransceiverId, bool aIsVideo,
nsISerialEventTarget* aStsThread, nsISerialEventTarget* aStsThread, MediaStreamTrack* aSendTrack,
MediaStreamTrack* aSendTrack, WebrtcCallWrapper* aCallWrapper, RTCStatsIdGenerator* aIdGenerator);
WebrtcCallWrapper* aCallWrapper,
RTCStatsIdGenerator* aIdGenerator);
void Init(const RTCRtpTransceiverInit& aInit, ErrorResult& aRv); void Init(const RTCRtpTransceiverInit& aInit, ErrorResult& aRv);
@ -145,6 +142,8 @@ class RTCRtpTransceiver : public nsISupports,
MediaSessionConduit* GetConduit() const { return mConduit; } MediaSessionConduit* GetConduit() const { return mConduit; }
const std::string& GetJsepTransceiverId() const { return mTransceiverId; }
// nsISupports // nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(RTCRtpTransceiver) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(RTCRtpTransceiver)
@ -188,7 +187,8 @@ class RTCRtpTransceiver : public nsISupports,
nsCOMPtr<nsPIDOMWindowInner> mWindow; nsCOMPtr<nsPIDOMWindowInner> mWindow;
RefPtr<PeerConnectionImpl> mPc; RefPtr<PeerConnectionImpl> mPc;
RefPtr<MediaTransportHandler> mTransportHandler; RefPtr<MediaTransportHandler> mTransportHandler;
const RefPtr<JsepTransceiver> mJsepTransceiver; const std::string mTransceiverId;
RefPtr<JsepTransceiver> mJsepTransceiver;
nsCOMPtr<nsISerialEventTarget> mStsThread; nsCOMPtr<nsISerialEventTarget> mStsThread;
// state for webrtc.org that is shared between all transceivers // state for webrtc.org that is shared between all transceivers
RefPtr<WebrtcCallWrapper> mCallWrapper; RefPtr<WebrtcCallWrapper> mCallWrapper;

Просмотреть файл

@ -107,8 +107,7 @@ class JsepSession {
template <class UnaryFunction> template <class UnaryFunction>
void ForEachCodec(UnaryFunction& function) { void ForEachCodec(UnaryFunction& function) {
std::for_each(Codecs().begin(), Codecs().end(), function); std::for_each(Codecs().begin(), Codecs().end(), function);
for (auto& [id, transceiver] : GetTransceivers()) { for (auto& transceiver : GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
transceiver->mSendTrack.ForEachCodec(function); transceiver->mSendTrack.ForEachCodec(function);
transceiver->mRecvTrack.ForEachCodec(function); transceiver->mRecvTrack.ForEachCodec(function);
} }
@ -117,16 +116,24 @@ class JsepSession {
template <class BinaryPredicate> template <class BinaryPredicate>
void SortCodecs(BinaryPredicate& sorter) { void SortCodecs(BinaryPredicate& sorter) {
std::stable_sort(Codecs().begin(), Codecs().end(), sorter); std::stable_sort(Codecs().begin(), Codecs().end(), sorter);
for (auto& [id, transceiver] : GetTransceivers()) { for (auto& transceiver : GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
transceiver->mSendTrack.SortCodecs(sorter); transceiver->mSendTrack.SortCodecs(sorter);
transceiver->mRecvTrack.SortCodecs(sorter); transceiver->mRecvTrack.SortCodecs(sorter);
} }
} }
virtual const std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers() // Returns transceivers in the order they were added.
virtual const std::vector<RefPtr<JsepTransceiver>>& GetTransceivers()
const = 0; const = 0;
virtual std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers() = 0; virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() = 0;
RefPtr<JsepTransceiver> GetTransceiver(const std::string& aId) const {
for (const auto& transceiver : GetTransceivers()) {
if (transceiver->GetUuid() == aId) {
return transceiver;
}
}
return nullptr;
}
virtual nsresult AddTransceiver(RefPtr<JsepTransceiver> transceiver) = 0; virtual nsresult AddTransceiver(RefPtr<JsepTransceiver> transceiver) = 0;
class Result { class Result {
@ -198,8 +205,7 @@ class JsepSession {
memset(receiving, 0, sizeof(receiving)); memset(receiving, 0, sizeof(receiving));
memset(sending, 0, sizeof(sending)); memset(sending, 0, sizeof(sending));
for (const auto& [id, transceiver] : GetTransceivers()) { for (const auto& transceiver : GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->mRecvTrack.GetActive() || if (transceiver->mRecvTrack.GetActive() ||
transceiver->GetMediaType() == SdpMediaSection::kApplication) { transceiver->GetMediaType() == SdpMediaSection::kApplication) {
receiving[transceiver->mRecvTrack.GetMediaType()]++; receiving[transceiver->mRecvTrack.GetMediaType()]++;

Просмотреть файл

@ -115,7 +115,8 @@ JsepSessionImpl::GetLocalIceCredentials() const {
nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) { nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) {
mLastError.clear(); mLastError.clear();
MOZ_MTLOG(ML_DEBUG, "[" << mName << "]: Adding transceiver."); MOZ_MTLOG(ML_DEBUG,
"[" << mName << "]: Adding transceiver " << transceiver->GetUuid());
if (transceiver->GetMediaType() != SdpMediaSection::kApplication) { if (transceiver->GetMediaType() != SdpMediaSection::kApplication) {
// Make sure we have an ssrc. Might already be set. // Make sure we have an ssrc. Might already be set.
@ -126,6 +127,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) {
// (man I hate this) // (man I hate this)
if (mEncodeTrackId) { if (mEncodeTrackId) {
std::string trackId; std::string trackId;
// TODO: Maybe reuse the transceiver's UUID here?
if (!mUuidGen->Generate(&trackId)) { if (!mUuidGen->Generate(&trackId)) {
JSEP_SET_ERROR("Failed to generate UUID for JsepTrack"); JSEP_SET_ERROR("Failed to generate UUID for JsepTrack");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -138,8 +140,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) {
// of asserting. // of asserting.
transceiver->mJsDirection = SdpDirectionAttribute::kSendrecv; transceiver->mJsDirection = SdpDirectionAttribute::kSendrecv;
#ifdef DEBUG #ifdef DEBUG
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
MOZ_ASSERT(transceiver->GetMediaType() != SdpMediaSection::kApplication); MOZ_ASSERT(transceiver->GetMediaType() != SdpMediaSection::kApplication);
} }
#endif #endif
@ -149,7 +150,7 @@ nsresult JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> transceiver) {
transceiver->mRecvTrack.PopulateCodecs(mSupportedCodecs); transceiver->mRecvTrack.PopulateCodecs(mSupportedCodecs);
// We do not set mLevel yet, we do that either on createOffer, or setRemote // We do not set mLevel yet, we do that either on createOffer, or setRemote
mTransceivers[mTransceiverIdCounter++] = transceiver; mTransceivers.push_back(transceiver);
return NS_OK; return NS_OK;
} }
@ -802,8 +803,8 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
if (type == kJsepSdpOffer) { if (type == kJsepSdpOffer) {
// Save in case we need to rollback // Save in case we need to rollback
mOldTransceivers.clear(); mOldTransceivers.clear();
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
mOldTransceivers[id] = new JsepTransceiver(*transceiver); mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
} }
} }
@ -1013,8 +1014,8 @@ JsepSession::Result JsepSessionImpl::SetRemoteDescription(
// Save in case we need to rollback. // Save in case we need to rollback.
if (type == kJsepSdpOffer) { if (type == kJsepSdpOffer) {
mOldTransceivers.clear(); mOldTransceivers.clear();
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
mOldTransceivers[id] = new JsepTransceiver(*transceiver); mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
if (!transceiver->IsNegotiated()) { if (!transceiver->IsNegotiated()) {
// We chose a level for this transceiver, but never negotiated it. // We chose a level for this transceiver, but never negotiated it.
// Discard this state. // Discard this state.
@ -1110,8 +1111,7 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(
CopyBundleTransports(); CopyBundleTransports();
std::vector<JsepTrack*> remoteTracks; std::vector<JsepTrack*> remoteTracks;
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
remoteTracks.push_back(&transceiver->mRecvTrack); remoteTracks.push_back(&transceiver->mRecvTrack);
} }
JsepTrack::SetUniquePayloadTypes(remoteTracks); JsepTrack::SetUniquePayloadTypes(remoteTracks);
@ -1215,8 +1215,7 @@ void JsepSessionImpl::EnsureHasOwnTransport(const SdpMediaSection& msection,
} }
void JsepSessionImpl::CopyBundleTransports() { void JsepSessionImpl::CopyBundleTransports() {
for (auto& [id, transceiver] : mTransceivers) { for (auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasBundleLevel()) { if (transceiver->HasBundleLevel()) {
MOZ_MTLOG(ML_DEBUG, MOZ_MTLOG(ML_DEBUG,
"[" << mName << "] Transceiver " << transceiver->GetLevel() "[" << mName << "] Transceiver " << transceiver->GetLevel()
@ -1497,8 +1496,7 @@ nsresult JsepSessionImpl::SetRemoteDescriptionAnswer(JsepSdpType type,
} }
JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) const { JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) const {
for (auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasLevel() && (transceiver->GetLevel() == level)) { if (transceiver->HasLevel() && (transceiver->GetLevel() == level)) {
return transceiver.get(); return transceiver.get();
} }
@ -1509,8 +1507,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) const {
JsepTransceiver* JsepSessionImpl::GetTransceiverForMid( JsepTransceiver* JsepSessionImpl::GetTransceiverForMid(
const std::string& mid) const { const std::string& mid) const {
for (auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->IsAssociated() && (transceiver->GetMid() == mid)) { if (transceiver->IsAssociated() && (transceiver->GetMid() == mid)) {
return transceiver.get(); return transceiver.get();
} }
@ -1540,8 +1537,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) {
// There is no transceiver for |level| right now. // There is no transceiver for |level| right now.
// Look for an RTP transceiver // Look for an RTP transceiver
for (auto& [id, transceiver] : mTransceivers) { for (auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->GetMediaType() != SdpMediaSection::kApplication && if (transceiver->GetMediaType() != SdpMediaSection::kApplication &&
!transceiver->IsStopped() && !transceiver->HasLevel()) { !transceiver->IsStopped() && !transceiver->HasLevel()) {
transceiver->SetLevel(level); transceiver->SetLevel(level);
@ -1550,8 +1546,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) {
} }
// Ok, look for a datachannel // Ok, look for a datachannel
for (auto& [id, transceiver] : mTransceivers) { for (auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (!transceiver->IsStopped() && !transceiver->HasLevel()) { if (!transceiver->IsStopped() && !transceiver->HasLevel()) {
transceiver->SetLevel(level); transceiver->SetLevel(level);
return transceiver.get(); return transceiver.get();
@ -1583,7 +1578,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForRemote(
// Make a new transceiver // Make a new transceiver
RefPtr<JsepTransceiver> newTransceiver(new JsepTransceiver( RefPtr<JsepTransceiver> newTransceiver(new JsepTransceiver(
msection.GetMediaType(), SdpDirectionAttribute::kRecvonly)); msection.GetMediaType(), *mUuidGen, SdpDirectionAttribute::kRecvonly));
newTransceiver->SetLevel(level); newTransceiver->SetLevel(level);
newTransceiver->SetCreatedBySetRemote(); newTransceiver->SetCreatedBySetRemote();
nsresult rv = AddTransceiver(newTransceiver); nsresult rv = AddTransceiver(newTransceiver);
@ -1593,8 +1588,7 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForRemote(
JsepTransceiver* JsepSessionImpl::GetTransceiverWithTransport( JsepTransceiver* JsepSessionImpl::GetTransceiverWithTransport(
const std::string& transportId) const { const std::string& transportId) const {
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasOwnTransport() && if (transceiver->HasOwnTransport() &&
(transceiver->mTransport.mTransportId == transportId)) { (transceiver->mTransport.mTransportId == transportId)) {
MOZ_ASSERT(transceiver->HasLevel(), MOZ_ASSERT(transceiver->HasLevel(),
@ -1657,8 +1651,7 @@ nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription(
JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver( JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver(
SdpMediaSection::MediaType type, bool magic) { SdpMediaSection::MediaType type, bool magic) {
// Look through transceivers that are not mapped to an m-section // Look through transceivers that are not mapped to an m-section
for (auto& [id, transceiver] : mTransceivers) { for (auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (type == SdpMediaSection::kApplication && if (type == SdpMediaSection::kApplication &&
type == transceiver->GetMediaType()) { type == transceiver->GetMediaType()) {
transceiver->RestartDatachannelTransceiver(); transceiver->RestartDatachannelTransceiver();
@ -1675,30 +1668,32 @@ JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver(
} }
void JsepSessionImpl::RollbackLocalOffer() { void JsepSessionImpl::RollbackLocalOffer() {
for (auto& [id, transceiver] : mTransceivers) { for (size_t i = 0; i < mTransceivers.size(); ++i) {
if (mOldTransceivers.count(id)) { auto transceiver = mTransceivers[i];
transceiver->Rollback(*mOldTransceivers[id], false); if (mOldTransceivers.size() > i) {
mOldTransceivers[id] = transceiver; transceiver->Rollback(*mOldTransceivers[i], false);
mOldTransceivers[i] = transceiver;
continue; continue;
} }
RefPtr<JsepTransceiver> temp( RefPtr<JsepTransceiver> temp(
new JsepTransceiver(transceiver->GetMediaType())); new JsepTransceiver(transceiver->GetMediaType(), *mUuidGen));
temp->mSendTrack.PopulateCodecs(mSupportedCodecs); temp->mSendTrack.PopulateCodecs(mSupportedCodecs);
temp->mRecvTrack.PopulateCodecs(mSupportedCodecs); temp->mRecvTrack.PopulateCodecs(mSupportedCodecs);
transceiver->Rollback(*temp, false); transceiver->Rollback(*temp, false);
mOldTransceivers[id] = transceiver; mOldTransceivers.push_back(transceiver);
} }
mTransceivers = std::move(mOldTransceivers); mTransceivers = std::move(mOldTransceivers);
} }
void JsepSessionImpl::RollbackRemoteOffer() { void JsepSessionImpl::RollbackRemoteOffer() {
for (auto& [id, transceiver] : mTransceivers) { for (size_t i = 0; i < mTransceivers.size(); ++i) {
if (mOldTransceivers.count(id)) { auto transceiver = mTransceivers[i];
if (mOldTransceivers.size() > i) {
// Some stuff cannot be rolled back. Save this information. // Some stuff cannot be rolled back. Save this information.
transceiver->Rollback(*mOldTransceivers[id], true); transceiver->Rollback(*mOldTransceivers[i], true);
mOldTransceivers[id] = transceiver; mOldTransceivers[i] = transceiver;
continue; continue;
} }
@ -1709,7 +1704,7 @@ void JsepSessionImpl::RollbackRemoteOffer() {
// We rollback even for transceivers we will remove, just to ensure we end // We rollback even for transceivers we will remove, just to ensure we end
// up at the starting state. // up at the starting state.
RefPtr<JsepTransceiver> temp( RefPtr<JsepTransceiver> temp(
new JsepTransceiver(transceiver->GetMediaType())); new JsepTransceiver(transceiver->GetMediaType(), *mUuidGen));
temp->mSendTrack.PopulateCodecs(mSupportedCodecs); temp->mSendTrack.PopulateCodecs(mSupportedCodecs);
temp->mRecvTrack.PopulateCodecs(mSupportedCodecs); temp->mRecvTrack.PopulateCodecs(mSupportedCodecs);
transceiver->Rollback(*temp, true); transceiver->Rollback(*temp, true);
@ -1717,9 +1712,8 @@ void JsepSessionImpl::RollbackRemoteOffer() {
if (shouldRemove) { if (shouldRemove) {
transceiver->Stop(); transceiver->Stop();
transceiver->SetRemoved(); transceiver->SetRemoved();
} else {
mOldTransceivers[id] = transceiver;
} }
mOldTransceivers.push_back(transceiver);
} }
mTransceivers = std::move(mOldTransceivers); mTransceivers = std::move(mOldTransceivers);
@ -2287,8 +2281,7 @@ nsresult JsepSessionImpl::UpdateDefaultCandidate(
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
// We set the default address for bundled m-sections, but not candidate // We set the default address for bundled m-sections, but not candidate
// attributes. Ugh. // attributes. Ugh.
if (transceiver->mTransport.mTransportId == transportId) { if (transceiver->mTransport.mTransportId == transportId) {
@ -2402,8 +2395,7 @@ JsepSessionImpl::GetLastSdpParsingErrors() const {
bool JsepSessionImpl::CheckNegotiationNeeded() const { bool JsepSessionImpl::CheckNegotiationNeeded() const {
MOZ_ASSERT(mState == kJsepStateStable); MOZ_ASSERT(mState == kJsepStateStable);
for (const auto& [id, transceiver] : mTransceivers) { for (const auto& transceiver : mTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->IsStopped()) { if (transceiver->IsStopped()) {
if (transceiver->IsAssociated()) { if (transceiver->IsAssociated()) {
MOZ_MTLOG(ML_DEBUG, "[" << mName MOZ_MTLOG(ML_DEBUG, "[" << mName

Просмотреть файл

@ -20,12 +20,6 @@
namespace mozilla { namespace mozilla {
class JsepUuidGenerator {
public:
virtual ~JsepUuidGenerator() {}
virtual bool Generate(std::string* id) = 0;
};
class JsepSessionImpl : public JsepSession { class JsepSessionImpl : public JsepSession {
public: public:
JsepSessionImpl(const std::string& name, UniquePtr<JsepUuidGenerator> uuidgen) JsepSessionImpl(const std::string& name, UniquePtr<JsepUuidGenerator> uuidgen)
@ -138,13 +132,12 @@ class JsepSessionImpl : public JsepSession {
virtual std::set<std::pair<std::string, std::string>> GetLocalIceCredentials() virtual std::set<std::pair<std::string, std::string>> GetLocalIceCredentials()
const override; const override;
virtual const std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers() virtual const std::vector<RefPtr<JsepTransceiver>>& GetTransceivers()
const override { const override {
return mTransceivers; return mTransceivers;
} }
virtual std::map<size_t, RefPtr<JsepTransceiver>>& GetTransceivers() virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() override {
override {
return mTransceivers; return mTransceivers;
} }
@ -237,11 +230,10 @@ class JsepSessionImpl : public JsepSession {
void SetIceRestarting(bool restarting); void SetIceRestarting(bool restarting);
// !!!NOT INDEXED BY LEVEL!!! The level mapping is done with // !!!NOT INDEXED BY LEVEL!!! The level mapping is done with
// JsepTransceiver::mLevel. The keys are opaque, stable identifiers that are // JsepTransceiver::mLevel. The keys are UUIDs.
// unique within the JsepSession. std::vector<RefPtr<JsepTransceiver>> mTransceivers;
std::map<size_t, RefPtr<JsepTransceiver>> mTransceivers;
// So we can rollback. Not as simple as just going back to the old, though... // So we can rollback. Not as simple as just going back to the old, though...
std::map<size_t, RefPtr<JsepTransceiver>> mOldTransceivers; std::vector<RefPtr<JsepTransceiver>> mOldTransceivers;
Maybe<bool> mIsPendingOfferer; Maybe<bool> mIsPendingOfferer;
Maybe<bool> mIsCurrentOfferer; Maybe<bool> mIsCurrentOfferer;

Просмотреть файл

@ -19,12 +19,20 @@
namespace mozilla { namespace mozilla {
class JsepUuidGenerator {
public:
virtual ~JsepUuidGenerator() = default;
virtual bool Generate(std::string* id) = 0;
virtual JsepUuidGenerator* Clone() const = 0;
};
class JsepTransceiver { class JsepTransceiver {
private: private:
~JsepTransceiver(){}; ~JsepTransceiver(){};
public: public:
explicit JsepTransceiver(SdpMediaSection::MediaType type, explicit JsepTransceiver(SdpMediaSection::MediaType type,
JsepUuidGenerator& aUuidGen,
SdpDirectionAttribute::Direction jsDirection = SdpDirectionAttribute::Direction jsDirection =
SdpDirectionAttribute::kSendrecv) SdpDirectionAttribute::kSendrecv)
: mJsDirection(jsDirection), : mJsDirection(jsDirection),
@ -37,7 +45,11 @@ class JsepTransceiver {
mStopped(false), mStopped(false),
mRemoved(false), mRemoved(false),
mNegotiated(false), mNegotiated(false),
mCanRecycle(false) {} mCanRecycle(false) {
if (!aUuidGen.Generate(&mUuid)) {
MOZ_CRASH();
}
}
// Can't use default copy c'tor because of the refcount members. Ugh. // Can't use default copy c'tor because of the refcount members. Ugh.
JsepTransceiver(const JsepTransceiver& orig) JsepTransceiver(const JsepTransceiver& orig)
@ -45,6 +57,7 @@ class JsepTransceiver {
mSendTrack(orig.mSendTrack), mSendTrack(orig.mSendTrack),
mRecvTrack(orig.mRecvTrack), mRecvTrack(orig.mRecvTrack),
mTransport(orig.mTransport), mTransport(orig.mTransport),
mUuid(orig.mUuid),
mMid(orig.mMid), mMid(orig.mMid),
mLevel(orig.mLevel), mLevel(orig.mLevel),
mBundleLevel(orig.mBundleLevel), mBundleLevel(orig.mBundleLevel),
@ -164,6 +177,8 @@ class JsepTransceiver {
bool CanRecycle() const { return mCanRecycle; } bool CanRecycle() const { return mCanRecycle; }
const std::string& GetUuid() const { return mUuid; }
// Convenience function // Convenience function
SdpMediaSection::MediaType GetMediaType() const { SdpMediaSection::MediaType GetMediaType() const {
MOZ_ASSERT(mRecvTrack.GetMediaType() == mSendTrack.GetMediaType()); MOZ_ASSERT(mRecvTrack.GetMediaType() == mSendTrack.GetMediaType());
@ -192,6 +207,7 @@ class JsepTransceiver {
JsepTransport mTransport; JsepTransport mTransport;
private: private:
std::string mUuid;
// Stuff that is not negotiated // Stuff that is not negotiated
std::string mMid; std::string mMid;
size_t mLevel; // SIZE_MAX if no level size_t mLevel; // SIZE_MAX if no level

Просмотреть файл

@ -46,6 +46,10 @@ class FakeUuidGenerator : public mozilla::JsepUuidGenerator {
return true; return true;
} }
mozilla::JsepUuidGenerator* Clone() const {
return new FakeUuidGenerator(*this);
}
private: private:
static uint64_t ctr; static uint64_t ctr;
}; };
@ -100,13 +104,12 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
void CheckTransceiverInvariants( void CheckTransceiverInvariants(
const std::map<size_t, RefPtr<JsepTransceiver>>& oldTransceivers, const std::vector<RefPtr<JsepTransceiver>>& oldTransceivers,
const std::map<size_t, RefPtr<JsepTransceiver>>& newTransceivers) { const std::vector<RefPtr<JsepTransceiver>>& newTransceivers) {
ASSERT_LE(oldTransceivers.size(), newTransceivers.size()); ASSERT_LE(oldTransceivers.size(), newTransceivers.size());
std::set<size_t> levels; std::set<size_t> levels;
for (const auto& [id, newTransceiver] : newTransceivers) { for (const auto& newTransceiver : newTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (newTransceiver->HasLevel()) { if (newTransceiver->HasLevel()) {
ASSERT_FALSE(levels.count(newTransceiver->GetLevel())) ASSERT_FALSE(levels.count(newTransceiver->GetLevel()))
<< "Two new transceivers are mapped to level " << "Two new transceivers are mapped to level "
@ -124,8 +127,7 @@ class JsepSessionTest : public JsepSessionTestBase,
"transceivers."; "transceivers.";
} }
for (const auto& [id, oldTransceiver] : oldTransceivers) { for (const auto& oldTransceiver : oldTransceivers) {
(void)id; // Lame, but no better way to do this right now.
if (oldTransceiver->HasLevel()) { if (oldTransceiver->HasLevel()) {
ASSERT_TRUE(levels.count(oldTransceiver->GetLevel())) ASSERT_TRUE(levels.count(oldTransceiver->GetLevel()))
<< "Level " << oldTransceiver->GetLevel() << "Level " << oldTransceiver->GetLevel()
@ -137,17 +139,18 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
} }
std::map<size_t, RefPtr<JsepTransceiver>> DeepCopy( std::vector<RefPtr<JsepTransceiver>> DeepCopy(
const std::map<size_t, RefPtr<JsepTransceiver>>& transceivers) { const std::vector<RefPtr<JsepTransceiver>>& transceivers) {
std::map<size_t, RefPtr<JsepTransceiver>> copy; std::vector<RefPtr<JsepTransceiver>> copy;
for (const auto& [id, transceiver] : transceivers) { copy.reserve(transceivers.size());
copy[id] = new JsepTransceiver(*transceiver); for (const auto& transceiver : transceivers) {
copy.push_back(new JsepTransceiver(*transceiver));
} }
return copy; return copy;
} }
std::string CreateOffer(const Maybe<JsepOfferOptions>& options = Nothing()) { std::string CreateOffer(const Maybe<JsepOfferOptions>& options = Nothing()) {
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore = std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
JsepOfferOptions defaultOptions; JsepOfferOptions defaultOptions;
const JsepOfferOptions& optionsRef = options ? *options : defaultOptions; const JsepOfferOptions& optionsRef = options ? *options : defaultOptions;
@ -267,11 +270,10 @@ class JsepSessionTest : public JsepSessionTestBase,
void AddTracks(JsepSessionImpl& side, void AddTracks(JsepSessionImpl& side,
const std::vector<SdpMediaSection::MediaType>& mediatypes, const std::vector<SdpMediaSection::MediaType>& mediatypes,
AddTrackMagic magic = ADDTRACK_MAGIC) { AddTrackMagic magic = ADDTRACK_MAGIC) {
FakeUuidGenerator uuid_gen;
std::string stream_id; std::string stream_id;
std::string track_id; std::string track_id;
ASSERT_TRUE(uuid_gen.Generate(&stream_id)); ASSERT_TRUE(mUuidGen.Generate(&stream_id));
AddTracksToStream(side, stream_id, mediatypes, magic); AddTracksToStream(side, stream_id, mediatypes, magic);
} }
@ -296,16 +298,16 @@ class JsepSessionTest : public JsepSessionTestBase,
AddTrackMagic magic = ADDTRACK_MAGIC) AddTrackMagic magic = ADDTRACK_MAGIC)
{ {
FakeUuidGenerator uuid_gen;
std::string track_id; std::string track_id;
for (auto type : mediatypes) { for (auto type : mediatypes) {
ASSERT_TRUE(uuid_gen.Generate(&track_id)); ASSERT_TRUE(mUuidGen.Generate(&track_id));
RefPtr<JsepTransceiver> suitableTransceiver; RefPtr<JsepTransceiver> suitableTransceiver;
size_t i; size_t i;
if (magic == ADDTRACK_MAGIC) { if (magic == ADDTRACK_MAGIC) {
for (auto& [id, transceiver] : side.GetTransceivers()) { for (i = 0; i < side.GetTransceivers().size(); ++i) {
auto transceiver = side.GetTransceivers()[i];
if (transceiver->mSendTrack.GetMediaType() != type) { if (transceiver->mSendTrack.GetMediaType() != type) {
continue; continue;
} }
@ -313,16 +315,15 @@ class JsepSessionTest : public JsepSessionTestBase,
if (IsNull(transceiver->mSendTrack) || if (IsNull(transceiver->mSendTrack) ||
transceiver->GetMediaType() == SdpMediaSection::kApplication) { transceiver->GetMediaType() == SdpMediaSection::kApplication) {
suitableTransceiver = transceiver; suitableTransceiver = transceiver;
i = id;
break; break;
} }
} }
} }
if (!suitableTransceiver) { if (!suitableTransceiver) {
suitableTransceiver = new JsepTransceiver(type); i = side.GetTransceivers().size();
suitableTransceiver = new JsepTransceiver(type, mUuidGen);
side.AddTransceiver(suitableTransceiver); side.AddTransceiver(suitableTransceiver);
i = side.GetTransceivers().rbegin()->first;
} }
std::cerr << "Updating send track for transceiver " << i << std::endl; std::cerr << "Updating send track for transceiver " << i << std::endl;
@ -352,8 +353,7 @@ class JsepSessionTest : public JsepSessionTestBase,
std::vector<JsepTrack> GetLocalTracks(const JsepSession& session) const { std::vector<JsepTrack> GetLocalTracks(const JsepSession& session) const {
std::vector<JsepTrack> result; std::vector<JsepTrack> result;
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!IsNull(transceiver->mSendTrack)) { if (!IsNull(transceiver->mSendTrack)) {
result.push_back(transceiver->mSendTrack); result.push_back(transceiver->mSendTrack);
} }
@ -363,8 +363,7 @@ class JsepSessionTest : public JsepSessionTestBase,
std::vector<JsepTrack> GetRemoteTracks(const JsepSession& session) const { std::vector<JsepTrack> GetRemoteTracks(const JsepSession& session) const {
std::vector<JsepTrack> result; std::vector<JsepTrack> result;
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!IsNull(transceiver->mRecvTrack)) { if (!IsNull(transceiver->mRecvTrack)) {
result.push_back(transceiver->mRecvTrack); result.push_back(transceiver->mRecvTrack);
} }
@ -373,8 +372,7 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
JsepTransceiver* GetDatachannelTransceiver(JsepSession& side) { JsepTransceiver* GetDatachannelTransceiver(JsepSession& side) {
for (const auto& [id, transceiver] : side.GetTransceivers()) { for (const auto& transceiver : side.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->mSendTrack.GetMediaType() == if (transceiver->mSendTrack.GetMediaType() ==
SdpMediaSection::MediaType::kApplication) { SdpMediaSection::MediaType::kApplication) {
return transceiver.get(); return transceiver.get();
@ -385,8 +383,7 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
JsepTransceiver* GetNegotiatedTransceiver(JsepSession& side, size_t index) { JsepTransceiver* GetNegotiatedTransceiver(JsepSession& side, size_t index) {
for (const auto& [id, transceiver] : side.GetTransceivers()) { for (const auto& transceiver : side.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->mSendTrack.GetNegotiatedDetails() || if (transceiver->mSendTrack.GetNegotiatedDetails() ||
transceiver->mRecvTrack.GetNegotiatedDetails()) { transceiver->mRecvTrack.GetNegotiatedDetails()) {
if (index) { if (index) {
@ -402,10 +399,8 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
JsepTransceiver* GetTransceiverByLevel( JsepTransceiver* GetTransceiverByLevel(
const std::map<size_t, RefPtr<JsepTransceiver>>& transceivers, const std::vector<RefPtr<JsepTransceiver>>& transceivers, size_t level) {
size_t level) { for (const auto& transceiver : transceivers) {
for (const auto& [id, transceiver] : transceivers) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasLevel() && transceiver->GetLevel() == level) { if (transceiver->HasLevel() && transceiver->GetLevel() == level) {
return transceiver.get(); return transceiver.get();
} }
@ -461,8 +456,7 @@ class JsepSessionTest : public JsepSessionTestBase,
JsepTrack GetTrack(JsepSessionImpl& side, SdpMediaSection::MediaType type, JsepTrack GetTrack(JsepSessionImpl& side, SdpMediaSection::MediaType type,
size_t index) const { size_t index) const {
for (const auto& [id, transceiver] : side.GetTransceivers()) { for (const auto& transceiver : side.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (IsNull(transceiver->mSendTrack) || if (IsNull(transceiver->mSendTrack) ||
transceiver->mSendTrack.GetMediaType() != type) { transceiver->mSendTrack.GetMediaType() != type) {
continue; continue;
@ -655,19 +649,16 @@ class JsepSessionTest : public JsepSessionTestBase,
return true; return true;
} }
bool Equals(const std::map<size_t, RefPtr<JsepTransceiver>>& t1, bool Equals(const std::vector<RefPtr<JsepTransceiver>>& t1,
const std::map<size_t, RefPtr<JsepTransceiver>>& t2) const { const std::vector<RefPtr<JsepTransceiver>>& t2) const {
if (t1.size() != t2.size()) { if (t1.size() != t2.size()) {
std::cerr << "Size differs: t1.size = " << t1.size() std::cerr << "Size differs: t1.size = " << t1.size()
<< ", t2.size = " << t2.size() << std::endl; << ", t2.size = " << t2.size() << std::endl;
return false; return false;
} }
for (const auto& [id, transceiver] : t1) { for (size_t i = 0; i < t1.size(); ++i) {
if (!t2.count(id)) { if (!Equals(*t1[i], *t2[i])) {
return false;
}
if (!Equals(*transceiver, *t2.at(id))) {
return false; return false;
} }
} }
@ -743,7 +734,7 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
std::string CreateAnswer() { std::string CreateAnswer() {
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore = std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
JsepAnswerOptions options; JsepAnswerOptions options;
@ -779,7 +770,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetLocalOffer(const std::string& offer, void SetLocalOffer(const std::string& offer,
uint32_t checkFlags = ALL_CHECKS) { uint32_t checkFlags = ALL_CHECKS) {
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore = std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
JsepSession::Result result = JsepSession::Result result =
@ -795,8 +786,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) { if (checkFlags & CHECK_TRACKS) {
// This assumes no recvonly or inactive transceivers. // This assumes no recvonly or inactive transceivers.
ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size()); ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size());
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { for (const auto& transceiver : mSessionOff->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!transceiver->HasLevel()) { if (!transceiver->HasLevel()) {
continue; continue;
} }
@ -820,7 +810,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetRemoteOffer(const std::string& offer, void SetRemoteOffer(const std::string& offer,
uint32_t checkFlags = ALL_CHECKS) { uint32_t checkFlags = ALL_CHECKS) {
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore = std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
JsepSession::Result result = JsepSession::Result result =
@ -836,8 +826,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) { if (checkFlags & CHECK_TRACKS) {
// This assumes no recvonly or inactive transceivers. // This assumes no recvonly or inactive transceivers.
ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size()); ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size());
for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) { for (const auto& transceiver : mSessionAns->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!transceiver->HasLevel()) { if (!transceiver->HasLevel()) {
continue; continue;
} }
@ -858,7 +847,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetLocalAnswer(const std::string& answer, void SetLocalAnswer(const std::string& answer,
uint32_t checkFlags = ALL_CHECKS) { uint32_t checkFlags = ALL_CHECKS) {
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore = std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
JsepSession::Result result = JsepSession::Result result =
@ -873,8 +862,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) { if (checkFlags & CHECK_TRACKS) {
// Verify that the right stuff is in the tracks. // Verify that the right stuff is in the tracks.
ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size()); ASSERT_EQ(types.size(), mSessionAns->GetTransceivers().size());
for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) { for (const auto& transceiver : mSessionAns->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!transceiver->HasLevel()) { if (!transceiver->HasLevel()) {
continue; continue;
} }
@ -906,7 +894,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void SetRemoteAnswer(const std::string& answer, void SetRemoteAnswer(const std::string& answer,
uint32_t checkFlags = ALL_CHECKS) { uint32_t checkFlags = ALL_CHECKS) {
std::map<size_t, RefPtr<JsepTransceiver>> transceiversBefore = std::vector<RefPtr<JsepTransceiver>> transceiversBefore =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
JsepSession::Result result = JsepSession::Result result =
@ -921,8 +909,7 @@ class JsepSessionTest : public JsepSessionTestBase,
if (checkFlags & CHECK_TRACKS) { if (checkFlags & CHECK_TRACKS) {
// Verify that the right stuff is in the tracks. // Verify that the right stuff is in the tracks.
ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size()); ASSERT_EQ(types.size(), mSessionOff->GetTransceivers().size());
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { for (const auto& transceiver : mSessionOff->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!transceiver->HasLevel()) { if (!transceiver->HasLevel()) {
continue; continue;
} }
@ -950,8 +937,7 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
std::string GetTransportId(const JsepSession& session, size_t level) { std::string GetTransportId(const JsepSession& session, size_t level) {
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasLevel() && transceiver->GetLevel() == level) { if (transceiver->HasLevel() && transceiver->GetLevel() == level) {
return transceiver->mTransport.mTransportId; return transceiver->mTransport.mTransportId;
} }
@ -966,8 +952,7 @@ class JsepSessionTest : public JsepSessionTestBase,
CandidateSet() {} CandidateSet() {}
void Gather(JsepSession& session, ComponentType maxComponent = RTCP) { void Gather(JsepSession& session, ComponentType maxComponent = RTCP) {
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->HasOwnTransport()) { if (transceiver->HasOwnTransport()) {
Gather(session, transceiver->mTransport.mTransportId, RTP); Gather(session, transceiver->mTransport.mTransportId, RTP);
if (transceiver->mTransport.mComponents > 1) { if (transceiver->mTransport.mComponents > 1) {
@ -1199,8 +1184,7 @@ class JsepSessionTest : public JsepSessionTestBase,
void CheckTransceiversAreBundled(const JsepSession& session, void CheckTransceiversAreBundled(const JsepSession& session,
const std::string& context) { const std::string& context) {
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
ASSERT_TRUE(transceiver->HasBundleLevel()) ASSERT_TRUE(transceiver->HasBundleLevel())
<< context; << context;
ASSERT_EQ(0U, transceiver->BundleLevel()) << context; ASSERT_EQ(0U, transceiver->BundleLevel()) << context;
@ -1357,8 +1341,7 @@ class JsepSessionTest : public JsepSessionTestBase,
} }
void DumpTransceivers(const JsepSessionImpl& session) { void DumpTransceivers(const JsepSessionImpl& session) {
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
std::cerr << "Transceiver "; std::cerr << "Transceiver ";
if (transceiver->HasLevel()) { if (transceiver->HasLevel()) {
std::cerr << transceiver->GetLevel() << std::endl; std::cerr << transceiver->GetLevel() << std::endl;
@ -1405,6 +1388,8 @@ class JsepSessionTest : public JsepSessionTestBase,
std::vector<SdpMediaSection::MediaType> types; std::vector<SdpMediaSection::MediaType> types;
std::vector<std::pair<std::string, uint16_t>> mGatheredCandidates; std::vector<std::pair<std::string, uint16_t>> mGatheredCandidates;
FakeUuidGenerator mUuidGen;
private: private:
void ValidateTransport(TransportData& source, const std::string& sdp_str, void ValidateTransport(TransportData& source, const std::string& sdp_str,
sdp::SdpType type) { sdp::SdpType type) {
@ -1596,9 +1581,9 @@ TEST_P(JsepSessionTest, RenegotiationNoChange) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
std::string reoffer = CreateOffer(); std::string reoffer = CreateOffer();
@ -1657,8 +1642,8 @@ TEST_P(JsepSessionTest, DISABLED_RenegotiationSwappedRolesNoChange) {
ASSERT_TRUE(Equals(answererTransceivers, newOffererTransceivers)); ASSERT_TRUE(Equals(answererTransceivers, newOffererTransceivers));
} }
static void RemoveLastN( static void RemoveLastN(std::vector<RefPtr<JsepTransceiver>>& aTransceivers,
std::map<size_t, RefPtr<JsepTransceiver>>& aTransceivers, size_t aNum) { size_t aNum) {
while (aNum--) { while (aNum--) {
// erase doesn't take reverse_iterator :( // erase doesn't take reverse_iterator :(
aTransceivers.erase(--aTransceivers.end()); aTransceivers.erase(--aTransceivers.end());
@ -1674,9 +1659,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererAddsTrack) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes; std::vector<SdpMediaSection::MediaType> extraTypes;
@ -1711,9 +1696,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererAddsTrack) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes; std::vector<SdpMediaSection::MediaType> extraTypes;
@ -1723,10 +1708,12 @@ TEST_P(JsepSessionTest, RenegotiationAnswererAddsTrack) {
types.insert(types.end(), extraTypes.begin(), extraTypes.end()); types.insert(types.end(), extraTypes.begin(), extraTypes.end());
// We need to add a recvonly m-section to the offer for this to work // We need to add a recvonly m-section to the offer for this to work
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(
SdpMediaSection::kAudio, SdpDirectionAttribute::Direction::kRecvonly)); new JsepTransceiver(SdpMediaSection::kAudio, mUuidGen,
mSessionOff->AddTransceiver(new JsepTransceiver( SdpDirectionAttribute::Direction::kRecvonly));
SdpMediaSection::kVideo, SdpDirectionAttribute::Direction::kRecvonly)); mSessionOff->AddTransceiver(
new JsepTransceiver(SdpMediaSection::kVideo, mUuidGen,
SdpDirectionAttribute::Direction::kRecvonly));
std::string offer = CreateOffer(); std::string offer = CreateOffer();
SetLocalOffer(offer, CHECK_SUCCESS); SetLocalOffer(offer, CHECK_SUCCESS);
@ -1760,9 +1747,9 @@ TEST_P(JsepSessionTest, RenegotiationBothAddTrack) {
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass); ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive); ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes; std::vector<SdpMediaSection::MediaType> extraTypes;
@ -1923,12 +1910,12 @@ TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver) {
OfferAnswer(); OfferAnswer();
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
auto lastTransceiver = mSessionOff->GetTransceivers().rbegin()->second; auto lastTransceiver = mSessionOff->GetTransceivers().back();
// Avoid bundle transport side effects; don't stop the BUNDLE-tag! // Avoid bundle transport side effects; don't stop the BUNDLE-tag!
lastTransceiver->Stop(); lastTransceiver->Stop();
JsepTrack removedTrack(lastTransceiver->mSendTrack); JsepTrack removedTrack(lastTransceiver->mSendTrack);
@ -1953,11 +1940,11 @@ TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver) {
ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size()); ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size());
ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped()); ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped()); ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped()); ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped()); ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped());
RemoveLastN(origOffererTransceivers, 1); // Ignore this one RemoveLastN(origOffererTransceivers, 1); // Ignore this one
RemoveLastN(newOffererTransceivers, 1); // Ignore this one RemoveLastN(newOffererTransceivers, 1); // Ignore this one
RemoveLastN(origAnswererTransceivers, 1); // Ignore this one RemoveLastN(origAnswererTransceivers, 1); // Ignore this one
@ -1976,15 +1963,14 @@ TEST_P(JsepSessionTest, RenegotiationAnswererStopsTransceiver) {
OfferAnswer(); OfferAnswer();
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
// Avoid bundle transport side effects; don't stop the BUNDLE-tag! // Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionAns->GetTransceivers().rbegin()->second->Stop(); mSessionAns->GetTransceivers().back()->Stop();
JsepTrack removedTrack( JsepTrack removedTrack(mSessionAns->GetTransceivers().back()->mSendTrack);
mSessionAns->GetTransceivers().rbegin()->second->mSendTrack);
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -2007,10 +1993,10 @@ TEST_P(JsepSessionTest, RenegotiationAnswererStopsTransceiver) {
ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size()); ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size());
ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped()); ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped()); ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped()); ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped()); ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped());
RemoveLastN(origOffererTransceivers, 1); // Ignore this one RemoveLastN(origOffererTransceivers, 1); // Ignore this one
RemoveLastN(newOffererTransceivers, 1); // Ignore this one RemoveLastN(newOffererTransceivers, 1); // Ignore this one
RemoveLastN(origAnswererTransceivers, 1); // Ignore this one RemoveLastN(origAnswererTransceivers, 1); // Ignore this one
@ -2029,18 +2015,18 @@ TEST_P(JsepSessionTest, RenegotiationBothStopSameTransceiver) {
OfferAnswer(); OfferAnswer();
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
// Avoid bundle transport side effects; don't stop the BUNDLE-tag! // Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().rbegin()->second->Stop(); mSessionOff->GetTransceivers().back()->Stop();
JsepTrack removedTrackOffer( JsepTrack removedTrackOffer(
mSessionOff->GetTransceivers().rbegin()->second->mSendTrack); mSessionOff->GetTransceivers().back()->mSendTrack);
mSessionAns->GetTransceivers().rbegin()->second->Stop(); mSessionAns->GetTransceivers().back()->Stop();
JsepTrack removedTrackAnswer( JsepTrack removedTrackAnswer(
mSessionAns->GetTransceivers().rbegin()->second->mSendTrack); mSessionAns->GetTransceivers().back()->mSendTrack);
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -2062,10 +2048,10 @@ TEST_P(JsepSessionTest, RenegotiationBothStopSameTransceiver) {
ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size()); ASSERT_EQ(origOffererTransceivers.size(), newOffererTransceivers.size());
ASSERT_FALSE(origOffererTransceivers.rbegin()->second->IsStopped()); ASSERT_FALSE(origOffererTransceivers.back()->IsStopped());
ASSERT_TRUE(newOffererTransceivers.rbegin()->second->IsStopped()); ASSERT_TRUE(newOffererTransceivers.back()->IsStopped());
ASSERT_FALSE(origAnswererTransceivers.rbegin()->second->IsStopped()); ASSERT_FALSE(origAnswererTransceivers.back()->IsStopped());
ASSERT_TRUE(newAnswererTransceivers.rbegin()->second->IsStopped()); ASSERT_TRUE(newAnswererTransceivers.back()->IsStopped());
RemoveLastN(origOffererTransceivers, 1); // Ignore this one RemoveLastN(origOffererTransceivers, 1); // Ignore this one
RemoveLastN(newOffererTransceivers, 1); // Ignore this one RemoveLastN(newOffererTransceivers, 1); // Ignore this one
RemoveLastN(origAnswererTransceivers, 1); // Ignore this one RemoveLastN(origAnswererTransceivers, 1); // Ignore this one
@ -2087,18 +2073,18 @@ TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverThenAddTrack) {
OfferAnswer(); OfferAnswer();
// Avoid bundle transport side effects; don't stop the BUNDLE-tag! // Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().rbegin()->second->Stop(); mSessionOff->GetTransceivers().back()->Stop();
JsepTrack removedTrackOffer( JsepTrack removedTrackOffer(
mSessionOff->GetTransceivers().rbegin()->second->mSendTrack); mSessionOff->GetTransceivers().back()->mSendTrack);
mSessionOff->GetTransceivers().rbegin()->second->Stop(); mSessionOff->GetTransceivers().back()->Stop();
JsepTrack removedTrackAnswer( JsepTrack removedTrackAnswer(
mSessionOff->GetTransceivers().rbegin()->second->mSendTrack); mSessionOff->GetTransceivers().back()->mSendTrack);
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
std::vector<SdpMediaSection::MediaType> extraTypes; std::vector<SdpMediaSection::MediaType> extraTypes;
@ -2117,11 +2103,11 @@ TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverThenAddTrack) {
newAnswererTransceivers.size()); newAnswererTransceivers.size());
// Ensure that the m-section was re-used; no gaps // Ensure that the m-section was re-used; no gaps
ASSERT_EQ(origOffererTransceivers.rbegin()->second->GetLevel(), ASSERT_EQ(origOffererTransceivers.back()->GetLevel(),
newOffererTransceivers.rbegin()->second->GetLevel()); newOffererTransceivers.back()->GetLevel());
ASSERT_EQ(origAnswererTransceivers.rbegin()->second->GetLevel(), ASSERT_EQ(origAnswererTransceivers.back()->GetLevel(),
newAnswererTransceivers.rbegin()->second->GetLevel()); newAnswererTransceivers.back()->GetLevel());
} }
TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverDifferentMsection) { TEST_P(JsepSessionTest, RenegotiationBothStopTransceiverDifferentMsection) {
@ -2204,9 +2190,9 @@ TEST_P(JsepSessionTest, RenegotiationAutoAssignedMsidIsStable) {
SetRemoteAnswer(answer, CHECK_SUCCESS); SetRemoteAnswer(answer, CHECK_SUCCESS);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
ASSERT_EQ(origOffererTransceivers.size(), origAnswererTransceivers.size()); ASSERT_EQ(origOffererTransceivers.size(), origAnswererTransceivers.size());
@ -2241,8 +2227,7 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) {
// check all the audio tracks to make sure they have 2 codecs (109 and 101), // check all the audio tracks to make sure they have 2 codecs (109 and 101),
// and dtmf is enabled on all audio tracks // and dtmf is enabled on all audio tracks
std::vector<JsepTrack> tracks; std::vector<JsepTrack> tracks;
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { for (const auto& transceiver : mSessionOff->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
tracks.push_back(transceiver->mSendTrack); tracks.push_back(transceiver->mSendTrack);
tracks.push_back(transceiver->mRecvTrack); tracks.push_back(transceiver->mRecvTrack);
} }
@ -2281,8 +2266,7 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) {
// check all the audio tracks to make sure they have 1 codec (109), // check all the audio tracks to make sure they have 1 codec (109),
// and dtmf is disabled on all audio tracks // and dtmf is disabled on all audio tracks
tracks.clear(); tracks.clear();
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { for (const auto& transceiver : mSessionOff->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
tracks.push_back(transceiver->mSendTrack); tracks.push_back(transceiver->mSendTrack);
tracks.push_back(transceiver->mRecvTrack); tracks.push_back(transceiver->mRecvTrack);
} }
@ -2320,9 +2304,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererEnablesMsid) {
SetRemoteAnswer(answer, CHECK_SUCCESS); SetRemoteAnswer(answer, CHECK_SUCCESS);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
offer = CreateOffer(); offer = CreateOffer();
@ -2366,9 +2350,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererDisablesMsid) {
SetLocalAnswer(answer); SetLocalAnswer(answer);
SetRemoteAnswer(answer, CHECK_SUCCESS); SetRemoteAnswer(answer, CHECK_SUCCESS);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
offer = CreateOffer(); offer = CreateOffer();
@ -2426,9 +2410,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererEnablesBundle) {
SetLocalAnswer(answer); SetLocalAnswer(answer);
SetRemoteAnswer(answer); SetRemoteAnswer(answer);
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
OfferAnswer(); OfferAnswer();
@ -2473,9 +2457,9 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesBundleTransport) {
GetTransceiverByLevel(*mSessionOff, 0)->Stop(); GetTransceiverByLevel(*mSessionOff, 0)->Stop();
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -2524,9 +2508,9 @@ TEST_P(JsepSessionTest, RenegotiationAnswererDisablesBundleTransport) {
OfferAnswer(); OfferAnswer();
std::map<size_t, RefPtr<JsepTransceiver>> origOffererTransceivers = std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers =
DeepCopy(mSessionOff->GetTransceivers()); DeepCopy(mSessionOff->GetTransceivers());
std::map<size_t, RefPtr<JsepTransceiver>> origAnswererTransceivers = std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers =
DeepCopy(mSessionAns->GetTransceivers()); DeepCopy(mSessionAns->GetTransceivers());
GetTransceiverByLevel(*mSessionAns, 0)->Stop(); GetTransceiverByLevel(*mSessionAns, 0)->Stop();
@ -3035,11 +3019,11 @@ INSTANTIATE_TEST_SUITE_P(
TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines) { TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines) {
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kAudio, SdpDirectionAttribute::kRecvonly)); SdpMediaSection::kAudio, mUuidGen, SdpDirectionAttribute::kRecvonly));
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kVideo, SdpDirectionAttribute::kRecvonly)); SdpMediaSection::kVideo, mUuidGen, SdpDirectionAttribute::kRecvonly));
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kVideo, SdpDirectionAttribute::kRecvonly)); SdpMediaSection::kVideo, mUuidGen, SdpDirectionAttribute::kRecvonly));
std::string offer = CreateOffer(); std::string offer = CreateOffer();
UniquePtr<Sdp> parsedOffer(Parse(offer)); UniquePtr<Sdp> parsedOffer(Parse(offer));
@ -3099,11 +3083,10 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines) {
SetLocalAnswer(answer, CHECK_SUCCESS); SetLocalAnswer(answer, CHECK_SUCCESS);
SetRemoteAnswer(answer, CHECK_SUCCESS); SetRemoteAnswer(answer, CHECK_SUCCESS);
std::map<size_t, RefPtr<JsepTransceiver>> transceivers( std::vector<RefPtr<JsepTransceiver>> transceivers(
mSessionOff->GetTransceivers()); mSessionOff->GetTransceivers());
ASSERT_EQ(3U, transceivers.size()); ASSERT_EQ(3U, transceivers.size());
for (const auto& [id, transceiver] : transceivers) { for (const auto& transceiver : transceivers) {
(void)id; // Lame, but no better way to do this right now.
const auto& msection = const auto& msection =
parsedOffer->GetMediaSection(transceiver->GetLevel()); parsedOffer->GetMediaSection(transceiver->GetLevel());
const auto& ssrcs = msection.GetAttributeList().GetSsrc().mSsrcs; const auto& ssrcs = msection.GetAttributeList().GetSsrc().mSsrcs;
@ -3167,7 +3150,7 @@ TEST_F(JsepSessionTest, OfferAnswerSendOnlyLines) {
TEST_F(JsepSessionTest, OfferToReceiveAudioNotUsed) { TEST_F(JsepSessionTest, OfferToReceiveAudioNotUsed) {
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kAudio, SdpDirectionAttribute::kRecvonly)); SdpMediaSection::kAudio, mUuidGen, SdpDirectionAttribute::kRecvonly));
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -3190,7 +3173,7 @@ TEST_F(JsepSessionTest, OfferToReceiveAudioNotUsed) {
TEST_F(JsepSessionTest, OfferToReceiveVideoNotUsed) { TEST_F(JsepSessionTest, OfferToReceiveVideoNotUsed) {
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kVideo, SdpDirectionAttribute::kRecvonly)); SdpMediaSection::kVideo, mUuidGen, SdpDirectionAttribute::kRecvonly));
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -3212,12 +3195,14 @@ TEST_F(JsepSessionTest, OfferToReceiveVideoNotUsed) {
} }
TEST_F(JsepSessionTest, CreateOfferNoDatachannelDefault) { TEST_F(JsepSessionTest, CreateOfferNoDatachannelDefault) {
RefPtr<JsepTransceiver> audio(new JsepTransceiver(SdpMediaSection::kAudio)); RefPtr<JsepTransceiver> audio(
new JsepTransceiver(SdpMediaSection::kAudio, mUuidGen));
audio->mSendTrack.UpdateStreamIds( audio->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, "offerer_stream")); std::vector<std::string>(1, "offerer_stream"));
mSessionOff->AddTransceiver(audio); mSessionOff->AddTransceiver(audio);
RefPtr<JsepTransceiver> video(new JsepTransceiver(SdpMediaSection::kVideo)); RefPtr<JsepTransceiver> video(
new JsepTransceiver(SdpMediaSection::kVideo, mUuidGen));
video->mSendTrack.UpdateStreamIds( video->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, "offerer_stream")); std::vector<std::string>(1, "offerer_stream"));
mSessionOff->AddTransceiver(video); mSessionOff->AddTransceiver(video);
@ -3238,12 +3223,14 @@ TEST_F(JsepSessionTest, ValidateOfferedVideoCodecParams) {
types.push_back(SdpMediaSection::kAudio); types.push_back(SdpMediaSection::kAudio);
types.push_back(SdpMediaSection::kVideo); types.push_back(SdpMediaSection::kVideo);
RefPtr<JsepTransceiver> audio(new JsepTransceiver(SdpMediaSection::kAudio)); RefPtr<JsepTransceiver> audio(
new JsepTransceiver(SdpMediaSection::kAudio, mUuidGen));
audio->mSendTrack.UpdateStreamIds( audio->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, "offerer_stream")); std::vector<std::string>(1, "offerer_stream"));
mSessionOff->AddTransceiver(audio); mSessionOff->AddTransceiver(audio);
RefPtr<JsepTransceiver> video(new JsepTransceiver(SdpMediaSection::kVideo)); RefPtr<JsepTransceiver> video(
new JsepTransceiver(SdpMediaSection::kVideo, mUuidGen));
video->mSendTrack.UpdateStreamIds( video->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, "offerer_stream")); std::vector<std::string>(1, "offerer_stream"));
mSessionOff->AddTransceiver(video); mSessionOff->AddTransceiver(video);
@ -3428,12 +3415,14 @@ TEST_F(JsepSessionTest, ValidateOfferedAudioCodecParams) {
types.push_back(SdpMediaSection::kAudio); types.push_back(SdpMediaSection::kAudio);
types.push_back(SdpMediaSection::kVideo); types.push_back(SdpMediaSection::kVideo);
RefPtr<JsepTransceiver> audio(new JsepTransceiver(SdpMediaSection::kAudio)); RefPtr<JsepTransceiver> audio(
new JsepTransceiver(SdpMediaSection::kAudio, mUuidGen));
audio->mSendTrack.UpdateStreamIds( audio->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, "offerer_stream")); std::vector<std::string>(1, "offerer_stream"));
mSessionOff->AddTransceiver(audio); mSessionOff->AddTransceiver(audio);
RefPtr<JsepTransceiver> video(new JsepTransceiver(SdpMediaSection::kVideo)); RefPtr<JsepTransceiver> video(
new JsepTransceiver(SdpMediaSection::kVideo, mUuidGen));
video->mSendTrack.UpdateStreamIds( video->mSendTrack.UpdateStreamIds(
std::vector<std::string>(1, "offerer_stream")); std::vector<std::string>(1, "offerer_stream"));
mSessionOff->AddTransceiver(video); mSessionOff->AddTransceiver(video);
@ -5106,8 +5095,7 @@ TEST_P(JsepSessionTest, TestRejectOfferRollback) {
ASSERT_FALSE( ASSERT_FALSE(
mSessionAns->SetRemoteDescription(kJsepSdpRollback, "").mError.isSome()); mSessionAns->SetRemoteDescription(kJsepSdpRollback, "").mError.isSome());
ASSERT_EQ(kJsepStateStable, mSessionAns->GetState()); ASSERT_EQ(kJsepStateStable, mSessionAns->GetState());
for (const auto& [id, transceiver] : mSessionAns->GetTransceivers()) { for (const auto& transceiver : mSessionAns->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
ASSERT_EQ(0U, transceiver->mRecvTrack.GetStreamIds().size()); ASSERT_EQ(0U, transceiver->mRecvTrack.GetStreamIds().size());
} }
@ -5160,8 +5148,7 @@ TEST_P(JsepSessionTest, TestInvalidRollback) {
size_t GetActiveTransportCount(const JsepSession& session) { size_t GetActiveTransportCount(const JsepSession& session) {
size_t activeTransportCount = 0; size_t activeTransportCount = 0;
for (const auto& [id, transceiver] : session.GetTransceivers()) { for (const auto& transceiver : session.GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!transceiver->HasBundleLevel() || if (!transceiver->HasBundleLevel() ||
(transceiver->BundleLevel() == transceiver->GetLevel())) { (transceiver->BundleLevel() == transceiver->GetLevel())) {
activeTransportCount += transceiver->mTransport.mComponents; activeTransportCount += transceiver->mTransport.mComponents;
@ -5225,8 +5212,7 @@ TEST_P(JsepSessionTest, TestMaxBundle) {
} }
SetLocalOffer(offer); SetLocalOffer(offer);
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { for (const auto& transceiver : mSessionOff->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (transceiver->GetLevel() == 0) { if (transceiver->GetLevel() == 0) {
// We do not set the bundle-level in have-local-offer unless the // We do not set the bundle-level in have-local-offer unless the
// m-section is bundle-only. // m-section is bundle-only.
@ -6663,7 +6649,7 @@ TEST_F(JsepSessionTest, NoAddTrackMagicReplaceTrack) {
ASSERT_EQ(2U, mSessionAns->GetTransceivers().size()); ASSERT_EQ(2U, mSessionAns->GetTransceivers().size());
AddTracks(*mSessionOff, "audio"); AddTracks(*mSessionOff, "audio");
mSessionAns->AddTransceiver( mSessionAns->AddTransceiver(
new JsepTransceiver(SdpMediaSection::MediaType::kAudio)); new JsepTransceiver(SdpMediaSection::MediaType::kAudio, mUuidGen));
mSessionAns->GetTransceivers()[2]->mSendTrack.UpdateStreamIds({"newstream"}); mSessionAns->GetTransceivers()[2]->mSendTrack.UpdateStreamIds({"newstream"});
@ -6710,7 +6696,7 @@ TEST_F(JsepSessionTest, AddTrackMakesTransceiverMagical) {
ASSERT_EQ(2U, mSessionAns->GetTransceivers().size()); ASSERT_EQ(2U, mSessionAns->GetTransceivers().size());
AddTracks(*mSessionOff, "audio"); AddTracks(*mSessionOff, "audio");
mSessionAns->AddTransceiver( mSessionAns->AddTransceiver(
new JsepTransceiver(SdpMediaSection::MediaType::kAudio)); new JsepTransceiver(SdpMediaSection::MediaType::kAudio, mUuidGen));
ASSERT_EQ(3U, mSessionAns->GetTransceivers().size()); ASSERT_EQ(3U, mSessionAns->GetTransceivers().size());
ASSERT_EQ(0U, mSessionAns->GetTransceivers()[0]->GetLevel()); ASSERT_EQ(0U, mSessionAns->GetTransceivers()[0]->GetLevel());
@ -6810,7 +6796,7 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) {
SdpDirectionAttribute::Direction::kRecvonly; SdpDirectionAttribute::Direction::kRecvonly;
// We do nothing with the second audio transceiver; when we rollback, it will // We do nothing with the second audio transceiver; when we rollback, it will
// disappear entirely. // be marked as removed.
// This will not cause the third audio transceiver to stick around; having a // This will not cause the third audio transceiver to stick around; having a
// track is _not_ enough to preserve it. It must have addTrack "magic"! // track is _not_ enough to preserve it. It must have addTrack "magic"!
@ -6819,15 +6805,14 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) {
// Create a fourth audio transceiver. Rollback will leave it alone, since we // Create a fourth audio transceiver. Rollback will leave it alone, since we
// created it. // created it.
mSessionAns->AddTransceiver( mSessionAns->AddTransceiver(
new JsepTransceiver(SdpMediaSection::MediaType::kAudio, new JsepTransceiver(SdpMediaSection::MediaType::kAudio, mUuidGen,
SdpDirectionAttribute::Direction::kRecvonly)); SdpDirectionAttribute::Direction::kRecvonly));
ASSERT_FALSE( ASSERT_FALSE(
mSessionAns->SetRemoteDescription(kJsepSdpRollback, "").mError.isSome()); mSessionAns->SetRemoteDescription(kJsepSdpRollback, "").mError.isSome());
// Three recvonly for audio, one sendrecv for video, and one (unmapped) for // Two of these (3 and 4) will be marked removed, if this all worked
// the second video track. ASSERT_EQ(6U, mSessionAns->GetTransceivers().size());
ASSERT_EQ(4U, mSessionAns->GetTransceivers().size());
// First video transceiver // First video transceiver
ASSERT_FALSE(mSessionAns->GetTransceivers()[0]->HasLevel()); ASSERT_FALSE(mSessionAns->GetTransceivers()[0]->HasLevel());
@ -6835,6 +6820,7 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) {
ASSERT_FALSE(mSessionAns->GetTransceivers()[0]->IsAssociated()); ASSERT_FALSE(mSessionAns->GetTransceivers()[0]->IsAssociated());
ASSERT_TRUE(mSessionAns->GetTransceivers()[0]->HasAddTrackMagic()); ASSERT_TRUE(mSessionAns->GetTransceivers()[0]->HasAddTrackMagic());
ASSERT_FALSE(IsNull(mSessionAns->GetTransceivers()[0]->mSendTrack)); ASSERT_FALSE(IsNull(mSessionAns->GetTransceivers()[0]->mSendTrack));
ASSERT_FALSE(mSessionAns->GetTransceivers()[0]->IsRemoved());
// Second video transceiver // Second video transceiver
ASSERT_FALSE(mSessionAns->GetTransceivers()[1]->HasLevel()); ASSERT_FALSE(mSessionAns->GetTransceivers()[1]->HasLevel());
@ -6842,6 +6828,7 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) {
ASSERT_FALSE(mSessionAns->GetTransceivers()[1]->IsAssociated()); ASSERT_FALSE(mSessionAns->GetTransceivers()[1]->IsAssociated());
ASSERT_TRUE(mSessionAns->GetTransceivers()[1]->HasAddTrackMagic()); ASSERT_TRUE(mSessionAns->GetTransceivers()[1]->HasAddTrackMagic());
ASSERT_FALSE(IsNull(mSessionAns->GetTransceivers()[1]->mSendTrack)); ASSERT_FALSE(IsNull(mSessionAns->GetTransceivers()[1]->mSendTrack));
ASSERT_FALSE(mSessionAns->GetTransceivers()[1]->IsRemoved());
// First audio transceiver, kept because AddTrack touched it, even though we // First audio transceiver, kept because AddTrack touched it, even though we
// removed the send track after. // removed the send track after.
@ -6850,10 +6837,23 @@ TEST_F(JsepSessionTest, ComplicatedRemoteRollback) {
ASSERT_FALSE(mSessionAns->GetTransceivers()[2]->IsAssociated()); ASSERT_FALSE(mSessionAns->GetTransceivers()[2]->IsAssociated());
ASSERT_TRUE(mSessionAns->GetTransceivers()[2]->HasAddTrackMagic()); ASSERT_TRUE(mSessionAns->GetTransceivers()[2]->HasAddTrackMagic());
ASSERT_TRUE(IsNull(mSessionAns->GetTransceivers()[2]->mSendTrack)); ASSERT_TRUE(IsNull(mSessionAns->GetTransceivers()[2]->mSendTrack));
ASSERT_FALSE(mSessionAns->GetTransceivers()[2]->IsRemoved());
// Second audio transceiver should be gone. // Second audio transceiver should be gone.
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->HasLevel());
ASSERT_TRUE(mSessionAns->GetTransceivers()[3]->IsStopped());
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->IsAssociated());
ASSERT_FALSE(mSessionAns->GetTransceivers()[3]->HasAddTrackMagic());
ASSERT_TRUE(IsNull(mSessionAns->GetTransceivers()[3]->mSendTrack));
ASSERT_TRUE(mSessionAns->GetTransceivers()[3]->IsRemoved());
// Third audio transceiver should also be gone. // Third audio transceiver should also be gone.
ASSERT_FALSE(mSessionAns->GetTransceivers()[4]->HasLevel());
ASSERT_TRUE(mSessionAns->GetTransceivers()[4]->IsStopped());
ASSERT_FALSE(mSessionAns->GetTransceivers()[4]->IsAssociated());
ASSERT_FALSE(mSessionAns->GetTransceivers()[4]->HasAddTrackMagic());
ASSERT_FALSE(IsNull(mSessionAns->GetTransceivers()[4]->mSendTrack));
ASSERT_TRUE(mSessionAns->GetTransceivers()[4]->IsRemoved());
// Fourth audio transceiver, created after SetRemote // Fourth audio transceiver, created after SetRemote
ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->HasLevel()); ASSERT_FALSE(mSessionAns->GetTransceivers()[5]->HasLevel());
@ -7126,7 +7126,7 @@ TEST_F(JsepSessionTest, TestOneWayRtx) {
TEST_F(JsepSessionTest, TestRtxNoSsrcGroup) { TEST_F(JsepSessionTest, TestRtxNoSsrcGroup) {
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kVideo, SdpDirectionAttribute::kRecvonly)); SdpMediaSection::kVideo, mUuidGen, SdpDirectionAttribute::kRecvonly));
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -7140,7 +7140,7 @@ TEST_F(JsepSessionTest, TestRtxNoSsrcGroup) {
TEST_F(JsepSessionTest, TestRtxSsrcGroupOnlyOffered) { TEST_F(JsepSessionTest, TestRtxSsrcGroupOnlyOffered) {
mSessionOff->AddTransceiver(new JsepTransceiver( mSessionOff->AddTransceiver(new JsepTransceiver(
SdpMediaSection::kVideo, SdpDirectionAttribute::kSendonly)); SdpMediaSection::kVideo, mUuidGen, SdpDirectionAttribute::kSendonly));
OfferAnswer(CHECK_SUCCESS); OfferAnswer(CHECK_SUCCESS);
@ -7166,8 +7166,7 @@ TEST_F(JsepSessionTest, TestOfferRtxNoMsid) {
AddTracks(*mSessionOff, "video"); AddTracks(*mSessionOff, "video");
std::vector<std::string> streamIds; std::vector<std::string> streamIds;
for (const auto& [id, transceiver] : mSessionOff->GetTransceivers()) { for (const auto& transceiver : mSessionOff->GetTransceivers()) {
(void)id; // Lame, but no better way to do this right now.
if (!IsNull(transceiver->mSendTrack)) { if (!IsNull(transceiver->mSendTrack)) {
transceiver->mSendTrack.UpdateStreamIds(streamIds); transceiver->mSendTrack.UpdateStreamIds(streamIds);
} }