blob: 4c351a69ef981b0d25c51e02b5b62130097ca626 [file] [log] [blame]
Zhi Huange818b6e2018-02-22 23:26:271/*
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 17:11:0011#include "pc/jsep_transport_controller.h"
Zhi Huange818b6e2018-02-22 23:26:2712
Harald Alvestrand5761e7b2021-01-29 14:45:0813#include <stddef.h>
14
Harald Alvestrand9dea3932021-06-10 06:03:0615#include <functional>
Zhi Huange818b6e2018-02-22 23:26:2716#include <memory>
Harald Alvestrandc24a2182022-02-23 13:44:5917#include <string>
Harald Alvestrandde22ab22021-06-17 10:45:3318#include <type_traits>
Zhi Huange818b6e2018-02-22 23:26:2719#include <utility>
20
Steve Anton64b626b2019-01-29 01:25:2621#include "absl/algorithm/container.h"
Mirko Bonadei9f6808b2021-05-21 18:46:0922#include "api/dtls_transport_interface.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0823#include "api/rtp_parameters.h"
Artem Titovd15a5752021-02-10 13:31:2424#include "api/sequence_checker.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0825#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 16:25:2128#include "p2p/base/ice_transport_internal.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0829#include "p2p/base/p2p_constants.h"
Zhi Huange818b6e2018-02-22 23:26:2730#include "p2p/base/port.h"
Zhi Huange818b6e2018-02-22 23:26:2731#include "rtc_base/checks.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0832#include "rtc_base/logging.h"
Zhi Huange818b6e2018-02-22 23:26:2733#include "rtc_base/thread.h"
Markus Handell518669d2021-06-07 11:30:4634#include "rtc_base/trace_event.h"
Zhi Huange818b6e2018-02-22 23:26:2735
36using webrtc::SdpType;
37
Zhi Huange818b6e2018-02-22 23:26:2738namespace webrtc {
39
40JsepTransportController::JsepTransportController(
Zhi Huange818b6e2018-02-22 23:26:2741 rtc::Thread* network_thread,
42 cricket::PortAllocator* port_allocator,
Harald Alvestrand0ccfbd22021-04-08 07:25:0443 AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
Zhi Huange818b6e2018-02-22 23:26:2744 Config config)
Tommic3257d02021-02-10 17:40:0845 : network_thread_(network_thread),
Zhi Huange818b6e2018-02-22 23:26:2746 port_allocator_(port_allocator),
Harald Alvestrand0ccfbd22021-04-08 07:25:0447 async_dns_resolver_factory_(async_dns_resolver_factory),
Harald Alvestrand9dea3932021-06-10 06:03:0648 transports_(
49 [this](const std::string& mid, cricket::JsepTransport* transport) {
50 return OnTransportChanged(mid, transport);
51 },
52 [this]() {
53 RTC_DCHECK_RUN_ON(network_thread_);
54 UpdateAggregateStates_n();
55 }),
Per Ke1e94ad2023-03-30 14:53:5956 config_(std::move(config)),
Taylor Brandstetter8591eff2021-08-11 21:56:3857 active_reset_srtp_params_(config.active_reset_srtp_params),
58 bundles_(config.bundle_policy) {
Artem Titov880fa812021-07-30 20:30:2359 // The `transport_observer` is assumed to be non-null.
Zhi Huang365381f2018-04-13 23:44:3460 RTC_DCHECK(config_.transport_observer);
Sebastian Jansson1b83a9e2019-09-18 16:22:1261 RTC_DCHECK(config_.rtcp_handler);
Qingsi Wang25ec8882019-11-15 20:33:0562 RTC_DCHECK(config_.ice_transport_factory);
Lahiru Ginnaliya Gamathige70f9e242021-01-28 07:32:4663 RTC_DCHECK(config_.on_dtls_handshake_error_);
Jonas Orelanded99dae2022-03-09 08:28:1064 RTC_DCHECK(config_.field_trials);
Philipp Hancke08b882d2022-10-27 07:56:0865 if (port_allocator_) {
66 port_allocator_->SetIceTiebreaker(ice_tiebreaker_);
67 }
Zhi Huang365381f2018-04-13 23:44:3468}
Zhi Huange818b6e2018-02-22 23:26:2769
70JsepTransportController::~JsepTransportController() {
71 // Channel destructors may try to send packets, so this needs to happen on
72 // the network thread.
Tomas Gunnarsson92eebef2021-02-10 12:05:4473 RTC_DCHECK_RUN_ON(network_thread_);
74 DestroyAllJsepTransports_n();
Zhi Huange818b6e2018-02-22 23:26:2775}
76
77RTCError JsepTransportController::SetLocalDescription(
78 SdpType type,
79 const cricket::SessionDescription* description) {
Markus Handell518669d2021-06-07 11:30:4680 TRACE_EVENT0("webrtc", "JsepTransportController::SetLocalDescription");
Zhi Huange818b6e2018-02-22 23:26:2781 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:1082 return network_thread_->BlockingCall(
83 [=] { return SetLocalDescription(type, description); });
Zhi Huange818b6e2018-02-22 23:26:2784 }
85
Niels Möller5cf0ef02021-01-18 13:00:3686 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:2787 if (!initial_offerer_.has_value()) {
88 initial_offerer_.emplace(type == SdpType::kOffer);
89 if (*initial_offerer_) {
90 SetIceRole_n(cricket::ICEROLE_CONTROLLING);
91 } else {
92 SetIceRole_n(cricket::ICEROLE_CONTROLLED);
93 }
94 }
95 return ApplyDescription_n(/*local=*/true, type, description);
96}
97
98RTCError JsepTransportController::SetRemoteDescription(
99 SdpType type,
100 const cricket::SessionDescription* description) {
Markus Handell518669d2021-06-07 11:30:46101 TRACE_EVENT0("webrtc", "JsepTransportController::SetRemoteDescription");
Zhi Huange818b6e2018-02-22 23:26:27102 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10103 return network_thread_->BlockingCall(
104 [=] { return SetRemoteDescription(type, description); });
Zhi Huange818b6e2018-02-22 23:26:27105 }
106
Niels Möller5cf0ef02021-01-18 13:00:36107 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27108 return ApplyDescription_n(/*local=*/false, type, description);
109}
110
111RtpTransportInternal* JsepTransportController::GetRtpTransport(
Harald Alvestrand8f429922022-05-04 10:32:30112 absl::string_view mid) const {
Tomas Gunnarsson92eebef2021-02-10 12:05:44113 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 17:48:35114 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 23:26:27115 if (!jsep_transport) {
116 return nullptr;
117 }
118 return jsep_transport->rtp_transport();
119}
120
Bjorn A Mellemb689af42019-08-21 17:44:59121DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
Anton Sukhanov316f3ac2019-05-23 22:50:38122 const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 12:05:44123 RTC_DCHECK_RUN_ON(network_thread_);
Anton Sukhanov316f3ac2019-05-23 22:50:38124 auto jsep_transport = GetJsepTransportForMid(mid);
Bjorn A Mellemb689af42019-08-21 17:44:59125 if (!jsep_transport) {
Anton Sukhanov7940da02018-10-10 17:34:49126 return nullptr;
127 }
Bjorn A Mellembc3eebc2019-09-23 21:53:54128 return jsep_transport->data_channel_transport();
Anton Sukhanov7940da02018-10-10 17:34:49129}
130
Zhi Huange818b6e2018-02-22 23:26:27131cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
Harald Alvestrandad88c882018-11-28 15:47:46132 const std::string& mid) {
Tomas Gunnarsson92eebef2021-02-10 12:05:44133 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 17:48:35134 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 23:26:27135 if (!jsep_transport) {
136 return nullptr;
137 }
138 return jsep_transport->rtp_dtls_transport();
139}
140
Harald Alvestrandad88c882018-11-28 15:47:46141const cricket::DtlsTransportInternal*
142JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 12:05:44143 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 17:48:35144 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 23:26:27145 if (!jsep_transport) {
146 return nullptr;
147 }
148 return jsep_transport->rtcp_dtls_transport();
149}
150
Harald Alvestrand4a7b3ac2019-01-17 09:39:40151rtc::scoped_refptr<webrtc::DtlsTransport>
Harald Alvestrandad88c882018-11-28 15:47:46152JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
Tomas Gunnarsson92eebef2021-02-10 12:05:44153 RTC_DCHECK_RUN_ON(network_thread_);
Harald Alvestrandad88c882018-11-28 15:47:46154 auto jsep_transport = GetJsepTransportForMid(mid);
155 if (!jsep_transport) {
156 return nullptr;
157 }
158 return jsep_transport->RtpDtlsTransport();
159}
160
Bjorn A Mellembc3eebc2019-09-23 21:53:54161rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
162 const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 12:05:44163 RTC_DCHECK_RUN_ON(network_thread_);
Bjorn A Mellembc3eebc2019-09-23 21:53:54164 auto jsep_transport = GetJsepTransportForMid(mid);
165 if (!jsep_transport) {
166 return nullptr;
167 }
168 return jsep_transport->SctpTransport();
169}
170
Zhi Huange818b6e2018-02-22 23:26:27171void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
Tomas Gunnarssone1c8a432021-04-08 13:15:28172 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27173 ice_config_ = config;
174 for (auto& dtls : GetDtlsTransports()) {
175 dtls->ice_transport()->SetIceConfig(ice_config_);
176 }
177}
178
179void JsepTransportController::SetNeedsIceRestartFlag() {
Tomas Gunnarsson20f74562021-02-04 09:22:50180 RTC_DCHECK_RUN_ON(network_thread_);
Harald Alvestrand9dea3932021-06-10 06:03:06181 for (auto& transport : transports_.Transports()) {
182 transport->SetNeedsIceRestartFlag();
Zhi Huange818b6e2018-02-22 23:26:27183 }
184}
185
186bool JsepTransportController::NeedsIceRestart(
187 const std::string& transport_name) const {
Tomas Gunnarsson20f74562021-02-04 09:22:50188 RTC_DCHECK_RUN_ON(network_thread_);
189
Zhi Huang365381f2018-04-13 23:44:34190 const cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 17:48:35191 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 23:26:27192 if (!transport) {
193 return false;
194 }
195 return transport->needs_ice_restart();
196}
197
Danil Chapovalov66cadcc2018-06-19 14:47:43198absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
Zhi Huange830e682018-03-30 17:48:35199 const std::string& mid) const {
Tomas Gunnarsson92eebef2021-02-10 12:05:44200 // TODO(tommi): Remove this hop. Currently it's called from the signaling
201 // thread during negotiations, potentially multiple times.
202 // WebRtcSessionDescriptionFactory::InternalCreateAnswer is one example.
Zhi Huange818b6e2018-02-22 23:26:27203 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10204 return network_thread_->BlockingCall([&] { return GetDtlsRole(mid); });
Zhi Huange818b6e2018-02-22 23:26:27205 }
206
Tomas Gunnarsson92eebef2021-02-10 12:05:44207 RTC_DCHECK_RUN_ON(network_thread_);
208
Zhi Huang365381f2018-04-13 23:44:34209 const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 23:26:27210 if (!t) {
Danil Chapovalov66cadcc2018-06-19 14:47:43211 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 23:26:27212 }
213 return t->GetDtlsRole();
214}
215
216bool JsepTransportController::SetLocalCertificate(
217 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
218 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10219 return network_thread_->BlockingCall(
220 [&] { return SetLocalCertificate(certificate); });
Zhi Huange818b6e2018-02-22 23:26:27221 }
222
Tomas Gunnarsson20f74562021-02-04 09:22:50223 RTC_DCHECK_RUN_ON(network_thread_);
224
Zhi Huange818b6e2018-02-22 23:26:27225 // Can't change a certificate, or set a null certificate.
226 if (certificate_ || !certificate) {
227 return false;
228 }
229 certificate_ = certificate;
230
231 // Set certificate for JsepTransport, which verifies it matches the
232 // fingerprint in SDP, and DTLS transport.
233 // Fallback from DTLS to SDES is not supported.
Harald Alvestrand9dea3932021-06-10 06:03:06234 for (auto& transport : transports_.Transports()) {
235 transport->SetLocalCertificate(certificate_);
Zhi Huange818b6e2018-02-22 23:26:27236 }
237 for (auto& dtls : GetDtlsTransports()) {
238 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
239 RTC_DCHECK(set_cert_success);
240 }
241 return true;
242}
243
244rtc::scoped_refptr<rtc::RTCCertificate>
245JsepTransportController::GetLocalCertificate(
246 const std::string& transport_name) const {
Tomas Gunnarsson20f74562021-02-04 09:22:50247 RTC_DCHECK_RUN_ON(network_thread_);
248
Zhi Huang365381f2018-04-13 23:44:34249 const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 23:26:27250 if (!t) {
251 return nullptr;
252 }
253 return t->GetLocalCertificate();
254}
255
Taylor Brandstetterc3928662018-02-23 21:04:51256std::unique_ptr<rtc::SSLCertChain>
257JsepTransportController::GetRemoteSSLCertChain(
Zhi Huange818b6e2018-02-22 23:26:27258 const std::string& transport_name) const {
Tomas Gunnarsson20f74562021-02-04 09:22:50259 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27260
Zhi Huange830e682018-03-30 17:48:35261 // Get the certificate from the RTP transport's DTLS handshake. Should be
262 // identical to the RTCP transport's, since they were given the same remote
Zhi Huange818b6e2018-02-22 23:26:27263 // fingerprint.
Zhi Huange830e682018-03-30 17:48:35264 auto jsep_transport = GetJsepTransportByName(transport_name);
265 if (!jsep_transport) {
266 return nullptr;
267 }
268 auto dtls = jsep_transport->rtp_dtls_transport();
Zhi Huange818b6e2018-02-22 23:26:27269 if (!dtls) {
270 return nullptr;
271 }
272
Taylor Brandstetterc3928662018-02-23 21:04:51273 return dtls->GetRemoteSSLCertChain();
Zhi Huange818b6e2018-02-22 23:26:27274}
275
276void JsepTransportController::MaybeStartGathering() {
277 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10278 network_thread_->BlockingCall([&] { MaybeStartGathering(); });
Zhi Huange818b6e2018-02-22 23:26:27279 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 09:22:50290 RTC_DCHECK_RUN_ON(network_thread_);
Tomas Gunnarsson8cb97062021-02-08 17:57:04291 RTC_DCHECK(VerifyCandidates(candidates).ok());
Zhi Huange830e682018-03-30 17:48:35292 auto jsep_transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 23:26:27293 if (!jsep_transport) {
Zhi Huange830e682018-03-30 17:48:35294 RTC_LOG(LS_WARNING) << "Not adding candidate because the JsepTransport "
295 "doesn't exist. Ignore it.";
296 return RTCError::OK();
Zhi Huange818b6e2018-02-22 23:26:27297 }
Zhi Huange818b6e2018-02-22 23:26:27298 return jsep_transport->AddRemoteCandidates(candidates);
299}
300
301RTCError JsepTransportController::RemoveRemoteCandidates(
302 const cricket::Candidates& candidates) {
303 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10304 return network_thread_->BlockingCall(
305 [&] { return RemoveRemoteCandidates(candidates); });
Zhi Huange818b6e2018-02-22 23:26:27306 }
307
Tomas Gunnarsson20f74562021-02-04 09:22:50308 RTC_DCHECK_RUN_ON(network_thread_);
309
Zhi Huange818b6e2018-02-22 23:26:27310 // 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 19:51:17323 << cand.ToSensitiveString();
Zhi Huange818b6e2018-02-22 23:26:27324 }
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 23:44:34330 cricket::JsepTransport* jsep_transport =
Zhi Huange830e682018-03-30 17:48:35331 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 23:26:27332 if (!jsep_transport) {
Zhi Huange830e682018-03-30 17:48:35333 RTC_LOG(LS_WARNING)
334 << "Not removing candidate because the JsepTransport doesn't exist.";
335 continue;
Zhi Huange818b6e2018-02-22 23:26:27336 }
337 for (const cricket::Candidate& candidate : candidates) {
Harald Alvestrandad88c882018-11-28 15:47:46338 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 23:26:27342 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 09:22:50352 RTC_DCHECK_RUN_ON(network_thread_);
353
Zhi Huang365381f2018-04-13 23:44:34354 cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 23:26:27355 if (!transport) {
356 return false;
357 }
358 return transport->GetStats(stats);
359}
360
Zhi Huangb57e1692018-06-12 18:41:11361void JsepTransportController::SetActiveResetSrtpParams(
362 bool active_reset_srtp_params) {
363 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10364 network_thread_->BlockingCall(
365 [=] { SetActiveResetSrtpParams(active_reset_srtp_params); });
Zhi Huangb57e1692018-06-12 18:41:11366 return;
367 }
Harald Alvestrand133c0522021-01-29 14:27:12368 RTC_DCHECK_RUN_ON(network_thread_);
Harald Alvestrand97597c02021-11-04 12:01:23369 RTC_LOG(LS_INFO)
Zhi Huangb57e1692018-06-12 18:41:11370 << "Updating the active_reset_srtp_params for JsepTransportController: "
371 << active_reset_srtp_params;
Harald Alvestrand133c0522021-01-29 14:27:12372 active_reset_srtp_params_ = active_reset_srtp_params;
Harald Alvestrand9dea3932021-06-10 06:03:06373 for (auto& transport : transports_.Transports()) {
374 transport->SetActiveResetSrtpParams(active_reset_srtp_params);
Zhi Huangb57e1692018-06-12 18:41:11375 }
376}
377
Taylor Brandstetter8591eff2021-08-11 21:56:38378RTCError JsepTransportController::RollbackTransports() {
Eldar Rello5ab79e62019-10-09 15:29:44379 if (!network_thread_->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 16:38:10380 return network_thread_->BlockingCall([=] { return RollbackTransports(); });
Eldar Rello5ab79e62019-10-09 15:29:44381 }
Eldar Rellod85ea752020-02-19 18:41:07382 RTC_DCHECK_RUN_ON(network_thread_);
Taylor Brandstetter8591eff2021-08-11 21:56:38383 bundles_.Rollback();
384 if (!transports_.RollbackTransports()) {
385 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
386 "Failed to roll back transport state.");
387 }
388 return RTCError::OK();
Eldar Rello5ab79e62019-10-09 15:29:44389}
390
Qingsi Wang25ec8882019-11-15 20:33:05391rtc::scoped_refptr<webrtc::IceTransportInterface>
392JsepTransportController::CreateIceTransport(const std::string& transport_name,
Piotr (Peter) Slatala2b5baee2019-01-16 16:25:21393 bool rtcp) {
Zhi Huange818b6e2018-02-22 23:26:27394 int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
395 : cricket::ICE_CANDIDATE_COMPONENT_RTP;
396
Qingsi Wang25ec8882019-11-15 20:33:05397 IceTransportInit init;
398 init.set_port_allocator(port_allocator_);
Harald Alvestrand0ccfbd22021-04-08 07:25:04399 init.set_async_dns_resolver_factory(async_dns_resolver_factory_);
Qingsi Wang25ec8882019-11-15 20:33:05400 init.set_event_log(config_.event_log);
Jonas Oreland340cb5e2022-03-17 08:14:16401 init.set_field_trials(config_.field_trials);
Philipp Hanckedf0a6222022-11-02 11:51:31402 auto transport = config_.ice_transport_factory->CreateIceTransport(
Qingsi Wang25ec8882019-11-15 20:33:05403 transport_name, component, std::move(init));
Philipp Hanckedf0a6222022-11-02 11:51:31404 RTC_DCHECK(transport);
405 transport->internal()->SetIceRole(ice_role_);
406 transport->internal()->SetIceTiebreaker(ice_tiebreaker_);
407 transport->internal()->SetIceConfig(ice_config_);
408 return transport;
Piotr (Peter) Slatala2b5baee2019-01-16 16:25:21409}
410
411std::unique_ptr<cricket::DtlsTransportInternal>
412JsepTransportController::CreateDtlsTransport(
Anton Sukhanovac6c0962019-07-10 22:44:56413 const cricket::ContentInfo& content_info,
Niels Möller2a707032020-06-16 14:39:13414 cricket::IceTransportInternal* ice) {
Tomas Gunnarsson20f74562021-02-04 09:22:50415 RTC_DCHECK_RUN_ON(network_thread_);
Piotr (Peter) Slatala2b5baee2019-01-16 16:25:21416
417 std::unique_ptr<cricket::DtlsTransportInternal> dtls;
Anton Sukhanov316f3ac2019-05-23 22:50:38418
Niels Möller2a707032020-06-16 14:39:13419 if (config_.dtls_transport_factory) {
Qingsi Wang25ec8882019-11-15 20:33:05420 dtls = config_.dtls_transport_factory->CreateDtlsTransport(
Tommi653bab62021-04-03 15:53:54421 ice, config_.crypto_options, config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 23:26:27422 } else {
Mirko Bonadei317a1f02019-09-17 15:06:18423 dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
Tommi653bab62021-04-03 15:53:54424 config_.event_log,
425 config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 23:26:27426 }
427
428 RTC_DCHECK(dtls);
Philipp Hanckedf0a6222022-11-02 11:51:31429 RTC_DCHECK_EQ(ice, dtls->ice_transport());
430
Zhi Huange818b6e2018-02-22 23:26:27431 if (certificate_) {
432 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
433 RTC_DCHECK(set_cert_success);
434 }
435
436 // Connect to signals offered by the DTLS and ICE transport.
437 dtls->SignalWritableState.connect(
438 this, &JsepTransportController::OnTransportWritableState_n);
439 dtls->SignalReceivingState.connect(
440 this, &JsepTransportController::OnTransportReceivingState_n);
Zhi Huange818b6e2018-02-22 23:26:27441 dtls->ice_transport()->SignalGatheringState.connect(
442 this, &JsepTransportController::OnTransportGatheringState_n);
443 dtls->ice_transport()->SignalCandidateGathered.connect(
444 this, &JsepTransportController::OnTransportCandidateGathered_n);
Eldar Relloda13ea22019-06-01 09:23:43445 dtls->ice_transport()->SignalCandidateError.connect(
446 this, &JsepTransportController::OnTransportCandidateError_n);
Zhi Huange818b6e2018-02-22 23:26:27447 dtls->ice_transport()->SignalCandidatesRemoved.connect(
448 this, &JsepTransportController::OnTransportCandidatesRemoved_n);
449 dtls->ice_transport()->SignalRoleConflict.connect(
450 this, &JsepTransportController::OnTransportRoleConflict_n);
451 dtls->ice_transport()->SignalStateChanged.connect(
452 this, &JsepTransportController::OnTransportStateChanged_n);
Jonas Olsson7a6739e2019-01-15 15:31:55453 dtls->ice_transport()->SignalIceTransportStateChanged.connect(
454 this, &JsepTransportController::OnTransportStateChanged_n);
Alex Drake00c7ecf2019-08-06 17:54:47455 dtls->ice_transport()->SignalCandidatePairChanged.connect(
456 this, &JsepTransportController::OnTransportCandidatePairChanged_n);
Lahiru Ginnaliya Gamathige16ab60c2021-02-02 15:27:09457
458 dtls->SubscribeDtlsHandshakeError(
459 [this](rtc::SSLHandshakeError error) { OnDtlsHandshakeError(error); });
Zhi Huange818b6e2018-02-22 23:26:27460 return dtls;
461}
462
463std::unique_ptr<webrtc::RtpTransport>
464JsepTransportController::CreateUnencryptedRtpTransport(
465 const std::string& transport_name,
466 rtc::PacketTransportInternal* rtp_packet_transport,
467 rtc::PacketTransportInternal* rtcp_packet_transport) {
Tomas Gunnarsson20f74562021-02-04 09:22:50468 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange830e682018-03-30 17:48:35469 auto unencrypted_rtp_transport =
Mirko Bonadei317a1f02019-09-17 15:06:18470 std::make_unique<RtpTransport>(rtcp_packet_transport == nullptr);
Zhi Huange830e682018-03-30 17:48:35471 unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
472 if (rtcp_packet_transport) {
473 unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
474 }
475 return unencrypted_rtp_transport;
Zhi Huange818b6e2018-02-22 23:26:27476}
477
478std::unique_ptr<webrtc::SrtpTransport>
479JsepTransportController::CreateSdesTransport(
480 const std::string& transport_name,
Zhi Huange830e682018-03-30 17:48:35481 cricket::DtlsTransportInternal* rtp_dtls_transport,
482 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Tomas Gunnarsson20f74562021-02-04 09:22:50483 RTC_DCHECK_RUN_ON(network_thread_);
Jonas Orelanded99dae2022-03-09 08:28:10484 auto srtp_transport = std::make_unique<webrtc::SrtpTransport>(
485 rtcp_dtls_transport == nullptr, *config_.field_trials);
Zhi Huange830e682018-03-30 17:48:35486 RTC_DCHECK(rtp_dtls_transport);
487 srtp_transport->SetRtpPacketTransport(rtp_dtls_transport);
488 if (rtcp_dtls_transport) {
489 srtp_transport->SetRtcpPacketTransport(rtcp_dtls_transport);
Zhi Huange818b6e2018-02-22 23:26:27490 }
491 if (config_.enable_external_auth) {
492 srtp_transport->EnableExternalAuth();
493 }
494 return srtp_transport;
495}
496
497std::unique_ptr<webrtc::DtlsSrtpTransport>
498JsepTransportController::CreateDtlsSrtpTransport(
499 const std::string& transport_name,
500 cricket::DtlsTransportInternal* rtp_dtls_transport,
501 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Harald Alvestrand133c0522021-01-29 14:27:12502 RTC_DCHECK_RUN_ON(network_thread_);
Mirko Bonadei317a1f02019-09-17 15:06:18503 auto dtls_srtp_transport = std::make_unique<webrtc::DtlsSrtpTransport>(
Jonas Orelanded99dae2022-03-09 08:28:10504 rtcp_dtls_transport == nullptr, *config_.field_trials);
Zhi Huang27f3bf52018-03-27 04:37:23505 if (config_.enable_external_auth) {
Zhi Huang365381f2018-04-13 23:44:34506 dtls_srtp_transport->EnableExternalAuth();
Zhi Huang27f3bf52018-03-27 04:37:23507 }
Zhi Huang97d5e5b2018-03-27 00:09:01508
Zhi Huange818b6e2018-02-22 23:26:27509 dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
510 rtcp_dtls_transport);
Harald Alvestrand133c0522021-01-29 14:27:12511 dtls_srtp_transport->SetActiveResetSrtpParams(active_reset_srtp_params_);
Lahiru Ginnaliya Gamathigec32f00e2021-02-17 08:43:21512 // Capturing this in the callback because JsepTransportController will always
513 // outlive the DtlsSrtpTransport.
514 dtls_srtp_transport->SetOnDtlsStateChange([this]() {
515 RTC_DCHECK_RUN_ON(this->network_thread_);
516 this->UpdateAggregateStates_n();
517 });
Zhi Huange818b6e2018-02-22 23:26:27518 return dtls_srtp_transport;
519}
520
521std::vector<cricket::DtlsTransportInternal*>
522JsepTransportController::GetDtlsTransports() {
Tomas Gunnarsson20f74562021-02-04 09:22:50523 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27524 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
Harald Alvestrand9dea3932021-06-10 06:03:06525 for (auto jsep_transport : transports_.Transports()) {
Zhi Huange818b6e2018-02-22 23:26:27526 RTC_DCHECK(jsep_transport);
527 if (jsep_transport->rtp_dtls_transport()) {
528 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
529 }
530
531 if (jsep_transport->rtcp_dtls_transport()) {
532 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
533 }
534 }
535 return dtls_transports;
536}
537
Taylor Brandstetter8591eff2021-08-11 21:56:38538std::vector<cricket::DtlsTransportInternal*>
539JsepTransportController::GetActiveDtlsTransports() {
540 RTC_DCHECK_RUN_ON(network_thread_);
541 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
542 for (auto jsep_transport : transports_.ActiveTransports()) {
543 RTC_DCHECK(jsep_transport);
544 if (jsep_transport->rtp_dtls_transport()) {
545 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
546 }
547
548 if (jsep_transport->rtcp_dtls_transport()) {
549 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
550 }
551 }
552 return dtls_transports;
553}
554
Zhi Huange818b6e2018-02-22 23:26:27555RTCError JsepTransportController::ApplyDescription_n(
556 bool local,
557 SdpType type,
558 const cricket::SessionDescription* description) {
Markus Handell518669d2021-06-07 11:30:46559 TRACE_EVENT0("webrtc", "JsepTransportController::ApplyDescription_n");
Zhi Huange818b6e2018-02-22 23:26:27560 RTC_DCHECK(description);
561
562 if (local) {
563 local_desc_ = description;
564 } else {
565 remote_desc_ = description;
566 }
567
Zhi Huange830e682018-03-30 17:48:35568 RTCError error;
Henrik Boströmf8187e02021-04-26 19:04:26569 error = ValidateAndMaybeUpdateBundleGroups(local, type, description);
Zhi Huange830e682018-03-30 17:48:35570 if (!error.ok()) {
571 return error;
Zhi Huange818b6e2018-02-22 23:26:27572 }
573
Henrik Boströmf8187e02021-04-26 19:04:26574 std::map<const cricket::ContentGroup*, std::vector<int>>
575 merged_encrypted_extension_ids_by_bundle;
Harald Alvestrand9f9bf382021-06-08 04:12:37576 if (!bundles_.bundle_groups().empty()) {
Henrik Boströmf8187e02021-04-26 19:04:26577 merged_encrypted_extension_ids_by_bundle =
Harald Alvestrand11b92cf2021-06-17 14:03:09578 MergeEncryptedHeaderExtensionIdsForBundles(description);
Zhi Huange818b6e2018-02-22 23:26:27579 }
580
581 for (const cricket::ContentInfo& content_info : description->contents()) {
Henrik Boströmf8187e02021-04-26 19:04:26582 // Don't create transports for rejected m-lines and bundled m-lines.
Zhi Huange818b6e2018-02-22 23:26:27583 if (content_info.rejected ||
Harald Alvestrand11b92cf2021-06-17 14:03:09584 !bundles_.IsFirstMidInGroup(content_info.name)) {
Zhi Huange818b6e2018-02-22 23:26:27585 continue;
586 }
Piotr (Peter) Slatala105ded32019-02-27 22:26:15587 error = MaybeCreateJsepTransport(local, content_info, *description);
Zhi Huange830e682018-03-30 17:48:35588 if (!error.ok()) {
589 return error;
590 }
Zhi Huange818b6e2018-02-22 23:26:27591 }
592
593 RTC_DCHECK(description->contents().size() ==
594 description->transport_infos().size());
595 for (size_t i = 0; i < description->contents().size(); ++i) {
596 const cricket::ContentInfo& content_info = description->contents()[i];
597 const cricket::TransportInfo& transport_info =
598 description->transport_infos()[i];
Taylor Brandstetter1c7ecef2021-08-11 19:38:35599
Zhi Huange818b6e2018-02-22 23:26:27600 if (content_info.rejected) {
Taylor Brandstetter8591eff2021-08-11 21:56:38601 // This may cause groups to be removed from |bundles_.bundle_groups()|.
602 HandleRejectedContent(content_info);
Zhi Huange818b6e2018-02-22 23:26:27603 continue;
604 }
605
Henrik Boströmf8187e02021-04-26 19:04:26606 const cricket::ContentGroup* established_bundle_group =
Harald Alvestrand11b92cf2021-06-17 14:03:09607 bundles_.LookupGroupByMid(content_info.name);
Henrik Boströmf8187e02021-04-26 19:04:26608
609 // For bundle members that are not BUNDLE-tagged (not first in the group),
610 // configure their transport to be the same as the BUNDLE-tagged transport.
611 if (established_bundle_group &&
612 content_info.name != *established_bundle_group->FirstContentName()) {
613 if (!HandleBundledContent(content_info, *established_bundle_group)) {
Zhi Huang365381f2018-04-13 23:44:34614 return RTCError(RTCErrorType::INVALID_PARAMETER,
Henrik Boströmf8187e02021-04-26 19:04:26615 "Failed to process the bundled m= section with "
616 "mid='" +
Yura Yaroshevichbc1f9102020-06-03 21:15:22617 content_info.name + "'.");
Zhi Huang365381f2018-04-13 23:44:34618 }
Zhi Huange818b6e2018-02-22 23:26:27619 continue;
620 }
621
Zhi Huange830e682018-03-30 17:48:35622 error = ValidateContent(content_info);
623 if (!error.ok()) {
624 return error;
625 }
626
Zhi Huange818b6e2018-02-22 23:26:27627 std::vector<int> extension_ids;
Henrik Boströmf8187e02021-04-26 19:04:26628 // Is BUNDLE-tagged (first in the group)?
629 if (established_bundle_group &&
630 content_info.name == *established_bundle_group->FirstContentName()) {
631 auto it = merged_encrypted_extension_ids_by_bundle.find(
632 established_bundle_group);
633 RTC_DCHECK(it != merged_encrypted_extension_ids_by_bundle.end());
634 extension_ids = it->second;
Zhi Huange818b6e2018-02-22 23:26:27635 } else {
636 extension_ids = GetEncryptedHeaderExtensionIds(content_info);
637 }
638
Zhi Huange830e682018-03-30 17:48:35639 int rtp_abs_sendtime_extn_id =
640 GetRtpAbsSendTimeHeaderExtensionId(content_info);
641
Zhi Huang365381f2018-04-13 23:44:34642 cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 17:48:35643 GetJsepTransportForMid(content_info.name);
Zhi Huange818b6e2018-02-22 23:26:27644 RTC_DCHECK(transport);
645
646 SetIceRole_n(DetermineIceRole(transport, transport_info, type, local));
647
Zhi Huange818b6e2018-02-22 23:26:27648 cricket::JsepTransportDescription jsep_description =
649 CreateJsepTransportDescription(content_info, transport_info,
Niels Möllerdc80aaf2020-06-18 08:10:17650 extension_ids, rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 23:26:27651 if (local) {
652 error =
653 transport->SetLocalJsepTransportDescription(jsep_description, type);
654 } else {
655 error =
656 transport->SetRemoteJsepTransportDescription(jsep_description, type);
657 }
658
659 if (!error.ok()) {
Yura Yaroshevichbc1f9102020-06-03 21:15:22660 LOG_AND_RETURN_ERROR(
661 RTCErrorType::INVALID_PARAMETER,
662 "Failed to apply the description for m= section with mid='" +
663 content_info.name + "': " + error.message());
Zhi Huange818b6e2018-02-22 23:26:27664 }
665 }
Eldar Rellod85ea752020-02-19 18:41:07666 if (type == SdpType::kAnswer) {
Harald Alvestrand9dea3932021-06-10 06:03:06667 transports_.CommitTransports();
Taylor Brandstetter8591eff2021-08-11 21:56:38668 bundles_.Commit();
Eldar Rellod85ea752020-02-19 18:41:07669 }
Zhi Huange818b6e2018-02-22 23:26:27670 return RTCError::OK();
671}
672
Henrik Boströmf8187e02021-04-26 19:04:26673RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroups(
Zhi Huangd2248f82018-04-10 21:41:03674 bool local,
675 SdpType type,
Zhi Huange830e682018-03-30 17:48:35676 const cricket::SessionDescription* description) {
677 RTC_DCHECK(description);
Zhi Huangd2248f82018-04-10 21:41:03678
Henrik Boströmf8187e02021-04-26 19:04:26679 std::vector<const cricket::ContentGroup*> new_bundle_groups =
680 description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
Artem Titov880fa812021-07-30 20:30:23681 // Verify `new_bundle_groups`.
Henrik Boströmf8187e02021-04-26 19:04:26682 std::map<std::string, const cricket::ContentGroup*> new_bundle_groups_by_mid;
683 for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
Yura Yaroshevichbc1f9102020-06-03 21:15:22684 for (const std::string& content_name : new_bundle_group->content_names()) {
Henrik Boströmf8187e02021-04-26 19:04:26685 // The BUNDLE group must not contain a MID that is a member of a different
686 // BUNDLE group, or that contains the same MID multiple times.
687 if (new_bundle_groups_by_mid.find(content_name) !=
688 new_bundle_groups_by_mid.end()) {
689 return RTCError(RTCErrorType::INVALID_PARAMETER,
690 "A BUNDLE group contains a MID='" + content_name +
691 "' that is already in a BUNDLE group.");
692 }
693 new_bundle_groups_by_mid.insert(
694 std::make_pair(content_name, new_bundle_group));
695 // The BUNDLE group must not contain a MID that no m= section has.
Zhi Huangd2248f82018-04-10 21:41:03696 if (!description->GetContentByName(content_name)) {
697 return RTCError(RTCErrorType::INVALID_PARAMETER,
Henrik Boströmf8187e02021-04-26 19:04:26698 "A BUNDLE group contains a MID='" + content_name +
Yura Yaroshevichbc1f9102020-06-03 21:15:22699 "' matching no m= section.");
Zhi Huangd2248f82018-04-10 21:41:03700 }
701 }
702 }
703
Taylor Brandstetter8591eff2021-08-11 21:56:38704 if (type == SdpType::kOffer) {
705 // For an offer, we need to verify that there is not a conflicting mapping
706 // between existing and new bundle groups. For example, if the existing
707 // groups are [[1,2],[3,4]] and new are [[1,3],[2,4]] or [[1,2,3,4]], or
708 // vice versa. Switching things around like this requires a separate offer
709 // that removes the relevant sections from their group, as per RFC 8843,
710 // section 7.5.2.
711 std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
712 new_bundle_groups_by_existing_bundle_groups;
713 std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
714 existing_bundle_groups_by_new_bundle_groups;
715 for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
716 for (const std::string& mid : new_bundle_group->content_names()) {
717 cricket::ContentGroup* existing_bundle_group =
718 bundles_.LookupGroupByMid(mid);
719 if (!existing_bundle_group) {
720 continue;
721 }
722 auto it = new_bundle_groups_by_existing_bundle_groups.find(
723 existing_bundle_group);
724 if (it != new_bundle_groups_by_existing_bundle_groups.end() &&
725 it->second != new_bundle_group) {
726 return RTCError(RTCErrorType::INVALID_PARAMETER,
727 "MID " + mid + " in the offer has changed group.");
728 }
729 new_bundle_groups_by_existing_bundle_groups.insert(
730 std::make_pair(existing_bundle_group, new_bundle_group));
731 it = existing_bundle_groups_by_new_bundle_groups.find(new_bundle_group);
732 if (it != existing_bundle_groups_by_new_bundle_groups.end() &&
733 it->second != existing_bundle_group) {
734 return RTCError(RTCErrorType::INVALID_PARAMETER,
735 "MID " + mid + " in the offer has changed group.");
736 }
737 existing_bundle_groups_by_new_bundle_groups.insert(
738 std::make_pair(new_bundle_group, existing_bundle_group));
739 }
740 }
741 } else if (type == SdpType::kAnswer) {
Henrik Boströmf8187e02021-04-26 19:04:26742 std::vector<const cricket::ContentGroup*> offered_bundle_groups =
743 local ? remote_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)
744 : local_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
Zhi Huangd2248f82018-04-10 21:41:03745
Henrik Boströmf8187e02021-04-26 19:04:26746 std::map<std::string, const cricket::ContentGroup*>
747 offered_bundle_groups_by_mid;
748 for (const cricket::ContentGroup* offered_bundle_group :
749 offered_bundle_groups) {
750 for (const std::string& content_name :
751 offered_bundle_group->content_names()) {
752 offered_bundle_groups_by_mid[content_name] = offered_bundle_group;
753 }
754 }
755
756 std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
757 new_bundle_groups_by_offered_bundle_groups;
758 for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
759 if (!new_bundle_group->FirstContentName()) {
760 // Empty groups could be a subset of any group.
761 continue;
762 }
763 // The group in the answer (new_bundle_group) must have a corresponding
764 // group in the offer (original_group), because the answer groups may only
765 // be subsets of the offer groups.
766 auto it = offered_bundle_groups_by_mid.find(
767 *new_bundle_group->FirstContentName());
768 if (it == offered_bundle_groups_by_mid.end()) {
769 return RTCError(RTCErrorType::INVALID_PARAMETER,
770 "A BUNDLE group was added in the answer that did not "
771 "exist in the offer.");
772 }
773 const cricket::ContentGroup* offered_bundle_group = it->second;
774 if (new_bundle_groups_by_offered_bundle_groups.find(
775 offered_bundle_group) !=
776 new_bundle_groups_by_offered_bundle_groups.end()) {
777 return RTCError(RTCErrorType::INVALID_PARAMETER,
778 "A MID in the answer has changed group.");
779 }
780 new_bundle_groups_by_offered_bundle_groups.insert(
781 std::make_pair(offered_bundle_group, new_bundle_group));
Yura Yaroshevichbc1f9102020-06-03 21:15:22782 for (const std::string& content_name :
783 new_bundle_group->content_names()) {
Henrik Boströmf8187e02021-04-26 19:04:26784 it = offered_bundle_groups_by_mid.find(content_name);
785 // The BUNDLE group in answer should be a subset of offered group.
786 if (it == offered_bundle_groups_by_mid.end() ||
787 it->second != offered_bundle_group) {
Zhi Huangd2248f82018-04-10 21:41:03788 return RTCError(RTCErrorType::INVALID_PARAMETER,
Henrik Boströmf8187e02021-04-26 19:04:26789 "A BUNDLE group in answer contains a MID='" +
Yura Yaroshevichbc1f9102020-06-03 21:15:22790 content_name +
Henrik Boströmf8187e02021-04-26 19:04:26791 "' that was not in the offered group.");
Zhi Huangd2248f82018-04-10 21:41:03792 }
793 }
794 }
795
Harald Alvestrand9f9bf382021-06-08 04:12:37796 for (const auto& bundle_group : bundles_.bundle_groups()) {
Henrik Boströmf8187e02021-04-26 19:04:26797 for (const std::string& content_name : bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 21:41:03798 // An answer that removes m= sections from pre-negotiated BUNDLE group
799 // without rejecting it, is invalid.
Henrik Boströmf8187e02021-04-26 19:04:26800 auto it = new_bundle_groups_by_mid.find(content_name);
801 if (it == new_bundle_groups_by_mid.end()) {
Zhi Huangd2248f82018-04-10 21:41:03802 auto* content_info = description->GetContentByName(content_name);
803 if (!content_info || !content_info->rejected) {
804 return RTCError(RTCErrorType::INVALID_PARAMETER,
Yura Yaroshevichbc1f9102020-06-03 21:15:22805 "Answer cannot remove m= section with mid='" +
806 content_name +
807 "' from already-established BUNDLE group.");
Zhi Huangd2248f82018-04-10 21:41:03808 }
809 }
810 }
811 }
812 }
813
814 if (config_.bundle_policy ==
815 PeerConnectionInterface::kBundlePolicyMaxBundle &&
816 !description->HasGroup(cricket::GROUP_TYPE_BUNDLE)) {
817 return RTCError(RTCErrorType::INVALID_PARAMETER,
818 "max-bundle is used but no bundle group found.");
819 }
820
Taylor Brandstetter8591eff2021-08-11 21:56:38821 bundles_.Update(description, type);
Zhi Huange830e682018-03-30 17:48:35822
Harald Alvestrand9f9bf382021-06-08 04:12:37823 for (const auto& bundle_group : bundles_.bundle_groups()) {
Henrik Boströmf8187e02021-04-26 19:04:26824 if (!bundle_group->FirstContentName())
825 continue;
826
827 // The first MID in a BUNDLE group is BUNDLE-tagged.
828 auto bundled_content =
829 description->GetContentByName(*bundle_group->FirstContentName());
830 if (!bundled_content) {
831 return RTCError(
832 RTCErrorType::INVALID_PARAMETER,
833 "An m= section associated with the BUNDLE-tag doesn't exist.");
834 }
835
Artem Titov880fa812021-07-30 20:30:23836 // If the `bundled_content` is rejected, other contents in the bundle group
Henrik Boströmf8187e02021-04-26 19:04:26837 // must also be rejected.
838 if (bundled_content->rejected) {
839 for (const auto& content_name : bundle_group->content_names()) {
840 auto other_content = description->GetContentByName(content_name);
841 if (!other_content->rejected) {
842 return RTCError(RTCErrorType::INVALID_PARAMETER,
843 "The m= section with mid='" + content_name +
844 "' should be rejected.");
845 }
846 }
847 }
848 }
Zhi Huange830e682018-03-30 17:48:35849 return RTCError::OK();
850}
851
852RTCError JsepTransportController::ValidateContent(
853 const cricket::ContentInfo& content_info) {
854 if (config_.rtcp_mux_policy ==
855 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
856 content_info.type == cricket::MediaProtocolType::kRtp &&
857 !content_info.media_description()->rtcp_mux()) {
858 return RTCError(RTCErrorType::INVALID_PARAMETER,
Yura Yaroshevichbc1f9102020-06-03 21:15:22859 "The m= section with mid='" + content_info.name +
860 "' is invalid. RTCP-MUX is not "
Zhi Huange830e682018-03-30 17:48:35861 "enabled when it is required.");
862 }
863 return RTCError::OK();
864}
865
Taylor Brandstettercbaa2542018-04-16 23:42:14866void JsepTransportController::HandleRejectedContent(
Harald Alvestrand11b92cf2021-06-17 14:03:09867 const cricket::ContentInfo& content_info) {
Zhi Huange818b6e2018-02-22 23:26:27868 // If the content is rejected, let the
869 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 23:44:34870 // then destroy the cricket::JsepTransport.
Henrik Boströmf8187e02021-04-26 19:04:26871 cricket::ContentGroup* bundle_group =
Harald Alvestrand11b92cf2021-06-17 14:03:09872 bundles_.LookupGroupByMid(content_info.name);
Henrik Boströmf8187e02021-04-26 19:04:26873 if (bundle_group && !bundle_group->content_names().empty() &&
874 content_info.name == *bundle_group->FirstContentName()) {
875 // Rejecting a BUNDLE group's first mid means we are rejecting the entire
876 // group.
877 for (const auto& content_name : bundle_group->content_names()) {
Harald Alvestrand9dea3932021-06-10 06:03:06878 transports_.RemoveTransportForMid(content_name);
Zhi Huange830e682018-03-30 17:48:35879 }
Henrik Boströmf8187e02021-04-26 19:04:26880 // Delete the BUNDLE group.
Harald Alvestrand2aa24f12021-06-08 09:51:19881 bundles_.DeleteGroup(bundle_group);
Henrik Boströmf8187e02021-04-26 19:04:26882 } else {
Harald Alvestrand9dea3932021-06-10 06:03:06883 transports_.RemoveTransportForMid(content_info.name);
Henrik Boströmf8187e02021-04-26 19:04:26884 if (bundle_group) {
Artem Titov880fa812021-07-30 20:30:23885 // Remove the rejected content from the `bundle_group`.
Harald Alvestrand2aa24f12021-06-08 09:51:19886 bundles_.DeleteMid(bundle_group, content_info.name);
Zhi Huange830e682018-03-30 17:48:35887 }
Zhi Huange818b6e2018-02-22 23:26:27888 }
Zhi Huange818b6e2018-02-22 23:26:27889}
890
Zhi Huang365381f2018-04-13 23:44:34891bool JsepTransportController::HandleBundledContent(
Henrik Boströmf8187e02021-04-26 19:04:26892 const cricket::ContentInfo& content_info,
893 const cricket::ContentGroup& bundle_group) {
Markus Handell518669d2021-06-07 11:30:46894 TRACE_EVENT0("webrtc", "JsepTransportController::HandleBundledContent");
Henrik Boströmf8187e02021-04-26 19:04:26895 RTC_DCHECK(bundle_group.FirstContentName());
896 auto jsep_transport =
897 GetJsepTransportByName(*bundle_group.FirstContentName());
Zhi Huangd2248f82018-04-10 21:41:03898 RTC_DCHECK(jsep_transport);
Zhi Huange818b6e2018-02-22 23:26:27899 // If the content is bundled, let the
900 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 23:44:34901 // then destroy the cricket::JsepTransport.
Harald Alvestrand4bb81ac2021-06-11 13:04:59902 // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
903 // because it means that we first create media transport and start
904 // connecting it, and then we destroy it. We will need to address it before
905 // video path is enabled.
906 return transports_.SetTransportForMid(content_info.name, jsep_transport);
Zhi Huange818b6e2018-02-22 23:26:27907}
908
909cricket::JsepTransportDescription
910JsepTransportController::CreateJsepTransportDescription(
Harald Alvestrand1716d392019-06-03 18:35:45911 const cricket::ContentInfo& content_info,
912 const cricket::TransportInfo& transport_info,
Zhi Huange830e682018-03-30 17:48:35913 const std::vector<int>& encrypted_extension_ids,
Niels Möllerdc80aaf2020-06-18 08:10:17914 int rtp_abs_sendtime_extn_id) {
Markus Handell518669d2021-06-07 11:30:46915 TRACE_EVENT0("webrtc",
916 "JsepTransportController::CreateJsepTransportDescription");
Zhi Huange818b6e2018-02-22 23:26:27917 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 18:35:45918 content_info.media_description();
Zhi Huange818b6e2018-02-22 23:26:27919 RTC_DCHECK(content_desc);
920 bool rtcp_mux_enabled = content_info.type == cricket::MediaProtocolType::kSctp
921 ? true
922 : content_desc->rtcp_mux();
923
924 return cricket::JsepTransportDescription(
Harald Alvestrand0d018412021-11-04 13:52:31925 rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
926 rtp_abs_sendtime_extn_id, transport_info.description);
Zhi Huange818b6e2018-02-22 23:26:27927}
928
Zhi Huange818b6e2018-02-22 23:26:27929std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
930 const cricket::ContentInfo& content_info) {
931 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 18:35:45932 content_info.media_description();
Zhi Huange818b6e2018-02-22 23:26:27933
Benjamin Wrighta54daf12018-10-11 22:33:17934 if (!config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions) {
Zhi Huange818b6e2018-02-22 23:26:27935 return std::vector<int>();
936 }
937
938 std::vector<int> encrypted_header_extension_ids;
Mirko Bonadei739baf02019-01-27 16:29:42939 for (const auto& extension : content_desc->rtp_header_extensions()) {
Zhi Huange818b6e2018-02-22 23:26:27940 if (!extension.encrypt) {
941 continue;
942 }
Steve Anton64b626b2019-01-29 01:25:26943 if (!absl::c_linear_search(encrypted_header_extension_ids, extension.id)) {
Zhi Huange818b6e2018-02-22 23:26:27944 encrypted_header_extension_ids.push_back(extension.id);
945 }
946 }
947 return encrypted_header_extension_ids;
948}
949
Henrik Boströmf8187e02021-04-26 19:04:26950std::map<const cricket::ContentGroup*, std::vector<int>>
951JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundles(
Zhi Huange818b6e2018-02-22 23:26:27952 const cricket::SessionDescription* description) {
953 RTC_DCHECK(description);
Harald Alvestrand9f9bf382021-06-08 04:12:37954 RTC_DCHECK(!bundles_.bundle_groups().empty());
Henrik Boströmf8187e02021-04-26 19:04:26955 std::map<const cricket::ContentGroup*, std::vector<int>>
956 merged_encrypted_extension_ids_by_bundle;
Zhi Huange818b6e2018-02-22 23:26:27957 // Union the encrypted header IDs in the group when bundle is enabled.
958 for (const cricket::ContentInfo& content_info : description->contents()) {
Harald Alvestrand11b92cf2021-06-17 14:03:09959 auto group = bundles_.LookupGroupByMid(content_info.name);
960 if (!group)
Henrik Boströmf8187e02021-04-26 19:04:26961 continue;
962 // Get or create list of IDs for the BUNDLE group.
963 std::vector<int>& merged_ids =
Harald Alvestrand11b92cf2021-06-17 14:03:09964 merged_encrypted_extension_ids_by_bundle[group];
Henrik Boströmf8187e02021-04-26 19:04:26965 // Add IDs not already in the list.
966 std::vector<int> extension_ids =
967 GetEncryptedHeaderExtensionIds(content_info);
968 for (int id : extension_ids) {
969 if (!absl::c_linear_search(merged_ids, id)) {
970 merged_ids.push_back(id);
Zhi Huange818b6e2018-02-22 23:26:27971 }
972 }
973 }
Henrik Boströmf8187e02021-04-26 19:04:26974 return merged_encrypted_extension_ids_by_bundle;
Zhi Huange818b6e2018-02-22 23:26:27975}
976
Zhi Huange830e682018-03-30 17:48:35977int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
Zhi Huange818b6e2018-02-22 23:26:27978 const cricket::ContentInfo& content_info) {
Zhi Huange830e682018-03-30 17:48:35979 if (!config_.enable_external_auth) {
980 return -1;
Zhi Huange818b6e2018-02-22 23:26:27981 }
982
983 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 18:35:45984 content_info.media_description();
Zhi Huange830e682018-03-30 17:48:35985
986 const webrtc::RtpExtension* send_time_extension =
987 webrtc::RtpExtension::FindHeaderExtensionByUri(
988 content_desc->rtp_header_extensions(),
Lennart Grahl0d0ed762021-05-17 14:06:37989 webrtc::RtpExtension::kAbsSendTimeUri,
990 config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions
991 ? webrtc::RtpExtension::kPreferEncryptedExtension
992 : webrtc::RtpExtension::kDiscardEncryptedExtension);
Zhi Huange830e682018-03-30 17:48:35993 return send_time_extension ? send_time_extension->id : -1;
994}
995
Zhi Huang365381f2018-04-13 23:44:34996const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 17:48:35997 const std::string& mid) const {
Harald Alvestrand9dea3932021-06-10 06:03:06998 return transports_.GetTransportForMid(mid);
Zhi Huange830e682018-03-30 17:48:35999}
1000
Zhi Huang365381f2018-04-13 23:44:341001cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 17:48:351002 const std::string& mid) {
Harald Alvestrand9dea3932021-06-10 06:03:061003 return transports_.GetTransportForMid(mid);
Zhi Huange830e682018-03-30 17:48:351004}
Harald Alvestrand8f429922022-05-04 10:32:301005const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1006 absl::string_view mid) const {
1007 return transports_.GetTransportForMid(mid);
1008}
1009
1010cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1011 absl::string_view mid) {
1012 return transports_.GetTransportForMid(mid);
1013}
Zhi Huange830e682018-03-30 17:48:351014
Zhi Huang365381f2018-04-13 23:44:341015const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 17:48:351016 const std::string& transport_name) const {
Harald Alvestrand9dea3932021-06-10 06:03:061017 return transports_.GetTransportByName(transport_name);
Zhi Huange830e682018-03-30 17:48:351018}
1019
Zhi Huang365381f2018-04-13 23:44:341020cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 17:48:351021 const std::string& transport_name) {
Harald Alvestrand9dea3932021-06-10 06:03:061022 return transports_.GetTransportByName(transport_name);
Zhi Huange830e682018-03-30 17:48:351023}
1024
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581025RTCError JsepTransportController::MaybeCreateJsepTransport(
1026 bool local,
Piotr (Peter) Slatala105ded32019-02-27 22:26:151027 const cricket::ContentInfo& content_info,
1028 const cricket::SessionDescription& description) {
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581029 cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
1030 if (transport) {
1031 return RTCError::OK();
1032 }
Harald Alvestrand0d018412021-11-04 13:52:311033 const cricket::MediaContentDescription* content_desc =
1034 content_info.media_description();
1035 if (certificate_ && !content_desc->cryptos().empty()) {
1036 return RTCError(RTCErrorType::INVALID_PARAMETER,
1037 "SDES and DTLS-SRTP cannot be enabled at the same time.");
1038 }
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581039
Qingsi Wang25ec8882019-11-15 20:33:051040 rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
Piotr (Peter) Slatala2b5baee2019-01-16 16:25:211041 CreateIceTransport(content_info.name, /*rtcp=*/false);
Piotr (Peter) Slatala2b5baee2019-01-16 16:25:211042
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581043 std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
Niels Möller2a707032020-06-16 14:39:131044 CreateDtlsTransport(content_info, ice->internal());
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581045
1046 std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
1047 std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
1048 std::unique_ptr<SrtpTransport> sdes_transport;
1049 std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581050
Qingsi Wang25ec8882019-11-15 20:33:051051 rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice;
Piotr (Peter) Slatala47dfdca2018-11-16 22:13:581052 if (config_.rtcp_mux_policy !=
1053 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
1054 content_info.type == cricket::MediaProtocolType::kRtp) {
Bjorn A Mellem0c1c1b42019-05-30 00:34:131055 rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
Qingsi Wang25ec8882019-11-15 20:33:051056 rtcp_dtls_transport =
Niels Möller2a707032020-06-16 14:39:131057 CreateDtlsTransport(content_info, rtcp_ice->internal());
Bjorn A Mellemc85ebbe2019-06-07 17:28:061058 }
1059
1060 if (config_.disable_encryption) {
Anton Sukhanov316f3ac2019-05-23 22:50:381061 RTC_LOG(LS_INFO)
1062 << "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
Zhi Huange818b6e2018-02-22 23:26:271063 unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
Zhi Huangd2248f82018-04-10 21:41:031064 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Harald Alvestrand0d018412021-11-04 13:52:311065 } else if (!content_desc->cryptos().empty()) {
1066 sdes_transport = CreateSdesTransport(
1067 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
1068 RTC_LOG(LS_INFO) << "Creating SdesTransport.";
Zhi Huange818b6e2018-02-22 23:26:271069 } else {
Anton Sukhanov316f3ac2019-05-23 22:50:381070 RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
Zhi Huangd2248f82018-04-10 21:41:031071 dtls_srtp_transport = CreateDtlsSrtpTransport(
1072 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 23:26:271073 }
1074
Bjorn A Mellembc3eebc2019-09-23 21:53:541075 std::unique_ptr<cricket::SctpTransportInternal> sctp_transport;
1076 if (config_.sctp_factory) {
1077 sctp_transport =
1078 config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
1079 }
1080
Zhi Huang365381f2018-04-13 23:44:341081 std::unique_ptr<cricket::JsepTransport> jsep_transport =
Mirko Bonadei317a1f02019-09-17 15:06:181082 std::make_unique<cricket::JsepTransport>(
Bjorn A Mellem0c1c1b42019-05-30 00:34:131083 content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
1084 std::move(unencrypted_rtp_transport), std::move(sdes_transport),
Niels Möllerab9d6e12021-02-02 15:49:021085 std::move(dtls_srtp_transport), std::move(rtp_dtls_transport),
Mirko Bonadei96dca922021-07-10 20:37:401086 std::move(rtcp_dtls_transport), std::move(sctp_transport), [&]() {
1087 RTC_DCHECK_RUN_ON(network_thread_);
1088 UpdateAggregateStates_n();
1089 });
Anton Sukhanov316f3ac2019-05-23 22:50:381090
Sebastian Jansson1b83a9e2019-09-18 16:22:121091 jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect(
1092 this, &JsepTransportController::OnRtcpPacketReceived_n);
Per Ke1e94ad2023-03-30 14:53:591093 jsep_transport->rtp_transport()->SignalUnDemuxableRtpPacketReceived.connect(
1094 this, &JsepTransportController::OnUnDemuxableRtpPacketReceived_n);
Sebastian Jansson1b83a9e2019-09-18 16:22:121095
Harald Alvestrand9dea3932021-06-10 06:03:061096 transports_.RegisterTransport(content_info.name, std::move(jsep_transport));
Zhi Huangd2248f82018-04-10 21:41:031097 UpdateAggregateStates_n();
Zhi Huange830e682018-03-30 17:48:351098 return RTCError::OK();
Zhi Huange818b6e2018-02-22 23:26:271099}
1100
Zhi Huange818b6e2018-02-22 23:26:271101void JsepTransportController::DestroyAllJsepTransports_n() {
Harald Alvestrand9dea3932021-06-10 06:03:061102 transports_.DestroyAllTransports();
Zhi Huange818b6e2018-02-22 23:26:271103}
1104
1105void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
Zhi Huange818b6e2018-02-22 23:26:271106 ice_role_ = ice_role;
Tomas Gunnarsson20f74562021-02-04 09:22:501107 auto dtls_transports = GetDtlsTransports();
1108 for (auto& dtls : dtls_transports) {
Zhi Huange818b6e2018-02-22 23:26:271109 dtls->ice_transport()->SetIceRole(ice_role_);
1110 }
1111}
1112
1113cricket::IceRole JsepTransportController::DetermineIceRole(
Zhi Huang365381f2018-04-13 23:44:341114 cricket::JsepTransport* jsep_transport,
Zhi Huange818b6e2018-02-22 23:26:271115 const cricket::TransportInfo& transport_info,
1116 SdpType type,
1117 bool local) {
1118 cricket::IceRole ice_role = ice_role_;
1119 auto tdesc = transport_info.description;
1120 if (local) {
1121 // The initial offer side may use ICE Lite, in which case, per RFC5245
1122 // Section 5.1.1, the answer side should take the controlling role if it is
1123 // in the full ICE mode.
1124 //
1125 // When both sides use ICE Lite, the initial offer side must take the
1126 // controlling role, and this is the default logic implemented in
1127 // SetLocalDescription in JsepTransportController.
1128 if (jsep_transport->remote_description() &&
1129 jsep_transport->remote_description()->transport_desc.ice_mode ==
1130 cricket::ICEMODE_LITE &&
1131 ice_role_ == cricket::ICEROLE_CONTROLLED &&
1132 tdesc.ice_mode == cricket::ICEMODE_FULL) {
1133 ice_role = cricket::ICEROLE_CONTROLLING;
1134 }
Zhi Huange818b6e2018-02-22 23:26:271135 } else {
1136 // If our role is cricket::ICEROLE_CONTROLLED and the remote endpoint
1137 // supports only ice_lite, this local endpoint should take the CONTROLLING
1138 // role.
1139 // TODO(deadbeef): This is a session-level attribute, so it really shouldn't
1140 // be in a TransportDescription in the first place...
1141 if (ice_role_ == cricket::ICEROLE_CONTROLLED &&
1142 tdesc.ice_mode == cricket::ICEMODE_LITE) {
1143 ice_role = cricket::ICEROLE_CONTROLLING;
1144 }
1145
1146 // If we use ICE Lite and the remote endpoint uses the full implementation
1147 // of ICE, the local endpoint must take the controlled role, and the other
1148 // side must be the controlling role.
1149 if (jsep_transport->local_description() &&
1150 jsep_transport->local_description()->transport_desc.ice_mode ==
1151 cricket::ICEMODE_LITE &&
1152 ice_role_ == cricket::ICEROLE_CONTROLLING &&
Zhi Huange830e682018-03-30 17:48:351153 tdesc.ice_mode == cricket::ICEMODE_FULL) {
Zhi Huange818b6e2018-02-22 23:26:271154 ice_role = cricket::ICEROLE_CONTROLLED;
1155 }
1156 }
1157
1158 return ice_role;
1159}
1160
1161void JsepTransportController::OnTransportWritableState_n(
1162 rtc::PacketTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 23:26:271163 RTC_LOG(LS_INFO) << " Transport " << transport->transport_name()
1164 << " writability changed to " << transport->writable()
1165 << ".";
1166 UpdateAggregateStates_n();
1167}
1168
1169void JsepTransportController::OnTransportReceivingState_n(
1170 rtc::PacketTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 23:26:271171 UpdateAggregateStates_n();
1172}
1173
1174void JsepTransportController::OnTransportGatheringState_n(
1175 cricket::IceTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 23:26:271176 UpdateAggregateStates_n();
1177}
1178
1179void JsepTransportController::OnTransportCandidateGathered_n(
1180 cricket::IceTransportInternal* transport,
1181 const cricket::Candidate& candidate) {
Zhi Huange818b6e2018-02-22 23:26:271182 // We should never signal peer-reflexive candidates.
1183 if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
Artem Titovd3251962021-11-15 15:57:071184 RTC_DCHECK_NOTREACHED();
Zhi Huange818b6e2018-02-22 23:26:271185 return;
1186 }
Tommic3257d02021-02-10 17:40:081187
1188 signal_ice_candidates_gathered_.Send(
1189 transport->transport_name(), std::vector<cricket::Candidate>{candidate});
Zhi Huange818b6e2018-02-22 23:26:271190}
1191
Eldar Relloda13ea22019-06-01 09:23:431192void JsepTransportController::OnTransportCandidateError_n(
1193 cricket::IceTransportInternal* transport,
1194 const cricket::IceCandidateErrorEvent& event) {
Tommic3257d02021-02-10 17:40:081195 signal_ice_candidate_error_.Send(event);
Eldar Relloda13ea22019-06-01 09:23:431196}
Zhi Huange818b6e2018-02-22 23:26:271197void JsepTransportController::OnTransportCandidatesRemoved_n(
1198 cricket::IceTransportInternal* transport,
1199 const cricket::Candidates& candidates) {
Tommic3257d02021-02-10 17:40:081200 signal_ice_candidates_removed_.Send(candidates);
Zhi Huange818b6e2018-02-22 23:26:271201}
Alex Drake00c7ecf2019-08-06 17:54:471202void JsepTransportController::OnTransportCandidatePairChanged_n(
1203 const cricket::CandidatePairChangeEvent& event) {
Tommic3257d02021-02-10 17:40:081204 signal_ice_candidate_pair_changed_.Send(event);
Alex Drake00c7ecf2019-08-06 17:54:471205}
Zhi Huange818b6e2018-02-22 23:26:271206
1207void JsepTransportController::OnTransportRoleConflict_n(
1208 cricket::IceTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 23:26:271209 // Note: since the role conflict is handled entirely on the network thread,
1210 // we don't need to worry about role conflicts occurring on two ports at
1211 // once. The first one encountered should immediately reverse the role.
1212 cricket::IceRole reversed_role = (ice_role_ == cricket::ICEROLE_CONTROLLING)
1213 ? cricket::ICEROLE_CONTROLLED
1214 : cricket::ICEROLE_CONTROLLING;
1215 RTC_LOG(LS_INFO) << "Got role conflict; switching to "
1216 << (reversed_role == cricket::ICEROLE_CONTROLLING
1217 ? "controlling"
1218 : "controlled")
1219 << " role.";
1220 SetIceRole_n(reversed_role);
1221}
1222
1223void JsepTransportController::OnTransportStateChanged_n(
1224 cricket::IceTransportInternal* transport) {
Zhi Huange818b6e2018-02-22 23:26:271225 RTC_LOG(LS_INFO) << transport->transport_name() << " Transport "
1226 << transport->component()
1227 << " state changed. Check if state is complete.";
1228 UpdateAggregateStates_n();
1229}
1230
1231void JsepTransportController::UpdateAggregateStates_n() {
Markus Handell518669d2021-06-07 11:30:461232 TRACE_EVENT0("webrtc", "JsepTransportController::UpdateAggregateStates_n");
Taylor Brandstetter8591eff2021-08-11 21:56:381233 auto dtls_transports = GetActiveDtlsTransports();
Alex Loiko9289eda2018-11-23 16:18:591234 cricket::IceConnectionState new_connection_state =
1235 cricket::kIceConnectionConnecting;
Jonas Olsson635474e2018-10-18 13:58:171236 PeerConnectionInterface::IceConnectionState new_ice_connection_state =
1237 PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
1238 PeerConnectionInterface::PeerConnectionState new_combined_state =
1239 PeerConnectionInterface::PeerConnectionState::kNew;
Zhi Huange818b6e2018-02-22 23:26:271240 cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
Alex Loiko9289eda2018-11-23 16:18:591241 bool any_failed = false;
Alex Loiko9289eda2018-11-23 16:18:591242 bool all_connected = !dtls_transports.empty();
1243 bool all_completed = !dtls_transports.empty();
Zhi Huange818b6e2018-02-22 23:26:271244 bool any_gathering = false;
1245 bool all_done_gathering = !dtls_transports.empty();
Jonas Olsson635474e2018-10-18 13:58:171246
1247 std::map<IceTransportState, int> ice_state_counts;
Mirko Bonadei9f6808b2021-05-21 18:46:091248 std::map<DtlsTransportState, int> dtls_state_counts;
Jonas Olsson635474e2018-10-18 13:58:171249
Zhi Huange818b6e2018-02-22 23:26:271250 for (const auto& dtls : dtls_transports) {
Alex Loiko9289eda2018-11-23 16:18:591251 any_failed = any_failed || dtls->ice_transport()->GetState() ==
1252 cricket::IceTransportState::STATE_FAILED;
1253 all_connected = all_connected && dtls->writable();
1254 all_completed =
1255 all_completed && dtls->writable() &&
1256 dtls->ice_transport()->GetState() ==
1257 cricket::IceTransportState::STATE_COMPLETED &&
1258 dtls->ice_transport()->GetIceRole() == cricket::ICEROLE_CONTROLLING &&
1259 dtls->ice_transport()->gathering_state() ==
1260 cricket::kIceGatheringComplete;
Zhi Huange818b6e2018-02-22 23:26:271261 any_gathering = any_gathering || dtls->ice_transport()->gathering_state() !=
1262 cricket::kIceGatheringNew;
1263 all_done_gathering =
1264 all_done_gathering && dtls->ice_transport()->gathering_state() ==
1265 cricket::kIceGatheringComplete;
Jonas Olsson635474e2018-10-18 13:58:171266
1267 dtls_state_counts[dtls->dtls_state()]++;
1268 ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
Zhi Huange818b6e2018-02-22 23:26:271269 }
Piotr (Peter) Slatala4eb41122018-11-01 14:26:031270
Alex Loiko9289eda2018-11-23 16:18:591271 if (any_failed) {
1272 new_connection_state = cricket::kIceConnectionFailed;
1273 } else if (all_completed) {
1274 new_connection_state = cricket::kIceConnectionCompleted;
1275 } else if (all_connected) {
1276 new_connection_state = cricket::kIceConnectionConnected;
1277 }
1278 if (ice_connection_state_ != new_connection_state) {
1279 ice_connection_state_ = new_connection_state;
Lahiru Ginnaliya Gamathigee99c68d2020-09-30 21:33:451280
Tommic3257d02021-02-10 17:40:081281 signal_ice_connection_state_.Send(new_connection_state);
Alex Loiko9289eda2018-11-23 16:18:591282 }
1283
Jonas Olsson635474e2018-10-18 13:58:171284 // Compute the current RTCIceConnectionState as described in
1285 // https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
1286 // The PeerConnection is responsible for handling the "closed" state.
1287 int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
1288 int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
1289 int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
1290 int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
1291 int total_ice_disconnected =
1292 ice_state_counts[IceTransportState::kDisconnected];
1293 int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
1294 int total_ice_new = ice_state_counts[IceTransportState::kNew];
1295 int total_ice = dtls_transports.size();
1296
1297 if (total_ice_failed > 0) {
Jonas Olsson6a8727b2018-12-07 12:11:441298 // Any RTCIceTransports are in the "failed" state.
Jonas Olsson635474e2018-10-18 13:58:171299 new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
Alex Loiko9289eda2018-11-23 16:18:591300 } else if (total_ice_disconnected > 0) {
Jonas Olsson6a8727b2018-12-07 12:11:441301 // None of the previous states apply and any RTCIceTransports are in the
1302 // "disconnected" state.
Jonas Olsson635474e2018-10-18 13:58:171303 new_ice_connection_state =
1304 PeerConnectionInterface::kIceConnectionDisconnected;
Jonas Olsson6a8727b2018-12-07 12:11:441305 } else if (total_ice_new + total_ice_closed == total_ice) {
1306 // None of the previous states apply and all RTCIceTransports are in the
1307 // "new" or "closed" state, or there are no transports.
1308 new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
1309 } else if (total_ice_new + total_ice_checking > 0) {
1310 // None of the previous states apply and any RTCIceTransports are in the
1311 // "new" or "checking" state.
Jonas Olsson635474e2018-10-18 13:58:171312 new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
Jonas Olssonacd8ae72019-02-25 14:26:241313 } else if (total_ice_completed + total_ice_closed == total_ice ||
1314 all_completed) {
Jonas Olsson6a8727b2018-12-07 12:11:441315 // None of the previous states apply and all RTCIceTransports are in the
1316 // "completed" or "closed" state.
Jonas Olssonacd8ae72019-02-25 14:26:241317 //
1318 // TODO(https://bugs.webrtc.org/10356): The all_completed condition is added
1319 // to mimic the behavior of the old ICE connection state, and should be
1320 // removed once we get end-of-candidates signaling in place.
Jonas Olsson635474e2018-10-18 13:58:171321 new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
1322 } else if (total_ice_connected + total_ice_completed + total_ice_closed ==
Jonas Olsson6a8727b2018-12-07 12:11:441323 total_ice) {
1324 // None of the previous states apply and all RTCIceTransports are in the
1325 // "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 13:58:171326 new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
Jonas Olsson635474e2018-10-18 13:58:171327 } else {
Artem Titovd3251962021-11-15 15:57:071328 RTC_DCHECK_NOTREACHED();
Jonas Olsson635474e2018-10-18 13:58:171329 }
1330
Alex Loiko9289eda2018-11-23 16:18:591331 if (standardized_ice_connection_state_ != new_ice_connection_state) {
Jonas Olssonacd8ae72019-02-25 14:26:241332 if (standardized_ice_connection_state_ ==
1333 PeerConnectionInterface::kIceConnectionChecking &&
1334 new_ice_connection_state ==
1335 PeerConnectionInterface::kIceConnectionCompleted) {
1336 // Ensure that we never skip over the "connected" state.
Tommic3257d02021-02-10 17:40:081337 signal_standardized_ice_connection_state_.Send(
1338 PeerConnectionInterface::kIceConnectionConnected);
Jonas Olssonacd8ae72019-02-25 14:26:241339 }
Alex Loiko9289eda2018-11-23 16:18:591340 standardized_ice_connection_state_ = new_ice_connection_state;
Tommic3257d02021-02-10 17:40:081341 signal_standardized_ice_connection_state_.Send(new_ice_connection_state);
Jonas Olsson635474e2018-10-18 13:58:171342 }
1343
1344 // Compute the current RTCPeerConnectionState as described in
1345 // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
1346 // The PeerConnection is responsible for handling the "closed" state.
1347 // Note that "connecting" is only a valid state for DTLS transports while
1348 // "checking", "completed" and "disconnected" are only valid for ICE
1349 // transports.
Mirko Bonadei9f6808b2021-05-21 18:46:091350 int total_connected =
1351 total_ice_connected + dtls_state_counts[DtlsTransportState::kConnected];
Jonas Olsson635474e2018-10-18 13:58:171352 int total_dtls_connecting =
Mirko Bonadei9f6808b2021-05-21 18:46:091353 dtls_state_counts[DtlsTransportState::kConnecting];
Jonas Olsson635474e2018-10-18 13:58:171354 int total_failed =
Mirko Bonadei9f6808b2021-05-21 18:46:091355 total_ice_failed + dtls_state_counts[DtlsTransportState::kFailed];
Jonas Olsson635474e2018-10-18 13:58:171356 int total_closed =
Mirko Bonadei9f6808b2021-05-21 18:46:091357 total_ice_closed + dtls_state_counts[DtlsTransportState::kClosed];
1358 int total_new = total_ice_new + dtls_state_counts[DtlsTransportState::kNew];
Jonas Olsson635474e2018-10-18 13:58:171359 int total_transports = total_ice * 2;
1360
1361 if (total_failed > 0) {
1362 // Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
1363 new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
Jonas Olsson6a8727b2018-12-07 12:11:441364 } else if (total_ice_disconnected > 0) {
1365 // None of the previous states apply and any RTCIceTransports or
1366 // RTCDtlsTransports are in the "disconnected" state.
Jonas Olsson635474e2018-10-18 13:58:171367 new_combined_state =
1368 PeerConnectionInterface::PeerConnectionState::kDisconnected;
Jonas Olsson6a8727b2018-12-07 12:11:441369 } else if (total_new + total_closed == total_transports) {
1370 // None of the previous states apply and all RTCIceTransports and
1371 // RTCDtlsTransports are in the "new" or "closed" state, or there are no
1372 // transports.
1373 new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
1374 } else if (total_new + total_dtls_connecting + total_ice_checking > 0) {
1375 // None of the previous states apply and all RTCIceTransports or
1376 // RTCDtlsTransports are in the "new", "connecting" or "checking" state.
Jonas Olsson635474e2018-10-18 13:58:171377 new_combined_state =
1378 PeerConnectionInterface::PeerConnectionState::kConnecting;
1379 } else if (total_connected + total_ice_completed + total_closed ==
Jonas Olsson6a8727b2018-12-07 12:11:441380 total_transports) {
1381 // None of the previous states apply and all RTCIceTransports and
1382 // RTCDtlsTransports are in the "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 13:58:171383 new_combined_state =
1384 PeerConnectionInterface::PeerConnectionState::kConnected;
Jonas Olsson635474e2018-10-18 13:58:171385 } else {
Artem Titovd3251962021-11-15 15:57:071386 RTC_DCHECK_NOTREACHED();
Jonas Olsson635474e2018-10-18 13:58:171387 }
1388
1389 if (combined_connection_state_ != new_combined_state) {
1390 combined_connection_state_ = new_combined_state;
Tommic3257d02021-02-10 17:40:081391 signal_connection_state_.Send(new_combined_state);
Jonas Olsson635474e2018-10-18 13:58:171392 }
1393
Harald Alvestrandbedb6052020-08-20 12:50:101394 // Compute the gathering state.
1395 if (dtls_transports.empty()) {
1396 new_gathering_state = cricket::kIceGatheringNew;
1397 } else if (all_done_gathering) {
Zhi Huange818b6e2018-02-22 23:26:271398 new_gathering_state = cricket::kIceGatheringComplete;
1399 } else if (any_gathering) {
1400 new_gathering_state = cricket::kIceGatheringGathering;
1401 }
1402 if (ice_gathering_state_ != new_gathering_state) {
1403 ice_gathering_state_ = new_gathering_state;
Tommic3257d02021-02-10 17:40:081404 signal_ice_gathering_state_.Send(new_gathering_state);
Zhi Huange818b6e2018-02-22 23:26:271405 }
1406}
1407
Sebastian Jansson1b83a9e2019-09-18 16:22:121408void JsepTransportController::OnRtcpPacketReceived_n(
1409 rtc::CopyOnWriteBuffer* packet,
1410 int64_t packet_time_us) {
1411 RTC_DCHECK(config_.rtcp_handler);
1412 config_.rtcp_handler(*packet, packet_time_us);
1413}
1414
Per Ke1e94ad2023-03-30 14:53:591415void JsepTransportController::OnUnDemuxableRtpPacketReceived_n(
1416 const webrtc::RtpPacketReceived& packet) {
1417 RTC_DCHECK(config_.un_demuxable_packet_handler);
1418 config_.un_demuxable_packet_handler(packet);
1419}
1420
Zhi Huange818b6e2018-02-22 23:26:271421void JsepTransportController::OnDtlsHandshakeError(
1422 rtc::SSLHandshakeError error) {
Lahiru Ginnaliya Gamathige70f9e242021-01-28 07:32:461423 config_.on_dtls_handshake_error_(error);
Zhi Huange818b6e2018-02-22 23:26:271424}
1425
Harald Alvestrand9dea3932021-06-10 06:03:061426bool JsepTransportController::OnTransportChanged(
1427 const std::string& mid,
1428 cricket::JsepTransport* jsep_transport) {
1429 if (config_.transport_observer) {
1430 if (jsep_transport) {
1431 return config_.transport_observer->OnTransportChanged(
1432 mid, jsep_transport->rtp_transport(),
1433 jsep_transport->RtpDtlsTransport(),
1434 jsep_transport->data_channel_transport());
1435 } else {
1436 return config_.transport_observer->OnTransportChanged(mid, nullptr,
1437 nullptr, nullptr);
1438 }
1439 }
1440 return false;
1441}
1442
Zhi Huange818b6e2018-02-22 23:26:271443} // namespace webrtc