blob: 0687a067f73ec6a11650714ae25f21c5fe3c2863 [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
Zhi Huange818b6e2018-02-22 15:26:27 -080013#include <memory>
14#include <utility>
15
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "absl/algorithm/container.h"
Qingsi Wang25ec8882019-11-15 12:33:05 -080017#include "api/ice_transport_factory.h"
Niels Möller65f17ca2019-09-12 13:59:36 +020018#include "api/transport/datagram_transport_interface.h"
19#include "api/transport/media/media_transport_interface.h"
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -080020#include "p2p/base/ice_transport_internal.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080021#include "p2p/base/port.h"
Bjorn A Mellem364b2672019-08-20 16:58:03 -070022#include "pc/datagram_rtp_transport.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "pc/srtp_filter.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080024#include "rtc_base/bind.h"
25#include "rtc_base/checks.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080026#include "rtc_base/thread.h"
27
28using webrtc::SdpType;
29
30namespace {
31
Zhi Huange818b6e2018-02-22 15:26:27 -080032webrtc::RTCError VerifyCandidate(const cricket::Candidate& cand) {
33 // No address zero.
34 if (cand.address().IsNil() || cand.address().IsAnyIP()) {
35 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
36 "candidate has address of zero");
37 }
38
39 // Disallow all ports below 1024, except for 80 and 443 on public addresses.
40 int port = cand.address().port();
41 if (cand.protocol() == cricket::TCP_PROTOCOL_NAME &&
42 (cand.tcptype() == cricket::TCPTYPE_ACTIVE_STR || port == 0)) {
43 // Expected for active-only candidates per
44 // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
45 // Libjingle clients emit port 0, in "active" mode.
46 return webrtc::RTCError::OK();
47 }
48 if (port < 1024) {
49 if ((port != 80) && (port != 443)) {
50 return webrtc::RTCError(
51 webrtc::RTCErrorType::INVALID_PARAMETER,
52 "candidate has port below 1024, but not 80 or 443");
53 }
54
55 if (cand.address().IsPrivateIP()) {
56 return webrtc::RTCError(
57 webrtc::RTCErrorType::INVALID_PARAMETER,
58 "candidate has port of 80 or 443 with private IP address");
59 }
60 }
61
Philipp Hancke712ebbb2020-02-04 17:44:46 +010062 // Disallow ICE-TCP with a private IP address.
63 if (cand.protocol() == cricket::TCP_PROTOCOL_NAME &&
64 cand.address().IsPrivateIP()) {
65 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
66 "candidate is TCP and has a private IP address");
67 }
68
Zhi Huange818b6e2018-02-22 15:26:27 -080069 return webrtc::RTCError::OK();
70}
71
72webrtc::RTCError VerifyCandidates(const cricket::Candidates& candidates) {
73 for (const cricket::Candidate& candidate : candidates) {
74 webrtc::RTCError error = VerifyCandidate(candidate);
75 if (!error.ok()) {
76 return error;
77 }
78 }
79 return webrtc::RTCError::OK();
80}
81
82} // namespace
83
84namespace webrtc {
85
86JsepTransportController::JsepTransportController(
87 rtc::Thread* signaling_thread,
88 rtc::Thread* network_thread,
89 cricket::PortAllocator* port_allocator,
Zach Steine20867f2018-08-02 13:20:15 -070090 AsyncResolverFactory* async_resolver_factory,
Zhi Huange818b6e2018-02-22 15:26:27 -080091 Config config)
92 : signaling_thread_(signaling_thread),
93 network_thread_(network_thread),
94 port_allocator_(port_allocator),
Zach Steine20867f2018-08-02 13:20:15 -070095 async_resolver_factory_(async_resolver_factory),
Zhi Huang365381f2018-04-13 16:44:34 -070096 config_(config) {
97 // The |transport_observer| is assumed to be non-null.
98 RTC_DCHECK(config_.transport_observer);
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +020099 RTC_DCHECK(config_.rtcp_handler);
Qingsi Wang25ec8882019-11-15 12:33:05 -0800100 RTC_DCHECK(config_.ice_transport_factory);
Zhi Huang365381f2018-04-13 16:44:34 -0700101}
Zhi Huange818b6e2018-02-22 15:26:27 -0800102
103JsepTransportController::~JsepTransportController() {
104 // Channel destructors may try to send packets, so this needs to happen on
105 // the network thread.
106 network_thread_->Invoke<void>(
107 RTC_FROM_HERE,
108 rtc::Bind(&JsepTransportController::DestroyAllJsepTransports_n, this));
109}
110
111RTCError JsepTransportController::SetLocalDescription(
112 SdpType type,
113 const cricket::SessionDescription* description) {
114 if (!network_thread_->IsCurrent()) {
115 return network_thread_->Invoke<RTCError>(
116 RTC_FROM_HERE, [=] { return SetLocalDescription(type, description); });
117 }
118
119 if (!initial_offerer_.has_value()) {
120 initial_offerer_.emplace(type == SdpType::kOffer);
121 if (*initial_offerer_) {
122 SetIceRole_n(cricket::ICEROLE_CONTROLLING);
123 } else {
124 SetIceRole_n(cricket::ICEROLE_CONTROLLED);
125 }
126 }
127 return ApplyDescription_n(/*local=*/true, type, description);
128}
129
130RTCError JsepTransportController::SetRemoteDescription(
131 SdpType type,
132 const cricket::SessionDescription* description) {
133 if (!network_thread_->IsCurrent()) {
134 return network_thread_->Invoke<RTCError>(
135 RTC_FROM_HERE, [=] { return SetRemoteDescription(type, description); });
136 }
137
138 return ApplyDescription_n(/*local=*/false, type, description);
139}
140
141RtpTransportInternal* JsepTransportController::GetRtpTransport(
142 const std::string& mid) const {
Zhi Huange830e682018-03-30 10:48:35 -0700143 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800144 if (!jsep_transport) {
145 return nullptr;
146 }
147 return jsep_transport->rtp_transport();
148}
149
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700150MediaTransportConfig JsepTransportController::GetMediaTransportConfig(
Anton Sukhanov7940da02018-10-10 10:34:49 -0700151 const std::string& mid) const {
152 auto jsep_transport = GetJsepTransportForMid(mid);
153 if (!jsep_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700154 return MediaTransportConfig();
155 }
156
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700157 DatagramTransportInterface* datagram_transport = nullptr;
158 if (config_.use_datagram_transport) {
159 datagram_transport = jsep_transport->datagram_transport();
160 }
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700161
Bjorn A Mellem7a9a0922019-11-26 09:19:40 -0800162 if (datagram_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700163 return MediaTransportConfig(
164 /*rtp_max_packet_size=*/datagram_transport->GetLargestDatagramSize());
165 } else {
166 return MediaTransportConfig();
167 }
168}
169
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700170DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700171 const std::string& mid) const {
172 auto jsep_transport = GetJsepTransportForMid(mid);
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700173 if (!jsep_transport) {
Anton Sukhanov7940da02018-10-10 10:34:49 -0700174 return nullptr;
175 }
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700176 return jsep_transport->data_channel_transport();
Anton Sukhanov7940da02018-10-10 10:34:49 -0700177}
178
Zhi Huange818b6e2018-02-22 15:26:27 -0800179cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
Harald Alvestrandad88c882018-11-28 16:47:46 +0100180 const std::string& mid) {
Zhi Huange830e682018-03-30 10:48:35 -0700181 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800182 if (!jsep_transport) {
183 return nullptr;
184 }
185 return jsep_transport->rtp_dtls_transport();
186}
187
Harald Alvestrandad88c882018-11-28 16:47:46 +0100188const cricket::DtlsTransportInternal*
189JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
Zhi Huange830e682018-03-30 10:48:35 -0700190 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800191 if (!jsep_transport) {
192 return nullptr;
193 }
194 return jsep_transport->rtcp_dtls_transport();
195}
196
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100197rtc::scoped_refptr<webrtc::DtlsTransport>
Harald Alvestrandad88c882018-11-28 16:47:46 +0100198JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
199 auto jsep_transport = GetJsepTransportForMid(mid);
200 if (!jsep_transport) {
201 return nullptr;
202 }
203 return jsep_transport->RtpDtlsTransport();
204}
205
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700206rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
207 const std::string& mid) const {
208 auto jsep_transport = GetJsepTransportForMid(mid);
209 if (!jsep_transport) {
210 return nullptr;
211 }
212 return jsep_transport->SctpTransport();
213}
214
Zhi Huange818b6e2018-02-22 15:26:27 -0800215void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
216 if (!network_thread_->IsCurrent()) {
217 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] { SetIceConfig(config); });
218 return;
219 }
220
221 ice_config_ = config;
222 for (auto& dtls : GetDtlsTransports()) {
223 dtls->ice_transport()->SetIceConfig(ice_config_);
224 }
225}
226
227void JsepTransportController::SetNeedsIceRestartFlag() {
Zhi Huange830e682018-03-30 10:48:35 -0700228 for (auto& kv : jsep_transports_by_name_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800229 kv.second->SetNeedsIceRestartFlag();
230 }
231}
232
233bool JsepTransportController::NeedsIceRestart(
234 const std::string& transport_name) const {
Zhi Huang365381f2018-04-13 16:44:34 -0700235 const cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700236 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800237 if (!transport) {
238 return false;
239 }
240 return transport->needs_ice_restart();
241}
242
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200243absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
Zhi Huange830e682018-03-30 10:48:35 -0700244 const std::string& mid) const {
Zhi Huange818b6e2018-02-22 15:26:27 -0800245 if (!network_thread_->IsCurrent()) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200246 return network_thread_->Invoke<absl::optional<rtc::SSLRole>>(
Zhi Huange830e682018-03-30 10:48:35 -0700247 RTC_FROM_HERE, [&] { return GetDtlsRole(mid); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800248 }
249
Zhi Huang365381f2018-04-13 16:44:34 -0700250 const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800251 if (!t) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200252 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 15:26:27 -0800253 }
254 return t->GetDtlsRole();
255}
256
257bool JsepTransportController::SetLocalCertificate(
258 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
259 if (!network_thread_->IsCurrent()) {
260 return network_thread_->Invoke<bool>(
261 RTC_FROM_HERE, [&] { return SetLocalCertificate(certificate); });
262 }
263
264 // Can't change a certificate, or set a null certificate.
265 if (certificate_ || !certificate) {
266 return false;
267 }
268 certificate_ = certificate;
269
270 // Set certificate for JsepTransport, which verifies it matches the
271 // fingerprint in SDP, and DTLS transport.
272 // Fallback from DTLS to SDES is not supported.
Zhi Huange830e682018-03-30 10:48:35 -0700273 for (auto& kv : jsep_transports_by_name_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800274 kv.second->SetLocalCertificate(certificate_);
275 }
276 for (auto& dtls : GetDtlsTransports()) {
277 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
278 RTC_DCHECK(set_cert_success);
279 }
280 return true;
281}
282
283rtc::scoped_refptr<rtc::RTCCertificate>
284JsepTransportController::GetLocalCertificate(
285 const std::string& transport_name) const {
286 if (!network_thread_->IsCurrent()) {
287 return network_thread_->Invoke<rtc::scoped_refptr<rtc::RTCCertificate>>(
288 RTC_FROM_HERE, [&] { return GetLocalCertificate(transport_name); });
289 }
290
Zhi Huang365381f2018-04-13 16:44:34 -0700291 const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800292 if (!t) {
293 return nullptr;
294 }
295 return t->GetLocalCertificate();
296}
297
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800298std::unique_ptr<rtc::SSLCertChain>
299JsepTransportController::GetRemoteSSLCertChain(
Zhi Huange818b6e2018-02-22 15:26:27 -0800300 const std::string& transport_name) const {
301 if (!network_thread_->IsCurrent()) {
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800302 return network_thread_->Invoke<std::unique_ptr<rtc::SSLCertChain>>(
303 RTC_FROM_HERE, [&] { return GetRemoteSSLCertChain(transport_name); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800304 }
305
Zhi Huange830e682018-03-30 10:48:35 -0700306 // Get the certificate from the RTP transport's DTLS handshake. Should be
307 // identical to the RTCP transport's, since they were given the same remote
Zhi Huange818b6e2018-02-22 15:26:27 -0800308 // fingerprint.
Zhi Huange830e682018-03-30 10:48:35 -0700309 auto jsep_transport = GetJsepTransportByName(transport_name);
310 if (!jsep_transport) {
311 return nullptr;
312 }
313 auto dtls = jsep_transport->rtp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800314 if (!dtls) {
315 return nullptr;
316 }
317
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800318 return dtls->GetRemoteSSLCertChain();
Zhi Huange818b6e2018-02-22 15:26:27 -0800319}
320
321void JsepTransportController::MaybeStartGathering() {
322 if (!network_thread_->IsCurrent()) {
323 network_thread_->Invoke<void>(RTC_FROM_HERE,
324 [&] { MaybeStartGathering(); });
325 return;
326 }
327
328 for (auto& dtls : GetDtlsTransports()) {
329 dtls->ice_transport()->MaybeStartGathering();
330 }
331}
332
333RTCError JsepTransportController::AddRemoteCandidates(
334 const std::string& transport_name,
335 const cricket::Candidates& candidates) {
336 if (!network_thread_->IsCurrent()) {
337 return network_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
338 return AddRemoteCandidates(transport_name, candidates);
339 });
340 }
341
342 // Verify each candidate before passing down to the transport layer.
343 RTCError error = VerifyCandidates(candidates);
344 if (!error.ok()) {
345 return error;
346 }
Zhi Huange830e682018-03-30 10:48:35 -0700347 auto jsep_transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800348 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700349 RTC_LOG(LS_WARNING) << "Not adding candidate because the JsepTransport "
350 "doesn't exist. Ignore it.";
351 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -0800352 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800353 return jsep_transport->AddRemoteCandidates(candidates);
354}
355
356RTCError JsepTransportController::RemoveRemoteCandidates(
357 const cricket::Candidates& candidates) {
358 if (!network_thread_->IsCurrent()) {
359 return network_thread_->Invoke<RTCError>(
360 RTC_FROM_HERE, [&] { return RemoveRemoteCandidates(candidates); });
361 }
362
363 // Verify each candidate before passing down to the transport layer.
364 RTCError error = VerifyCandidates(candidates);
365 if (!error.ok()) {
366 return error;
367 }
368
369 std::map<std::string, cricket::Candidates> candidates_by_transport_name;
370 for (const cricket::Candidate& cand : candidates) {
371 if (!cand.transport_name().empty()) {
372 candidates_by_transport_name[cand.transport_name()].push_back(cand);
373 } else {
374 RTC_LOG(LS_ERROR) << "Not removing candidate because it does not have a "
375 "transport name set: "
Qingsi Wang20232a92019-09-06 12:51:17 -0700376 << cand.ToSensitiveString();
Zhi Huange818b6e2018-02-22 15:26:27 -0800377 }
378 }
379
380 for (const auto& kv : candidates_by_transport_name) {
381 const std::string& transport_name = kv.first;
382 const cricket::Candidates& candidates = kv.second;
Zhi Huang365381f2018-04-13 16:44:34 -0700383 cricket::JsepTransport* jsep_transport =
Zhi Huange830e682018-03-30 10:48:35 -0700384 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800385 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700386 RTC_LOG(LS_WARNING)
387 << "Not removing candidate because the JsepTransport doesn't exist.";
388 continue;
Zhi Huange818b6e2018-02-22 15:26:27 -0800389 }
390 for (const cricket::Candidate& candidate : candidates) {
Harald Alvestrandad88c882018-11-28 16:47:46 +0100391 cricket::DtlsTransportInternal* dtls =
392 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
393 ? jsep_transport->rtp_dtls_transport()
394 : jsep_transport->rtcp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800395 if (dtls) {
396 dtls->ice_transport()->RemoveRemoteCandidate(candidate);
397 }
398 }
399 }
400 return RTCError::OK();
401}
402
403bool JsepTransportController::GetStats(const std::string& transport_name,
404 cricket::TransportStats* stats) {
405 if (!network_thread_->IsCurrent()) {
406 return network_thread_->Invoke<bool>(
407 RTC_FROM_HERE, [=] { return GetStats(transport_name, stats); });
408 }
409
Zhi Huang365381f2018-04-13 16:44:34 -0700410 cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800411 if (!transport) {
412 return false;
413 }
414 return transport->GetStats(stats);
415}
416
Zhi Huangb57e1692018-06-12 11:41:11 -0700417void JsepTransportController::SetActiveResetSrtpParams(
418 bool active_reset_srtp_params) {
419 if (!network_thread_->IsCurrent()) {
420 network_thread_->Invoke<void>(RTC_FROM_HERE, [=] {
421 SetActiveResetSrtpParams(active_reset_srtp_params);
422 });
423 return;
424 }
425
426 RTC_LOG(INFO)
427 << "Updating the active_reset_srtp_params for JsepTransportController: "
428 << active_reset_srtp_params;
429 config_.active_reset_srtp_params = active_reset_srtp_params;
430 for (auto& kv : jsep_transports_by_name_) {
431 kv.second->SetActiveResetSrtpParams(active_reset_srtp_params);
432 }
433}
434
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800435void JsepTransportController::SetMediaTransportSettings(
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700436 bool use_datagram_transport,
Bjorn A Mellem7da4e562019-09-26 11:02:11 -0700437 bool use_datagram_transport_for_data_channels,
438 bool use_datagram_transport_for_data_channels_receive_only) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700439 config_.use_datagram_transport = use_datagram_transport;
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700440 config_.use_datagram_transport_for_data_channels =
441 use_datagram_transport_for_data_channels;
Bjorn A Mellem7da4e562019-09-26 11:02:11 -0700442 config_.use_datagram_transport_for_data_channels_receive_only =
443 use_datagram_transport_for_data_channels_receive_only;
Piotr (Peter) Slatala97fc11f2018-10-18 12:57:59 -0700444}
445
Eldar Rellod85ea752020-02-19 20:41:07 +0200446void JsepTransportController::RollbackTransports() {
Eldar Rello5ab79e62019-10-09 18:29:44 +0300447 if (!network_thread_->IsCurrent()) {
Eldar Rellod85ea752020-02-19 20:41:07 +0200448 network_thread_->Invoke<void>(RTC_FROM_HERE, [=] { RollbackTransports(); });
Eldar Rello5ab79e62019-10-09 18:29:44 +0300449 return;
450 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200451 RTC_DCHECK_RUN_ON(network_thread_);
452 for (auto&& mid : pending_mids_) {
Eldar Rello353a7182019-11-25 18:49:44 +0200453 RemoveTransportForMid(mid);
454 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200455 for (auto&& mid : pending_mids_) {
Eldar Rello353a7182019-11-25 18:49:44 +0200456 MaybeDestroyJsepTransport(mid);
457 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200458 pending_mids_.clear();
Eldar Rello5ab79e62019-10-09 18:29:44 +0300459}
460
Qingsi Wang25ec8882019-11-15 12:33:05 -0800461rtc::scoped_refptr<webrtc::IceTransportInterface>
462JsepTransportController::CreateIceTransport(const std::string& transport_name,
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800463 bool rtcp) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800464 int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
465 : cricket::ICE_CANDIDATE_COMPONENT_RTP;
466
Qingsi Wang25ec8882019-11-15 12:33:05 -0800467 IceTransportInit init;
468 init.set_port_allocator(port_allocator_);
469 init.set_async_resolver_factory(async_resolver_factory_);
470 init.set_event_log(config_.event_log);
471 return config_.ice_transport_factory->CreateIceTransport(
472 transport_name, component, std::move(init));
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800473}
474
475std::unique_ptr<cricket::DtlsTransportInternal>
476JsepTransportController::CreateDtlsTransport(
Anton Sukhanovac6c0962019-07-10 15:44:56 -0700477 const cricket::ContentInfo& content_info,
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700478 cricket::IceTransportInternal* ice,
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700479 DatagramTransportInterface* datagram_transport) {
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800480 RTC_DCHECK(network_thread_->IsCurrent());
481
482 std::unique_ptr<cricket::DtlsTransportInternal> dtls;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700483
484 if (datagram_transport) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700485 RTC_DCHECK(config_.use_datagram_transport ||
486 config_.use_datagram_transport_for_data_channels);
Qingsi Wang25ec8882019-11-15 12:33:05 -0800487 } else if (config_.dtls_transport_factory) {
488 dtls = config_.dtls_transport_factory->CreateDtlsTransport(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700489 ice, config_.crypto_options);
Zhi Huange818b6e2018-02-22 15:26:27 -0800490 } else {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200491 dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
492 config_.event_log);
Zhi Huange818b6e2018-02-22 15:26:27 -0800493 }
494
495 RTC_DCHECK(dtls);
496 dtls->SetSslMaxProtocolVersion(config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 15:26:27 -0800497 dtls->ice_transport()->SetIceRole(ice_role_);
498 dtls->ice_transport()->SetIceTiebreaker(ice_tiebreaker_);
499 dtls->ice_transport()->SetIceConfig(ice_config_);
500 if (certificate_) {
501 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
502 RTC_DCHECK(set_cert_success);
503 }
504
505 // Connect to signals offered by the DTLS and ICE transport.
506 dtls->SignalWritableState.connect(
507 this, &JsepTransportController::OnTransportWritableState_n);
508 dtls->SignalReceivingState.connect(
509 this, &JsepTransportController::OnTransportReceivingState_n);
510 dtls->SignalDtlsHandshakeError.connect(
511 this, &JsepTransportController::OnDtlsHandshakeError);
512 dtls->ice_transport()->SignalGatheringState.connect(
513 this, &JsepTransportController::OnTransportGatheringState_n);
514 dtls->ice_transport()->SignalCandidateGathered.connect(
515 this, &JsepTransportController::OnTransportCandidateGathered_n);
Eldar Relloda13ea22019-06-01 12:23:43 +0300516 dtls->ice_transport()->SignalCandidateError.connect(
517 this, &JsepTransportController::OnTransportCandidateError_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800518 dtls->ice_transport()->SignalCandidatesRemoved.connect(
519 this, &JsepTransportController::OnTransportCandidatesRemoved_n);
520 dtls->ice_transport()->SignalRoleConflict.connect(
521 this, &JsepTransportController::OnTransportRoleConflict_n);
522 dtls->ice_transport()->SignalStateChanged.connect(
523 this, &JsepTransportController::OnTransportStateChanged_n);
Jonas Olsson7a6739e2019-01-15 16:31:55 +0100524 dtls->ice_transport()->SignalIceTransportStateChanged.connect(
525 this, &JsepTransportController::OnTransportStateChanged_n);
Alex Drake00c7ecf2019-08-06 10:54:47 -0700526 dtls->ice_transport()->SignalCandidatePairChanged.connect(
527 this, &JsepTransportController::OnTransportCandidatePairChanged_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800528 return dtls;
529}
530
531std::unique_ptr<webrtc::RtpTransport>
532JsepTransportController::CreateUnencryptedRtpTransport(
533 const std::string& transport_name,
534 rtc::PacketTransportInternal* rtp_packet_transport,
535 rtc::PacketTransportInternal* rtcp_packet_transport) {
536 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange830e682018-03-30 10:48:35 -0700537 auto unencrypted_rtp_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200538 std::make_unique<RtpTransport>(rtcp_packet_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700539 unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
540 if (rtcp_packet_transport) {
541 unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
542 }
543 return unencrypted_rtp_transport;
Zhi Huange818b6e2018-02-22 15:26:27 -0800544}
545
546std::unique_ptr<webrtc::SrtpTransport>
547JsepTransportController::CreateSdesTransport(
548 const std::string& transport_name,
Zhi Huange830e682018-03-30 10:48:35 -0700549 cricket::DtlsTransportInternal* rtp_dtls_transport,
550 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800551 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange818b6e2018-02-22 15:26:27 -0800552 auto srtp_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200553 std::make_unique<webrtc::SrtpTransport>(rtcp_dtls_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700554 RTC_DCHECK(rtp_dtls_transport);
555 srtp_transport->SetRtpPacketTransport(rtp_dtls_transport);
556 if (rtcp_dtls_transport) {
557 srtp_transport->SetRtcpPacketTransport(rtcp_dtls_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800558 }
559 if (config_.enable_external_auth) {
560 srtp_transport->EnableExternalAuth();
561 }
562 return srtp_transport;
563}
564
565std::unique_ptr<webrtc::DtlsSrtpTransport>
566JsepTransportController::CreateDtlsSrtpTransport(
567 const std::string& transport_name,
568 cricket::DtlsTransportInternal* rtp_dtls_transport,
569 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
570 RTC_DCHECK(network_thread_->IsCurrent());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200571 auto dtls_srtp_transport = std::make_unique<webrtc::DtlsSrtpTransport>(
Zhi Huang365381f2018-04-13 16:44:34 -0700572 rtcp_dtls_transport == nullptr);
Zhi Huang27f3bf52018-03-26 21:37:23 -0700573 if (config_.enable_external_auth) {
Zhi Huang365381f2018-04-13 16:44:34 -0700574 dtls_srtp_transport->EnableExternalAuth();
Zhi Huang27f3bf52018-03-26 21:37:23 -0700575 }
Zhi Huang97d5e5b2018-03-27 00:09:01 +0000576
Zhi Huange818b6e2018-02-22 15:26:27 -0800577 dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
578 rtcp_dtls_transport);
Zhi Huangb57e1692018-06-12 11:41:11 -0700579 dtls_srtp_transport->SetActiveResetSrtpParams(
580 config_.active_reset_srtp_params);
Jonas Olsson635474e2018-10-18 15:58:17 +0200581 dtls_srtp_transport->SignalDtlsStateChange.connect(
582 this, &JsepTransportController::UpdateAggregateStates_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800583 return dtls_srtp_transport;
584}
585
586std::vector<cricket::DtlsTransportInternal*>
587JsepTransportController::GetDtlsTransports() {
588 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
Zhi Huange830e682018-03-30 10:48:35 -0700589 for (auto it = jsep_transports_by_name_.begin();
590 it != jsep_transports_by_name_.end(); ++it) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800591 auto jsep_transport = it->second.get();
592 RTC_DCHECK(jsep_transport);
593 if (jsep_transport->rtp_dtls_transport()) {
594 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
595 }
596
597 if (jsep_transport->rtcp_dtls_transport()) {
598 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
599 }
600 }
601 return dtls_transports;
602}
603
Zhi Huange818b6e2018-02-22 15:26:27 -0800604RTCError JsepTransportController::ApplyDescription_n(
605 bool local,
606 SdpType type,
607 const cricket::SessionDescription* description) {
Eldar Rellod85ea752020-02-19 20:41:07 +0200608 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800609 RTC_DCHECK(description);
610
611 if (local) {
612 local_desc_ = description;
613 } else {
614 remote_desc_ = description;
615 }
616
Zhi Huange830e682018-03-30 10:48:35 -0700617 RTCError error;
Zhi Huangd2248f82018-04-10 14:41:03 -0700618 error = ValidateAndMaybeUpdateBundleGroup(local, type, description);
Zhi Huange830e682018-03-30 10:48:35 -0700619 if (!error.ok()) {
620 return error;
Zhi Huange818b6e2018-02-22 15:26:27 -0800621 }
622
623 std::vector<int> merged_encrypted_extension_ids;
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700624 absl::optional<std::string> bundle_media_alt_protocol;
625 absl::optional<std::string> bundle_data_alt_protocol;
Zhi Huange818b6e2018-02-22 15:26:27 -0800626 if (bundle_group_) {
627 merged_encrypted_extension_ids =
628 MergeEncryptedHeaderExtensionIdsForBundle(description);
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700629 error = GetAltProtocolsForBundle(description, &bundle_media_alt_protocol,
630 &bundle_data_alt_protocol);
631 if (!error.ok()) {
632 return error;
633 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800634 }
635
636 for (const cricket::ContentInfo& content_info : description->contents()) {
637 // Don't create transports for rejected m-lines and bundled m-lines."
638 if (content_info.rejected ||
639 (IsBundled(content_info.name) && content_info.name != *bundled_mid())) {
640 continue;
641 }
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -0800642 error = MaybeCreateJsepTransport(local, content_info, *description);
Zhi Huange830e682018-03-30 10:48:35 -0700643 if (!error.ok()) {
644 return error;
645 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800646 }
647
648 RTC_DCHECK(description->contents().size() ==
649 description->transport_infos().size());
650 for (size_t i = 0; i < description->contents().size(); ++i) {
651 const cricket::ContentInfo& content_info = description->contents()[i];
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700652 const cricket::MediaContentDescription* media_description =
653 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800654 const cricket::TransportInfo& transport_info =
655 description->transport_infos()[i];
656 if (content_info.rejected) {
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700657 HandleRejectedContent(content_info, description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800658 continue;
659 }
660
661 if (IsBundled(content_info.name) && content_info.name != *bundled_mid()) {
Zhi Huang365381f2018-04-13 16:44:34 -0700662 if (!HandleBundledContent(content_info)) {
663 return RTCError(RTCErrorType::INVALID_PARAMETER,
664 "Failed to process the bundled m= section.");
665 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800666 continue;
667 }
668
Zhi Huange830e682018-03-30 10:48:35 -0700669 error = ValidateContent(content_info);
670 if (!error.ok()) {
671 return error;
672 }
673
Zhi Huange818b6e2018-02-22 15:26:27 -0800674 std::vector<int> extension_ids;
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700675 absl::optional<std::string> media_alt_protocol;
676 absl::optional<std::string> data_alt_protocol;
Taylor Brandstetter0ab56512018-04-12 10:30:48 -0700677 if (bundled_mid() && content_info.name == *bundled_mid()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800678 extension_ids = merged_encrypted_extension_ids;
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700679 media_alt_protocol = bundle_media_alt_protocol;
680 data_alt_protocol = bundle_data_alt_protocol;
Zhi Huange818b6e2018-02-22 15:26:27 -0800681 } else {
682 extension_ids = GetEncryptedHeaderExtensionIds(content_info);
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700683 switch (media_description->type()) {
684 case cricket::MEDIA_TYPE_AUDIO:
685 case cricket::MEDIA_TYPE_VIDEO:
686 media_alt_protocol = media_description->alt_protocol();
687 break;
688 case cricket::MEDIA_TYPE_DATA:
689 data_alt_protocol = media_description->alt_protocol();
690 break;
691 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800692 }
693
Zhi Huange830e682018-03-30 10:48:35 -0700694 int rtp_abs_sendtime_extn_id =
695 GetRtpAbsSendTimeHeaderExtensionId(content_info);
696
Zhi Huang365381f2018-04-13 16:44:34 -0700697 cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700698 GetJsepTransportForMid(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800699 RTC_DCHECK(transport);
700
701 SetIceRole_n(DetermineIceRole(transport, transport_info, type, local));
702
Zhi Huange818b6e2018-02-22 15:26:27 -0800703 cricket::JsepTransportDescription jsep_description =
704 CreateJsepTransportDescription(content_info, transport_info,
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700705 extension_ids, rtp_abs_sendtime_extn_id,
706 media_alt_protocol, data_alt_protocol);
Zhi Huange818b6e2018-02-22 15:26:27 -0800707 if (local) {
708 error =
709 transport->SetLocalJsepTransportDescription(jsep_description, type);
710 } else {
711 error =
712 transport->SetRemoteJsepTransportDescription(jsep_description, type);
713 }
714
715 if (!error.ok()) {
716 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
717 "Failed to apply the description for " +
718 content_info.name + ": " + error.message());
719 }
720 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200721 if (type == SdpType::kAnswer) {
722 pending_mids_.clear();
723 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800724 return RTCError::OK();
725}
726
Zhi Huangd2248f82018-04-10 14:41:03 -0700727RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup(
728 bool local,
729 SdpType type,
Zhi Huange830e682018-03-30 10:48:35 -0700730 const cricket::SessionDescription* description) {
731 RTC_DCHECK(description);
Zhi Huangd2248f82018-04-10 14:41:03 -0700732 const cricket::ContentGroup* new_bundle_group =
733 description->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
734
735 // The BUNDLE group containing a MID that no m= section has is invalid.
736 if (new_bundle_group) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100737 for (const auto& content_name : new_bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700738 if (!description->GetContentByName(content_name)) {
739 return RTCError(RTCErrorType::INVALID_PARAMETER,
740 "The BUNDLE group contains MID:" + content_name +
741 " matching no m= section.");
742 }
743 }
744 }
745
746 if (type == SdpType::kAnswer) {
747 const cricket::ContentGroup* offered_bundle_group =
748 local ? remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE)
749 : local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
750
751 if (new_bundle_group) {
752 // The BUNDLE group in answer should be a subset of offered group.
Mirko Bonadei739baf02019-01-27 17:29:42 +0100753 for (const auto& content_name : new_bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700754 if (!offered_bundle_group ||
755 !offered_bundle_group->HasContentName(content_name)) {
756 return RTCError(RTCErrorType::INVALID_PARAMETER,
757 "The BUNDLE group in answer contains a MID that was "
758 "not in the offered group.");
759 }
760 }
761 }
762
763 if (bundle_group_) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100764 for (const auto& content_name : bundle_group_->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700765 // An answer that removes m= sections from pre-negotiated BUNDLE group
766 // without rejecting it, is invalid.
767 if (!new_bundle_group ||
768 !new_bundle_group->HasContentName(content_name)) {
769 auto* content_info = description->GetContentByName(content_name);
770 if (!content_info || !content_info->rejected) {
771 return RTCError(RTCErrorType::INVALID_PARAMETER,
772 "Answer cannot remove m= section " + content_name +
773 " from already-established BUNDLE group.");
774 }
775 }
776 }
777 }
778 }
779
780 if (config_.bundle_policy ==
781 PeerConnectionInterface::kBundlePolicyMaxBundle &&
782 !description->HasGroup(cricket::GROUP_TYPE_BUNDLE)) {
783 return RTCError(RTCErrorType::INVALID_PARAMETER,
784 "max-bundle is used but no bundle group found.");
785 }
786
787 if (ShouldUpdateBundleGroup(type, description)) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700788 bundle_group_ = *new_bundle_group;
789 }
Zhi Huange830e682018-03-30 10:48:35 -0700790
791 if (!bundled_mid()) {
792 return RTCError::OK();
793 }
794
795 auto bundled_content = description->GetContentByName(*bundled_mid());
796 if (!bundled_content) {
797 return RTCError(
798 RTCErrorType::INVALID_PARAMETER,
799 "An m= section associated with the BUNDLE-tag doesn't exist.");
800 }
801
802 // If the |bundled_content| is rejected, other contents in the bundle group
803 // should be rejected.
804 if (bundled_content->rejected) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100805 for (const auto& content_name : bundle_group_->content_names()) {
Zhi Huange830e682018-03-30 10:48:35 -0700806 auto other_content = description->GetContentByName(content_name);
807 if (!other_content->rejected) {
808 return RTCError(
809 RTCErrorType::INVALID_PARAMETER,
810 "The m= section:" + content_name + " should be rejected.");
811 }
812 }
813 }
814
815 return RTCError::OK();
816}
817
818RTCError JsepTransportController::ValidateContent(
819 const cricket::ContentInfo& content_info) {
820 if (config_.rtcp_mux_policy ==
821 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
822 content_info.type == cricket::MediaProtocolType::kRtp &&
823 !content_info.media_description()->rtcp_mux()) {
824 return RTCError(RTCErrorType::INVALID_PARAMETER,
825 "The m= section:" + content_info.name +
826 " is invalid. RTCP-MUX is not "
827 "enabled when it is required.");
828 }
829 return RTCError::OK();
830}
831
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700832void JsepTransportController::HandleRejectedContent(
Zhi Huangd2248f82018-04-10 14:41:03 -0700833 const cricket::ContentInfo& content_info,
834 const cricket::SessionDescription* description) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800835 // If the content is rejected, let the
836 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700837 // then destroy the cricket::JsepTransport.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700838 RemoveTransportForMid(content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700839 if (content_info.name == bundled_mid()) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100840 for (const auto& content_name : bundle_group_->content_names()) {
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700841 RemoveTransportForMid(content_name);
Zhi Huange830e682018-03-30 10:48:35 -0700842 }
843 bundle_group_.reset();
844 } else if (IsBundled(content_info.name)) {
845 // Remove the rejected content from the |bundle_group_|.
Zhi Huange818b6e2018-02-22 15:26:27 -0800846 bundle_group_->RemoveContentName(content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700847 // Reset the bundle group if nothing left.
848 if (!bundle_group_->FirstContentName()) {
849 bundle_group_.reset();
850 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800851 }
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700852 MaybeDestroyJsepTransport(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800853}
854
Zhi Huang365381f2018-04-13 16:44:34 -0700855bool JsepTransportController::HandleBundledContent(
Zhi Huange818b6e2018-02-22 15:26:27 -0800856 const cricket::ContentInfo& content_info) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700857 auto jsep_transport = GetJsepTransportByName(*bundled_mid());
858 RTC_DCHECK(jsep_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800859 // If the content is bundled, let the
860 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700861 // then destroy the cricket::JsepTransport.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700862 if (SetTransportForMid(content_info.name, jsep_transport)) {
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -0800863 // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
864 // because it means that we first create media transport and start
865 // connecting it, and then we destroy it. We will need to address it before
866 // video path is enabled.
Zhi Huang365381f2018-04-13 16:44:34 -0700867 MaybeDestroyJsepTransport(content_info.name);
868 return true;
869 }
870 return false;
Zhi Huange818b6e2018-02-22 15:26:27 -0800871}
872
Zhi Huang365381f2018-04-13 16:44:34 -0700873bool JsepTransportController::SetTransportForMid(
Zhi Huangd2248f82018-04-10 14:41:03 -0700874 const std::string& mid,
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700875 cricket::JsepTransport* jsep_transport) {
Zhi Huang365381f2018-04-13 16:44:34 -0700876 RTC_DCHECK(jsep_transport);
Zhi Huangd2248f82018-04-10 14:41:03 -0700877 if (mid_to_transport_[mid] == jsep_transport) {
Zhi Huang365381f2018-04-13 16:44:34 -0700878 return true;
Zhi Huangd2248f82018-04-10 14:41:03 -0700879 }
Eldar Rellod85ea752020-02-19 20:41:07 +0200880 RTC_DCHECK_RUN_ON(network_thread_);
881 pending_mids_.push_back(mid);
Zhi Huangd2248f82018-04-10 14:41:03 -0700882 mid_to_transport_[mid] = jsep_transport;
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700883 return config_.transport_observer->OnTransportChanged(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100884 mid, jsep_transport->rtp_transport(), jsep_transport->RtpDtlsTransport(),
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700885 jsep_transport->data_channel_transport());
Zhi Huangd2248f82018-04-10 14:41:03 -0700886}
887
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700888void JsepTransportController::RemoveTransportForMid(const std::string& mid) {
Bjorn A Mellem7a9a0922019-11-26 09:19:40 -0800889 bool ret = config_.transport_observer->OnTransportChanged(mid, nullptr,
890 nullptr, nullptr);
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700891 // Calling OnTransportChanged with nullptr should always succeed, since it is
892 // only expected to fail when adding media to a transport (not removing).
893 RTC_DCHECK(ret);
Zhi Huangd2248f82018-04-10 14:41:03 -0700894 mid_to_transport_.erase(mid);
895}
896
Zhi Huange818b6e2018-02-22 15:26:27 -0800897cricket::JsepTransportDescription
898JsepTransportController::CreateJsepTransportDescription(
Harald Alvestrand1716d392019-06-03 20:35:45 +0200899 const cricket::ContentInfo& content_info,
900 const cricket::TransportInfo& transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700901 const std::vector<int>& encrypted_extension_ids,
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700902 int rtp_abs_sendtime_extn_id,
903 absl::optional<std::string> media_alt_protocol,
904 absl::optional<std::string> data_alt_protocol) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800905 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200906 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800907 RTC_DCHECK(content_desc);
908 bool rtcp_mux_enabled = content_info.type == cricket::MediaProtocolType::kSctp
909 ? true
910 : content_desc->rtcp_mux();
911
912 return cricket::JsepTransportDescription(
913 rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700914 rtp_abs_sendtime_extn_id, transport_info.description, media_alt_protocol,
915 data_alt_protocol);
Zhi Huange818b6e2018-02-22 15:26:27 -0800916}
917
918bool JsepTransportController::ShouldUpdateBundleGroup(
919 SdpType type,
920 const cricket::SessionDescription* description) {
921 if (config_.bundle_policy ==
922 PeerConnectionInterface::kBundlePolicyMaxBundle) {
923 return true;
924 }
925
926 if (type != SdpType::kAnswer) {
927 return false;
928 }
929
930 RTC_DCHECK(local_desc_ && remote_desc_);
931 const cricket::ContentGroup* local_bundle =
932 local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
933 const cricket::ContentGroup* remote_bundle =
934 remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
935 return local_bundle && remote_bundle;
936}
937
938std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
939 const cricket::ContentInfo& content_info) {
940 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200941 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800942
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700943 if (!config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800944 return std::vector<int>();
945 }
946
947 std::vector<int> encrypted_header_extension_ids;
Mirko Bonadei739baf02019-01-27 17:29:42 +0100948 for (const auto& extension : content_desc->rtp_header_extensions()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800949 if (!extension.encrypt) {
950 continue;
951 }
Steve Anton64b626b2019-01-28 17:25:26 -0800952 if (!absl::c_linear_search(encrypted_header_extension_ids, extension.id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800953 encrypted_header_extension_ids.push_back(extension.id);
954 }
955 }
956 return encrypted_header_extension_ids;
957}
958
959std::vector<int>
960JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundle(
961 const cricket::SessionDescription* description) {
962 RTC_DCHECK(description);
963 RTC_DCHECK(bundle_group_);
964
965 std::vector<int> merged_ids;
966 // Union the encrypted header IDs in the group when bundle is enabled.
967 for (const cricket::ContentInfo& content_info : description->contents()) {
968 if (bundle_group_->HasContentName(content_info.name)) {
969 std::vector<int> extension_ids =
970 GetEncryptedHeaderExtensionIds(content_info);
971 for (int id : extension_ids) {
Steve Anton64b626b2019-01-28 17:25:26 -0800972 if (!absl::c_linear_search(merged_ids, id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800973 merged_ids.push_back(id);
974 }
975 }
976 }
977 }
978 return merged_ids;
979}
980
Bjorn A Mellem8e1343a2019-09-30 15:12:47 -0700981RTCError JsepTransportController::GetAltProtocolsForBundle(
982 const cricket::SessionDescription* description,
983 absl::optional<std::string>* media_alt_protocol,
984 absl::optional<std::string>* data_alt_protocol) {
985 RTC_DCHECK(description);
986 RTC_DCHECK(bundle_group_);
987 RTC_DCHECK(media_alt_protocol);
988 RTC_DCHECK(data_alt_protocol);
989
990 bool found_media = false;
991 bool found_data = false;
992 for (const cricket::ContentInfo& content : description->contents()) {
993 if (bundle_group_->HasContentName(content.name)) {
994 const cricket::MediaContentDescription* media_description =
995 content.media_description();
996 switch (media_description->type()) {
997 case cricket::MEDIA_TYPE_AUDIO:
998 case cricket::MEDIA_TYPE_VIDEO:
999 if (found_media &&
1000 *media_alt_protocol != media_description->alt_protocol()) {
1001 return RTCError(RTCErrorType::INVALID_PARAMETER,
1002 "The BUNDLE group contains conflicting "
1003 "alt-protocols for media ('" +
1004 media_alt_protocol->value_or("") + "' and '" +
1005 media_description->alt_protocol().value_or("") +
1006 "')");
1007 }
1008 found_media = true;
1009 *media_alt_protocol = media_description->alt_protocol();
1010 break;
1011 case cricket::MEDIA_TYPE_DATA:
1012 if (found_data &&
1013 *data_alt_protocol != media_description->alt_protocol()) {
1014 return RTCError(RTCErrorType::INVALID_PARAMETER,
1015 "The BUNDLE group contains conflicting "
1016 "alt-protocols for data ('" +
1017 data_alt_protocol->value_or("") + "' and '" +
1018 media_description->alt_protocol().value_or("") +
1019 "')");
1020 }
1021 found_data = true;
1022 *data_alt_protocol = media_description->alt_protocol();
1023 break;
1024 }
1025 }
1026 }
1027 return RTCError::OK();
1028}
1029
Zhi Huange830e682018-03-30 10:48:35 -07001030int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
Zhi Huange818b6e2018-02-22 15:26:27 -08001031 const cricket::ContentInfo& content_info) {
Zhi Huange830e682018-03-30 10:48:35 -07001032 if (!config_.enable_external_auth) {
1033 return -1;
Zhi Huange818b6e2018-02-22 15:26:27 -08001034 }
1035
1036 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +02001037 content_info.media_description();
Zhi Huange830e682018-03-30 10:48:35 -07001038
1039 const webrtc::RtpExtension* send_time_extension =
1040 webrtc::RtpExtension::FindHeaderExtensionByUri(
1041 content_desc->rtp_header_extensions(),
1042 webrtc::RtpExtension::kAbsSendTimeUri);
1043 return send_time_extension ? send_time_extension->id : -1;
1044}
1045
Zhi Huang365381f2018-04-13 16:44:34 -07001046const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -07001047 const std::string& mid) const {
Zhi Huangd2248f82018-04-10 14:41:03 -07001048 auto it = mid_to_transport_.find(mid);
1049 return it == mid_to_transport_.end() ? nullptr : it->second;
Zhi Huange830e682018-03-30 10:48:35 -07001050}
1051
Zhi Huang365381f2018-04-13 16:44:34 -07001052cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -07001053 const std::string& mid) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001054 auto it = mid_to_transport_.find(mid);
1055 return it == mid_to_transport_.end() ? nullptr : it->second;
Zhi Huange830e682018-03-30 10:48:35 -07001056}
1057
Zhi Huang365381f2018-04-13 16:44:34 -07001058const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -07001059 const std::string& transport_name) const {
1060 auto it = jsep_transports_by_name_.find(transport_name);
1061 return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
1062}
1063
Zhi Huang365381f2018-04-13 16:44:34 -07001064cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -07001065 const std::string& transport_name) {
1066 auto it = jsep_transports_by_name_.find(transport_name);
1067 return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
1068}
1069
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001070// TODO(sukhanov): Refactor to avoid code duplication for Media and Datagram
1071// transports setup.
1072std::unique_ptr<webrtc::DatagramTransportInterface>
1073JsepTransportController::MaybeCreateDatagramTransport(
1074 const cricket::ContentInfo& content_info,
1075 const cricket::SessionDescription& description,
1076 bool local) {
1077 if (config_.media_transport_factory == nullptr) {
1078 return nullptr;
1079 }
1080
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001081 if (!(config_.use_datagram_transport ||
1082 config_.use_datagram_transport_for_data_channels)) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001083 return nullptr;
1084 }
1085
1086 // Caller (offerer) datagram transport.
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001087 if (offer_datagram_transport_) {
1088 RTC_DCHECK(local);
1089 RTC_LOG(LS_INFO) << "Offered datagram transport has now been activated.";
1090 return std::move(offer_datagram_transport_);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001091 }
1092
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001093 const cricket::TransportDescription* transport_description =
1094 description.GetTransportDescriptionByName(content_info.mid());
1095 RTC_DCHECK(transport_description)
1096 << "Missing transport description for mid=" << content_info.mid();
1097
1098 if (!transport_description->opaque_parameters) {
1099 RTC_LOG(LS_INFO)
1100 << "No opaque transport parameters, not creating datagram transport";
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001101 return nullptr;
1102 }
1103
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001104 if (transport_description->opaque_parameters->protocol !=
1105 config_.media_transport_factory->GetTransportName()) {
1106 RTC_LOG(LS_INFO) << "Opaque transport parameters for protocol="
1107 << transport_description->opaque_parameters->protocol
1108 << ", which does not match supported protocol="
1109 << config_.media_transport_factory->GetTransportName();
1110 return nullptr;
1111 }
1112
1113 RTC_DCHECK(!local);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001114 // When bundle is enabled, two JsepTransports are created, and then
1115 // the second transport is destroyed (right away).
1116 // For datagram transport, we don't want to create the second
1117 // datagram transport in the first place.
1118 RTC_LOG(LS_INFO) << "Returning new, client datagram transport.";
1119
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001120 MediaTransportSettings settings;
1121 settings.is_caller = local;
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001122 settings.remote_transport_parameters =
1123 transport_description->opaque_parameters->parameters;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001124 settings.event_log = config_.event_log;
1125
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001126 auto datagram_transport_result =
1127 config_.media_transport_factory->CreateDatagramTransport(network_thread_,
1128 settings);
1129
Bjorn A Mellem0cda7b82020-01-28 17:06:55 -08001130 if (!datagram_transport_result.ok()) {
1131 // Datagram transport negotiation will fail and we'll fall back to RTP.
1132 return nullptr;
1133 }
1134
1135 if (!datagram_transport_result.value()
1136 ->SetRemoteTransportParameters(
1137 transport_description->opaque_parameters->parameters)
1138 .ok()) {
1139 // Datagram transport negotiation failed (parameters are incompatible).
1140 // Fall back to RTP.
1141 return nullptr;
1142 }
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001143
1144 return datagram_transport_result.MoveValue();
1145}
1146
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001147RTCError JsepTransportController::MaybeCreateJsepTransport(
1148 bool local,
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001149 const cricket::ContentInfo& content_info,
1150 const cricket::SessionDescription& description) {
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001151 RTC_DCHECK(network_thread_->IsCurrent());
1152 cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
1153 if (transport) {
1154 return RTCError::OK();
1155 }
1156
1157 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +02001158 content_info.media_description();
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001159 if (certificate_ && !content_desc->cryptos().empty()) {
1160 return RTCError(RTCErrorType::INVALID_PARAMETER,
1161 "SDES and DTLS-SRTP cannot be enabled at the same time.");
1162 }
1163
Qingsi Wang25ec8882019-11-15 12:33:05 -08001164 rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001165 CreateIceTransport(content_info.name, /*rtcp=*/false);
Qingsi Wang25ec8882019-11-15 12:33:05 -08001166 RTC_DCHECK(ice);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001167
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001168 std::unique_ptr<DatagramTransportInterface> datagram_transport =
1169 MaybeCreateDatagramTransport(content_info, description, local);
1170 if (datagram_transport) {
Qingsi Wang25ec8882019-11-15 12:33:05 -08001171 datagram_transport->Connect(ice->internal());
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001172 }
1173
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001174 std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
Qingsi Wang25ec8882019-11-15 12:33:05 -08001175 CreateDtlsTransport(content_info, ice->internal(), nullptr);
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001176
1177 std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
1178 std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
1179 std::unique_ptr<SrtpTransport> sdes_transport;
1180 std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
Bjorn A Mellem364b2672019-08-20 16:58:03 -07001181 std::unique_ptr<RtpTransportInternal> datagram_rtp_transport;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001182
Qingsi Wang25ec8882019-11-15 12:33:05 -08001183 rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001184 if (config_.rtcp_mux_policy !=
1185 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
1186 content_info.type == cricket::MediaProtocolType::kRtp) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001187 RTC_DCHECK(datagram_transport == nullptr);
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001188 rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
Qingsi Wang25ec8882019-11-15 12:33:05 -08001189 rtcp_dtls_transport =
1190 CreateDtlsTransport(content_info, rtcp_ice->internal(),
1191 /*datagram_transport=*/nullptr);
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001192 }
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001193
Bjorn A Mellem703ea952019-08-23 10:31:11 -07001194 // Only create a datagram RTP transport if the datagram transport should be
1195 // used for RTP.
1196 if (datagram_transport && config_.use_datagram_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001197 // TODO(sukhanov): We use unencrypted RTP transport over DatagramTransport,
1198 // because MediaTransport encrypts. In the future we may want to
1199 // implement our own version of RtpTransport over MediaTransport, because
1200 // it will give us more control over things like:
1201 // - Fusing
1202 // - Rtp header compression
1203 // - Handling Rtcp feedback.
1204 RTC_LOG(LS_INFO) << "Creating UnencryptedRtpTransport, because datagram "
1205 "transport is used.";
1206 RTC_DCHECK(!rtcp_dtls_transport);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001207 datagram_rtp_transport = std::make_unique<DatagramRtpTransport>(
Qingsi Wang25ec8882019-11-15 12:33:05 -08001208 content_info.media_description()->rtp_header_extensions(),
1209 ice->internal(), datagram_transport.get());
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001210 }
1211
1212 if (config_.disable_encryption) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001213 RTC_LOG(LS_INFO)
1214 << "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001215 unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
Zhi Huangd2248f82018-04-10 14:41:03 -07001216 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001217 } else if (!content_desc->cryptos().empty()) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001218 sdes_transport = CreateSdesTransport(
1219 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001220 RTC_LOG(LS_INFO) << "Creating SdesTransport.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001221 } else {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001222 RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
Zhi Huangd2248f82018-04-10 14:41:03 -07001223 dtls_srtp_transport = CreateDtlsSrtpTransport(
1224 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001225 }
1226
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001227 std::unique_ptr<cricket::SctpTransportInternal> sctp_transport;
1228 if (config_.sctp_factory) {
1229 sctp_transport =
1230 config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
1231 }
1232
1233 DataChannelTransportInterface* data_channel_transport = nullptr;
1234 if (config_.use_datagram_transport_for_data_channels) {
1235 data_channel_transport = datagram_transport.get();
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001236 }
1237
Zhi Huang365381f2018-04-13 16:44:34 -07001238 std::unique_ptr<cricket::JsepTransport> jsep_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001239 std::make_unique<cricket::JsepTransport>(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001240 content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
1241 std::move(unencrypted_rtp_transport), std::move(sdes_transport),
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001242 std::move(dtls_srtp_transport), std::move(datagram_rtp_transport),
1243 std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport),
Bjorn A Mellem7a9a0922019-11-26 09:19:40 -08001244 std::move(sctp_transport), std::move(datagram_transport),
1245 data_channel_transport);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001246
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +02001247 jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect(
1248 this, &JsepTransportController::OnRtcpPacketReceived_n);
1249
Zhi Huange818b6e2018-02-22 15:26:27 -08001250 jsep_transport->SignalRtcpMuxActive.connect(
1251 this, &JsepTransportController::UpdateAggregateStates_n);
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001252 jsep_transport->SignalDataChannelTransportNegotiated.connect(
1253 this, &JsepTransportController::OnDataChannelTransportNegotiated_n);
Taylor Brandstettercbaa2542018-04-16 16:42:14 -07001254 SetTransportForMid(content_info.name, jsep_transport.get());
Zhi Huange830e682018-03-30 10:48:35 -07001255
Zhi Huangd2248f82018-04-10 14:41:03 -07001256 jsep_transports_by_name_[content_info.name] = std::move(jsep_transport);
1257 UpdateAggregateStates_n();
Zhi Huange830e682018-03-30 10:48:35 -07001258 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -08001259}
1260
1261void JsepTransportController::MaybeDestroyJsepTransport(
1262 const std::string& mid) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001263 auto jsep_transport = GetJsepTransportByName(mid);
1264 if (!jsep_transport) {
1265 return;
1266 }
1267
1268 // Don't destroy the JsepTransport if there are still media sections referring
1269 // to it.
1270 for (const auto& kv : mid_to_transport_) {
1271 if (kv.second == jsep_transport) {
1272 return;
1273 }
1274 }
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001275
Zhi Huange830e682018-03-30 10:48:35 -07001276 jsep_transports_by_name_.erase(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -08001277 UpdateAggregateStates_n();
1278}
1279
1280void JsepTransportController::DestroyAllJsepTransports_n() {
1281 RTC_DCHECK(network_thread_->IsCurrent());
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001282
1283 for (const auto& jsep_transport : jsep_transports_by_name_) {
Bjorn A Mellem7a9a0922019-11-26 09:19:40 -08001284 config_.transport_observer->OnTransportChanged(jsep_transport.first,
1285 nullptr, nullptr, nullptr);
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001286 }
1287
Zhi Huange830e682018-03-30 10:48:35 -07001288 jsep_transports_by_name_.clear();
Zhi Huange818b6e2018-02-22 15:26:27 -08001289}
1290
1291void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
1292 RTC_DCHECK(network_thread_->IsCurrent());
1293
1294 ice_role_ = ice_role;
1295 for (auto& dtls : GetDtlsTransports()) {
1296 dtls->ice_transport()->SetIceRole(ice_role_);
1297 }
1298}
1299
1300cricket::IceRole JsepTransportController::DetermineIceRole(
Zhi Huang365381f2018-04-13 16:44:34 -07001301 cricket::JsepTransport* jsep_transport,
Zhi Huange818b6e2018-02-22 15:26:27 -08001302 const cricket::TransportInfo& transport_info,
1303 SdpType type,
1304 bool local) {
1305 cricket::IceRole ice_role = ice_role_;
1306 auto tdesc = transport_info.description;
1307 if (local) {
1308 // The initial offer side may use ICE Lite, in which case, per RFC5245
1309 // Section 5.1.1, the answer side should take the controlling role if it is
1310 // in the full ICE mode.
1311 //
1312 // When both sides use ICE Lite, the initial offer side must take the
1313 // controlling role, and this is the default logic implemented in
1314 // SetLocalDescription in JsepTransportController.
1315 if (jsep_transport->remote_description() &&
1316 jsep_transport->remote_description()->transport_desc.ice_mode ==
1317 cricket::ICEMODE_LITE &&
1318 ice_role_ == cricket::ICEROLE_CONTROLLED &&
1319 tdesc.ice_mode == cricket::ICEMODE_FULL) {
1320 ice_role = cricket::ICEROLE_CONTROLLING;
1321 }
1322
1323 // Older versions of Chrome expect the ICE role to be re-determined when an
1324 // ICE restart occurs, and also don't perform conflict resolution correctly,
1325 // so for now we can't safely stop doing this, unless the application opts
1326 // in by setting |config_.redetermine_role_on_ice_restart_| to false. See:
1327 // https://bugs.chromium.org/p/chromium/issues/detail?id=628676
1328 // TODO(deadbeef): Remove this when these old versions of Chrome reach a low
1329 // enough population.
1330 if (config_.redetermine_role_on_ice_restart &&
1331 jsep_transport->local_description() &&
1332 cricket::IceCredentialsChanged(
1333 jsep_transport->local_description()->transport_desc.ice_ufrag,
1334 jsep_transport->local_description()->transport_desc.ice_pwd,
1335 tdesc.ice_ufrag, tdesc.ice_pwd) &&
1336 // Don't change the ICE role if the remote endpoint is ICE lite; we
1337 // should always be controlling in that case.
1338 (!jsep_transport->remote_description() ||
1339 jsep_transport->remote_description()->transport_desc.ice_mode !=
1340 cricket::ICEMODE_LITE)) {
1341 ice_role = (type == SdpType::kOffer) ? cricket::ICEROLE_CONTROLLING
1342 : cricket::ICEROLE_CONTROLLED;
1343 }
1344 } else {
1345 // If our role is cricket::ICEROLE_CONTROLLED and the remote endpoint
1346 // supports only ice_lite, this local endpoint should take the CONTROLLING
1347 // role.
1348 // TODO(deadbeef): This is a session-level attribute, so it really shouldn't
1349 // be in a TransportDescription in the first place...
1350 if (ice_role_ == cricket::ICEROLE_CONTROLLED &&
1351 tdesc.ice_mode == cricket::ICEMODE_LITE) {
1352 ice_role = cricket::ICEROLE_CONTROLLING;
1353 }
1354
1355 // If we use ICE Lite and the remote endpoint uses the full implementation
1356 // of ICE, the local endpoint must take the controlled role, and the other
1357 // side must be the controlling role.
1358 if (jsep_transport->local_description() &&
1359 jsep_transport->local_description()->transport_desc.ice_mode ==
1360 cricket::ICEMODE_LITE &&
1361 ice_role_ == cricket::ICEROLE_CONTROLLING &&
Zhi Huange830e682018-03-30 10:48:35 -07001362 tdesc.ice_mode == cricket::ICEMODE_FULL) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001363 ice_role = cricket::ICEROLE_CONTROLLED;
1364 }
1365 }
1366
1367 return ice_role;
1368}
1369
1370void JsepTransportController::OnTransportWritableState_n(
1371 rtc::PacketTransportInternal* transport) {
1372 RTC_DCHECK(network_thread_->IsCurrent());
1373 RTC_LOG(LS_INFO) << " Transport " << transport->transport_name()
1374 << " writability changed to " << transport->writable()
1375 << ".";
1376 UpdateAggregateStates_n();
1377}
1378
1379void JsepTransportController::OnTransportReceivingState_n(
1380 rtc::PacketTransportInternal* transport) {
1381 RTC_DCHECK(network_thread_->IsCurrent());
1382 UpdateAggregateStates_n();
1383}
1384
1385void JsepTransportController::OnTransportGatheringState_n(
1386 cricket::IceTransportInternal* transport) {
1387 RTC_DCHECK(network_thread_->IsCurrent());
1388 UpdateAggregateStates_n();
1389}
1390
1391void JsepTransportController::OnTransportCandidateGathered_n(
1392 cricket::IceTransportInternal* transport,
1393 const cricket::Candidate& candidate) {
1394 RTC_DCHECK(network_thread_->IsCurrent());
1395
1396 // We should never signal peer-reflexive candidates.
1397 if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
1398 RTC_NOTREACHED();
1399 return;
1400 }
Steve Antond25828a2018-08-31 13:06:05 -07001401 std::string transport_name = transport->transport_name();
1402 invoker_.AsyncInvoke<void>(
1403 RTC_FROM_HERE, signaling_thread_, [this, transport_name, candidate] {
1404 SignalIceCandidatesGathered(transport_name, {candidate});
1405 });
Zhi Huange818b6e2018-02-22 15:26:27 -08001406}
1407
Eldar Relloda13ea22019-06-01 12:23:43 +03001408void JsepTransportController::OnTransportCandidateError_n(
1409 cricket::IceTransportInternal* transport,
1410 const cricket::IceCandidateErrorEvent& event) {
1411 RTC_DCHECK(network_thread_->IsCurrent());
1412
1413 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1414 [this, event] { SignalIceCandidateError(event); });
1415}
Zhi Huange818b6e2018-02-22 15:26:27 -08001416void JsepTransportController::OnTransportCandidatesRemoved_n(
1417 cricket::IceTransportInternal* transport,
1418 const cricket::Candidates& candidates) {
1419 invoker_.AsyncInvoke<void>(
1420 RTC_FROM_HERE, signaling_thread_,
Steve Antond25828a2018-08-31 13:06:05 -07001421 [this, candidates] { SignalIceCandidatesRemoved(candidates); });
Zhi Huange818b6e2018-02-22 15:26:27 -08001422}
Alex Drake00c7ecf2019-08-06 10:54:47 -07001423void JsepTransportController::OnTransportCandidatePairChanged_n(
1424 const cricket::CandidatePairChangeEvent& event) {
1425 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, [this, event] {
1426 SignalIceCandidatePairChanged(event);
1427 });
1428}
Zhi Huange818b6e2018-02-22 15:26:27 -08001429
1430void JsepTransportController::OnTransportRoleConflict_n(
1431 cricket::IceTransportInternal* transport) {
1432 RTC_DCHECK(network_thread_->IsCurrent());
1433 // Note: since the role conflict is handled entirely on the network thread,
1434 // we don't need to worry about role conflicts occurring on two ports at
1435 // once. The first one encountered should immediately reverse the role.
1436 cricket::IceRole reversed_role = (ice_role_ == cricket::ICEROLE_CONTROLLING)
1437 ? cricket::ICEROLE_CONTROLLED
1438 : cricket::ICEROLE_CONTROLLING;
1439 RTC_LOG(LS_INFO) << "Got role conflict; switching to "
1440 << (reversed_role == cricket::ICEROLE_CONTROLLING
1441 ? "controlling"
1442 : "controlled")
1443 << " role.";
1444 SetIceRole_n(reversed_role);
1445}
1446
1447void JsepTransportController::OnTransportStateChanged_n(
1448 cricket::IceTransportInternal* transport) {
1449 RTC_DCHECK(network_thread_->IsCurrent());
1450 RTC_LOG(LS_INFO) << transport->transport_name() << " Transport "
1451 << transport->component()
1452 << " state changed. Check if state is complete.";
1453 UpdateAggregateStates_n();
1454}
1455
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001456void JsepTransportController::OnDataChannelTransportNegotiated_n(
1457 cricket::JsepTransport* transport,
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001458 DataChannelTransportInterface* data_channel_transport) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001459 for (auto it : mid_to_transport_) {
1460 if (it.second == transport) {
1461 config_.transport_observer->OnTransportChanged(
1462 it.first, transport->rtp_transport(), transport->RtpDtlsTransport(),
Bjorn A Mellem7a9a0922019-11-26 09:19:40 -08001463 data_channel_transport);
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001464 }
1465 }
1466}
1467
Zhi Huange818b6e2018-02-22 15:26:27 -08001468void JsepTransportController::UpdateAggregateStates_n() {
1469 RTC_DCHECK(network_thread_->IsCurrent());
1470
1471 auto dtls_transports = GetDtlsTransports();
Alex Loiko9289eda2018-11-23 16:18:59 +00001472 cricket::IceConnectionState new_connection_state =
1473 cricket::kIceConnectionConnecting;
Jonas Olsson635474e2018-10-18 15:58:17 +02001474 PeerConnectionInterface::IceConnectionState new_ice_connection_state =
1475 PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
1476 PeerConnectionInterface::PeerConnectionState new_combined_state =
1477 PeerConnectionInterface::PeerConnectionState::kNew;
Zhi Huange818b6e2018-02-22 15:26:27 -08001478 cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
Alex Loiko9289eda2018-11-23 16:18:59 +00001479 bool any_failed = false;
Alex Loiko9289eda2018-11-23 16:18:59 +00001480 bool all_connected = !dtls_transports.empty();
1481 bool all_completed = !dtls_transports.empty();
Zhi Huange818b6e2018-02-22 15:26:27 -08001482 bool any_gathering = false;
1483 bool all_done_gathering = !dtls_transports.empty();
Jonas Olsson635474e2018-10-18 15:58:17 +02001484
1485 std::map<IceTransportState, int> ice_state_counts;
1486 std::map<cricket::DtlsTransportState, int> dtls_state_counts;
1487
Zhi Huange818b6e2018-02-22 15:26:27 -08001488 for (const auto& dtls : dtls_transports) {
Alex Loiko9289eda2018-11-23 16:18:59 +00001489 any_failed = any_failed || dtls->ice_transport()->GetState() ==
1490 cricket::IceTransportState::STATE_FAILED;
1491 all_connected = all_connected && dtls->writable();
1492 all_completed =
1493 all_completed && dtls->writable() &&
1494 dtls->ice_transport()->GetState() ==
1495 cricket::IceTransportState::STATE_COMPLETED &&
1496 dtls->ice_transport()->GetIceRole() == cricket::ICEROLE_CONTROLLING &&
1497 dtls->ice_transport()->gathering_state() ==
1498 cricket::kIceGatheringComplete;
Zhi Huange818b6e2018-02-22 15:26:27 -08001499 any_gathering = any_gathering || dtls->ice_transport()->gathering_state() !=
1500 cricket::kIceGatheringNew;
1501 all_done_gathering =
1502 all_done_gathering && dtls->ice_transport()->gathering_state() ==
1503 cricket::kIceGatheringComplete;
Jonas Olsson635474e2018-10-18 15:58:17 +02001504
1505 dtls_state_counts[dtls->dtls_state()]++;
1506 ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
Zhi Huange818b6e2018-02-22 15:26:27 -08001507 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -07001508
Alex Loiko9289eda2018-11-23 16:18:59 +00001509 if (any_failed) {
1510 new_connection_state = cricket::kIceConnectionFailed;
1511 } else if (all_completed) {
1512 new_connection_state = cricket::kIceConnectionCompleted;
1513 } else if (all_connected) {
1514 new_connection_state = cricket::kIceConnectionConnected;
1515 }
1516 if (ice_connection_state_ != new_connection_state) {
1517 ice_connection_state_ = new_connection_state;
1518 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1519 [this, new_connection_state] {
1520 SignalIceConnectionState(new_connection_state);
1521 });
1522 }
1523
Jonas Olsson635474e2018-10-18 15:58:17 +02001524 // Compute the current RTCIceConnectionState as described in
1525 // https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
1526 // The PeerConnection is responsible for handling the "closed" state.
1527 int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
1528 int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
1529 int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
1530 int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
1531 int total_ice_disconnected =
1532 ice_state_counts[IceTransportState::kDisconnected];
1533 int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
1534 int total_ice_new = ice_state_counts[IceTransportState::kNew];
1535 int total_ice = dtls_transports.size();
1536
1537 if (total_ice_failed > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001538 // Any RTCIceTransports are in the "failed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001539 new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
Alex Loiko9289eda2018-11-23 16:18:59 +00001540 } else if (total_ice_disconnected > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001541 // None of the previous states apply and any RTCIceTransports are in the
1542 // "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001543 new_ice_connection_state =
1544 PeerConnectionInterface::kIceConnectionDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001545 } else if (total_ice_new + total_ice_closed == total_ice) {
1546 // None of the previous states apply and all RTCIceTransports are in the
1547 // "new" or "closed" state, or there are no transports.
1548 new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
1549 } else if (total_ice_new + total_ice_checking > 0) {
1550 // None of the previous states apply and any RTCIceTransports are in the
1551 // "new" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001552 new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001553 } else if (total_ice_completed + total_ice_closed == total_ice ||
1554 all_completed) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001555 // None of the previous states apply and all RTCIceTransports are in the
1556 // "completed" or "closed" state.
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001557 //
1558 // TODO(https://bugs.webrtc.org/10356): The all_completed condition is added
1559 // to mimic the behavior of the old ICE connection state, and should be
1560 // removed once we get end-of-candidates signaling in place.
Jonas Olsson635474e2018-10-18 15:58:17 +02001561 new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
1562 } else if (total_ice_connected + total_ice_completed + total_ice_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001563 total_ice) {
1564 // None of the previous states apply and all RTCIceTransports are in the
1565 // "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001566 new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001567 } else {
1568 RTC_NOTREACHED();
1569 }
1570
Alex Loiko9289eda2018-11-23 16:18:59 +00001571 if (standardized_ice_connection_state_ != new_ice_connection_state) {
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001572 if (standardized_ice_connection_state_ ==
1573 PeerConnectionInterface::kIceConnectionChecking &&
1574 new_ice_connection_state ==
1575 PeerConnectionInterface::kIceConnectionCompleted) {
1576 // Ensure that we never skip over the "connected" state.
1577 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, [this] {
1578 SignalStandardizedIceConnectionState(
1579 PeerConnectionInterface::kIceConnectionConnected);
1580 });
1581 }
Alex Loiko9289eda2018-11-23 16:18:59 +00001582 standardized_ice_connection_state_ = new_ice_connection_state;
Jonas Olsson635474e2018-10-18 15:58:17 +02001583 invoker_.AsyncInvoke<void>(
1584 RTC_FROM_HERE, signaling_thread_, [this, new_ice_connection_state] {
Alex Loiko9289eda2018-11-23 16:18:59 +00001585 SignalStandardizedIceConnectionState(new_ice_connection_state);
Jonas Olsson635474e2018-10-18 15:58:17 +02001586 });
1587 }
1588
1589 // Compute the current RTCPeerConnectionState as described in
1590 // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
1591 // The PeerConnection is responsible for handling the "closed" state.
1592 // Note that "connecting" is only a valid state for DTLS transports while
1593 // "checking", "completed" and "disconnected" are only valid for ICE
1594 // transports.
1595 int total_connected = total_ice_connected +
1596 dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTED];
1597 int total_dtls_connecting =
1598 dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTING];
1599 int total_failed =
1600 total_ice_failed + dtls_state_counts[cricket::DTLS_TRANSPORT_FAILED];
1601 int total_closed =
1602 total_ice_closed + dtls_state_counts[cricket::DTLS_TRANSPORT_CLOSED];
1603 int total_new =
1604 total_ice_new + dtls_state_counts[cricket::DTLS_TRANSPORT_NEW];
1605 int total_transports = total_ice * 2;
1606
1607 if (total_failed > 0) {
1608 // Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
1609 new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001610 } else if (total_ice_disconnected > 0) {
1611 // None of the previous states apply and any RTCIceTransports or
1612 // RTCDtlsTransports are in the "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001613 new_combined_state =
1614 PeerConnectionInterface::PeerConnectionState::kDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001615 } else if (total_new + total_closed == total_transports) {
1616 // None of the previous states apply and all RTCIceTransports and
1617 // RTCDtlsTransports are in the "new" or "closed" state, or there are no
1618 // transports.
1619 new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
1620 } else if (total_new + total_dtls_connecting + total_ice_checking > 0) {
1621 // None of the previous states apply and all RTCIceTransports or
1622 // RTCDtlsTransports are in the "new", "connecting" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001623 new_combined_state =
1624 PeerConnectionInterface::PeerConnectionState::kConnecting;
1625 } else if (total_connected + total_ice_completed + total_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001626 total_transports) {
1627 // None of the previous states apply and all RTCIceTransports and
1628 // RTCDtlsTransports are in the "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001629 new_combined_state =
1630 PeerConnectionInterface::PeerConnectionState::kConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001631 } else {
1632 RTC_NOTREACHED();
1633 }
1634
1635 if (combined_connection_state_ != new_combined_state) {
1636 combined_connection_state_ = new_combined_state;
1637 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1638 [this, new_combined_state] {
1639 SignalConnectionState(new_combined_state);
1640 });
1641 }
1642
Zhi Huange818b6e2018-02-22 15:26:27 -08001643 if (all_done_gathering) {
1644 new_gathering_state = cricket::kIceGatheringComplete;
1645 } else if (any_gathering) {
1646 new_gathering_state = cricket::kIceGatheringGathering;
1647 }
1648 if (ice_gathering_state_ != new_gathering_state) {
1649 ice_gathering_state_ = new_gathering_state;
Steve Antond25828a2018-08-31 13:06:05 -07001650 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1651 [this, new_gathering_state] {
1652 SignalIceGatheringState(new_gathering_state);
1653 });
Zhi Huange818b6e2018-02-22 15:26:27 -08001654 }
1655}
1656
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +02001657void JsepTransportController::OnRtcpPacketReceived_n(
1658 rtc::CopyOnWriteBuffer* packet,
1659 int64_t packet_time_us) {
1660 RTC_DCHECK(config_.rtcp_handler);
1661 config_.rtcp_handler(*packet, packet_time_us);
1662}
1663
Zhi Huange818b6e2018-02-22 15:26:27 -08001664void JsepTransportController::OnDtlsHandshakeError(
1665 rtc::SSLHandshakeError error) {
1666 SignalDtlsHandshakeError(error);
1667}
1668
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001669absl::optional<cricket::OpaqueTransportParameters>
1670JsepTransportController::GetTransportParameters(const std::string& mid) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001671 if (!(config_.use_datagram_transport ||
1672 config_.use_datagram_transport_for_data_channels)) {
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001673 return absl::nullopt;
1674 }
1675
1676 cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
1677 if (transport) {
1678 absl::optional<cricket::OpaqueTransportParameters> params =
1679 transport->GetTransportParameters();
1680 if (params) {
1681 params->protocol = config_.media_transport_factory->GetTransportName();
1682 }
1683 return params;
1684 }
1685
1686 RTC_DCHECK(!local_desc_ && !remote_desc_)
1687 << "JsepTransport should exist for every mid once any description is set";
1688
Bjorn A Mellem7da4e562019-09-26 11:02:11 -07001689 if (config_.use_datagram_transport_for_data_channels_receive_only) {
1690 return absl::nullopt;
1691 }
1692
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001693 // Need to generate a transport for the offer.
1694 if (!offer_datagram_transport_) {
1695 webrtc::MediaTransportSettings settings;
1696 settings.is_caller = true;
1697 settings.pre_shared_key = rtc::CreateRandomString(32);
1698 settings.event_log = config_.event_log;
1699 auto datagram_transport_or_error =
1700 config_.media_transport_factory->CreateDatagramTransport(
1701 network_thread_, settings);
1702
1703 if (datagram_transport_or_error.ok()) {
1704 offer_datagram_transport_ =
1705 std::move(datagram_transport_or_error.value());
1706 } else {
1707 RTC_LOG(LS_INFO) << "Unable to create datagram transport, error="
1708 << datagram_transport_or_error.error().message();
1709 }
1710 }
1711
1712 // We have prepared a transport for the offer, and can now use its parameters.
1713 cricket::OpaqueTransportParameters params;
1714 params.parameters = offer_datagram_transport_->GetTransportParameters();
1715 params.protocol = config_.media_transport_factory->GetTransportName();
1716 return params;
1717}
1718
Zhi Huange818b6e2018-02-22 15:26:27 -08001719} // namespace webrtc