aboutsummaryrefslogtreecommitdiff
path: root/pc/jsep_transport_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pc/jsep_transport_controller.cc')
-rw-r--r--pc/jsep_transport_controller.cc447
1 files changed, 252 insertions, 195 deletions
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc
index 312b1280b1..95cf21587d 100644
--- a/pc/jsep_transport_controller.cc
+++ b/pc/jsep_transport_controller.cc
@@ -13,10 +13,13 @@
#include <stddef.h>
#include <algorithm>
+#include <functional>
#include <memory>
+#include <type_traits>
#include <utility>
#include "absl/algorithm/container.h"
+#include "api/dtls_transport_interface.h"
#include "api/rtp_parameters.h"
#include "api/sequence_checker.h"
#include "api/transport/enums.h"
@@ -28,9 +31,8 @@
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
-#include "rtc_base/net_helper.h"
-#include "rtc_base/socket_address.h"
#include "rtc_base/thread.h"
+#include "rtc_base/trace_event.h"
using webrtc::SdpType;
@@ -44,6 +46,14 @@ JsepTransportController::JsepTransportController(
: network_thread_(network_thread),
port_allocator_(port_allocator),
async_dns_resolver_factory_(async_dns_resolver_factory),
+ transports_(
+ [this](const std::string& mid, cricket::JsepTransport* transport) {
+ return OnTransportChanged(mid, transport);
+ },
+ [this]() {
+ RTC_DCHECK_RUN_ON(network_thread_);
+ UpdateAggregateStates_n();
+ }),
config_(config),
active_reset_srtp_params_(config.active_reset_srtp_params) {
// The |transport_observer| is assumed to be non-null.
@@ -63,6 +73,7 @@ JsepTransportController::~JsepTransportController() {
RTCError JsepTransportController::SetLocalDescription(
SdpType type,
const cricket::SessionDescription* description) {
+ TRACE_EVENT0("webrtc", "JsepTransportController::SetLocalDescription");
if (!network_thread_->IsCurrent()) {
return network_thread_->Invoke<RTCError>(
RTC_FROM_HERE, [=] { return SetLocalDescription(type, description); });
@@ -83,6 +94,7 @@ RTCError JsepTransportController::SetLocalDescription(
RTCError JsepTransportController::SetRemoteDescription(
SdpType type,
const cricket::SessionDescription* description) {
+ TRACE_EVENT0("webrtc", "JsepTransportController::SetRemoteDescription");
if (!network_thread_->IsCurrent()) {
return network_thread_->Invoke<RTCError>(
RTC_FROM_HERE, [=] { return SetRemoteDescription(type, description); });
@@ -162,8 +174,8 @@ void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
void JsepTransportController::SetNeedsIceRestartFlag() {
RTC_DCHECK_RUN_ON(network_thread_);
- for (auto& kv : jsep_transports_by_name_) {
- kv.second->SetNeedsIceRestartFlag();
+ for (auto& transport : transports_.Transports()) {
+ transport->SetNeedsIceRestartFlag();
}
}
@@ -216,8 +228,8 @@ bool JsepTransportController::SetLocalCertificate(
// Set certificate for JsepTransport, which verifies it matches the
// fingerprint in SDP, and DTLS transport.
// Fallback from DTLS to SDES is not supported.
- for (auto& kv : jsep_transports_by_name_) {
- kv.second->SetLocalCertificate(certificate_);
+ for (auto& transport : transports_.Transports()) {
+ transport->SetLocalCertificate(certificate_);
}
for (auto& dtls : GetDtlsTransports()) {
bool set_cert_success = dtls->SetLocalCertificate(certificate_);
@@ -357,8 +369,8 @@ void JsepTransportController::SetActiveResetSrtpParams(
<< "Updating the active_reset_srtp_params for JsepTransportController: "
<< active_reset_srtp_params;
active_reset_srtp_params_ = active_reset_srtp_params;
- for (auto& kv : jsep_transports_by_name_) {
- kv.second->SetActiveResetSrtpParams(active_reset_srtp_params);
+ for (auto& transport : transports_.Transports()) {
+ transport->SetActiveResetSrtpParams(active_reset_srtp_params);
}
}
@@ -368,13 +380,7 @@ void JsepTransportController::RollbackTransports() {
return;
}
RTC_DCHECK_RUN_ON(network_thread_);
- for (auto&& mid : pending_mids_) {
- RemoveTransportForMid(mid);
- }
- for (auto&& mid : pending_mids_) {
- MaybeDestroyJsepTransport(mid);
- }
- pending_mids_.clear();
+ transports_.RollbackTransports();
}
rtc::scoped_refptr<webrtc::IceTransportInterface>
@@ -506,9 +512,7 @@ std::vector<cricket::DtlsTransportInternal*>
JsepTransportController::GetDtlsTransports() {
RTC_DCHECK_RUN_ON(network_thread_);
std::vector<cricket::DtlsTransportInternal*> dtls_transports;
- for (auto it = jsep_transports_by_name_.begin();
- it != jsep_transports_by_name_.end(); ++it) {
- auto jsep_transport = it->second.get();
+ for (auto jsep_transport : transports_.Transports()) {
RTC_DCHECK(jsep_transport);
if (jsep_transport->rtp_dtls_transport()) {
dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
@@ -525,6 +529,7 @@ RTCError JsepTransportController::ApplyDescription_n(
bool local,
SdpType type,
const cricket::SessionDescription* description) {
+ TRACE_EVENT0("webrtc", "JsepTransportController::ApplyDescription_n");
RTC_DCHECK(description);
if (local) {
@@ -534,21 +539,33 @@ RTCError JsepTransportController::ApplyDescription_n(
}
RTCError error;
- error = ValidateAndMaybeUpdateBundleGroup(local, type, description);
+ error = ValidateAndMaybeUpdateBundleGroups(local, type, description);
if (!error.ok()) {
return error;
}
- std::vector<int> merged_encrypted_extension_ids;
- if (bundle_group_) {
- merged_encrypted_extension_ids =
- MergeEncryptedHeaderExtensionIdsForBundle(description);
+ std::map<const cricket::ContentGroup*, std::vector<int>>
+ merged_encrypted_extension_ids_by_bundle;
+ if (!bundles_.bundle_groups().empty()) {
+ merged_encrypted_extension_ids_by_bundle =
+ 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."
+ // Don't create transports for rejected m-lines and bundled m-lines.
if (content_info.rejected ||
- (IsBundled(content_info.name) && content_info.name != *bundled_mid())) {
+ !bundles_.IsFirstMidInGroup(content_info.name)) {
continue;
}
error = MaybeCreateJsepTransport(local, content_info, *description);
@@ -563,15 +580,22 @@ RTCError JsepTransportController::ApplyDescription_n(
const cricket::ContentInfo& content_info = description->contents()[i];
const cricket::TransportInfo& transport_info =
description->transport_infos()[i];
+
if (content_info.rejected) {
- HandleRejectedContent(content_info, description);
continue;
}
- if (IsBundled(content_info.name) && content_info.name != *bundled_mid()) {
- if (!HandleBundledContent(content_info)) {
+ const cricket::ContentGroup* established_bundle_group =
+ bundles_.LookupGroupByMid(content_info.name);
+
+ // For bundle members that are not BUNDLE-tagged (not first in the group),
+ // configure their transport to be the same as the BUNDLE-tagged transport.
+ if (established_bundle_group &&
+ content_info.name != *established_bundle_group->FirstContentName()) {
+ if (!HandleBundledContent(content_info, *established_bundle_group)) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
- "Failed to process the bundled m= section with mid='" +
+ "Failed to process the bundled m= section with "
+ "mid='" +
content_info.name + "'.");
}
continue;
@@ -583,8 +607,13 @@ RTCError JsepTransportController::ApplyDescription_n(
}
std::vector<int> extension_ids;
- if (bundled_mid() && content_info.name == *bundled_mid()) {
- extension_ids = merged_encrypted_extension_ids;
+ // Is BUNDLE-tagged (first in the group)?
+ if (established_bundle_group &&
+ content_info.name == *established_bundle_group->FirstContentName()) {
+ auto it = merged_encrypted_extension_ids_by_bundle.find(
+ established_bundle_group);
+ RTC_DCHECK(it != merged_encrypted_extension_ids_by_bundle.end());
+ extension_ids = it->second;
} else {
extension_ids = GetEncryptedHeaderExtensionIds(content_info);
}
@@ -617,56 +646,103 @@ RTCError JsepTransportController::ApplyDescription_n(
}
}
if (type == SdpType::kAnswer) {
- pending_mids_.clear();
+ transports_.CommitTransports();
}
return RTCError::OK();
}
-RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup(
+RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroups(
bool local,
SdpType type,
const cricket::SessionDescription* description) {
RTC_DCHECK(description);
- const cricket::ContentGroup* new_bundle_group =
- description->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
- // The BUNDLE group containing a MID that no m= section has is invalid.
- if (new_bundle_group) {
+ std::vector<const cricket::ContentGroup*> new_bundle_groups =
+ description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
+ // Verify |new_bundle_groups|.
+ std::map<std::string, const cricket::ContentGroup*> new_bundle_groups_by_mid;
+ for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
for (const std::string& content_name : new_bundle_group->content_names()) {
+ // The BUNDLE group must not contain a MID that is a member of a different
+ // BUNDLE group, or that contains the same MID multiple times.
+ if (new_bundle_groups_by_mid.find(content_name) !=
+ new_bundle_groups_by_mid.end()) {
+ return RTCError(RTCErrorType::INVALID_PARAMETER,
+ "A BUNDLE group contains a MID='" + content_name +
+ "' that is already in a BUNDLE group.");
+ }
+ new_bundle_groups_by_mid.insert(
+ std::make_pair(content_name, new_bundle_group));
+ // The BUNDLE group must not contain a MID that no m= section has.
if (!description->GetContentByName(content_name)) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
- "The BUNDLE group contains MID='" + content_name +
+ "A BUNDLE group contains a MID='" + content_name +
"' matching no m= section.");
}
}
}
if (type == SdpType::kAnswer) {
- const cricket::ContentGroup* offered_bundle_group =
- local ? remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE)
- : local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
+ std::vector<const cricket::ContentGroup*> offered_bundle_groups =
+ local ? remote_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)
+ : local_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
+
+ std::map<std::string, const cricket::ContentGroup*>
+ offered_bundle_groups_by_mid;
+ for (const cricket::ContentGroup* offered_bundle_group :
+ offered_bundle_groups) {
+ for (const std::string& content_name :
+ offered_bundle_group->content_names()) {
+ offered_bundle_groups_by_mid[content_name] = offered_bundle_group;
+ }
+ }
- if (new_bundle_group) {
- // The BUNDLE group in answer should be a subset of offered group.
+ std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
+ new_bundle_groups_by_offered_bundle_groups;
+ for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
+ if (!new_bundle_group->FirstContentName()) {
+ // Empty groups could be a subset of any group.
+ continue;
+ }
+ // The group in the answer (new_bundle_group) must have a corresponding
+ // group in the offer (original_group), because the answer groups may only
+ // be subsets of the offer groups.
+ auto it = offered_bundle_groups_by_mid.find(
+ *new_bundle_group->FirstContentName());
+ if (it == offered_bundle_groups_by_mid.end()) {
+ return RTCError(RTCErrorType::INVALID_PARAMETER,
+ "A BUNDLE group was added in the answer that did not "
+ "exist in the offer.");
+ }
+ const cricket::ContentGroup* offered_bundle_group = it->second;
+ if (new_bundle_groups_by_offered_bundle_groups.find(
+ offered_bundle_group) !=
+ new_bundle_groups_by_offered_bundle_groups.end()) {
+ return RTCError(RTCErrorType::INVALID_PARAMETER,
+ "A MID in the answer has changed group.");
+ }
+ new_bundle_groups_by_offered_bundle_groups.insert(
+ std::make_pair(offered_bundle_group, new_bundle_group));
for (const std::string& content_name :
new_bundle_group->content_names()) {
- if (!offered_bundle_group ||
- !offered_bundle_group->HasContentName(content_name)) {
+ it = offered_bundle_groups_by_mid.find(content_name);
+ // The BUNDLE group in answer should be a subset of offered group.
+ if (it == offered_bundle_groups_by_mid.end() ||
+ it->second != offered_bundle_group) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
- "The BUNDLE group in answer contains a MID='" +
+ "A BUNDLE group in answer contains a MID='" +
content_name +
- "' that was "
- "not in the offered group.");
+ "' that was not in the offered group.");
}
}
}
- if (bundle_group_) {
- for (const std::string& content_name : bundle_group_->content_names()) {
+ for (const auto& bundle_group : bundles_.bundle_groups()) {
+ for (const std::string& content_name : bundle_group->content_names()) {
// An answer that removes m= sections from pre-negotiated BUNDLE group
// without rejecting it, is invalid.
- if (!new_bundle_group ||
- !new_bundle_group->HasContentName(content_name)) {
+ auto it = new_bundle_groups_by_mid.find(content_name);
+ if (it == new_bundle_groups_by_mid.end()) {
auto* content_info = description->GetContentByName(content_name);
if (!content_info || !content_info->rejected) {
return RTCError(RTCErrorType::INVALID_PARAMETER,
@@ -687,33 +763,35 @@ RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup(
}
if (ShouldUpdateBundleGroup(type, description)) {
- bundle_group_ = *new_bundle_group;
+ bundles_.Update(description);
}
- if (!bundled_mid()) {
- return RTCError::OK();
- }
+ for (const auto& bundle_group : bundles_.bundle_groups()) {
+ if (!bundle_group->FirstContentName())
+ continue;
- auto bundled_content = description->GetContentByName(*bundled_mid());
- if (!bundled_content) {
- return RTCError(
- RTCErrorType::INVALID_PARAMETER,
- "An m= section associated with the BUNDLE-tag doesn't exist.");
- }
+ // The first MID in a BUNDLE group is BUNDLE-tagged.
+ auto bundled_content =
+ description->GetContentByName(*bundle_group->FirstContentName());
+ if (!bundled_content) {
+ return RTCError(
+ RTCErrorType::INVALID_PARAMETER,
+ "An m= section associated with the BUNDLE-tag doesn't exist.");
+ }
- // If the |bundled_content| is rejected, other contents in the bundle group
- // should be rejected.
- if (bundled_content->rejected) {
- for (const auto& content_name : bundle_group_->content_names()) {
- auto other_content = description->GetContentByName(content_name);
- if (!other_content->rejected) {
- return RTCError(RTCErrorType::INVALID_PARAMETER,
- "The m= section with mid='" + content_name +
- "' should be rejected.");
+ // If the |bundled_content| is rejected, other contents in the bundle group
+ // must also be rejected.
+ if (bundled_content->rejected) {
+ for (const auto& content_name : bundle_group->content_names()) {
+ auto other_content = description->GetContentByName(content_name);
+ if (!other_content->rejected) {
+ return RTCError(RTCErrorType::INVALID_PARAMETER,
+ "The m= section with mid='" + content_name +
+ "' should be rejected.");
+ }
}
}
}
-
return RTCError::OK();
}
@@ -732,78 +810,46 @@ RTCError JsepTransportController::ValidateContent(
}
void JsepTransportController::HandleRejectedContent(
- const cricket::ContentInfo& content_info,
- const cricket::SessionDescription* description) {
+ const cricket::ContentInfo& content_info) {
// If the content is rejected, let the
// BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
// then destroy the cricket::JsepTransport.
- RemoveTransportForMid(content_info.name);
- if (content_info.name == bundled_mid()) {
- for (const auto& content_name : bundle_group_->content_names()) {
- RemoveTransportForMid(content_name);
+ cricket::ContentGroup* bundle_group =
+ bundles_.LookupGroupByMid(content_info.name);
+ if (bundle_group && !bundle_group->content_names().empty() &&
+ content_info.name == *bundle_group->FirstContentName()) {
+ // Rejecting a BUNDLE group's first mid means we are rejecting the entire
+ // group.
+ for (const auto& content_name : bundle_group->content_names()) {
+ transports_.RemoveTransportForMid(content_name);
}
- bundle_group_.reset();
- } else if (IsBundled(content_info.name)) {
- // Remove the rejected content from the |bundle_group_|.
- bundle_group_->RemoveContentName(content_info.name);
- // Reset the bundle group if nothing left.
- if (!bundle_group_->FirstContentName()) {
- bundle_group_.reset();
+ // Delete the BUNDLE group.
+ bundles_.DeleteGroup(bundle_group);
+ } else {
+ transports_.RemoveTransportForMid(content_info.name);
+ if (bundle_group) {
+ // Remove the rejected content from the |bundle_group|.
+ bundles_.DeleteMid(bundle_group, content_info.name);
}
}
- MaybeDestroyJsepTransport(content_info.name);
}
bool JsepTransportController::HandleBundledContent(
- const cricket::ContentInfo& content_info) {
- auto jsep_transport = GetJsepTransportByName(*bundled_mid());
+ const cricket::ContentInfo& content_info,
+ const cricket::ContentGroup& bundle_group) {
+ TRACE_EVENT0("webrtc", "JsepTransportController::HandleBundledContent");
+ RTC_DCHECK(bundle_group.FirstContentName());
+ auto jsep_transport =
+ GetJsepTransportByName(*bundle_group.FirstContentName());
RTC_DCHECK(jsep_transport);
// If the content is bundled, let the
// BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
// then destroy the cricket::JsepTransport.
- if (SetTransportForMid(content_info.name, jsep_transport)) {
- // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
- // because it means that we first create media transport and start
- // connecting it, and then we destroy it. We will need to address it before
- // video path is enabled.
- MaybeDestroyJsepTransport(content_info.name);
- return true;
- }
- return false;
-}
-
-bool JsepTransportController::SetTransportForMid(
- const std::string& mid,
- cricket::JsepTransport* jsep_transport) {
- RTC_DCHECK_RUN_ON(network_thread_);
- RTC_DCHECK(jsep_transport);
-
- auto it = mid_to_transport_.find(mid);
- if (it != mid_to_transport_.end() && it->second == jsep_transport)
- return true;
-
- pending_mids_.push_back(mid);
-
- if (it == mid_to_transport_.end()) {
- mid_to_transport_.insert(std::make_pair(mid, jsep_transport));
- } else {
- it->second = jsep_transport;
- }
-
- return config_.transport_observer->OnTransportChanged(
- mid, jsep_transport->rtp_transport(), jsep_transport->RtpDtlsTransport(),
- jsep_transport->data_channel_transport());
-}
-
-void JsepTransportController::RemoveTransportForMid(const std::string& mid) {
- RTC_DCHECK_RUN_ON(network_thread_);
- bool ret = config_.transport_observer->OnTransportChanged(mid, nullptr,
- nullptr, nullptr);
- // Calling OnTransportChanged with nullptr should always succeed, since it is
- // only expected to fail when adding media to a transport (not removing).
- RTC_DCHECK(ret);
-
- mid_to_transport_.erase(mid);
+ // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
+ // because it means that we first create media transport and start
+ // connecting it, and then we destroy it. We will need to address it before
+ // video path is enabled.
+ return transports_.SetTransportForMid(content_info.name, jsep_transport);
}
cricket::JsepTransportDescription
@@ -812,6 +858,8 @@ JsepTransportController::CreateJsepTransportDescription(
const cricket::TransportInfo& transport_info,
const std::vector<int>& encrypted_extension_ids,
int rtp_abs_sendtime_extn_id) {
+ TRACE_EVENT0("webrtc",
+ "JsepTransportController::CreateJsepTransportDescription");
const cricket::MediaContentDescription* content_desc =
content_info.media_description();
RTC_DCHECK(content_desc);
@@ -837,11 +885,11 @@ bool JsepTransportController::ShouldUpdateBundleGroup(
}
RTC_DCHECK(local_desc_ && remote_desc_);
- const cricket::ContentGroup* local_bundle =
- local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
- const cricket::ContentGroup* remote_bundle =
- remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
- return local_bundle && remote_bundle;
+ 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(
@@ -865,26 +913,31 @@ std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
return encrypted_header_extension_ids;
}
-std::vector<int>
-JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundle(
+std::map<const cricket::ContentGroup*, std::vector<int>>
+JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundles(
const cricket::SessionDescription* description) {
RTC_DCHECK(description);
- RTC_DCHECK(bundle_group_);
-
- std::vector<int> merged_ids;
+ RTC_DCHECK(!bundles_.bundle_groups().empty());
+ std::map<const cricket::ContentGroup*, std::vector<int>>
+ merged_encrypted_extension_ids_by_bundle;
// Union the encrypted header IDs in the group when bundle is enabled.
for (const cricket::ContentInfo& content_info : description->contents()) {
- if (bundle_group_->HasContentName(content_info.name)) {
- std::vector<int> extension_ids =
- GetEncryptedHeaderExtensionIds(content_info);
- for (int id : extension_ids) {
- if (!absl::c_linear_search(merged_ids, id)) {
- merged_ids.push_back(id);
- }
+ auto group = bundles_.LookupGroupByMid(content_info.name);
+ if (!group)
+ continue;
+ // Get or create list of IDs for the BUNDLE group.
+ std::vector<int>& merged_ids =
+ merged_encrypted_extension_ids_by_bundle[group];
+ // Add IDs not already in the list.
+ std::vector<int> extension_ids =
+ GetEncryptedHeaderExtensionIds(content_info);
+ for (int id : extension_ids) {
+ if (!absl::c_linear_search(merged_ids, id)) {
+ merged_ids.push_back(id);
}
}
}
- return merged_ids;
+ return merged_encrypted_extension_ids_by_bundle;
}
int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
@@ -899,32 +952,31 @@ int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
const webrtc::RtpExtension* send_time_extension =
webrtc::RtpExtension::FindHeaderExtensionByUri(
content_desc->rtp_header_extensions(),
- webrtc::RtpExtension::kAbsSendTimeUri);
+ webrtc::RtpExtension::kAbsSendTimeUri,
+ config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions
+ ? webrtc::RtpExtension::kPreferEncryptedExtension
+ : webrtc::RtpExtension::kDiscardEncryptedExtension);
return send_time_extension ? send_time_extension->id : -1;
}
const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
const std::string& mid) const {
- auto it = mid_to_transport_.find(mid);
- return it == mid_to_transport_.end() ? nullptr : it->second;
+ return transports_.GetTransportForMid(mid);
}
cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
const std::string& mid) {
- auto it = mid_to_transport_.find(mid);
- return it == mid_to_transport_.end() ? nullptr : it->second;
+ return transports_.GetTransportForMid(mid);
}
const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
const std::string& transport_name) const {
- auto it = jsep_transports_by_name_.find(transport_name);
- return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
+ return transports_.GetTransportByName(transport_name);
}
cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
const std::string& transport_name) {
- auto it = jsep_transports_by_name_.find(transport_name);
- return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
+ return transports_.GetTransportByName(transport_name);
}
RTCError JsepTransportController::MaybeCreateJsepTransport(
@@ -935,7 +987,21 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
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()) {
@@ -997,39 +1063,13 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
jsep_transport->SignalRtcpMuxActive.connect(
this, &JsepTransportController::UpdateAggregateStates_n);
- SetTransportForMid(content_info.name, jsep_transport.get());
-
- jsep_transports_by_name_[content_info.name] = std::move(jsep_transport);
+ transports_.RegisterTransport(content_info.name, std::move(jsep_transport));
UpdateAggregateStates_n();
return RTCError::OK();
}
-void JsepTransportController::MaybeDestroyJsepTransport(
- const std::string& mid) {
- auto jsep_transport = GetJsepTransportByName(mid);
- if (!jsep_transport) {
- return;
- }
-
- // Don't destroy the JsepTransport if there are still media sections referring
- // to it.
- for (const auto& kv : mid_to_transport_) {
- if (kv.second == jsep_transport) {
- return;
- }
- }
-
- jsep_transports_by_name_.erase(mid);
- UpdateAggregateStates_n();
-}
-
void JsepTransportController::DestroyAllJsepTransports_n() {
- for (const auto& jsep_transport : jsep_transports_by_name_) {
- config_.transport_observer->OnTransportChanged(jsep_transport.first,
- nullptr, nullptr, nullptr);
- }
-
- jsep_transports_by_name_.clear();
+ transports_.DestroyAllTransports();
}
void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
@@ -1159,6 +1199,7 @@ void JsepTransportController::OnTransportStateChanged_n(
}
void JsepTransportController::UpdateAggregateStates_n() {
+ TRACE_EVENT0("webrtc", "JsepTransportController::UpdateAggregateStates_n");
auto dtls_transports = GetDtlsTransports();
cricket::IceConnectionState new_connection_state =
cricket::kIceConnectionConnecting;
@@ -1174,7 +1215,7 @@ void JsepTransportController::UpdateAggregateStates_n() {
bool all_done_gathering = !dtls_transports.empty();
std::map<IceTransportState, int> ice_state_counts;
- std::map<cricket::DtlsTransportState, int> dtls_state_counts;
+ std::map<DtlsTransportState, int> dtls_state_counts;
for (const auto& dtls : dtls_transports) {
any_failed = any_failed || dtls->ice_transport()->GetState() ==
@@ -1276,16 +1317,15 @@ void JsepTransportController::UpdateAggregateStates_n() {
// Note that "connecting" is only a valid state for DTLS transports while
// "checking", "completed" and "disconnected" are only valid for ICE
// transports.
- int total_connected = total_ice_connected +
- dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTED];
+ int total_connected =
+ total_ice_connected + dtls_state_counts[DtlsTransportState::kConnected];
int total_dtls_connecting =
- dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTING];
+ dtls_state_counts[DtlsTransportState::kConnecting];
int total_failed =
- total_ice_failed + dtls_state_counts[cricket::DTLS_TRANSPORT_FAILED];
+ total_ice_failed + dtls_state_counts[DtlsTransportState::kFailed];
int total_closed =
- total_ice_closed + dtls_state_counts[cricket::DTLS_TRANSPORT_CLOSED];
- int total_new =
- total_ice_new + dtls_state_counts[cricket::DTLS_TRANSPORT_NEW];
+ total_ice_closed + dtls_state_counts[DtlsTransportState::kClosed];
+ int total_new = total_ice_new + dtls_state_counts[DtlsTransportState::kNew];
int total_transports = total_ice * 2;
if (total_failed > 0) {
@@ -1347,4 +1387,21 @@ void JsepTransportController::OnDtlsHandshakeError(
config_.on_dtls_handshake_error_(error);
}
+bool JsepTransportController::OnTransportChanged(
+ const std::string& mid,
+ cricket::JsepTransport* jsep_transport) {
+ if (config_.transport_observer) {
+ if (jsep_transport) {
+ return config_.transport_observer->OnTransportChanged(
+ mid, jsep_transport->rtp_transport(),
+ jsep_transport->RtpDtlsTransport(),
+ jsep_transport->data_channel_transport());
+ } else {
+ return config_.transport_observer->OnTransportChanged(mid, nullptr,
+ nullptr, nullptr);
+ }
+ }
+ return false;
+}
+
} // namespace webrtc