Revert "Fix bug where we assume new m= sections will always be bundled."
This reverts commit d2b885fd91909f1b17fb11292a8c989d5d883b22.
Reason for revert: Speculative revert for Chromium importer
Original change's description:
> Fix bug where we assume new m= sections will always be bundled.
>
> A recent change [1] assumes that all new m= sections will share the
> first BUNDLE group (if one already exists), which avoids generating
> ICE candidates that are ultimately unnecessary. This is fine for JSEP
> endpoints, but it breaks the following scenarios for non-JSEP endpoints:
>
> * Remote offer adding a new m= section that's not part of any BUNDLE
> group.
> * Remote offer adding an m= section to the second BUNDLE group.
>
> The latter is specifically problematic for any application that wants
> to bundle all audio streams in one group and all video streams in
> another group when using Unified Plan SDP, to replicate the behavior of
> using Plan B without bundling. It may try to add a video stream only
> for WebRTC to bundle it with audio.
>
> This is fixed by doing some minor re-factoring, having BundleManager
> update the bundle groups at offer time.
>
> Also:
> * Added some additional validation for multiple bundle groups in a
> subsequent offer, since that now becomes relevant.
> * Improved rollback support, because now rolling back an offer may need
> to not only remove mid->transport mappings but alter them.
>
> [1]: https://webrtc-review.googlesource.com/c/src/+/221601
>
> Bug: webrtc:12906, webrtc:12999
> Change-Id: I4c6e7020c0be33a782d3608dee88e4e2fceb1be1
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/225642
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Taylor Brandstetter <deadbeef@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#34544}
# Not skipping CQ checks because original CL landed > 1 day ago.
Bug: webrtc:12906, webrtc:12999
Change-Id: I00179d7573f322ad539ff16cad1f85320cfb2270
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/227081
Reviewed-by: Björn Terelius <terelius@google.com>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Commit-Queue: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34578}
diff --git a/pc/jsep_transport_collection.cc b/pc/jsep_transport_collection.cc
index 98b8cd2..ce068d9 100644
--- a/pc/jsep_transport_collection.cc
+++ b/pc/jsep_transport_collection.cc
@@ -20,53 +20,21 @@
namespace webrtc {
-void BundleManager::Update(const cricket::SessionDescription* description,
- SdpType type) {
+void BundleManager::Update(const cricket::SessionDescription* description) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- // Rollbacks should call Rollback, not Update.
- RTC_DCHECK(type != SdpType::kRollback);
- bool bundle_groups_changed = false;
- // TODO(bugs.webrtc.org/3349): Do this for kPrAnswer as well. To make this
- // work, we also need to make sure PRANSWERs don't call
- // MaybeDestroyJsepTransport, because the final answer may need the destroyed
- // transport if it changes the BUNDLE group.
- if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle ||
- type == SdpType::kAnswer) {
- // If our policy is "max-bundle" or this is an answer, update all bundle
- // groups.
- bundle_groups_changed = true;
- bundle_groups_.clear();
- for (const cricket::ContentGroup* new_bundle_group :
- description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)) {
- bundle_groups_.push_back(
- std::make_unique<cricket::ContentGroup>(*new_bundle_group));
- RTC_DLOG(LS_VERBOSE) << "Establishing bundle group "
- << new_bundle_group->ToString();
- }
- } else if (type == SdpType::kOffer) {
- // If this is an offer, update existing bundle groups.
- // We do this because as per RFC 8843, section 7.3.2, the answerer cannot
- // remove an m= section from an existing BUNDLE group without rejecting it.
- // Thus any m= sections added to a BUNDLE group in this offer can
- // preemptively start using the bundled transport, as there is no possible
- // non-bundled fallback.
- for (const cricket::ContentGroup* new_bundle_group :
- description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)) {
- // Attempt to find a matching existing group.
- for (const std::string& mid : new_bundle_group->content_names()) {
- auto it = established_bundle_groups_by_mid_.find(mid);
- if (it != established_bundle_groups_by_mid_.end()) {
- *it->second = *new_bundle_group;
- bundle_groups_changed = true;
- RTC_DLOG(LS_VERBOSE)
- << "Establishing bundle group " << new_bundle_group->ToString();
- break;
- }
- }
- }
+ bundle_groups_.clear();
+ for (const cricket::ContentGroup* new_bundle_group :
+ description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)) {
+ bundle_groups_.push_back(
+ std::make_unique<cricket::ContentGroup>(*new_bundle_group));
+ RTC_DLOG(LS_VERBOSE) << "Establishing bundle group "
+ << new_bundle_group->ToString();
}
- if (bundle_groups_changed) {
- RefreshEstablishedBundleGroupsByMid();
+ established_bundle_groups_by_mid_.clear();
+ for (const auto& bundle_group : bundle_groups_) {
+ for (const std::string& content_name : bundle_group->content_names()) {
+ established_bundle_groups_by_mid_[content_name] = bundle_group.get();
+ }
}
}
@@ -124,34 +92,6 @@
bundle_groups_.erase(bundle_group_it);
}
-void BundleManager::Rollback() {
- RTC_DCHECK_RUN_ON(&sequence_checker_);
- bundle_groups_.clear();
- for (const auto& bundle_group : stable_bundle_groups_) {
- bundle_groups_.push_back(
- std::make_unique<cricket::ContentGroup>(*bundle_group));
- }
- RefreshEstablishedBundleGroupsByMid();
-}
-
-void BundleManager::Commit() {
- RTC_DCHECK_RUN_ON(&sequence_checker_);
- stable_bundle_groups_.clear();
- for (const auto& bundle_group : bundle_groups_) {
- stable_bundle_groups_.push_back(
- std::make_unique<cricket::ContentGroup>(*bundle_group));
- }
-}
-
-void BundleManager::RefreshEstablishedBundleGroupsByMid() {
- established_bundle_groups_by_mid_.clear();
- for (const auto& bundle_group : bundle_groups_) {
- for (const std::string& content_name : bundle_group->content_names()) {
- established_bundle_groups_by_mid_[content_name] = bundle_group.get();
- }
- }
-}
-
void JsepTransportCollection::RegisterTransport(
const std::string& mid,
std::unique_ptr<cricket::JsepTransport> transport) {
@@ -217,6 +157,8 @@
if (it != mid_to_transport_.end() && it->second == jsep_transport)
return true;
+ pending_mids_.push_back(mid);
+
// The map_change_callback must be called before destroying the
// transport, because it removes references to the transport
// in the RTP demuxer.
@@ -249,33 +191,17 @@
RTC_DCHECK(IsConsistent());
}
-bool JsepTransportCollection::RollbackTransports() {
+void JsepTransportCollection::RollbackTransports() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- bool ret = true;
- // First, remove any new mid->transport mappings.
- for (const auto& kv : mid_to_transport_) {
- if (stable_mid_to_transport_.count(kv.first) == 0) {
- ret = ret && map_change_callback_(kv.first, nullptr);
- }
+ for (auto&& mid : pending_mids_) {
+ RemoveTransportForMid(mid);
}
- // Next, restore old mappings.
- for (const auto& kv : stable_mid_to_transport_) {
- auto it = mid_to_transport_.find(kv.first);
- if (it == mid_to_transport_.end() || it->second != kv.second) {
- ret = ret && map_change_callback_(kv.first, kv.second);
- }
- }
- mid_to_transport_ = stable_mid_to_transport_;
- DestroyUnusedTransports();
- RTC_DCHECK(IsConsistent());
- return ret;
+ pending_mids_.clear();
}
void JsepTransportCollection::CommitTransports() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- stable_mid_to_transport_ = mid_to_transport_;
- DestroyUnusedTransports();
- RTC_DCHECK(IsConsistent());
+ pending_mids_.clear();
}
bool JsepTransportCollection::TransportInUse(
@@ -286,11 +212,6 @@
return true;
}
}
- for (const auto& kv : stable_mid_to_transport_) {
- if (kv.second == jsep_transport) {
- return true;
- }
- }
return false;
}
@@ -298,7 +219,7 @@
cricket::JsepTransport* transport) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
// Don't destroy the JsepTransport if there are still media sections referring
- // to it, or if it will be needed in case of rollback.
+ // to it.
if (TransportInUse(transport)) {
return;
}
@@ -312,23 +233,6 @@
RTC_DCHECK(IsConsistent());
}
-void JsepTransportCollection::DestroyUnusedTransports() {
- RTC_DCHECK_RUN_ON(&sequence_checker_);
- bool need_state_change_callback = false;
- auto it = jsep_transports_by_name_.begin();
- while (it != jsep_transports_by_name_.end()) {
- if (TransportInUse(it->second.get())) {
- ++it;
- } else {
- it = jsep_transports_by_name_.erase(it);
- need_state_change_callback = true;
- }
- }
- if (need_state_change_callback) {
- state_change_callback_();
- }
-}
-
bool JsepTransportCollection::IsConsistent() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
for (const auto& it : jsep_transports_by_name_) {
@@ -337,6 +241,13 @@
<< " is not in use, transport " << it.second.get();
return false;
}
+ const auto& lookup = mid_to_transport_.find(it.first);
+ if (lookup->second != it.second.get()) {
+ // Not an error, but unusual.
+ RTC_DLOG(LS_INFO) << "Note: Mid " << it.first << " was registered to "
+ << it.second.get() << " but currently maps to "
+ << lookup->second;
+ }
}
return true;
}
diff --git a/pc/jsep_transport_collection.h b/pc/jsep_transport_collection.h
index 9357037..0dd528d 100644
--- a/pc/jsep_transport_collection.h
+++ b/pc/jsep_transport_collection.h
@@ -18,7 +18,6 @@
#include <utility>
#include <vector>
-#include "api/peer_connection_interface.h"
#include "api/sequence_checker.h"
#include "pc/jsep_transport.h"
#include "pc/session_description.h"
@@ -42,8 +41,7 @@
// 6) Change the logic to do what's right.
class BundleManager {
public:
- explicit BundleManager(PeerConnectionInterface::BundlePolicy bundle_policy)
- : bundle_policy_(bundle_policy) {
+ BundleManager() {
// Allow constructor to be called on a different thread.
sequence_checker_.Detach();
}
@@ -60,27 +58,17 @@
bool IsFirstMidInGroup(const std::string& mid) const;
// Update the groups description. This completely replaces the group
// description with the one from the SessionDescription.
- void Update(const cricket::SessionDescription* description, SdpType type);
+ void Update(const cricket::SessionDescription* description);
// Delete a MID from the group that contains it.
void DeleteMid(const cricket::ContentGroup* bundle_group,
const std::string& mid);
// Delete a group.
void DeleteGroup(const cricket::ContentGroup* bundle_group);
- // Roll back to previous stable state.
- void Rollback();
- // Commit current bundle groups.
- void Commit();
private:
- // Recalculate established_bundle_groups_by_mid_ from bundle_groups_.
- void RefreshEstablishedBundleGroupsByMid() RTC_RUN_ON(sequence_checker_);
-
RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
- PeerConnectionInterface::BundlePolicy bundle_policy_;
std::vector<std::unique_ptr<cricket::ContentGroup>> bundle_groups_
RTC_GUARDED_BY(sequence_checker_);
- std::vector<std::unique_ptr<cricket::ContentGroup>> stable_bundle_groups_
- RTC_GUARDED_BY(sequence_checker_);
std::map<std::string, cricket::ContentGroup*>
established_bundle_groups_by_mid_;
};
@@ -120,25 +108,17 @@
// Remove a transport for a MID. This may destroy a transport if it is
// no longer in use.
void RemoveTransportForMid(const std::string& mid);
- // Roll back to previous stable mid-to-transport mappings.
- bool RollbackTransports();
- // Commit pending mid-transport mappings (rollback is no longer possible),
- // and destroy unused transports because we know now we'll never need them
- // again.
+ // Roll back pending mid-to-transport mappings.
+ void RollbackTransports();
+ // Commit pending mid-transport mappings (rollback is no longer possible).
void CommitTransports();
-
- private:
- // Returns true if any mid currently maps to this transport, in either the
- // pending or stable mapping.
+ // Returns true if any mid currently maps to this transport.
bool TransportInUse(cricket::JsepTransport* jsep_transport) const;
- // Destroy a transport if it's no longer in use. This includes whether it
- // will be needed in case of rollback.
+ private:
+ // Destroy a transport if it's no longer in use.
void MaybeDestroyJsepTransport(cricket::JsepTransport* transport);
- // Destroys all transports that are no longer in use.
- void DestroyUnusedTransports();
-
bool IsConsistent(); // For testing only: Verify internal structure.
RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
@@ -150,10 +130,8 @@
// (BaseChannel/SctpTransport) and the JsepTransport underneath.
std::map<std::string, cricket::JsepTransport*> mid_to_transport_
RTC_GUARDED_BY(sequence_checker_);
- // A snapshot of mid_to_transport_ at the last stable state. Used for
- // rollback.
- std::map<std::string, cricket::JsepTransport*> stable_mid_to_transport_
- RTC_GUARDED_BY(sequence_checker_);
+ // Keep track of mids that have been mapped to transports. Used for rollback.
+ std::vector<std::string> pending_mids_ RTC_GUARDED_BY(sequence_checker_);
// Callback used to inform subscribers of altered transports.
const std::function<bool(const std::string& mid,
cricket::JsepTransport* transport)>
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc
index 8b9596b..47fddd4 100644
--- a/pc/jsep_transport_controller.cc
+++ b/pc/jsep_transport_controller.cc
@@ -55,8 +55,7 @@
UpdateAggregateStates_n();
}),
config_(config),
- active_reset_srtp_params_(config.active_reset_srtp_params),
- bundles_(config.bundle_policy) {
+ active_reset_srtp_params_(config.active_reset_srtp_params) {
// The |transport_observer| is assumed to be non-null.
RTC_DCHECK(config_.transport_observer);
RTC_DCHECK(config_.rtcp_handler);
@@ -375,18 +374,13 @@
}
}
-RTCError JsepTransportController::RollbackTransports() {
+void JsepTransportController::RollbackTransports() {
if (!network_thread_->IsCurrent()) {
- return network_thread_->Invoke<RTCError>(
- RTC_FROM_HERE, [=] { return RollbackTransports(); });
+ network_thread_->Invoke<void>(RTC_FROM_HERE, [=] { RollbackTransports(); });
+ return;
}
RTC_DCHECK_RUN_ON(network_thread_);
- bundles_.Rollback();
- if (!transports_.RollbackTransports()) {
- LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
- "Failed to roll back transport state.");
- }
- return RTCError::OK();
+ transports_.RollbackTransports();
}
rtc::scoped_refptr<webrtc::IceTransportInterface>
@@ -557,6 +551,17 @@
MergeEncryptedHeaderExtensionIdsForBundles(description);
}
+ // Because the creation of transports depends on whether
+ // certain mids are present, we have to process rejection
+ // before we try to create transports.
+ for (size_t i = 0; i < description->contents().size(); ++i) {
+ const cricket::ContentInfo& content_info = description->contents()[i];
+ if (content_info.rejected) {
+ // This may cause groups to be removed from |bundles_.bundle_groups()|.
+ HandleRejectedContent(content_info);
+ }
+ }
+
for (const cricket::ContentInfo& content_info : description->contents()) {
// Don't create transports for rejected m-lines and bundled m-lines.
if (content_info.rejected ||
@@ -577,8 +582,6 @@
description->transport_infos()[i];
if (content_info.rejected) {
- // This may cause groups to be removed from |bundles_.bundle_groups()|.
- HandleRejectedContent(content_info);
continue;
}
@@ -644,7 +647,6 @@
}
if (type == SdpType::kAnswer) {
transports_.CommitTransports();
- bundles_.Commit();
}
return RTCError::OK();
}
@@ -680,44 +682,7 @@
}
}
- if (type == SdpType::kOffer) {
- // For an offer, we need to verify that there is not a conflicting mapping
- // between existing and new bundle groups. For example, if the existing
- // groups are [[1,2],[3,4]] and new are [[1,3],[2,4]] or [[1,2,3,4]], or
- // vice versa. Switching things around like this requires a separate offer
- // that removes the relevant sections from their group, as per RFC 8843,
- // section 7.5.2.
- std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
- new_bundle_groups_by_existing_bundle_groups;
- std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
- existing_bundle_groups_by_new_bundle_groups;
- for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
- for (const std::string& mid : new_bundle_group->content_names()) {
- cricket::ContentGroup* existing_bundle_group =
- bundles_.LookupGroupByMid(mid);
- if (!existing_bundle_group) {
- continue;
- }
- auto it = new_bundle_groups_by_existing_bundle_groups.find(
- existing_bundle_group);
- if (it != new_bundle_groups_by_existing_bundle_groups.end() &&
- it->second != new_bundle_group) {
- return RTCError(RTCErrorType::INVALID_PARAMETER,
- "MID " + mid + " in the offer has changed group.");
- }
- new_bundle_groups_by_existing_bundle_groups.insert(
- std::make_pair(existing_bundle_group, new_bundle_group));
- it = existing_bundle_groups_by_new_bundle_groups.find(new_bundle_group);
- if (it != existing_bundle_groups_by_new_bundle_groups.end() &&
- it->second != existing_bundle_group) {
- return RTCError(RTCErrorType::INVALID_PARAMETER,
- "MID " + mid + " in the offer has changed group.");
- }
- existing_bundle_groups_by_new_bundle_groups.insert(
- std::make_pair(new_bundle_group, existing_bundle_group));
- }
- }
- } else if (type == SdpType::kAnswer) {
+ if (type == SdpType::kAnswer) {
std::vector<const cricket::ContentGroup*> offered_bundle_groups =
local ? remote_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)
: local_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
@@ -797,7 +762,9 @@
"max-bundle is used but no bundle group found.");
}
- bundles_.Update(description, type);
+ if (ShouldUpdateBundleGroup(type, description)) {
+ bundles_.Update(description);
+ }
for (const auto& bundle_group : bundles_.bundle_groups()) {
if (!bundle_group->FirstContentName())
@@ -905,6 +872,26 @@
rtp_abs_sendtime_extn_id, transport_info.description);
}
+bool JsepTransportController::ShouldUpdateBundleGroup(
+ SdpType type,
+ const cricket::SessionDescription* description) {
+ if (config_.bundle_policy ==
+ PeerConnectionInterface::kBundlePolicyMaxBundle) {
+ return true;
+ }
+
+ if (type != SdpType::kAnswer) {
+ return false;
+ }
+
+ RTC_DCHECK(local_desc_ && remote_desc_);
+ std::vector<const cricket::ContentGroup*> local_bundles =
+ local_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
+ std::vector<const cricket::ContentGroup*> remote_bundles =
+ remote_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
+ return !local_bundles.empty() && !remote_bundles.empty();
+}
+
std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
const cricket::ContentInfo& content_info) {
const cricket::MediaContentDescription* content_desc =
@@ -1000,6 +987,21 @@
if (transport) {
return RTCError::OK();
}
+ // If we have agreed to a bundle, the new mid will be added to the bundle
+ // according to JSEP, and the responder can't move it out of the group
+ // according to BUNDLE. So don't create a transport.
+ // The MID will be added to the bundle elsewhere in the code.
+ if (bundles_.bundle_groups().size() > 0) {
+ const auto& default_bundle_group = bundles_.bundle_groups()[0];
+ if (default_bundle_group->content_names().size() > 0) {
+ auto bundle_transport =
+ GetJsepTransportByName(default_bundle_group->content_names()[0]);
+ if (bundle_transport) {
+ transports_.SetTransportForMid(content_info.name, bundle_transport);
+ return RTCError::OK();
+ }
+ }
+ }
const cricket::MediaContentDescription* content_desc =
content_info.media_description();
if (certificate_ && !content_desc->cryptos().empty()) {
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h
index 3b20bbb..71b01bf 100644
--- a/pc/jsep_transport_controller.h
+++ b/pc/jsep_transport_controller.h
@@ -224,7 +224,9 @@
void SetActiveResetSrtpParams(bool active_reset_srtp_params);
- RTCError RollbackTransports();
+ // For now the rollback only removes mid to transport mappings
+ // and deletes unused transports, but doesn't consider anything more complex.
+ void RollbackTransports();
// F: void(const std::string&, const std::vector<cricket::Candidate>&)
template <typename F>
@@ -340,6 +342,9 @@
const std::vector<int>& encrypted_extension_ids,
int rtp_abs_sendtime_extn_id);
+ bool ShouldUpdateBundleGroup(SdpType type,
+ const cricket::SessionDescription* description);
+
std::map<const cricket::ContentGroup*, std::vector<int>>
MergeEncryptedHeaderExtensionIdsForBundles(
const cricket::SessionDescription* description);
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc
index bc7cfeb..a06f580 100644
--- a/pc/jsep_transport_controller_unittest.cc
+++ b/pc/jsep_transport_controller_unittest.cc
@@ -1608,356 +1608,6 @@
EXPECT_EQ(mid5_transport, mid6_transport);
}
-TEST_F(JsepTransportControllerTest,
- MultipleBundleGroupsSectionsAddedInSubsequentOffer) {
- static const char kMid1Audio[] = "1_audio";
- static const char kMid2Audio[] = "2_audio";
- static const char kMid3Audio[] = "3_audio";
- static const char kMid4Video[] = "4_video";
- static const char kMid5Video[] = "5_video";
- static const char kMid6Video[] = "6_video";
-
- CreateJsepTransportController(JsepTransportController::Config());
- // Start by grouping (kMid1Audio,kMid2Audio) and (kMid4Video,kMid4f5Video).
- cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- bundle_group1.AddContentName(kMid1Audio);
- bundle_group1.AddContentName(kMid2Audio);
- cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- bundle_group2.AddContentName(kMid4Video);
- bundle_group2.AddContentName(kMid5Video);
-
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(local_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid5Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_offer->AddGroup(bundle_group1);
- local_offer->AddGroup(bundle_group2);
-
- auto remote_answer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(remote_answer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(remote_answer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid5Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- remote_answer->AddGroup(bundle_group1);
- remote_answer->AddGroup(bundle_group2);
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- // Add kMid3Audio and kMid6Video to the respective audio/video bundle groups.
- cricket::ContentGroup new_bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- bundle_group1.AddContentName(kMid3Audio);
- cricket::ContentGroup new_bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- bundle_group2.AddContentName(kMid6Video);
-
- auto subsequent_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(subsequent_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(subsequent_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(subsequent_offer.get(), kMid3Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid5Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid6Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- subsequent_offer->AddGroup(bundle_group1);
- subsequent_offer->AddGroup(bundle_group2);
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, subsequent_offer.get())
- .ok());
- auto mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- auto mid2_transport = transport_controller_->GetRtpTransport(kMid2Audio);
- auto mid3_transport = transport_controller_->GetRtpTransport(kMid3Audio);
- auto mid4_transport = transport_controller_->GetRtpTransport(kMid4Video);
- auto mid5_transport = transport_controller_->GetRtpTransport(kMid5Video);
- auto mid6_transport = transport_controller_->GetRtpTransport(kMid6Video);
- EXPECT_NE(mid1_transport, mid4_transport);
- EXPECT_EQ(mid1_transport, mid2_transport);
- EXPECT_EQ(mid2_transport, mid3_transport);
- EXPECT_EQ(mid4_transport, mid5_transport);
- EXPECT_EQ(mid5_transport, mid6_transport);
-}
-
-TEST_F(JsepTransportControllerTest,
- MultipleBundleGroupsCombinedInSubsequentOffer) {
- static const char kMid1Audio[] = "1_audio";
- static const char kMid2Audio[] = "2_audio";
- static const char kMid3Video[] = "3_video";
- static const char kMid4Video[] = "4_video";
-
- CreateJsepTransportController(JsepTransportController::Config());
- // Start by grouping (kMid1Audio,kMid2Audio) and (kMid3Video,kMid4Video).
- cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- bundle_group1.AddContentName(kMid1Audio);
- bundle_group1.AddContentName(kMid2Audio);
- cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- bundle_group2.AddContentName(kMid3Video);
- bundle_group2.AddContentName(kMid4Video);
-
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(local_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_offer->AddGroup(bundle_group1);
- local_offer->AddGroup(bundle_group2);
-
- auto remote_answer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(remote_answer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(remote_answer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- remote_answer->AddGroup(bundle_group1);
- remote_answer->AddGroup(bundle_group2);
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- // Switch to grouping (kMid1Audio,kMid2Audio,kMid3Video,kMid4Video).
- // This is a illegal without first removing m= sections from their groups.
- cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
- new_bundle_group.AddContentName(kMid1Audio);
- new_bundle_group.AddContentName(kMid2Audio);
- new_bundle_group.AddContentName(kMid3Video);
- new_bundle_group.AddContentName(kMid4Video);
-
- auto subsequent_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(subsequent_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(subsequent_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- subsequent_offer->AddGroup(new_bundle_group);
- EXPECT_FALSE(
- transport_controller_
- ->SetLocalDescription(SdpType::kOffer, subsequent_offer.get())
- .ok());
-}
-
-TEST_F(JsepTransportControllerTest,
- MultipleBundleGroupsSplitInSubsequentOffer) {
- static const char kMid1Audio[] = "1_audio";
- static const char kMid2Audio[] = "2_audio";
- static const char kMid3Video[] = "3_video";
- static const char kMid4Video[] = "4_video";
-
- CreateJsepTransportController(JsepTransportController::Config());
- // Start by grouping (kMid1Audio,kMid2Audio,kMid3Video,kMid4Video).
- cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
- bundle_group.AddContentName(kMid1Audio);
- bundle_group.AddContentName(kMid2Audio);
- bundle_group.AddContentName(kMid3Video);
- bundle_group.AddContentName(kMid4Video);
-
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(local_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_offer->AddGroup(bundle_group);
-
- auto remote_answer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(remote_answer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(remote_answer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- remote_answer->AddGroup(bundle_group);
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- // Switch to grouping (kMid1Audio,kMid2Audio) and (kMid3Video,kMid4Video).
- // This is a illegal without first removing m= sections from their groups.
- cricket::ContentGroup new_bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- new_bundle_group1.AddContentName(kMid1Audio);
- new_bundle_group1.AddContentName(kMid2Audio);
- cricket::ContentGroup new_bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- new_bundle_group2.AddContentName(kMid3Video);
- new_bundle_group2.AddContentName(kMid4Video);
-
- auto subsequent_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(subsequent_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(subsequent_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- subsequent_offer->AddGroup(new_bundle_group1);
- subsequent_offer->AddGroup(new_bundle_group2);
- EXPECT_FALSE(
- transport_controller_
- ->SetLocalDescription(SdpType::kOffer, subsequent_offer.get())
- .ok());
-}
-
-TEST_F(JsepTransportControllerTest,
- MultipleBundleGroupsShuffledInSubsequentOffer) {
- static const char kMid1Audio[] = "1_audio";
- static const char kMid2Audio[] = "2_audio";
- static const char kMid3Video[] = "3_video";
- static const char kMid4Video[] = "4_video";
-
- CreateJsepTransportController(JsepTransportController::Config());
- // Start by grouping (kMid1Audio,kMid2Audio) and (kMid3Video,kMid4Video).
- cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- bundle_group1.AddContentName(kMid1Audio);
- bundle_group1.AddContentName(kMid2Audio);
- cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- bundle_group2.AddContentName(kMid3Video);
- bundle_group2.AddContentName(kMid4Video);
-
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(local_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_offer->AddGroup(bundle_group1);
- local_offer->AddGroup(bundle_group2);
-
- auto remote_answer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(remote_answer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(remote_answer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(remote_answer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- remote_answer->AddGroup(bundle_group1);
- remote_answer->AddGroup(bundle_group2);
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- // Switch to grouping (kMid1Audio,kMid3Video) and (kMid2Audio,kMid3Video).
- // This is a illegal without first removing m= sections from their groups.
- cricket::ContentGroup new_bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- new_bundle_group1.AddContentName(kMid1Audio);
- new_bundle_group1.AddContentName(kMid3Video);
- cricket::ContentGroup new_bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- new_bundle_group2.AddContentName(kMid2Audio);
- new_bundle_group2.AddContentName(kMid4Video);
-
- auto subsequent_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(subsequent_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(subsequent_offer.get(), kMid2Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid3Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer.get(), kMid4Video, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- subsequent_offer->AddGroup(new_bundle_group1);
- subsequent_offer->AddGroup(new_bundle_group2);
- EXPECT_FALSE(
- transport_controller_
- ->SetLocalDescription(SdpType::kOffer, subsequent_offer.get())
- .ok());
-}
-
// Tests that only a subset of all the m= sections are bundled.
TEST_F(JsepTransportControllerTest, BundleSubsetOfMediaSections) {
CreateJsepTransportController(JsepTransportController::Config());
@@ -2409,220 +2059,4 @@
.ok());
}
-TEST_F(JsepTransportControllerTest, RollbackRestoresRejectedTransport) {
- static const char kMid1Audio[] = "1_audio";
-
- // Perform initial offer/answer.
- CreateJsepTransportController(JsepTransportController::Config());
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- std::unique_ptr<cricket::SessionDescription> remote_answer(
- local_offer->Clone());
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- auto mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
-
- // Apply a reoffer which rejects the m= section, causing the transport to be
- // set to null.
- auto local_reoffer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_reoffer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_reoffer->contents()[0].rejected = true;
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_reoffer.get())
- .ok());
- auto old_mid1_transport = mid1_transport;
- mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- EXPECT_EQ(nullptr, mid1_transport);
-
- // Rolling back shouldn't just create a new transport for MID 1, it should
- // restore the old transport.
- EXPECT_TRUE(transport_controller_->RollbackTransports().ok());
- mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- EXPECT_EQ(old_mid1_transport, mid1_transport);
-}
-
-// If an offer with a modified BUNDLE group causes a MID->transport mapping to
-// change, rollback should restore the previous mapping.
-TEST_F(JsepTransportControllerTest, RollbackRestoresPreviousTransportMapping) {
- static const char kMid1Audio[] = "1_audio";
- static const char kMid2Audio[] = "2_audio";
- static const char kMid3Audio[] = "3_audio";
-
- // Perform an initial offer/answer to establish a (kMid1Audio,kMid2Audio)
- // group.
- CreateJsepTransportController(JsepTransportController::Config());
- cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
- bundle_group.AddContentName(kMid1Audio);
- bundle_group.AddContentName(kMid2Audio);
-
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid2Audio, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(local_offer.get(), kMid3Audio, kIceUfrag3, kIcePwd3,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_offer->AddGroup(bundle_group);
-
- std::unique_ptr<cricket::SessionDescription> remote_answer(
- local_offer->Clone());
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- auto mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- auto mid2_transport = transport_controller_->GetRtpTransport(kMid2Audio);
- auto mid3_transport = transport_controller_->GetRtpTransport(kMid3Audio);
- EXPECT_EQ(mid1_transport, mid2_transport);
- EXPECT_NE(mid1_transport, mid3_transport);
-
- // Apply a reoffer adding kMid3Audio to the group; transport mapping should
- // change, even without an answer, since this is an existing group.
- bundle_group.AddContentName(kMid3Audio);
- auto local_reoffer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_reoffer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_reoffer.get(), kMid2Audio, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddAudioSection(local_reoffer.get(), kMid3Audio, kIceUfrag3, kIcePwd3,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_reoffer->AddGroup(bundle_group);
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_reoffer.get())
- .ok());
-
- // Store the old transport pointer and verify that the offer actually changed
- // transports.
- auto old_mid3_transport = mid3_transport;
- mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- mid2_transport = transport_controller_->GetRtpTransport(kMid2Audio);
- mid3_transport = transport_controller_->GetRtpTransport(kMid3Audio);
- EXPECT_EQ(mid1_transport, mid2_transport);
- EXPECT_EQ(mid1_transport, mid3_transport);
-
- // Rolling back shouldn't just create a new transport for MID 3, it should
- // restore the old transport.
- EXPECT_TRUE(transport_controller_->RollbackTransports().ok());
- mid3_transport = transport_controller_->GetRtpTransport(kMid3Audio);
- EXPECT_EQ(old_mid3_transport, mid3_transport);
-}
-
-// Test that if an offer adds a MID to a specific BUNDLE group and is then
-// rolled back, it can be added to a different BUNDLE group in a new offer.
-// This is effectively testing that rollback resets the BundleManager state.
-TEST_F(JsepTransportControllerTest, RollbackAndAddToDifferentBundleGroup) {
- static const char kMid1Audio[] = "1_audio";
- static const char kMid2Audio[] = "2_audio";
- static const char kMid3Audio[] = "3_audio";
-
- // Perform an initial offer/answer to establish two bundle groups, each with
- // one MID.
- CreateJsepTransportController(JsepTransportController::Config());
- cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- bundle_group1.AddContentName(kMid1Audio);
- cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- bundle_group2.AddContentName(kMid2Audio);
-
- auto local_offer = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(local_offer.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(local_offer.get(), kMid2Audio, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- local_offer->AddGroup(bundle_group1);
- local_offer->AddGroup(bundle_group2);
-
- std::unique_ptr<cricket::SessionDescription> remote_answer(
- local_offer->Clone());
-
- EXPECT_TRUE(transport_controller_
- ->SetLocalDescription(SdpType::kOffer, local_offer.get())
- .ok());
- EXPECT_TRUE(transport_controller_
- ->SetRemoteDescription(SdpType::kAnswer, remote_answer.get())
- .ok());
-
- // Apply an offer that adds kMid3Audio to the first BUNDLE group.,
- cricket::ContentGroup modified_bundle_group1(cricket::GROUP_TYPE_BUNDLE);
- modified_bundle_group1.AddContentName(kMid1Audio);
- modified_bundle_group1.AddContentName(kMid3Audio);
- auto subsequent_offer_1 = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(subsequent_offer_1.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer_1.get(), kMid2Audio, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer_1.get(), kMid3Audio, kIceUfrag3, kIcePwd3,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- subsequent_offer_1->AddGroup(modified_bundle_group1);
- subsequent_offer_1->AddGroup(bundle_group2);
-
- EXPECT_TRUE(
- transport_controller_
- ->SetLocalDescription(SdpType::kOffer, subsequent_offer_1.get())
- .ok());
-
- auto mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- auto mid2_transport = transport_controller_->GetRtpTransport(kMid2Audio);
- auto mid3_transport = transport_controller_->GetRtpTransport(kMid3Audio);
- EXPECT_NE(mid1_transport, mid2_transport);
- EXPECT_EQ(mid1_transport, mid3_transport);
-
- // Rollback and expect the transport to be reset.
- EXPECT_TRUE(transport_controller_->RollbackTransports().ok());
- EXPECT_EQ(nullptr, transport_controller_->GetRtpTransport(kMid3Audio));
-
- // Apply an offer that adds kMid3Audio to the second BUNDLE group.,
- cricket::ContentGroup modified_bundle_group2(cricket::GROUP_TYPE_BUNDLE);
- modified_bundle_group2.AddContentName(kMid2Audio);
- modified_bundle_group2.AddContentName(kMid3Audio);
- auto subsequent_offer_2 = std::make_unique<cricket::SessionDescription>();
- AddAudioSection(subsequent_offer_2.get(), kMid1Audio, kIceUfrag1, kIcePwd1,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer_2.get(), kMid2Audio, kIceUfrag2, kIcePwd2,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- AddVideoSection(subsequent_offer_2.get(), kMid3Audio, kIceUfrag3, kIcePwd3,
- cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS,
- nullptr);
- subsequent_offer_2->AddGroup(bundle_group1);
- subsequent_offer_2->AddGroup(modified_bundle_group2);
-
- EXPECT_TRUE(
- transport_controller_
- ->SetLocalDescription(SdpType::kOffer, subsequent_offer_2.get())
- .ok());
-
- mid1_transport = transport_controller_->GetRtpTransport(kMid1Audio);
- mid2_transport = transport_controller_->GetRtpTransport(kMid2Audio);
- mid3_transport = transport_controller_->GetRtpTransport(kMid3Audio);
- EXPECT_NE(mid1_transport, mid2_transport);
- EXPECT_EQ(mid2_transport, mid3_transport);
-}
-
} // namespace webrtc
diff --git a/pc/peer_connection_bundle_unittest.cc b/pc/peer_connection_bundle_unittest.cc
index be05af9..08754c6 100644
--- a/pc/peer_connection_bundle_unittest.cc
+++ b/pc/peer_connection_bundle_unittest.cc
@@ -909,11 +909,11 @@
EXPECT_TRUE(
caller->SetLocalDescription(CloneSessionDescription(offer.get())));
- EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+ callee->SetRemoteDescription(std::move(offer));
auto answer = callee->CreateAnswer();
EXPECT_TRUE(
callee->SetLocalDescription(CloneSessionDescription(answer.get())));
- EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
+ caller->SetRemoteDescription(std::move(answer));
// Verify bundling on sender side.
auto senders = caller->pc()->GetSenders();
@@ -938,59 +938,4 @@
EXPECT_NE(receiver0_transport, receiver2_transport);
}
-// Test that, with the "max-compat" bundle policy, it's possible to add an m=
-// section that's not part of an existing bundle group.
-TEST_F(PeerConnectionBundleTestUnifiedPlan, AddNonBundledSection) {
- RTCConfiguration config;
- config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxCompat;
- auto caller = CreatePeerConnection(config);
- caller->AddAudioTrack("0_audio");
- caller->AddAudioTrack("1_audio");
- auto callee = CreatePeerConnection(config);
-
- // Establish an existing BUNDLE group.
- auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
- EXPECT_TRUE(
- caller->SetLocalDescription(CloneSessionDescription(offer.get())));
- EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
- auto answer = callee->CreateAnswer();
- EXPECT_TRUE(
- callee->SetLocalDescription(CloneSessionDescription(answer.get())));
- EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
-
- // Add a track but munge SDP so it's not part of the bundle group.
- caller->AddAudioTrack("3_audio");
- offer = caller->CreateOffer(RTCOfferAnswerOptions());
- offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
- cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
- bundle_group.AddContentName("0");
- bundle_group.AddContentName("1");
- offer->description()->AddGroup(bundle_group);
- EXPECT_TRUE(
- caller->SetLocalDescription(CloneSessionDescription(offer.get())));
- EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
- answer = callee->CreateAnswer();
- EXPECT_TRUE(
- callee->SetLocalDescription(CloneSessionDescription(answer.get())));
- EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
-
- // Verify bundling on the sender side.
- auto senders = caller->pc()->GetSenders();
- ASSERT_EQ(senders.size(), 3u);
- auto sender0_transport = senders[0]->dtls_transport();
- auto sender1_transport = senders[1]->dtls_transport();
- auto sender2_transport = senders[2]->dtls_transport();
- EXPECT_EQ(sender0_transport, sender1_transport);
- EXPECT_NE(sender0_transport, sender2_transport);
-
- // Verify bundling on receiver side.
- auto receivers = callee->pc()->GetReceivers();
- ASSERT_EQ(receivers.size(), 3u);
- auto receiver0_transport = receivers[0]->dtls_transport();
- auto receiver1_transport = receivers[1]->dtls_transport();
- auto receiver2_transport = receivers[2]->dtls_transport();
- EXPECT_EQ(receiver0_transport, receiver1_transport);
- EXPECT_NE(receiver0_transport, receiver2_transport);
-}
-
} // namespace webrtc
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc
index 929736e..533bd84 100644
--- a/pc/sdp_offer_answer.cc
+++ b/pc/sdp_offer_answer.cc
@@ -2737,10 +2737,7 @@
transceiver->internal()->set_mid(state.mid());
transceiver->internal()->set_mline_index(state.mline_index());
}
- RTCError e = transport_controller()->RollbackTransports();
- if (!e.ok()) {
- return e;
- }
+ transport_controller()->RollbackTransports();
transceivers()->DiscardStableStates();
pending_local_description_.reset();
pending_remote_description_.reset();