blob: 7b445741a2f35d6814785baebb575013d874d48a [file] [log] [blame]
Zhi Huange818b6e2018-02-22 15:26:27 -08001/*
2 * Copyright 2017 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/jsep_transport_controller.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080012
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000013#include <stddef.h>
14
Harald Alvestrand9dea3932021-06-10 06:03:06 +000015#include <functional>
Zhi Huange818b6e2018-02-22 15:26:27 -080016#include <memory>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000017#include <string>
Harald Alvestrandde22ab22021-06-17 10:45:33 +000018#include <type_traits>
Zhi Huange818b6e2018-02-22 15:26:27 -080019#include <utility>
20
Steve Anton64b626b2019-01-28 17:25:26 -080021#include "absl/algorithm/container.h"
Mirko Bonadei9f6808b2021-05-21 20:46:09 +020022#include "api/dtls_transport_interface.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000023#include "api/rtp_parameters.h"
Artem Titovd15a5752021-02-10 14:31:24 +010024#include "api/sequence_checker.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000025#include "api/transport/enums.h"
26#include "media/sctp/sctp_transport_internal.h"
27#include "p2p/base/dtls_transport.h"
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -080028#include "p2p/base/ice_transport_internal.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000029#include "p2p/base/p2p_constants.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080030#include "p2p/base/port.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080031#include "rtc_base/checks.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000032#include "rtc_base/location.h"
33#include "rtc_base/logging.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080034#include "rtc_base/thread.h"
Markus Handell518669d2021-06-07 13:30:46 +020035#include "rtc_base/trace_event.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080036
37using webrtc::SdpType;
38
Zhi Huange818b6e2018-02-22 15:26:27 -080039namespace webrtc {
40
41JsepTransportController::JsepTransportController(
Zhi Huange818b6e2018-02-22 15:26:27 -080042 rtc::Thread* network_thread,
43 cricket::PortAllocator* port_allocator,
Harald Alvestrand0ccfbd22021-04-08 07:25:04 +000044 AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
Zhi Huange818b6e2018-02-22 15:26:27 -080045 Config config)
Tommic3257d02021-02-10 17:40:08 +000046 : network_thread_(network_thread),
Zhi Huange818b6e2018-02-22 15:26:27 -080047 port_allocator_(port_allocator),
Harald Alvestrand0ccfbd22021-04-08 07:25:04 +000048 async_dns_resolver_factory_(async_dns_resolver_factory),
Harald Alvestrand9dea3932021-06-10 06:03:06 +000049 transports_(
50 [this](const std::string& mid, cricket::JsepTransport* transport) {
51 return OnTransportChanged(mid, transport);
52 },
53 [this]() {
54 RTC_DCHECK_RUN_ON(network_thread_);
55 UpdateAggregateStates_n();
56 }),
Harald Alvestrand133c0522021-01-29 14:27:12 +000057 config_(config),
Taylor Brandstetter8591eff2021-08-11 14:56:38 -070058 active_reset_srtp_params_(config.active_reset_srtp_params),
59 bundles_(config.bundle_policy) {
Artem Titov880fa812021-07-30 22:30:23 +020060 // The `transport_observer` is assumed to be non-null.
Zhi Huang365381f2018-04-13 16:44:34 -070061 RTC_DCHECK(config_.transport_observer);
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +020062 RTC_DCHECK(config_.rtcp_handler);
Qingsi Wang25ec8882019-11-15 12:33:05 -080063 RTC_DCHECK(config_.ice_transport_factory);
Lahiru Ginnaliya Gamathige70f9e242021-01-27 23:32:46 -080064 RTC_DCHECK(config_.on_dtls_handshake_error_);
Jonas Orelanded99dae2022-03-09 09:28:10 +010065 RTC_DCHECK(config_.field_trials);
Zhi Huang365381f2018-04-13 16:44:34 -070066}
Zhi Huange818b6e2018-02-22 15:26:27 -080067
68JsepTransportController::~JsepTransportController() {
69 // Channel destructors may try to send packets, so this needs to happen on
70 // the network thread.
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +010071 RTC_DCHECK_RUN_ON(network_thread_);
72 DestroyAllJsepTransports_n();
Zhi Huange818b6e2018-02-22 15:26:27 -080073}
74
75RTCError JsepTransportController::SetLocalDescription(
76 SdpType type,
77 const cricket::SessionDescription* description) {
Markus Handell518669d2021-06-07 13:30:46 +020078 TRACE_EVENT0("webrtc", "JsepTransportController::SetLocalDescription");
Zhi Huange818b6e2018-02-22 15:26:27 -080079 if (!network_thread_->IsCurrent()) {
80 return network_thread_->Invoke<RTCError>(
81 RTC_FROM_HERE, [=] { return SetLocalDescription(type, description); });
82 }
83
Niels Möller5cf0ef02021-01-18 14:00:36 +010084 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -080085 if (!initial_offerer_.has_value()) {
86 initial_offerer_.emplace(type == SdpType::kOffer);
87 if (*initial_offerer_) {
88 SetIceRole_n(cricket::ICEROLE_CONTROLLING);
89 } else {
90 SetIceRole_n(cricket::ICEROLE_CONTROLLED);
91 }
92 }
93 return ApplyDescription_n(/*local=*/true, type, description);
94}
95
96RTCError JsepTransportController::SetRemoteDescription(
97 SdpType type,
98 const cricket::SessionDescription* description) {
Markus Handell518669d2021-06-07 13:30:46 +020099 TRACE_EVENT0("webrtc", "JsepTransportController::SetRemoteDescription");
Zhi Huange818b6e2018-02-22 15:26:27 -0800100 if (!network_thread_->IsCurrent()) {
101 return network_thread_->Invoke<RTCError>(
102 RTC_FROM_HERE, [=] { return SetRemoteDescription(type, description); });
103 }
104
Niels Möller5cf0ef02021-01-18 14:00:36 +0100105 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800106 return ApplyDescription_n(/*local=*/false, type, description);
107}
108
109RtpTransportInternal* JsepTransportController::GetRtpTransport(
Harald Alvestrand8f429922022-05-04 10:32:30 +0000110 absl::string_view mid) const {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100111 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 10:48:35 -0700112 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800113 if (!jsep_transport) {
114 return nullptr;
115 }
116 return jsep_transport->rtp_transport();
117}
118
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700119DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700120 const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100121 RTC_DCHECK_RUN_ON(network_thread_);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700122 auto jsep_transport = GetJsepTransportForMid(mid);
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700123 if (!jsep_transport) {
Anton Sukhanov7940da02018-10-10 10:34:49 -0700124 return nullptr;
125 }
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700126 return jsep_transport->data_channel_transport();
Anton Sukhanov7940da02018-10-10 10:34:49 -0700127}
128
Zhi Huange818b6e2018-02-22 15:26:27 -0800129cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
Harald Alvestrandad88c882018-11-28 16:47:46 +0100130 const std::string& mid) {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100131 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 10:48:35 -0700132 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800133 if (!jsep_transport) {
134 return nullptr;
135 }
136 return jsep_transport->rtp_dtls_transport();
137}
138
Harald Alvestrandad88c882018-11-28 16:47:46 +0100139const cricket::DtlsTransportInternal*
140JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100141 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 10:48:35 -0700142 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800143 if (!jsep_transport) {
144 return nullptr;
145 }
146 return jsep_transport->rtcp_dtls_transport();
147}
148
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100149rtc::scoped_refptr<webrtc::DtlsTransport>
Harald Alvestrandad88c882018-11-28 16:47:46 +0100150JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100151 RTC_DCHECK_RUN_ON(network_thread_);
Harald Alvestrandad88c882018-11-28 16:47:46 +0100152 auto jsep_transport = GetJsepTransportForMid(mid);
153 if (!jsep_transport) {
154 return nullptr;
155 }
156 return jsep_transport->RtpDtlsTransport();
157}
158
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700159rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
160 const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100161 RTC_DCHECK_RUN_ON(network_thread_);
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700162 auto jsep_transport = GetJsepTransportForMid(mid);
163 if (!jsep_transport) {
164 return nullptr;
165 }
166 return jsep_transport->SctpTransport();
167}
168
Zhi Huange818b6e2018-02-22 15:26:27 -0800169void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
Tomas Gunnarssone1c8a432021-04-08 15:15:28 +0200170 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800171 ice_config_ = config;
172 for (auto& dtls : GetDtlsTransports()) {
173 dtls->ice_transport()->SetIceConfig(ice_config_);
174 }
175}
176
177void JsepTransportController::SetNeedsIceRestartFlag() {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100178 RTC_DCHECK_RUN_ON(network_thread_);
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000179 for (auto& transport : transports_.Transports()) {
180 transport->SetNeedsIceRestartFlag();
Zhi Huange818b6e2018-02-22 15:26:27 -0800181 }
182}
183
184bool JsepTransportController::NeedsIceRestart(
185 const std::string& transport_name) const {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100186 RTC_DCHECK_RUN_ON(network_thread_);
187
Zhi Huang365381f2018-04-13 16:44:34 -0700188 const cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700189 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800190 if (!transport) {
191 return false;
192 }
193 return transport->needs_ice_restart();
194}
195
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200196absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
Zhi Huange830e682018-03-30 10:48:35 -0700197 const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100198 // TODO(tommi): Remove this hop. Currently it's called from the signaling
199 // thread during negotiations, potentially multiple times.
200 // WebRtcSessionDescriptionFactory::InternalCreateAnswer is one example.
Zhi Huange818b6e2018-02-22 15:26:27 -0800201 if (!network_thread_->IsCurrent()) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200202 return network_thread_->Invoke<absl::optional<rtc::SSLRole>>(
Zhi Huange830e682018-03-30 10:48:35 -0700203 RTC_FROM_HERE, [&] { return GetDtlsRole(mid); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800204 }
205
Tomas Gunnarsson92eebef2021-02-10 13:05:44 +0100206 RTC_DCHECK_RUN_ON(network_thread_);
207
Zhi Huang365381f2018-04-13 16:44:34 -0700208 const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800209 if (!t) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200210 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 15:26:27 -0800211 }
212 return t->GetDtlsRole();
213}
214
215bool JsepTransportController::SetLocalCertificate(
216 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
217 if (!network_thread_->IsCurrent()) {
218 return network_thread_->Invoke<bool>(
219 RTC_FROM_HERE, [&] { return SetLocalCertificate(certificate); });
220 }
221
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100222 RTC_DCHECK_RUN_ON(network_thread_);
223
Zhi Huange818b6e2018-02-22 15:26:27 -0800224 // Can't change a certificate, or set a null certificate.
225 if (certificate_ || !certificate) {
226 return false;
227 }
228 certificate_ = certificate;
229
230 // Set certificate for JsepTransport, which verifies it matches the
231 // fingerprint in SDP, and DTLS transport.
232 // Fallback from DTLS to SDES is not supported.
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000233 for (auto& transport : transports_.Transports()) {
234 transport->SetLocalCertificate(certificate_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800235 }
236 for (auto& dtls : GetDtlsTransports()) {
237 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
238 RTC_DCHECK(set_cert_success);
239 }
240 return true;
241}
242
243rtc::scoped_refptr<rtc::RTCCertificate>
244JsepTransportController::GetLocalCertificate(
245 const std::string& transport_name) const {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100246 RTC_DCHECK_RUN_ON(network_thread_);
247
Zhi Huang365381f2018-04-13 16:44:34 -0700248 const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800249 if (!t) {
250 return nullptr;
251 }
252 return t->GetLocalCertificate();
253}
254
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800255std::unique_ptr<rtc::SSLCertChain>
256JsepTransportController::GetRemoteSSLCertChain(
Zhi Huange818b6e2018-02-22 15:26:27 -0800257 const std::string& transport_name) const {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100258 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800259
Zhi Huange830e682018-03-30 10:48:35 -0700260 // Get the certificate from the RTP transport's DTLS handshake. Should be
261 // identical to the RTCP transport's, since they were given the same remote
Zhi Huange818b6e2018-02-22 15:26:27 -0800262 // fingerprint.
Zhi Huange830e682018-03-30 10:48:35 -0700263 auto jsep_transport = GetJsepTransportByName(transport_name);
264 if (!jsep_transport) {
265 return nullptr;
266 }
267 auto dtls = jsep_transport->rtp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800268 if (!dtls) {
269 return nullptr;
270 }
271
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800272 return dtls->GetRemoteSSLCertChain();
Zhi Huange818b6e2018-02-22 15:26:27 -0800273}
274
275void JsepTransportController::MaybeStartGathering() {
276 if (!network_thread_->IsCurrent()) {
277 network_thread_->Invoke<void>(RTC_FROM_HERE,
278 [&] { MaybeStartGathering(); });
279 return;
280 }
281
282 for (auto& dtls : GetDtlsTransports()) {
283 dtls->ice_transport()->MaybeStartGathering();
284 }
285}
286
287RTCError JsepTransportController::AddRemoteCandidates(
288 const std::string& transport_name,
289 const cricket::Candidates& candidates) {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100290 RTC_DCHECK_RUN_ON(network_thread_);
Tomas Gunnarsson8cb97062021-02-08 18:57:04 +0100291 RTC_DCHECK(VerifyCandidates(candidates).ok());
Zhi Huange830e682018-03-30 10:48:35 -0700292 auto jsep_transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800293 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700294 RTC_LOG(LS_WARNING) << "Not adding candidate because the JsepTransport "
295 "doesn't exist. Ignore it.";
296 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -0800297 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800298 return jsep_transport->AddRemoteCandidates(candidates);
299}
300
301RTCError JsepTransportController::RemoveRemoteCandidates(
302 const cricket::Candidates& candidates) {
303 if (!network_thread_->IsCurrent()) {
304 return network_thread_->Invoke<RTCError>(
305 RTC_FROM_HERE, [&] { return RemoveRemoteCandidates(candidates); });
306 }
307
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100308 RTC_DCHECK_RUN_ON(network_thread_);
309
Zhi Huange818b6e2018-02-22 15:26:27 -0800310 // Verify each candidate before passing down to the transport layer.
311 RTCError error = VerifyCandidates(candidates);
312 if (!error.ok()) {
313 return error;
314 }
315
316 std::map<std::string, cricket::Candidates> candidates_by_transport_name;
317 for (const cricket::Candidate& cand : candidates) {
318 if (!cand.transport_name().empty()) {
319 candidates_by_transport_name[cand.transport_name()].push_back(cand);
320 } else {
321 RTC_LOG(LS_ERROR) << "Not removing candidate because it does not have a "
322 "transport name set: "
Qingsi Wang20232a92019-09-06 12:51:17 -0700323 << cand.ToSensitiveString();
Zhi Huange818b6e2018-02-22 15:26:27 -0800324 }
325 }
326
327 for (const auto& kv : candidates_by_transport_name) {
328 const std::string& transport_name = kv.first;
329 const cricket::Candidates& candidates = kv.second;
Zhi Huang365381f2018-04-13 16:44:34 -0700330 cricket::JsepTransport* jsep_transport =
Zhi Huange830e682018-03-30 10:48:35 -0700331 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800332 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700333 RTC_LOG(LS_WARNING)
334 << "Not removing candidate because the JsepTransport doesn't exist.";
335 continue;
Zhi Huange818b6e2018-02-22 15:26:27 -0800336 }
337 for (const cricket::Candidate& candidate : candidates) {
Harald Alvestrandad88c882018-11-28 16:47:46 +0100338 cricket::DtlsTransportInternal* dtls =
339 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
340 ? jsep_transport->rtp_dtls_transport()
341 : jsep_transport->rtcp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800342 if (dtls) {
343 dtls->ice_transport()->RemoveRemoteCandidate(candidate);
344 }
345 }
346 }
347 return RTCError::OK();
348}
349
350bool JsepTransportController::GetStats(const std::string& transport_name,
351 cricket::TransportStats* stats) {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100352 RTC_DCHECK_RUN_ON(network_thread_);
353
Zhi Huang365381f2018-04-13 16:44:34 -0700354 cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800355 if (!transport) {
356 return false;
357 }
358 return transport->GetStats(stats);
359}
360
Zhi Huangb57e1692018-06-12 11:41:11 -0700361void JsepTransportController::SetActiveResetSrtpParams(
362 bool active_reset_srtp_params) {
363 if (!network_thread_->IsCurrent()) {
364 network_thread_->Invoke<void>(RTC_FROM_HERE, [=] {
365 SetActiveResetSrtpParams(active_reset_srtp_params);
366 });
367 return;
368 }
Harald Alvestrand133c0522021-01-29 14:27:12 +0000369 RTC_DCHECK_RUN_ON(network_thread_);
Harald Alvestrand97597c02021-11-04 12:01:23 +0000370 RTC_LOG(LS_INFO)
Zhi Huangb57e1692018-06-12 11:41:11 -0700371 << "Updating the active_reset_srtp_params for JsepTransportController: "
372 << active_reset_srtp_params;
Harald Alvestrand133c0522021-01-29 14:27:12 +0000373 active_reset_srtp_params_ = active_reset_srtp_params;
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000374 for (auto& transport : transports_.Transports()) {
375 transport->SetActiveResetSrtpParams(active_reset_srtp_params);
Zhi Huangb57e1692018-06-12 11:41:11 -0700376 }
377}
378
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700379RTCError JsepTransportController::RollbackTransports() {
Eldar Rello5ab79e62019-10-09 18:29:44 +0300380 if (!network_thread_->IsCurrent()) {
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700381 return network_thread_->Invoke<RTCError>(
382 RTC_FROM_HERE, [=] { return RollbackTransports(); });
Eldar Rello5ab79e62019-10-09 18:29:44 +0300383 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200384 RTC_DCHECK_RUN_ON(network_thread_);
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700385 bundles_.Rollback();
386 if (!transports_.RollbackTransports()) {
387 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
388 "Failed to roll back transport state.");
389 }
390 return RTCError::OK();
Eldar Rello5ab79e62019-10-09 18:29:44 +0300391}
392
Qingsi Wang25ec8882019-11-15 12:33:05 -0800393rtc::scoped_refptr<webrtc::IceTransportInterface>
394JsepTransportController::CreateIceTransport(const std::string& transport_name,
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800395 bool rtcp) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800396 int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
397 : cricket::ICE_CANDIDATE_COMPONENT_RTP;
398
Qingsi Wang25ec8882019-11-15 12:33:05 -0800399 IceTransportInit init;
400 init.set_port_allocator(port_allocator_);
Harald Alvestrand0ccfbd22021-04-08 07:25:04 +0000401 init.set_async_dns_resolver_factory(async_dns_resolver_factory_);
Qingsi Wang25ec8882019-11-15 12:33:05 -0800402 init.set_event_log(config_.event_log);
Jonas Oreland340cb5e2022-03-17 09:14:16 +0100403 init.set_field_trials(config_.field_trials);
Qingsi Wang25ec8882019-11-15 12:33:05 -0800404 return config_.ice_transport_factory->CreateIceTransport(
405 transport_name, component, std::move(init));
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800406}
407
408std::unique_ptr<cricket::DtlsTransportInternal>
409JsepTransportController::CreateDtlsTransport(
Anton Sukhanovac6c0962019-07-10 15:44:56 -0700410 const cricket::ContentInfo& content_info,
Niels Möller2a707032020-06-16 16:39:13 +0200411 cricket::IceTransportInternal* ice) {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100412 RTC_DCHECK_RUN_ON(network_thread_);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800413
414 std::unique_ptr<cricket::DtlsTransportInternal> dtls;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700415
Niels Möller2a707032020-06-16 16:39:13 +0200416 if (config_.dtls_transport_factory) {
Qingsi Wang25ec8882019-11-15 12:33:05 -0800417 dtls = config_.dtls_transport_factory->CreateDtlsTransport(
Tommi653bab62021-04-03 17:53:54 +0200418 ice, config_.crypto_options, config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 15:26:27 -0800419 } else {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200420 dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
Tommi653bab62021-04-03 17:53:54 +0200421 config_.event_log,
422 config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 15:26:27 -0800423 }
424
425 RTC_DCHECK(dtls);
Zhi Huange818b6e2018-02-22 15:26:27 -0800426 dtls->ice_transport()->SetIceRole(ice_role_);
427 dtls->ice_transport()->SetIceTiebreaker(ice_tiebreaker_);
428 dtls->ice_transport()->SetIceConfig(ice_config_);
429 if (certificate_) {
430 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
431 RTC_DCHECK(set_cert_success);
432 }
433
434 // Connect to signals offered by the DTLS and ICE transport.
435 dtls->SignalWritableState.connect(
436 this, &JsepTransportController::OnTransportWritableState_n);
437 dtls->SignalReceivingState.connect(
438 this, &JsepTransportController::OnTransportReceivingState_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800439 dtls->ice_transport()->SignalGatheringState.connect(
440 this, &JsepTransportController::OnTransportGatheringState_n);
441 dtls->ice_transport()->SignalCandidateGathered.connect(
442 this, &JsepTransportController::OnTransportCandidateGathered_n);
Eldar Relloda13ea22019-06-01 12:23:43 +0300443 dtls->ice_transport()->SignalCandidateError.connect(
444 this, &JsepTransportController::OnTransportCandidateError_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800445 dtls->ice_transport()->SignalCandidatesRemoved.connect(
446 this, &JsepTransportController::OnTransportCandidatesRemoved_n);
447 dtls->ice_transport()->SignalRoleConflict.connect(
448 this, &JsepTransportController::OnTransportRoleConflict_n);
449 dtls->ice_transport()->SignalStateChanged.connect(
450 this, &JsepTransportController::OnTransportStateChanged_n);
Jonas Olsson7a6739e2019-01-15 16:31:55 +0100451 dtls->ice_transport()->SignalIceTransportStateChanged.connect(
452 this, &JsepTransportController::OnTransportStateChanged_n);
Alex Drake00c7ecf2019-08-06 10:54:47 -0700453 dtls->ice_transport()->SignalCandidatePairChanged.connect(
454 this, &JsepTransportController::OnTransportCandidatePairChanged_n);
Lahiru Ginnaliya Gamathige16ab60c2021-02-02 07:27:09 -0800455
456 dtls->SubscribeDtlsHandshakeError(
457 [this](rtc::SSLHandshakeError error) { OnDtlsHandshakeError(error); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800458 return dtls;
459}
460
461std::unique_ptr<webrtc::RtpTransport>
462JsepTransportController::CreateUnencryptedRtpTransport(
463 const std::string& transport_name,
464 rtc::PacketTransportInternal* rtp_packet_transport,
465 rtc::PacketTransportInternal* rtcp_packet_transport) {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100466 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 10:48:35 -0700467 auto unencrypted_rtp_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200468 std::make_unique<RtpTransport>(rtcp_packet_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700469 unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
470 if (rtcp_packet_transport) {
471 unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
472 }
473 return unencrypted_rtp_transport;
Zhi Huange818b6e2018-02-22 15:26:27 -0800474}
475
476std::unique_ptr<webrtc::SrtpTransport>
477JsepTransportController::CreateSdesTransport(
478 const std::string& transport_name,
Zhi Huange830e682018-03-30 10:48:35 -0700479 cricket::DtlsTransportInternal* rtp_dtls_transport,
480 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100481 RTC_DCHECK_RUN_ON(network_thread_);
Jonas Orelanded99dae2022-03-09 09:28:10 +0100482 auto srtp_transport = std::make_unique<webrtc::SrtpTransport>(
483 rtcp_dtls_transport == nullptr, *config_.field_trials);
Zhi Huange830e682018-03-30 10:48:35 -0700484 RTC_DCHECK(rtp_dtls_transport);
485 srtp_transport->SetRtpPacketTransport(rtp_dtls_transport);
486 if (rtcp_dtls_transport) {
487 srtp_transport->SetRtcpPacketTransport(rtcp_dtls_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800488 }
489 if (config_.enable_external_auth) {
490 srtp_transport->EnableExternalAuth();
491 }
492 return srtp_transport;
493}
494
495std::unique_ptr<webrtc::DtlsSrtpTransport>
496JsepTransportController::CreateDtlsSrtpTransport(
497 const std::string& transport_name,
498 cricket::DtlsTransportInternal* rtp_dtls_transport,
499 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Harald Alvestrand133c0522021-01-29 14:27:12 +0000500 RTC_DCHECK_RUN_ON(network_thread_);
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200501 auto dtls_srtp_transport = std::make_unique<webrtc::DtlsSrtpTransport>(
Jonas Orelanded99dae2022-03-09 09:28:10 +0100502 rtcp_dtls_transport == nullptr, *config_.field_trials);
Zhi Huang27f3bf52018-03-26 21:37:23 -0700503 if (config_.enable_external_auth) {
Zhi Huang365381f2018-04-13 16:44:34 -0700504 dtls_srtp_transport->EnableExternalAuth();
Zhi Huang27f3bf52018-03-26 21:37:23 -0700505 }
Zhi Huang97d5e5b2018-03-27 00:09:01 +0000506
Zhi Huange818b6e2018-02-22 15:26:27 -0800507 dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
508 rtcp_dtls_transport);
Harald Alvestrand133c0522021-01-29 14:27:12 +0000509 dtls_srtp_transport->SetActiveResetSrtpParams(active_reset_srtp_params_);
Lahiru Ginnaliya Gamathigec32f00e2021-02-17 00:43:21 -0800510 // Capturing this in the callback because JsepTransportController will always
511 // outlive the DtlsSrtpTransport.
512 dtls_srtp_transport->SetOnDtlsStateChange([this]() {
513 RTC_DCHECK_RUN_ON(this->network_thread_);
514 this->UpdateAggregateStates_n();
515 });
Zhi Huange818b6e2018-02-22 15:26:27 -0800516 return dtls_srtp_transport;
517}
518
519std::vector<cricket::DtlsTransportInternal*>
520JsepTransportController::GetDtlsTransports() {
Tomas Gunnarsson20f74562021-02-04 10:22:50 +0100521 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800522 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000523 for (auto jsep_transport : transports_.Transports()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800524 RTC_DCHECK(jsep_transport);
525 if (jsep_transport->rtp_dtls_transport()) {
526 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
527 }
528
529 if (jsep_transport->rtcp_dtls_transport()) {
530 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
531 }
532 }
533 return dtls_transports;
534}
535
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700536std::vector<cricket::DtlsTransportInternal*>
537JsepTransportController::GetActiveDtlsTransports() {
538 RTC_DCHECK_RUN_ON(network_thread_);
539 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
540 for (auto jsep_transport : transports_.ActiveTransports()) {
541 RTC_DCHECK(jsep_transport);
542 if (jsep_transport->rtp_dtls_transport()) {
543 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
544 }
545
546 if (jsep_transport->rtcp_dtls_transport()) {
547 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
548 }
549 }
550 return dtls_transports;
551}
552
Zhi Huange818b6e2018-02-22 15:26:27 -0800553RTCError JsepTransportController::ApplyDescription_n(
554 bool local,
555 SdpType type,
556 const cricket::SessionDescription* description) {
Markus Handell518669d2021-06-07 13:30:46 +0200557 TRACE_EVENT0("webrtc", "JsepTransportController::ApplyDescription_n");
Zhi Huange818b6e2018-02-22 15:26:27 -0800558 RTC_DCHECK(description);
559
560 if (local) {
561 local_desc_ = description;
562 } else {
563 remote_desc_ = description;
564 }
565
Zhi Huange830e682018-03-30 10:48:35 -0700566 RTCError error;
Henrik Boströmf8187e02021-04-26 21:04:26 +0200567 error = ValidateAndMaybeUpdateBundleGroups(local, type, description);
Zhi Huange830e682018-03-30 10:48:35 -0700568 if (!error.ok()) {
569 return error;
Zhi Huange818b6e2018-02-22 15:26:27 -0800570 }
571
Henrik Boströmf8187e02021-04-26 21:04:26 +0200572 std::map<const cricket::ContentGroup*, std::vector<int>>
573 merged_encrypted_extension_ids_by_bundle;
Harald Alvestrand9f9bf382021-06-08 04:12:37 +0000574 if (!bundles_.bundle_groups().empty()) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200575 merged_encrypted_extension_ids_by_bundle =
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000576 MergeEncryptedHeaderExtensionIdsForBundles(description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800577 }
578
579 for (const cricket::ContentInfo& content_info : description->contents()) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200580 // Don't create transports for rejected m-lines and bundled m-lines.
Zhi Huange818b6e2018-02-22 15:26:27 -0800581 if (content_info.rejected ||
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000582 !bundles_.IsFirstMidInGroup(content_info.name)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800583 continue;
584 }
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -0800585 error = MaybeCreateJsepTransport(local, content_info, *description);
Zhi Huange830e682018-03-30 10:48:35 -0700586 if (!error.ok()) {
587 return error;
588 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800589 }
590
591 RTC_DCHECK(description->contents().size() ==
592 description->transport_infos().size());
593 for (size_t i = 0; i < description->contents().size(); ++i) {
594 const cricket::ContentInfo& content_info = description->contents()[i];
595 const cricket::TransportInfo& transport_info =
596 description->transport_infos()[i];
Taylor Brandstetter1c7ecef2021-08-11 12:38:35 -0700597
Zhi Huange818b6e2018-02-22 15:26:27 -0800598 if (content_info.rejected) {
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700599 // This may cause groups to be removed from |bundles_.bundle_groups()|.
600 HandleRejectedContent(content_info);
Zhi Huange818b6e2018-02-22 15:26:27 -0800601 continue;
602 }
603
Henrik Boströmf8187e02021-04-26 21:04:26 +0200604 const cricket::ContentGroup* established_bundle_group =
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000605 bundles_.LookupGroupByMid(content_info.name);
Henrik Boströmf8187e02021-04-26 21:04:26 +0200606
607 // For bundle members that are not BUNDLE-tagged (not first in the group),
608 // configure their transport to be the same as the BUNDLE-tagged transport.
609 if (established_bundle_group &&
610 content_info.name != *established_bundle_group->FirstContentName()) {
611 if (!HandleBundledContent(content_info, *established_bundle_group)) {
Zhi Huang365381f2018-04-13 16:44:34 -0700612 return RTCError(RTCErrorType::INVALID_PARAMETER,
Henrik Boströmf8187e02021-04-26 21:04:26 +0200613 "Failed to process the bundled m= section with "
614 "mid='" +
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000615 content_info.name + "'.");
Zhi Huang365381f2018-04-13 16:44:34 -0700616 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800617 continue;
618 }
619
Zhi Huange830e682018-03-30 10:48:35 -0700620 error = ValidateContent(content_info);
621 if (!error.ok()) {
622 return error;
623 }
624
Zhi Huange818b6e2018-02-22 15:26:27 -0800625 std::vector<int> extension_ids;
Henrik Boströmf8187e02021-04-26 21:04:26 +0200626 // Is BUNDLE-tagged (first in the group)?
627 if (established_bundle_group &&
628 content_info.name == *established_bundle_group->FirstContentName()) {
629 auto it = merged_encrypted_extension_ids_by_bundle.find(
630 established_bundle_group);
631 RTC_DCHECK(it != merged_encrypted_extension_ids_by_bundle.end());
632 extension_ids = it->second;
Zhi Huange818b6e2018-02-22 15:26:27 -0800633 } else {
634 extension_ids = GetEncryptedHeaderExtensionIds(content_info);
635 }
636
Zhi Huange830e682018-03-30 10:48:35 -0700637 int rtp_abs_sendtime_extn_id =
638 GetRtpAbsSendTimeHeaderExtensionId(content_info);
639
Zhi Huang365381f2018-04-13 16:44:34 -0700640 cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700641 GetJsepTransportForMid(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800642 RTC_DCHECK(transport);
643
644 SetIceRole_n(DetermineIceRole(transport, transport_info, type, local));
645
Zhi Huange818b6e2018-02-22 15:26:27 -0800646 cricket::JsepTransportDescription jsep_description =
647 CreateJsepTransportDescription(content_info, transport_info,
Niels Möllerdc80aaf2020-06-18 10:10:17 +0200648 extension_ids, rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800649 if (local) {
650 error =
651 transport->SetLocalJsepTransportDescription(jsep_description, type);
652 } else {
653 error =
654 transport->SetRemoteJsepTransportDescription(jsep_description, type);
655 }
656
657 if (!error.ok()) {
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000658 LOG_AND_RETURN_ERROR(
659 RTCErrorType::INVALID_PARAMETER,
660 "Failed to apply the description for m= section with mid='" +
661 content_info.name + "': " + error.message());
Zhi Huange818b6e2018-02-22 15:26:27 -0800662 }
663 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200664 if (type == SdpType::kAnswer) {
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000665 transports_.CommitTransports();
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700666 bundles_.Commit();
Eldar Rellod85ea752020-02-19 20:41:07 +0200667 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800668 return RTCError::OK();
669}
670
Henrik Boströmf8187e02021-04-26 21:04:26 +0200671RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroups(
Zhi Huangd2248f82018-04-10 14:41:03 -0700672 bool local,
673 SdpType type,
Zhi Huange830e682018-03-30 10:48:35 -0700674 const cricket::SessionDescription* description) {
675 RTC_DCHECK(description);
Zhi Huangd2248f82018-04-10 14:41:03 -0700676
Henrik Boströmf8187e02021-04-26 21:04:26 +0200677 std::vector<const cricket::ContentGroup*> new_bundle_groups =
678 description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
Artem Titov880fa812021-07-30 22:30:23 +0200679 // Verify `new_bundle_groups`.
Henrik Boströmf8187e02021-04-26 21:04:26 +0200680 std::map<std::string, const cricket::ContentGroup*> new_bundle_groups_by_mid;
681 for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000682 for (const std::string& content_name : new_bundle_group->content_names()) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200683 // The BUNDLE group must not contain a MID that is a member of a different
684 // BUNDLE group, or that contains the same MID multiple times.
685 if (new_bundle_groups_by_mid.find(content_name) !=
686 new_bundle_groups_by_mid.end()) {
687 return RTCError(RTCErrorType::INVALID_PARAMETER,
688 "A BUNDLE group contains a MID='" + content_name +
689 "' that is already in a BUNDLE group.");
690 }
691 new_bundle_groups_by_mid.insert(
692 std::make_pair(content_name, new_bundle_group));
693 // The BUNDLE group must not contain a MID that no m= section has.
Zhi Huangd2248f82018-04-10 14:41:03 -0700694 if (!description->GetContentByName(content_name)) {
695 return RTCError(RTCErrorType::INVALID_PARAMETER,
Henrik Boströmf8187e02021-04-26 21:04:26 +0200696 "A BUNDLE group contains a MID='" + content_name +
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000697 "' matching no m= section.");
Zhi Huangd2248f82018-04-10 14:41:03 -0700698 }
699 }
700 }
701
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700702 if (type == SdpType::kOffer) {
703 // For an offer, we need to verify that there is not a conflicting mapping
704 // between existing and new bundle groups. For example, if the existing
705 // groups are [[1,2],[3,4]] and new are [[1,3],[2,4]] or [[1,2,3,4]], or
706 // vice versa. Switching things around like this requires a separate offer
707 // that removes the relevant sections from their group, as per RFC 8843,
708 // section 7.5.2.
709 std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
710 new_bundle_groups_by_existing_bundle_groups;
711 std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
712 existing_bundle_groups_by_new_bundle_groups;
713 for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
714 for (const std::string& mid : new_bundle_group->content_names()) {
715 cricket::ContentGroup* existing_bundle_group =
716 bundles_.LookupGroupByMid(mid);
717 if (!existing_bundle_group) {
718 continue;
719 }
720 auto it = new_bundle_groups_by_existing_bundle_groups.find(
721 existing_bundle_group);
722 if (it != new_bundle_groups_by_existing_bundle_groups.end() &&
723 it->second != new_bundle_group) {
724 return RTCError(RTCErrorType::INVALID_PARAMETER,
725 "MID " + mid + " in the offer has changed group.");
726 }
727 new_bundle_groups_by_existing_bundle_groups.insert(
728 std::make_pair(existing_bundle_group, new_bundle_group));
729 it = existing_bundle_groups_by_new_bundle_groups.find(new_bundle_group);
730 if (it != existing_bundle_groups_by_new_bundle_groups.end() &&
731 it->second != existing_bundle_group) {
732 return RTCError(RTCErrorType::INVALID_PARAMETER,
733 "MID " + mid + " in the offer has changed group.");
734 }
735 existing_bundle_groups_by_new_bundle_groups.insert(
736 std::make_pair(new_bundle_group, existing_bundle_group));
737 }
738 }
739 } else if (type == SdpType::kAnswer) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200740 std::vector<const cricket::ContentGroup*> offered_bundle_groups =
741 local ? remote_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)
742 : local_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
Zhi Huangd2248f82018-04-10 14:41:03 -0700743
Henrik Boströmf8187e02021-04-26 21:04:26 +0200744 std::map<std::string, const cricket::ContentGroup*>
745 offered_bundle_groups_by_mid;
746 for (const cricket::ContentGroup* offered_bundle_group :
747 offered_bundle_groups) {
748 for (const std::string& content_name :
749 offered_bundle_group->content_names()) {
750 offered_bundle_groups_by_mid[content_name] = offered_bundle_group;
751 }
752 }
753
754 std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
755 new_bundle_groups_by_offered_bundle_groups;
756 for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
757 if (!new_bundle_group->FirstContentName()) {
758 // Empty groups could be a subset of any group.
759 continue;
760 }
761 // The group in the answer (new_bundle_group) must have a corresponding
762 // group in the offer (original_group), because the answer groups may only
763 // be subsets of the offer groups.
764 auto it = offered_bundle_groups_by_mid.find(
765 *new_bundle_group->FirstContentName());
766 if (it == offered_bundle_groups_by_mid.end()) {
767 return RTCError(RTCErrorType::INVALID_PARAMETER,
768 "A BUNDLE group was added in the answer that did not "
769 "exist in the offer.");
770 }
771 const cricket::ContentGroup* offered_bundle_group = it->second;
772 if (new_bundle_groups_by_offered_bundle_groups.find(
773 offered_bundle_group) !=
774 new_bundle_groups_by_offered_bundle_groups.end()) {
775 return RTCError(RTCErrorType::INVALID_PARAMETER,
776 "A MID in the answer has changed group.");
777 }
778 new_bundle_groups_by_offered_bundle_groups.insert(
779 std::make_pair(offered_bundle_group, new_bundle_group));
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000780 for (const std::string& content_name :
781 new_bundle_group->content_names()) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200782 it = offered_bundle_groups_by_mid.find(content_name);
783 // The BUNDLE group in answer should be a subset of offered group.
784 if (it == offered_bundle_groups_by_mid.end() ||
785 it->second != offered_bundle_group) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700786 return RTCError(RTCErrorType::INVALID_PARAMETER,
Henrik Boströmf8187e02021-04-26 21:04:26 +0200787 "A BUNDLE group in answer contains a MID='" +
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000788 content_name +
Henrik Boströmf8187e02021-04-26 21:04:26 +0200789 "' that was not in the offered group.");
Zhi Huangd2248f82018-04-10 14:41:03 -0700790 }
791 }
792 }
793
Harald Alvestrand9f9bf382021-06-08 04:12:37 +0000794 for (const auto& bundle_group : bundles_.bundle_groups()) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200795 for (const std::string& content_name : bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700796 // An answer that removes m= sections from pre-negotiated BUNDLE group
797 // without rejecting it, is invalid.
Henrik Boströmf8187e02021-04-26 21:04:26 +0200798 auto it = new_bundle_groups_by_mid.find(content_name);
799 if (it == new_bundle_groups_by_mid.end()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700800 auto* content_info = description->GetContentByName(content_name);
801 if (!content_info || !content_info->rejected) {
802 return RTCError(RTCErrorType::INVALID_PARAMETER,
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000803 "Answer cannot remove m= section with mid='" +
804 content_name +
805 "' from already-established BUNDLE group.");
Zhi Huangd2248f82018-04-10 14:41:03 -0700806 }
807 }
808 }
809 }
810 }
811
812 if (config_.bundle_policy ==
813 PeerConnectionInterface::kBundlePolicyMaxBundle &&
814 !description->HasGroup(cricket::GROUP_TYPE_BUNDLE)) {
815 return RTCError(RTCErrorType::INVALID_PARAMETER,
816 "max-bundle is used but no bundle group found.");
817 }
818
Taylor Brandstetter8591eff2021-08-11 14:56:38 -0700819 bundles_.Update(description, type);
Zhi Huange830e682018-03-30 10:48:35 -0700820
Harald Alvestrand9f9bf382021-06-08 04:12:37 +0000821 for (const auto& bundle_group : bundles_.bundle_groups()) {
Henrik Boströmf8187e02021-04-26 21:04:26 +0200822 if (!bundle_group->FirstContentName())
823 continue;
824
825 // The first MID in a BUNDLE group is BUNDLE-tagged.
826 auto bundled_content =
827 description->GetContentByName(*bundle_group->FirstContentName());
828 if (!bundled_content) {
829 return RTCError(
830 RTCErrorType::INVALID_PARAMETER,
831 "An m= section associated with the BUNDLE-tag doesn't exist.");
832 }
833
Artem Titov880fa812021-07-30 22:30:23 +0200834 // If the `bundled_content` is rejected, other contents in the bundle group
Henrik Boströmf8187e02021-04-26 21:04:26 +0200835 // must also be rejected.
836 if (bundled_content->rejected) {
837 for (const auto& content_name : bundle_group->content_names()) {
838 auto other_content = description->GetContentByName(content_name);
839 if (!other_content->rejected) {
840 return RTCError(RTCErrorType::INVALID_PARAMETER,
841 "The m= section with mid='" + content_name +
842 "' should be rejected.");
843 }
844 }
845 }
846 }
Zhi Huange830e682018-03-30 10:48:35 -0700847 return RTCError::OK();
848}
849
850RTCError JsepTransportController::ValidateContent(
851 const cricket::ContentInfo& content_info) {
852 if (config_.rtcp_mux_policy ==
853 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
854 content_info.type == cricket::MediaProtocolType::kRtp &&
855 !content_info.media_description()->rtcp_mux()) {
856 return RTCError(RTCErrorType::INVALID_PARAMETER,
Yura Yaroshevichbc1f9102020-06-03 21:15:22 +0000857 "The m= section with mid='" + content_info.name +
858 "' is invalid. RTCP-MUX is not "
Zhi Huange830e682018-03-30 10:48:35 -0700859 "enabled when it is required.");
860 }
861 return RTCError::OK();
862}
863
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700864void JsepTransportController::HandleRejectedContent(
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000865 const cricket::ContentInfo& content_info) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800866 // If the content is rejected, let the
867 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700868 // then destroy the cricket::JsepTransport.
Henrik Boströmf8187e02021-04-26 21:04:26 +0200869 cricket::ContentGroup* bundle_group =
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000870 bundles_.LookupGroupByMid(content_info.name);
Henrik Boströmf8187e02021-04-26 21:04:26 +0200871 if (bundle_group && !bundle_group->content_names().empty() &&
872 content_info.name == *bundle_group->FirstContentName()) {
873 // Rejecting a BUNDLE group's first mid means we are rejecting the entire
874 // group.
875 for (const auto& content_name : bundle_group->content_names()) {
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000876 transports_.RemoveTransportForMid(content_name);
Zhi Huange830e682018-03-30 10:48:35 -0700877 }
Henrik Boströmf8187e02021-04-26 21:04:26 +0200878 // Delete the BUNDLE group.
Harald Alvestrand2aa24f12021-06-08 09:51:19 +0000879 bundles_.DeleteGroup(bundle_group);
Henrik Boströmf8187e02021-04-26 21:04:26 +0200880 } else {
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000881 transports_.RemoveTransportForMid(content_info.name);
Henrik Boströmf8187e02021-04-26 21:04:26 +0200882 if (bundle_group) {
Artem Titov880fa812021-07-30 22:30:23 +0200883 // Remove the rejected content from the `bundle_group`.
Harald Alvestrand2aa24f12021-06-08 09:51:19 +0000884 bundles_.DeleteMid(bundle_group, content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700885 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800886 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800887}
888
Zhi Huang365381f2018-04-13 16:44:34 -0700889bool JsepTransportController::HandleBundledContent(
Henrik Boströmf8187e02021-04-26 21:04:26 +0200890 const cricket::ContentInfo& content_info,
891 const cricket::ContentGroup& bundle_group) {
Markus Handell518669d2021-06-07 13:30:46 +0200892 TRACE_EVENT0("webrtc", "JsepTransportController::HandleBundledContent");
Henrik Boströmf8187e02021-04-26 21:04:26 +0200893 RTC_DCHECK(bundle_group.FirstContentName());
894 auto jsep_transport =
895 GetJsepTransportByName(*bundle_group.FirstContentName());
Zhi Huangd2248f82018-04-10 14:41:03 -0700896 RTC_DCHECK(jsep_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800897 // If the content is bundled, let the
898 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700899 // then destroy the cricket::JsepTransport.
Harald Alvestrand4bb81ac2021-06-11 13:04:59 +0000900 // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
901 // because it means that we first create media transport and start
902 // connecting it, and then we destroy it. We will need to address it before
903 // video path is enabled.
904 return transports_.SetTransportForMid(content_info.name, jsep_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800905}
906
907cricket::JsepTransportDescription
908JsepTransportController::CreateJsepTransportDescription(
Harald Alvestrand1716d392019-06-03 20:35:45 +0200909 const cricket::ContentInfo& content_info,
910 const cricket::TransportInfo& transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700911 const std::vector<int>& encrypted_extension_ids,
Niels Möllerdc80aaf2020-06-18 10:10:17 +0200912 int rtp_abs_sendtime_extn_id) {
Markus Handell518669d2021-06-07 13:30:46 +0200913 TRACE_EVENT0("webrtc",
914 "JsepTransportController::CreateJsepTransportDescription");
Zhi Huange818b6e2018-02-22 15:26:27 -0800915 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200916 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800917 RTC_DCHECK(content_desc);
918 bool rtcp_mux_enabled = content_info.type == cricket::MediaProtocolType::kSctp
919 ? true
920 : content_desc->rtcp_mux();
921
922 return cricket::JsepTransportDescription(
Harald Alvestrand0d018412021-11-04 13:52:31 +0000923 rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
924 rtp_abs_sendtime_extn_id, transport_info.description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800925}
926
Zhi Huange818b6e2018-02-22 15:26:27 -0800927std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
928 const cricket::ContentInfo& content_info) {
929 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200930 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800931
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700932 if (!config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800933 return std::vector<int>();
934 }
935
936 std::vector<int> encrypted_header_extension_ids;
Mirko Bonadei739baf02019-01-27 17:29:42 +0100937 for (const auto& extension : content_desc->rtp_header_extensions()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800938 if (!extension.encrypt) {
939 continue;
940 }
Steve Anton64b626b2019-01-28 17:25:26 -0800941 if (!absl::c_linear_search(encrypted_header_extension_ids, extension.id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800942 encrypted_header_extension_ids.push_back(extension.id);
943 }
944 }
945 return encrypted_header_extension_ids;
946}
947
Henrik Boströmf8187e02021-04-26 21:04:26 +0200948std::map<const cricket::ContentGroup*, std::vector<int>>
949JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundles(
Zhi Huange818b6e2018-02-22 15:26:27 -0800950 const cricket::SessionDescription* description) {
951 RTC_DCHECK(description);
Harald Alvestrand9f9bf382021-06-08 04:12:37 +0000952 RTC_DCHECK(!bundles_.bundle_groups().empty());
Henrik Boströmf8187e02021-04-26 21:04:26 +0200953 std::map<const cricket::ContentGroup*, std::vector<int>>
954 merged_encrypted_extension_ids_by_bundle;
Zhi Huange818b6e2018-02-22 15:26:27 -0800955 // Union the encrypted header IDs in the group when bundle is enabled.
956 for (const cricket::ContentInfo& content_info : description->contents()) {
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000957 auto group = bundles_.LookupGroupByMid(content_info.name);
958 if (!group)
Henrik Boströmf8187e02021-04-26 21:04:26 +0200959 continue;
960 // Get or create list of IDs for the BUNDLE group.
961 std::vector<int>& merged_ids =
Harald Alvestrand11b92cf2021-06-17 14:03:09 +0000962 merged_encrypted_extension_ids_by_bundle[group];
Henrik Boströmf8187e02021-04-26 21:04:26 +0200963 // Add IDs not already in the list.
964 std::vector<int> extension_ids =
965 GetEncryptedHeaderExtensionIds(content_info);
966 for (int id : extension_ids) {
967 if (!absl::c_linear_search(merged_ids, id)) {
968 merged_ids.push_back(id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800969 }
970 }
971 }
Henrik Boströmf8187e02021-04-26 21:04:26 +0200972 return merged_encrypted_extension_ids_by_bundle;
Zhi Huange818b6e2018-02-22 15:26:27 -0800973}
974
Zhi Huange830e682018-03-30 10:48:35 -0700975int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
Zhi Huange818b6e2018-02-22 15:26:27 -0800976 const cricket::ContentInfo& content_info) {
Zhi Huange830e682018-03-30 10:48:35 -0700977 if (!config_.enable_external_auth) {
978 return -1;
Zhi Huange818b6e2018-02-22 15:26:27 -0800979 }
980
981 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200982 content_info.media_description();
Zhi Huange830e682018-03-30 10:48:35 -0700983
984 const webrtc::RtpExtension* send_time_extension =
985 webrtc::RtpExtension::FindHeaderExtensionByUri(
986 content_desc->rtp_header_extensions(),
Lennart Grahl0d0ed762021-05-17 16:06:37 +0200987 webrtc::RtpExtension::kAbsSendTimeUri,
988 config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions
989 ? webrtc::RtpExtension::kPreferEncryptedExtension
990 : webrtc::RtpExtension::kDiscardEncryptedExtension);
Zhi Huange830e682018-03-30 10:48:35 -0700991 return send_time_extension ? send_time_extension->id : -1;
992}
993
Zhi Huang365381f2018-04-13 16:44:34 -0700994const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -0700995 const std::string& mid) const {
Harald Alvestrand9dea3932021-06-10 06:03:06 +0000996 return transports_.GetTransportForMid(mid);
Zhi Huange830e682018-03-30 10:48:35 -0700997}
998
Zhi Huang365381f2018-04-13 16:44:34 -0700999cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -07001000 const std::string& mid) {
Harald Alvestrand9dea3932021-06-10 06:03:06 +00001001 return transports_.GetTransportForMid(mid);
Zhi Huange830e682018-03-30 10:48:35 -07001002}
Harald Alvestrand8f429922022-05-04 10:32:30 +00001003const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1004 absl::string_view mid) const {
1005 return transports_.GetTransportForMid(mid);
1006}
1007
1008cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1009 absl::string_view mid) {
1010 return transports_.GetTransportForMid(mid);
1011}
Zhi Huange830e682018-03-30 10:48:35 -07001012
Zhi Huang365381f2018-04-13 16:44:34 -07001013const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -07001014 const std::string& transport_name) const {
Harald Alvestrand9dea3932021-06-10 06:03:06 +00001015 return transports_.GetTransportByName(transport_name);
Zhi Huange830e682018-03-30 10:48:35 -07001016}
1017
Zhi Huang365381f2018-04-13 16:44:34 -07001018cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -07001019 const std::string& transport_name) {
Harald Alvestrand9dea3932021-06-10 06:03:06 +00001020 return transports_.GetTransportByName(transport_name);
Zhi Huange830e682018-03-30 10:48:35 -07001021}
1022
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001023RTCError JsepTransportController::MaybeCreateJsepTransport(
1024 bool local,
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001025 const cricket::ContentInfo& content_info,
1026 const cricket::SessionDescription& description) {
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001027 cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
1028 if (transport) {
1029 return RTCError::OK();
1030 }
Harald Alvestrand0d018412021-11-04 13:52:31 +00001031 const cricket::MediaContentDescription* content_desc =
1032 content_info.media_description();
1033 if (certificate_ && !content_desc->cryptos().empty()) {
1034 return RTCError(RTCErrorType::INVALID_PARAMETER,
1035 "SDES and DTLS-SRTP cannot be enabled at the same time.");
1036 }
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001037
Qingsi Wang25ec8882019-11-15 12:33:05 -08001038 rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001039 CreateIceTransport(content_info.name, /*rtcp=*/false);
Qingsi Wang25ec8882019-11-15 12:33:05 -08001040 RTC_DCHECK(ice);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001041
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001042 std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
Niels Möller2a707032020-06-16 16:39:13 +02001043 CreateDtlsTransport(content_info, ice->internal());
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001044
1045 std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
1046 std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
1047 std::unique_ptr<SrtpTransport> sdes_transport;
1048 std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001049
Qingsi Wang25ec8882019-11-15 12:33:05 -08001050 rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001051 if (config_.rtcp_mux_policy !=
1052 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
1053 content_info.type == cricket::MediaProtocolType::kRtp) {
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001054 rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
Qingsi Wang25ec8882019-11-15 12:33:05 -08001055 rtcp_dtls_transport =
Niels Möller2a707032020-06-16 16:39:13 +02001056 CreateDtlsTransport(content_info, rtcp_ice->internal());
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001057 }
1058
1059 if (config_.disable_encryption) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001060 RTC_LOG(LS_INFO)
1061 << "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001062 unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
Zhi Huangd2248f82018-04-10 14:41:03 -07001063 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Harald Alvestrand0d018412021-11-04 13:52:31 +00001064 } else if (!content_desc->cryptos().empty()) {
1065 sdes_transport = CreateSdesTransport(
1066 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
1067 RTC_LOG(LS_INFO) << "Creating SdesTransport.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001068 } else {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001069 RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
Zhi Huangd2248f82018-04-10 14:41:03 -07001070 dtls_srtp_transport = CreateDtlsSrtpTransport(
1071 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001072 }
1073
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001074 std::unique_ptr<cricket::SctpTransportInternal> sctp_transport;
1075 if (config_.sctp_factory) {
1076 sctp_transport =
1077 config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
1078 }
1079
Zhi Huang365381f2018-04-13 16:44:34 -07001080 std::unique_ptr<cricket::JsepTransport> jsep_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001081 std::make_unique<cricket::JsepTransport>(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001082 content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
1083 std::move(unencrypted_rtp_transport), std::move(sdes_transport),
Niels Möllerab9d6e12021-02-02 16:49:02 +01001084 std::move(dtls_srtp_transport), std::move(rtp_dtls_transport),
Mirko Bonadei96dca922021-07-10 22:37:40 +02001085 std::move(rtcp_dtls_transport), std::move(sctp_transport), [&]() {
1086 RTC_DCHECK_RUN_ON(network_thread_);
1087 UpdateAggregateStates_n();
1088 });
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001089
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +02001090 jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect(
1091 this, &JsepTransportController::OnRtcpPacketReceived_n);
1092
Harald Alvestrand9dea3932021-06-10 06:03:06 +00001093 transports_.RegisterTransport(content_info.name, std::move(jsep_transport));
Zhi Huangd2248f82018-04-10 14:41:03 -07001094 UpdateAggregateStates_n();
Zhi Huange830e682018-03-30 10:48:35 -07001095 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -08001096}
1097
Zhi Huange818b6e2018-02-22 15:26:27 -08001098void JsepTransportController::DestroyAllJsepTransports_n() {
Harald Alvestrand9dea3932021-06-10 06:03:06 +00001099 transports_.DestroyAllTransports();
Zhi Huange818b6e2018-02-22 15:26:27 -08001100}
1101
1102void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001103 ice_role_ = ice_role;
Tomas Gunnarsson20f74562021-02-04 10:22:50 +01001104 auto dtls_transports = GetDtlsTransports();
1105 for (auto& dtls : dtls_transports) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001106 dtls->ice_transport()->SetIceRole(ice_role_);
1107 }
1108}
1109
1110cricket::IceRole JsepTransportController::DetermineIceRole(
Zhi Huang365381f2018-04-13 16:44:34 -07001111 cricket::JsepTransport* jsep_transport,
Zhi Huange818b6e2018-02-22 15:26:27 -08001112 const cricket::TransportInfo& transport_info,
1113 SdpType type,
1114 bool local) {
1115 cricket::IceRole ice_role = ice_role_;
1116 auto tdesc = transport_info.description;
1117 if (local) {
1118 // The initial offer side may use ICE Lite, in which case, per RFC5245
1119 // Section 5.1.1, the answer side should take the controlling role if it is
1120 // in the full ICE mode.
1121 //
1122 // When both sides use ICE Lite, the initial offer side must take the
1123 // controlling role, and this is the default logic implemented in
1124 // SetLocalDescription in JsepTransportController.
1125 if (jsep_transport->remote_description() &&
1126 jsep_transport->remote_description()->transport_desc.ice_mode ==
1127 cricket::ICEMODE_LITE &&
1128 ice_role_ == cricket::ICEROLE_CONTROLLED &&
1129 tdesc.ice_mode == cricket::ICEMODE_FULL) {
1130 ice_role = cricket::ICEROLE_CONTROLLING;
1131 }
Zhi Huange818b6e2018-02-22 15:26:27 -08001132 } else {
1133 // If our role is cricket::ICEROLE_CONTROLLED and the remote endpoint
1134 // supports only ice_lite, this local endpoint should take the CONTROLLING
1135 // role.
1136 // TODO(deadbeef): This is a session-level attribute, so it really shouldn't
1137 // be in a TransportDescription in the first place...
1138 if (ice_role_ == cricket::ICEROLE_CONTROLLED &&
1139 tdesc.ice_mode == cricket::ICEMODE_LITE) {
1140 ice_role = cricket::ICEROLE_CONTROLLING;
1141 }
1142
1143 // If we use ICE Lite and the remote endpoint uses the full implementation
1144 // of ICE, the local endpoint must take the controlled role, and the other
1145 // side must be the controlling role.
1146 if (jsep_transport->local_description() &&
1147 jsep_transport->local_description()->transport_desc.ice_mode ==
1148 cricket::ICEMODE_LITE &&
1149 ice_role_ == cricket::ICEROLE_CONTROLLING &&
Zhi Huange830e682018-03-30 10:48:35 -07001150 tdesc.ice_mode == cricket::ICEMODE_FULL) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001151 ice_role = cricket::ICEROLE_CONTROLLED;
1152 }
1153 }
1154
1155 return ice_role;
1156}
1157
1158void JsepTransportController::OnTransportWritableState_n(
1159 rtc::PacketTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001160 RTC_LOG(LS_INFO) << " Transport " << transport->transport_name()
1161 << " writability changed to " << transport->writable()
1162 << ".";
1163 UpdateAggregateStates_n();
1164}
1165
1166void JsepTransportController::OnTransportReceivingState_n(
1167 rtc::PacketTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001168 UpdateAggregateStates_n();
1169}
1170
1171void JsepTransportController::OnTransportGatheringState_n(
1172 cricket::IceTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001173 UpdateAggregateStates_n();
1174}
1175
1176void JsepTransportController::OnTransportCandidateGathered_n(
1177 cricket::IceTransportInternal* transport,
1178 const cricket::Candidate& candidate) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001179 // We should never signal peer-reflexive candidates.
1180 if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
Artem Titovd3251962021-11-15 16:57:07 +01001181 RTC_DCHECK_NOTREACHED();
Zhi Huange818b6e2018-02-22 15:26:27 -08001182 return;
1183 }
Tommic3257d02021-02-10 17:40:08 +00001184
1185 signal_ice_candidates_gathered_.Send(
1186 transport->transport_name(), std::vector<cricket::Candidate>{candidate});
Zhi Huange818b6e2018-02-22 15:26:27 -08001187}
1188
Eldar Relloda13ea22019-06-01 12:23:43 +03001189void JsepTransportController::OnTransportCandidateError_n(
1190 cricket::IceTransportInternal* transport,
1191 const cricket::IceCandidateErrorEvent& event) {
Tommic3257d02021-02-10 17:40:08 +00001192 signal_ice_candidate_error_.Send(event);
Eldar Relloda13ea22019-06-01 12:23:43 +03001193}
Zhi Huange818b6e2018-02-22 15:26:27 -08001194void JsepTransportController::OnTransportCandidatesRemoved_n(
1195 cricket::IceTransportInternal* transport,
1196 const cricket::Candidates& candidates) {
Tommic3257d02021-02-10 17:40:08 +00001197 signal_ice_candidates_removed_.Send(candidates);
Zhi Huange818b6e2018-02-22 15:26:27 -08001198}
Alex Drake00c7ecf2019-08-06 10:54:47 -07001199void JsepTransportController::OnTransportCandidatePairChanged_n(
1200 const cricket::CandidatePairChangeEvent& event) {
Tommic3257d02021-02-10 17:40:08 +00001201 signal_ice_candidate_pair_changed_.Send(event);
Alex Drake00c7ecf2019-08-06 10:54:47 -07001202}
Zhi Huange818b6e2018-02-22 15:26:27 -08001203
1204void JsepTransportController::OnTransportRoleConflict_n(
1205 cricket::IceTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001206 // Note: since the role conflict is handled entirely on the network thread,
1207 // we don't need to worry about role conflicts occurring on two ports at
1208 // once. The first one encountered should immediately reverse the role.
1209 cricket::IceRole reversed_role = (ice_role_ == cricket::ICEROLE_CONTROLLING)
1210 ? cricket::ICEROLE_CONTROLLED
1211 : cricket::ICEROLE_CONTROLLING;
1212 RTC_LOG(LS_INFO) << "Got role conflict; switching to "
1213 << (reversed_role == cricket::ICEROLE_CONTROLLING
1214 ? "controlling"
1215 : "controlled")
1216 << " role.";
1217 SetIceRole_n(reversed_role);
1218}
1219
1220void JsepTransportController::OnTransportStateChanged_n(
1221 cricket::IceTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001222 RTC_LOG(LS_INFO) << transport->transport_name() << " Transport "
1223 << transport->component()
1224 << " state changed. Check if state is complete.";
1225 UpdateAggregateStates_n();
1226}
1227
1228void JsepTransportController::UpdateAggregateStates_n() {
Markus Handell518669d2021-06-07 13:30:46 +02001229 TRACE_EVENT0("webrtc", "JsepTransportController::UpdateAggregateStates_n");
Taylor Brandstetter8591eff2021-08-11 14:56:38 -07001230 auto dtls_transports = GetActiveDtlsTransports();
Alex Loiko9289eda2018-11-23 16:18:59 +00001231 cricket::IceConnectionState new_connection_state =
1232 cricket::kIceConnectionConnecting;
Jonas Olsson635474e2018-10-18 15:58:17 +02001233 PeerConnectionInterface::IceConnectionState new_ice_connection_state =
1234 PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
1235 PeerConnectionInterface::PeerConnectionState new_combined_state =
1236 PeerConnectionInterface::PeerConnectionState::kNew;
Zhi Huange818b6e2018-02-22 15:26:27 -08001237 cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
Alex Loiko9289eda2018-11-23 16:18:59 +00001238 bool any_failed = false;
Alex Loiko9289eda2018-11-23 16:18:59 +00001239 bool all_connected = !dtls_transports.empty();
1240 bool all_completed = !dtls_transports.empty();
Zhi Huange818b6e2018-02-22 15:26:27 -08001241 bool any_gathering = false;
1242 bool all_done_gathering = !dtls_transports.empty();
Jonas Olsson635474e2018-10-18 15:58:17 +02001243
1244 std::map<IceTransportState, int> ice_state_counts;
Mirko Bonadei9f6808b2021-05-21 20:46:09 +02001245 std::map<DtlsTransportState, int> dtls_state_counts;
Jonas Olsson635474e2018-10-18 15:58:17 +02001246
Zhi Huange818b6e2018-02-22 15:26:27 -08001247 for (const auto& dtls : dtls_transports) {
Alex Loiko9289eda2018-11-23 16:18:59 +00001248 any_failed = any_failed || dtls->ice_transport()->GetState() ==
1249 cricket::IceTransportState::STATE_FAILED;
1250 all_connected = all_connected && dtls->writable();
1251 all_completed =
1252 all_completed && dtls->writable() &&
1253 dtls->ice_transport()->GetState() ==
1254 cricket::IceTransportState::STATE_COMPLETED &&
1255 dtls->ice_transport()->GetIceRole() == cricket::ICEROLE_CONTROLLING &&
1256 dtls->ice_transport()->gathering_state() ==
1257 cricket::kIceGatheringComplete;
Zhi Huange818b6e2018-02-22 15:26:27 -08001258 any_gathering = any_gathering || dtls->ice_transport()->gathering_state() !=
1259 cricket::kIceGatheringNew;
1260 all_done_gathering =
1261 all_done_gathering && dtls->ice_transport()->gathering_state() ==
1262 cricket::kIceGatheringComplete;
Jonas Olsson635474e2018-10-18 15:58:17 +02001263
1264 dtls_state_counts[dtls->dtls_state()]++;
1265 ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
Zhi Huange818b6e2018-02-22 15:26:27 -08001266 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -07001267
Alex Loiko9289eda2018-11-23 16:18:59 +00001268 if (any_failed) {
1269 new_connection_state = cricket::kIceConnectionFailed;
1270 } else if (all_completed) {
1271 new_connection_state = cricket::kIceConnectionCompleted;
1272 } else if (all_connected) {
1273 new_connection_state = cricket::kIceConnectionConnected;
1274 }
1275 if (ice_connection_state_ != new_connection_state) {
1276 ice_connection_state_ = new_connection_state;
Lahiru Ginnaliya Gamathigee99c68d2020-09-30 14:33:45 -07001277
Tommic3257d02021-02-10 17:40:08 +00001278 signal_ice_connection_state_.Send(new_connection_state);
Alex Loiko9289eda2018-11-23 16:18:59 +00001279 }
1280
Jonas Olsson635474e2018-10-18 15:58:17 +02001281 // Compute the current RTCIceConnectionState as described in
1282 // https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
1283 // The PeerConnection is responsible for handling the "closed" state.
1284 int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
1285 int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
1286 int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
1287 int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
1288 int total_ice_disconnected =
1289 ice_state_counts[IceTransportState::kDisconnected];
1290 int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
1291 int total_ice_new = ice_state_counts[IceTransportState::kNew];
1292 int total_ice = dtls_transports.size();
1293
1294 if (total_ice_failed > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001295 // Any RTCIceTransports are in the "failed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001296 new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
Alex Loiko9289eda2018-11-23 16:18:59 +00001297 } else if (total_ice_disconnected > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001298 // None of the previous states apply and any RTCIceTransports are in the
1299 // "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001300 new_ice_connection_state =
1301 PeerConnectionInterface::kIceConnectionDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001302 } else if (total_ice_new + total_ice_closed == total_ice) {
1303 // None of the previous states apply and all RTCIceTransports are in the
1304 // "new" or "closed" state, or there are no transports.
1305 new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
1306 } else if (total_ice_new + total_ice_checking > 0) {
1307 // None of the previous states apply and any RTCIceTransports are in the
1308 // "new" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001309 new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001310 } else if (total_ice_completed + total_ice_closed == total_ice ||
1311 all_completed) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001312 // None of the previous states apply and all RTCIceTransports are in the
1313 // "completed" or "closed" state.
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001314 //
1315 // TODO(https://bugs.webrtc.org/10356): The all_completed condition is added
1316 // to mimic the behavior of the old ICE connection state, and should be
1317 // removed once we get end-of-candidates signaling in place.
Jonas Olsson635474e2018-10-18 15:58:17 +02001318 new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
1319 } else if (total_ice_connected + total_ice_completed + total_ice_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001320 total_ice) {
1321 // None of the previous states apply and all RTCIceTransports are in the
1322 // "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001323 new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001324 } else {
Artem Titovd3251962021-11-15 16:57:07 +01001325 RTC_DCHECK_NOTREACHED();
Jonas Olsson635474e2018-10-18 15:58:17 +02001326 }
1327
Alex Loiko9289eda2018-11-23 16:18:59 +00001328 if (standardized_ice_connection_state_ != new_ice_connection_state) {
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001329 if (standardized_ice_connection_state_ ==
1330 PeerConnectionInterface::kIceConnectionChecking &&
1331 new_ice_connection_state ==
1332 PeerConnectionInterface::kIceConnectionCompleted) {
1333 // Ensure that we never skip over the "connected" state.
Tommic3257d02021-02-10 17:40:08 +00001334 signal_standardized_ice_connection_state_.Send(
1335 PeerConnectionInterface::kIceConnectionConnected);
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001336 }
Alex Loiko9289eda2018-11-23 16:18:59 +00001337 standardized_ice_connection_state_ = new_ice_connection_state;
Tommic3257d02021-02-10 17:40:08 +00001338 signal_standardized_ice_connection_state_.Send(new_ice_connection_state);
Jonas Olsson635474e2018-10-18 15:58:17 +02001339 }
1340
1341 // Compute the current RTCPeerConnectionState as described in
1342 // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
1343 // The PeerConnection is responsible for handling the "closed" state.
1344 // Note that "connecting" is only a valid state for DTLS transports while
1345 // "checking", "completed" and "disconnected" are only valid for ICE
1346 // transports.
Mirko Bonadei9f6808b2021-05-21 20:46:09 +02001347 int total_connected =
1348 total_ice_connected + dtls_state_counts[DtlsTransportState::kConnected];
Jonas Olsson635474e2018-10-18 15:58:17 +02001349 int total_dtls_connecting =
Mirko Bonadei9f6808b2021-05-21 20:46:09 +02001350 dtls_state_counts[DtlsTransportState::kConnecting];
Jonas Olsson635474e2018-10-18 15:58:17 +02001351 int total_failed =
Mirko Bonadei9f6808b2021-05-21 20:46:09 +02001352 total_ice_failed + dtls_state_counts[DtlsTransportState::kFailed];
Jonas Olsson635474e2018-10-18 15:58:17 +02001353 int total_closed =
Mirko Bonadei9f6808b2021-05-21 20:46:09 +02001354 total_ice_closed + dtls_state_counts[DtlsTransportState::kClosed];
1355 int total_new = total_ice_new + dtls_state_counts[DtlsTransportState::kNew];
Jonas Olsson635474e2018-10-18 15:58:17 +02001356 int total_transports = total_ice * 2;
1357
1358 if (total_failed > 0) {
1359 // Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
1360 new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001361 } else if (total_ice_disconnected > 0) {
1362 // None of the previous states apply and any RTCIceTransports or
1363 // RTCDtlsTransports are in the "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001364 new_combined_state =
1365 PeerConnectionInterface::PeerConnectionState::kDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001366 } else if (total_new + total_closed == total_transports) {
1367 // None of the previous states apply and all RTCIceTransports and
1368 // RTCDtlsTransports are in the "new" or "closed" state, or there are no
1369 // transports.
1370 new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
1371 } else if (total_new + total_dtls_connecting + total_ice_checking > 0) {
1372 // None of the previous states apply and all RTCIceTransports or
1373 // RTCDtlsTransports are in the "new", "connecting" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001374 new_combined_state =
1375 PeerConnectionInterface::PeerConnectionState::kConnecting;
1376 } else if (total_connected + total_ice_completed + total_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001377 total_transports) {
1378 // None of the previous states apply and all RTCIceTransports and
1379 // RTCDtlsTransports are in the "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001380 new_combined_state =
1381 PeerConnectionInterface::PeerConnectionState::kConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001382 } else {
Artem Titovd3251962021-11-15 16:57:07 +01001383 RTC_DCHECK_NOTREACHED();
Jonas Olsson635474e2018-10-18 15:58:17 +02001384 }
1385
1386 if (combined_connection_state_ != new_combined_state) {
1387 combined_connection_state_ = new_combined_state;
Tommic3257d02021-02-10 17:40:08 +00001388 signal_connection_state_.Send(new_combined_state);
Jonas Olsson635474e2018-10-18 15:58:17 +02001389 }
1390
Harald Alvestrandbedb6052020-08-20 14:50:10 +02001391 // Compute the gathering state.
1392 if (dtls_transports.empty()) {
1393 new_gathering_state = cricket::kIceGatheringNew;
1394 } else if (all_done_gathering) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001395 new_gathering_state = cricket::kIceGatheringComplete;
1396 } else if (any_gathering) {
1397 new_gathering_state = cricket::kIceGatheringGathering;
1398 }
1399 if (ice_gathering_state_ != new_gathering_state) {
1400 ice_gathering_state_ = new_gathering_state;
Tommic3257d02021-02-10 17:40:08 +00001401 signal_ice_gathering_state_.Send(new_gathering_state);
Zhi Huange818b6e2018-02-22 15:26:27 -08001402 }
1403}
1404
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +02001405void JsepTransportController::OnRtcpPacketReceived_n(
1406 rtc::CopyOnWriteBuffer* packet,
1407 int64_t packet_time_us) {
1408 RTC_DCHECK(config_.rtcp_handler);
1409 config_.rtcp_handler(*packet, packet_time_us);
1410}
1411
Zhi Huange818b6e2018-02-22 15:26:27 -08001412void JsepTransportController::OnDtlsHandshakeError(
1413 rtc::SSLHandshakeError error) {
Lahiru Ginnaliya Gamathige70f9e242021-01-27 23:32:46 -08001414 config_.on_dtls_handshake_error_(error);
Zhi Huange818b6e2018-02-22 15:26:27 -08001415}
1416
Harald Alvestrand9dea3932021-06-10 06:03:06 +00001417bool JsepTransportController::OnTransportChanged(
1418 const std::string& mid,
1419 cricket::JsepTransport* jsep_transport) {
1420 if (config_.transport_observer) {
1421 if (jsep_transport) {
1422 return config_.transport_observer->OnTransportChanged(
1423 mid, jsep_transport->rtp_transport(),
1424 jsep_transport->RtpDtlsTransport(),
1425 jsep_transport->data_channel_transport());
1426 } else {
1427 return config_.transport_observer->OnTransportChanged(mid, nullptr,
1428 nullptr, nullptr);
1429 }
1430 }
1431 return false;
1432}
1433
Zhi Huange818b6e2018-02-22 15:26:27 -08001434} // namespace webrtc