blob: 6db58dea6bcd0a65c23336cb4d8aa54c947dc697 [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"
Zach Steinc64078f2018-11-27 15:53:01 -080017#include "absl/memory/memory.h"
Anton Sukhanov316f3ac2019-05-23 15:50:38 -070018#include "api/datagram_transport_interface.h"
19#include "api/media_transport_interface.h"
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -080020#include "p2p/base/ice_transport_internal.h"
21#include "p2p/base/no_op_dtls_transport.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080022#include "p2p/base/port.h"
Anton Sukhanovee303fa2019-07-10 11:07:40 -070023#include "pc/datagram_dtls_adaptor.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "pc/srtp_filter.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080025#include "rtc_base/bind.h"
26#include "rtc_base/checks.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080027#include "rtc_base/thread.h"
28
29using webrtc::SdpType;
30
31namespace {
32
Zhi Huange818b6e2018-02-22 15:26:27 -080033webrtc::RTCError VerifyCandidate(const cricket::Candidate& cand) {
34 // No address zero.
35 if (cand.address().IsNil() || cand.address().IsAnyIP()) {
36 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
37 "candidate has address of zero");
38 }
39
40 // Disallow all ports below 1024, except for 80 and 443 on public addresses.
41 int port = cand.address().port();
42 if (cand.protocol() == cricket::TCP_PROTOCOL_NAME &&
43 (cand.tcptype() == cricket::TCPTYPE_ACTIVE_STR || port == 0)) {
44 // Expected for active-only candidates per
45 // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
46 // Libjingle clients emit port 0, in "active" mode.
47 return webrtc::RTCError::OK();
48 }
49 if (port < 1024) {
50 if ((port != 80) && (port != 443)) {
51 return webrtc::RTCError(
52 webrtc::RTCErrorType::INVALID_PARAMETER,
53 "candidate has port below 1024, but not 80 or 443");
54 }
55
56 if (cand.address().IsPrivateIP()) {
57 return webrtc::RTCError(
58 webrtc::RTCErrorType::INVALID_PARAMETER,
59 "candidate has port of 80 or 443 with private IP address");
60 }
61 }
62
63 return webrtc::RTCError::OK();
64}
65
66webrtc::RTCError VerifyCandidates(const cricket::Candidates& candidates) {
67 for (const cricket::Candidate& candidate : candidates) {
68 webrtc::RTCError error = VerifyCandidate(candidate);
69 if (!error.ok()) {
70 return error;
71 }
72 }
73 return webrtc::RTCError::OK();
74}
75
76} // namespace
77
78namespace webrtc {
79
80JsepTransportController::JsepTransportController(
81 rtc::Thread* signaling_thread,
82 rtc::Thread* network_thread,
83 cricket::PortAllocator* port_allocator,
Zach Steine20867f2018-08-02 13:20:15 -070084 AsyncResolverFactory* async_resolver_factory,
Zhi Huange818b6e2018-02-22 15:26:27 -080085 Config config)
86 : signaling_thread_(signaling_thread),
87 network_thread_(network_thread),
88 port_allocator_(port_allocator),
Zach Steine20867f2018-08-02 13:20:15 -070089 async_resolver_factory_(async_resolver_factory),
Zhi Huang365381f2018-04-13 16:44:34 -070090 config_(config) {
91 // The |transport_observer| is assumed to be non-null.
92 RTC_DCHECK(config_.transport_observer);
93}
Zhi Huange818b6e2018-02-22 15:26:27 -080094
95JsepTransportController::~JsepTransportController() {
96 // Channel destructors may try to send packets, so this needs to happen on
97 // the network thread.
98 network_thread_->Invoke<void>(
99 RTC_FROM_HERE,
100 rtc::Bind(&JsepTransportController::DestroyAllJsepTransports_n, this));
101}
102
103RTCError JsepTransportController::SetLocalDescription(
104 SdpType type,
105 const cricket::SessionDescription* description) {
106 if (!network_thread_->IsCurrent()) {
107 return network_thread_->Invoke<RTCError>(
108 RTC_FROM_HERE, [=] { return SetLocalDescription(type, description); });
109 }
110
111 if (!initial_offerer_.has_value()) {
112 initial_offerer_.emplace(type == SdpType::kOffer);
113 if (*initial_offerer_) {
114 SetIceRole_n(cricket::ICEROLE_CONTROLLING);
115 } else {
116 SetIceRole_n(cricket::ICEROLE_CONTROLLED);
117 }
118 }
119 return ApplyDescription_n(/*local=*/true, type, description);
120}
121
122RTCError JsepTransportController::SetRemoteDescription(
123 SdpType type,
124 const cricket::SessionDescription* description) {
125 if (!network_thread_->IsCurrent()) {
126 return network_thread_->Invoke<RTCError>(
127 RTC_FROM_HERE, [=] { return SetRemoteDescription(type, description); });
128 }
129
130 return ApplyDescription_n(/*local=*/false, type, description);
131}
132
133RtpTransportInternal* JsepTransportController::GetRtpTransport(
134 const std::string& mid) const {
Zhi Huange830e682018-03-30 10:48:35 -0700135 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800136 if (!jsep_transport) {
137 return nullptr;
138 }
139 return jsep_transport->rtp_transport();
140}
141
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700142MediaTransportConfig JsepTransportController::GetMediaTransportConfig(
Anton Sukhanov7940da02018-10-10 10:34:49 -0700143 const std::string& mid) const {
144 auto jsep_transport = GetJsepTransportForMid(mid);
145 if (!jsep_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700146 return MediaTransportConfig();
147 }
148
149 MediaTransportInterface* media_transport = nullptr;
150 if (config_.use_media_transport_for_media) {
151 media_transport = jsep_transport->media_transport();
152 }
153
154 DatagramTransportInterface* datagram_transport =
155 jsep_transport->datagram_transport();
156
157 // Media transport and datagram transports can not be used together.
158 RTC_DCHECK(!media_transport || !datagram_transport);
159
160 if (media_transport) {
161 return MediaTransportConfig(media_transport);
162 } else if (datagram_transport) {
163 return MediaTransportConfig(
164 /*rtp_max_packet_size=*/datagram_transport->GetLargestDatagramSize());
165 } else {
166 return MediaTransportConfig();
167 }
168}
169
170MediaTransportInterface*
171JsepTransportController::GetMediaTransportForDataChannel(
172 const std::string& mid) const {
173 auto jsep_transport = GetJsepTransportForMid(mid);
174 if (!jsep_transport || !config_.use_media_transport_for_data_channels) {
Anton Sukhanov7940da02018-10-10 10:34:49 -0700175 return nullptr;
176 }
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700177
Anton Sukhanov7940da02018-10-10 10:34:49 -0700178 return jsep_transport->media_transport();
179}
180
Bjorn Mellem175aa2e2018-11-08 11:23:22 -0800181MediaTransportState JsepTransportController::GetMediaTransportState(
182 const std::string& mid) const {
183 auto jsep_transport = GetJsepTransportForMid(mid);
184 if (!jsep_transport) {
185 return MediaTransportState::kPending;
186 }
187 return jsep_transport->media_transport_state();
188}
189
Zhi Huange818b6e2018-02-22 15:26:27 -0800190cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
Harald Alvestrandad88c882018-11-28 16:47:46 +0100191 const std::string& mid) {
Zhi Huange830e682018-03-30 10:48:35 -0700192 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800193 if (!jsep_transport) {
194 return nullptr;
195 }
196 return jsep_transport->rtp_dtls_transport();
197}
198
Harald Alvestrandad88c882018-11-28 16:47:46 +0100199const cricket::DtlsTransportInternal*
200JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
Zhi Huange830e682018-03-30 10:48:35 -0700201 auto jsep_transport = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800202 if (!jsep_transport) {
203 return nullptr;
204 }
205 return jsep_transport->rtcp_dtls_transport();
206}
207
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100208rtc::scoped_refptr<webrtc::DtlsTransport>
Harald Alvestrandad88c882018-11-28 16:47:46 +0100209JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
210 auto jsep_transport = GetJsepTransportForMid(mid);
211 if (!jsep_transport) {
212 return nullptr;
213 }
214 return jsep_transport->RtpDtlsTransport();
215}
216
Zhi Huange818b6e2018-02-22 15:26:27 -0800217void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
218 if (!network_thread_->IsCurrent()) {
219 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] { SetIceConfig(config); });
220 return;
221 }
222
223 ice_config_ = config;
224 for (auto& dtls : GetDtlsTransports()) {
225 dtls->ice_transport()->SetIceConfig(ice_config_);
226 }
227}
228
229void JsepTransportController::SetNeedsIceRestartFlag() {
Zhi Huange830e682018-03-30 10:48:35 -0700230 for (auto& kv : jsep_transports_by_name_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800231 kv.second->SetNeedsIceRestartFlag();
232 }
233}
234
235bool JsepTransportController::NeedsIceRestart(
236 const std::string& transport_name) const {
Zhi Huang365381f2018-04-13 16:44:34 -0700237 const cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700238 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800239 if (!transport) {
240 return false;
241 }
242 return transport->needs_ice_restart();
243}
244
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200245absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
Zhi Huange830e682018-03-30 10:48:35 -0700246 const std::string& mid) const {
Zhi Huange818b6e2018-02-22 15:26:27 -0800247 if (!network_thread_->IsCurrent()) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200248 return network_thread_->Invoke<absl::optional<rtc::SSLRole>>(
Zhi Huange830e682018-03-30 10:48:35 -0700249 RTC_FROM_HERE, [&] { return GetDtlsRole(mid); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800250 }
251
Zhi Huang365381f2018-04-13 16:44:34 -0700252 const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800253 if (!t) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200254 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 15:26:27 -0800255 }
256 return t->GetDtlsRole();
257}
258
259bool JsepTransportController::SetLocalCertificate(
260 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
261 if (!network_thread_->IsCurrent()) {
262 return network_thread_->Invoke<bool>(
263 RTC_FROM_HERE, [&] { return SetLocalCertificate(certificate); });
264 }
265
266 // Can't change a certificate, or set a null certificate.
267 if (certificate_ || !certificate) {
268 return false;
269 }
270 certificate_ = certificate;
271
272 // Set certificate for JsepTransport, which verifies it matches the
273 // fingerprint in SDP, and DTLS transport.
274 // Fallback from DTLS to SDES is not supported.
Zhi Huange830e682018-03-30 10:48:35 -0700275 for (auto& kv : jsep_transports_by_name_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800276 kv.second->SetLocalCertificate(certificate_);
277 }
278 for (auto& dtls : GetDtlsTransports()) {
279 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
280 RTC_DCHECK(set_cert_success);
281 }
282 return true;
283}
284
285rtc::scoped_refptr<rtc::RTCCertificate>
286JsepTransportController::GetLocalCertificate(
287 const std::string& transport_name) const {
288 if (!network_thread_->IsCurrent()) {
289 return network_thread_->Invoke<rtc::scoped_refptr<rtc::RTCCertificate>>(
290 RTC_FROM_HERE, [&] { return GetLocalCertificate(transport_name); });
291 }
292
Zhi Huang365381f2018-04-13 16:44:34 -0700293 const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800294 if (!t) {
295 return nullptr;
296 }
297 return t->GetLocalCertificate();
298}
299
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800300std::unique_ptr<rtc::SSLCertChain>
301JsepTransportController::GetRemoteSSLCertChain(
Zhi Huange818b6e2018-02-22 15:26:27 -0800302 const std::string& transport_name) const {
303 if (!network_thread_->IsCurrent()) {
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800304 return network_thread_->Invoke<std::unique_ptr<rtc::SSLCertChain>>(
305 RTC_FROM_HERE, [&] { return GetRemoteSSLCertChain(transport_name); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800306 }
307
Zhi Huange830e682018-03-30 10:48:35 -0700308 // Get the certificate from the RTP transport's DTLS handshake. Should be
309 // identical to the RTCP transport's, since they were given the same remote
Zhi Huange818b6e2018-02-22 15:26:27 -0800310 // fingerprint.
Zhi Huange830e682018-03-30 10:48:35 -0700311 auto jsep_transport = GetJsepTransportByName(transport_name);
312 if (!jsep_transport) {
313 return nullptr;
314 }
315 auto dtls = jsep_transport->rtp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800316 if (!dtls) {
317 return nullptr;
318 }
319
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800320 return dtls->GetRemoteSSLCertChain();
Zhi Huange818b6e2018-02-22 15:26:27 -0800321}
322
323void JsepTransportController::MaybeStartGathering() {
324 if (!network_thread_->IsCurrent()) {
325 network_thread_->Invoke<void>(RTC_FROM_HERE,
326 [&] { MaybeStartGathering(); });
327 return;
328 }
329
330 for (auto& dtls : GetDtlsTransports()) {
331 dtls->ice_transport()->MaybeStartGathering();
332 }
333}
334
335RTCError JsepTransportController::AddRemoteCandidates(
336 const std::string& transport_name,
337 const cricket::Candidates& candidates) {
338 if (!network_thread_->IsCurrent()) {
339 return network_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
340 return AddRemoteCandidates(transport_name, candidates);
341 });
342 }
343
344 // Verify each candidate before passing down to the transport layer.
345 RTCError error = VerifyCandidates(candidates);
346 if (!error.ok()) {
347 return error;
348 }
Zhi Huange830e682018-03-30 10:48:35 -0700349 auto jsep_transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800350 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700351 RTC_LOG(LS_WARNING) << "Not adding candidate because the JsepTransport "
352 "doesn't exist. Ignore it.";
353 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -0800354 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800355 return jsep_transport->AddRemoteCandidates(candidates);
356}
357
358RTCError JsepTransportController::RemoveRemoteCandidates(
359 const cricket::Candidates& candidates) {
360 if (!network_thread_->IsCurrent()) {
361 return network_thread_->Invoke<RTCError>(
362 RTC_FROM_HERE, [&] { return RemoveRemoteCandidates(candidates); });
363 }
364
365 // Verify each candidate before passing down to the transport layer.
366 RTCError error = VerifyCandidates(candidates);
367 if (!error.ok()) {
368 return error;
369 }
370
371 std::map<std::string, cricket::Candidates> candidates_by_transport_name;
372 for (const cricket::Candidate& cand : candidates) {
373 if (!cand.transport_name().empty()) {
374 candidates_by_transport_name[cand.transport_name()].push_back(cand);
375 } else {
376 RTC_LOG(LS_ERROR) << "Not removing candidate because it does not have a "
377 "transport name set: "
378 << cand.ToString();
379 }
380 }
381
382 for (const auto& kv : candidates_by_transport_name) {
383 const std::string& transport_name = kv.first;
384 const cricket::Candidates& candidates = kv.second;
Zhi Huang365381f2018-04-13 16:44:34 -0700385 cricket::JsepTransport* jsep_transport =
Zhi Huange830e682018-03-30 10:48:35 -0700386 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800387 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700388 RTC_LOG(LS_WARNING)
389 << "Not removing candidate because the JsepTransport doesn't exist.";
390 continue;
Zhi Huange818b6e2018-02-22 15:26:27 -0800391 }
392 for (const cricket::Candidate& candidate : candidates) {
Harald Alvestrandad88c882018-11-28 16:47:46 +0100393 cricket::DtlsTransportInternal* dtls =
394 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
395 ? jsep_transport->rtp_dtls_transport()
396 : jsep_transport->rtcp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800397 if (dtls) {
398 dtls->ice_transport()->RemoveRemoteCandidate(candidate);
399 }
400 }
401 }
402 return RTCError::OK();
403}
404
405bool JsepTransportController::GetStats(const std::string& transport_name,
406 cricket::TransportStats* stats) {
407 if (!network_thread_->IsCurrent()) {
408 return network_thread_->Invoke<bool>(
409 RTC_FROM_HERE, [=] { return GetStats(transport_name, stats); });
410 }
411
Zhi Huang365381f2018-04-13 16:44:34 -0700412 cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800413 if (!transport) {
414 return false;
415 }
416 return transport->GetStats(stats);
417}
418
Zhi Huangb57e1692018-06-12 11:41:11 -0700419void JsepTransportController::SetActiveResetSrtpParams(
420 bool active_reset_srtp_params) {
421 if (!network_thread_->IsCurrent()) {
422 network_thread_->Invoke<void>(RTC_FROM_HERE, [=] {
423 SetActiveResetSrtpParams(active_reset_srtp_params);
424 });
425 return;
426 }
427
428 RTC_LOG(INFO)
429 << "Updating the active_reset_srtp_params for JsepTransportController: "
430 << active_reset_srtp_params;
431 config_.active_reset_srtp_params = active_reset_srtp_params;
432 for (auto& kv : jsep_transports_by_name_) {
433 kv.second->SetActiveResetSrtpParams(active_reset_srtp_params);
434 }
435}
436
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800437void JsepTransportController::SetMediaTransportSettings(
438 bool use_media_transport_for_media,
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700439 bool use_media_transport_for_data_channels,
440 bool use_datagram_transport) {
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800441 RTC_DCHECK(use_media_transport_for_media ==
442 config_.use_media_transport_for_media ||
Piotr (Peter) Slatala97fc11f2018-10-18 12:57:59 -0700443 jsep_transports_by_name_.empty())
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800444 << "You can only change media transport configuration before creating "
445 "the first transport.";
446
447 RTC_DCHECK(use_media_transport_for_data_channels ==
448 config_.use_media_transport_for_data_channels ||
449 jsep_transports_by_name_.empty())
450 << "You can only change media transport configuration before creating "
451 "the first transport.";
452
453 config_.use_media_transport_for_media = use_media_transport_for_media;
454 config_.use_media_transport_for_data_channels =
455 use_media_transport_for_data_channels;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700456 config_.use_datagram_transport = use_datagram_transport;
Piotr (Peter) Slatala97fc11f2018-10-18 12:57:59 -0700457}
458
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800459std::unique_ptr<cricket::IceTransportInternal>
460JsepTransportController::CreateIceTransport(const std::string transport_name,
461 bool rtcp) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800462 int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
463 : cricket::ICE_CANDIDATE_COMPONENT_RTP;
464
Zhi Huange818b6e2018-02-22 15:26:27 -0800465 if (config_.external_transport_factory) {
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800466 return config_.external_transport_factory->CreateIceTransport(
Zhi Huange818b6e2018-02-22 15:26:27 -0800467 transport_name, component);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800468 } else {
469 return absl::make_unique<cricket::P2PTransportChannel>(
470 transport_name, component, port_allocator_, async_resolver_factory_,
471 config_.event_log);
472 }
473}
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) {
485 RTC_DCHECK(config_.use_datagram_transport);
486
487 // Create DTLS wrapper around DatagramTransportInterface.
488 dtls = absl::make_unique<cricket::DatagramDtlsAdaptor>(
Anton Sukhanovac6c0962019-07-10 15:44:56 -0700489 content_info.media_description()->rtp_header_extensions(), ice,
490 datagram_transport, config_.crypto_options, config_.event_log);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700491 } else if (config_.media_transport_factory &&
492 config_.use_media_transport_for_media &&
493 config_.use_media_transport_for_data_channels) {
494 // If media transport is used for both media and data channels,
495 // then we don't need to create DTLS.
496 // Otherwise, DTLS is still created.
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800497 dtls = absl::make_unique<cricket::NoOpDtlsTransport>(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700498 ice, config_.crypto_options);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800499 } else if (config_.external_transport_factory) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800500 dtls = config_.external_transport_factory->CreateDtlsTransport(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700501 ice, config_.crypto_options);
Zhi Huange818b6e2018-02-22 15:26:27 -0800502 } else {
Zach Steinc64078f2018-11-27 15:53:01 -0800503 dtls = absl::make_unique<cricket::DtlsTransport>(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700504 ice, config_.crypto_options, config_.event_log);
Zhi Huange818b6e2018-02-22 15:26:27 -0800505 }
506
507 RTC_DCHECK(dtls);
508 dtls->SetSslMaxProtocolVersion(config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 15:26:27 -0800509 dtls->ice_transport()->SetIceRole(ice_role_);
510 dtls->ice_transport()->SetIceTiebreaker(ice_tiebreaker_);
511 dtls->ice_transport()->SetIceConfig(ice_config_);
512 if (certificate_) {
513 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
514 RTC_DCHECK(set_cert_success);
515 }
516
517 // Connect to signals offered by the DTLS and ICE transport.
518 dtls->SignalWritableState.connect(
519 this, &JsepTransportController::OnTransportWritableState_n);
520 dtls->SignalReceivingState.connect(
521 this, &JsepTransportController::OnTransportReceivingState_n);
522 dtls->SignalDtlsHandshakeError.connect(
523 this, &JsepTransportController::OnDtlsHandshakeError);
524 dtls->ice_transport()->SignalGatheringState.connect(
525 this, &JsepTransportController::OnTransportGatheringState_n);
526 dtls->ice_transport()->SignalCandidateGathered.connect(
527 this, &JsepTransportController::OnTransportCandidateGathered_n);
Eldar Relloda13ea22019-06-01 12:23:43 +0300528 dtls->ice_transport()->SignalCandidateError.connect(
529 this, &JsepTransportController::OnTransportCandidateError_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800530 dtls->ice_transport()->SignalCandidatesRemoved.connect(
531 this, &JsepTransportController::OnTransportCandidatesRemoved_n);
532 dtls->ice_transport()->SignalRoleConflict.connect(
533 this, &JsepTransportController::OnTransportRoleConflict_n);
534 dtls->ice_transport()->SignalStateChanged.connect(
535 this, &JsepTransportController::OnTransportStateChanged_n);
Jonas Olsson7a6739e2019-01-15 16:31:55 +0100536 dtls->ice_transport()->SignalIceTransportStateChanged.connect(
537 this, &JsepTransportController::OnTransportStateChanged_n);
Alex Drake00c7ecf2019-08-06 10:54:47 -0700538 dtls->ice_transport()->SignalCandidatePairChanged.connect(
539 this, &JsepTransportController::OnTransportCandidatePairChanged_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800540 return dtls;
541}
542
543std::unique_ptr<webrtc::RtpTransport>
544JsepTransportController::CreateUnencryptedRtpTransport(
545 const std::string& transport_name,
546 rtc::PacketTransportInternal* rtp_packet_transport,
547 rtc::PacketTransportInternal* rtcp_packet_transport) {
548 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange830e682018-03-30 10:48:35 -0700549 auto unencrypted_rtp_transport =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200550 absl::make_unique<RtpTransport>(rtcp_packet_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700551 unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
552 if (rtcp_packet_transport) {
553 unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
554 }
555 return unencrypted_rtp_transport;
Zhi Huange818b6e2018-02-22 15:26:27 -0800556}
557
558std::unique_ptr<webrtc::SrtpTransport>
559JsepTransportController::CreateSdesTransport(
560 const std::string& transport_name,
Zhi Huange830e682018-03-30 10:48:35 -0700561 cricket::DtlsTransportInternal* rtp_dtls_transport,
562 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800563 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange818b6e2018-02-22 15:26:27 -0800564 auto srtp_transport =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200565 absl::make_unique<webrtc::SrtpTransport>(rtcp_dtls_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700566 RTC_DCHECK(rtp_dtls_transport);
567 srtp_transport->SetRtpPacketTransport(rtp_dtls_transport);
568 if (rtcp_dtls_transport) {
569 srtp_transport->SetRtcpPacketTransport(rtcp_dtls_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800570 }
571 if (config_.enable_external_auth) {
572 srtp_transport->EnableExternalAuth();
573 }
574 return srtp_transport;
575}
576
577std::unique_ptr<webrtc::DtlsSrtpTransport>
578JsepTransportController::CreateDtlsSrtpTransport(
579 const std::string& transport_name,
580 cricket::DtlsTransportInternal* rtp_dtls_transport,
581 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
582 RTC_DCHECK(network_thread_->IsCurrent());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200583 auto dtls_srtp_transport = absl::make_unique<webrtc::DtlsSrtpTransport>(
Zhi Huang365381f2018-04-13 16:44:34 -0700584 rtcp_dtls_transport == nullptr);
Zhi Huang27f3bf52018-03-26 21:37:23 -0700585 if (config_.enable_external_auth) {
Zhi Huang365381f2018-04-13 16:44:34 -0700586 dtls_srtp_transport->EnableExternalAuth();
Zhi Huang27f3bf52018-03-26 21:37:23 -0700587 }
Zhi Huang97d5e5b2018-03-27 00:09:01 +0000588
Zhi Huange818b6e2018-02-22 15:26:27 -0800589 dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
590 rtcp_dtls_transport);
Zhi Huangb57e1692018-06-12 11:41:11 -0700591 dtls_srtp_transport->SetActiveResetSrtpParams(
592 config_.active_reset_srtp_params);
Jonas Olsson635474e2018-10-18 15:58:17 +0200593 dtls_srtp_transport->SignalDtlsStateChange.connect(
594 this, &JsepTransportController::UpdateAggregateStates_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800595 return dtls_srtp_transport;
596}
597
598std::vector<cricket::DtlsTransportInternal*>
599JsepTransportController::GetDtlsTransports() {
600 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
Zhi Huange830e682018-03-30 10:48:35 -0700601 for (auto it = jsep_transports_by_name_.begin();
602 it != jsep_transports_by_name_.end(); ++it) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800603 auto jsep_transport = it->second.get();
604 RTC_DCHECK(jsep_transport);
605 if (jsep_transport->rtp_dtls_transport()) {
606 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
607 }
608
609 if (jsep_transport->rtcp_dtls_transport()) {
610 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
611 }
612 }
613 return dtls_transports;
614}
615
Zhi Huange818b6e2018-02-22 15:26:27 -0800616RTCError JsepTransportController::ApplyDescription_n(
617 bool local,
618 SdpType type,
619 const cricket::SessionDescription* description) {
620 RTC_DCHECK(network_thread_->IsCurrent());
621 RTC_DCHECK(description);
622
623 if (local) {
624 local_desc_ = description;
625 } else {
626 remote_desc_ = description;
627 }
628
Zhi Huange830e682018-03-30 10:48:35 -0700629 RTCError error;
Zhi Huangd2248f82018-04-10 14:41:03 -0700630 error = ValidateAndMaybeUpdateBundleGroup(local, type, description);
Zhi Huange830e682018-03-30 10:48:35 -0700631 if (!error.ok()) {
632 return error;
Zhi Huange818b6e2018-02-22 15:26:27 -0800633 }
634
635 std::vector<int> merged_encrypted_extension_ids;
636 if (bundle_group_) {
637 merged_encrypted_extension_ids =
638 MergeEncryptedHeaderExtensionIdsForBundle(description);
639 }
640
641 for (const cricket::ContentInfo& content_info : description->contents()) {
642 // Don't create transports for rejected m-lines and bundled m-lines."
643 if (content_info.rejected ||
644 (IsBundled(content_info.name) && content_info.name != *bundled_mid())) {
645 continue;
646 }
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -0800647 error = MaybeCreateJsepTransport(local, content_info, *description);
Zhi Huange830e682018-03-30 10:48:35 -0700648 if (!error.ok()) {
649 return error;
650 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800651 }
652
653 RTC_DCHECK(description->contents().size() ==
654 description->transport_infos().size());
655 for (size_t i = 0; i < description->contents().size(); ++i) {
656 const cricket::ContentInfo& content_info = description->contents()[i];
657 const cricket::TransportInfo& transport_info =
658 description->transport_infos()[i];
659 if (content_info.rejected) {
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700660 HandleRejectedContent(content_info, description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800661 continue;
662 }
663
664 if (IsBundled(content_info.name) && content_info.name != *bundled_mid()) {
Zhi Huang365381f2018-04-13 16:44:34 -0700665 if (!HandleBundledContent(content_info)) {
666 return RTCError(RTCErrorType::INVALID_PARAMETER,
667 "Failed to process the bundled m= section.");
668 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800669 continue;
670 }
671
Zhi Huange830e682018-03-30 10:48:35 -0700672 error = ValidateContent(content_info);
673 if (!error.ok()) {
674 return error;
675 }
676
Zhi Huange818b6e2018-02-22 15:26:27 -0800677 std::vector<int> extension_ids;
Taylor Brandstetter0ab56512018-04-12 10:30:48 -0700678 if (bundled_mid() && content_info.name == *bundled_mid()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800679 extension_ids = merged_encrypted_extension_ids;
680 } else {
681 extension_ids = GetEncryptedHeaderExtensionIds(content_info);
682 }
683
Zhi Huange830e682018-03-30 10:48:35 -0700684 int rtp_abs_sendtime_extn_id =
685 GetRtpAbsSendTimeHeaderExtensionId(content_info);
686
Zhi Huang365381f2018-04-13 16:44:34 -0700687 cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700688 GetJsepTransportForMid(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800689 RTC_DCHECK(transport);
690
691 SetIceRole_n(DetermineIceRole(transport, transport_info, type, local));
692
Zhi Huange818b6e2018-02-22 15:26:27 -0800693 cricket::JsepTransportDescription jsep_description =
694 CreateJsepTransportDescription(content_info, transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700695 extension_ids, rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800696 if (local) {
697 error =
698 transport->SetLocalJsepTransportDescription(jsep_description, type);
699 } else {
700 error =
701 transport->SetRemoteJsepTransportDescription(jsep_description, type);
702 }
703
704 if (!error.ok()) {
705 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
706 "Failed to apply the description for " +
707 content_info.name + ": " + error.message());
708 }
709 }
710 return RTCError::OK();
711}
712
Zhi Huangd2248f82018-04-10 14:41:03 -0700713RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup(
714 bool local,
715 SdpType type,
Zhi Huange830e682018-03-30 10:48:35 -0700716 const cricket::SessionDescription* description) {
717 RTC_DCHECK(description);
Zhi Huangd2248f82018-04-10 14:41:03 -0700718 const cricket::ContentGroup* new_bundle_group =
719 description->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
720
721 // The BUNDLE group containing a MID that no m= section has is invalid.
722 if (new_bundle_group) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100723 for (const auto& content_name : new_bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700724 if (!description->GetContentByName(content_name)) {
725 return RTCError(RTCErrorType::INVALID_PARAMETER,
726 "The BUNDLE group contains MID:" + content_name +
727 " matching no m= section.");
728 }
729 }
730 }
731
732 if (type == SdpType::kAnswer) {
733 const cricket::ContentGroup* offered_bundle_group =
734 local ? remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE)
735 : local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
736
737 if (new_bundle_group) {
738 // The BUNDLE group in answer should be a subset of offered group.
Mirko Bonadei739baf02019-01-27 17:29:42 +0100739 for (const auto& content_name : new_bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700740 if (!offered_bundle_group ||
741 !offered_bundle_group->HasContentName(content_name)) {
742 return RTCError(RTCErrorType::INVALID_PARAMETER,
743 "The BUNDLE group in answer contains a MID that was "
744 "not in the offered group.");
745 }
746 }
747 }
748
749 if (bundle_group_) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100750 for (const auto& content_name : bundle_group_->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700751 // An answer that removes m= sections from pre-negotiated BUNDLE group
752 // without rejecting it, is invalid.
753 if (!new_bundle_group ||
754 !new_bundle_group->HasContentName(content_name)) {
755 auto* content_info = description->GetContentByName(content_name);
756 if (!content_info || !content_info->rejected) {
757 return RTCError(RTCErrorType::INVALID_PARAMETER,
758 "Answer cannot remove m= section " + content_name +
759 " from already-established BUNDLE group.");
760 }
761 }
762 }
763 }
764 }
765
766 if (config_.bundle_policy ==
767 PeerConnectionInterface::kBundlePolicyMaxBundle &&
768 !description->HasGroup(cricket::GROUP_TYPE_BUNDLE)) {
769 return RTCError(RTCErrorType::INVALID_PARAMETER,
770 "max-bundle is used but no bundle group found.");
771 }
772
773 if (ShouldUpdateBundleGroup(type, description)) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700774 bundle_group_ = *new_bundle_group;
775 }
Zhi Huange830e682018-03-30 10:48:35 -0700776
777 if (!bundled_mid()) {
778 return RTCError::OK();
779 }
780
781 auto bundled_content = description->GetContentByName(*bundled_mid());
782 if (!bundled_content) {
783 return RTCError(
784 RTCErrorType::INVALID_PARAMETER,
785 "An m= section associated with the BUNDLE-tag doesn't exist.");
786 }
787
788 // If the |bundled_content| is rejected, other contents in the bundle group
789 // should be rejected.
790 if (bundled_content->rejected) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100791 for (const auto& content_name : bundle_group_->content_names()) {
Zhi Huange830e682018-03-30 10:48:35 -0700792 auto other_content = description->GetContentByName(content_name);
793 if (!other_content->rejected) {
794 return RTCError(
795 RTCErrorType::INVALID_PARAMETER,
796 "The m= section:" + content_name + " should be rejected.");
797 }
798 }
799 }
800
801 return RTCError::OK();
802}
803
804RTCError JsepTransportController::ValidateContent(
805 const cricket::ContentInfo& content_info) {
806 if (config_.rtcp_mux_policy ==
807 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
808 content_info.type == cricket::MediaProtocolType::kRtp &&
809 !content_info.media_description()->rtcp_mux()) {
810 return RTCError(RTCErrorType::INVALID_PARAMETER,
811 "The m= section:" + content_info.name +
812 " is invalid. RTCP-MUX is not "
813 "enabled when it is required.");
814 }
815 return RTCError::OK();
816}
817
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700818void JsepTransportController::HandleRejectedContent(
Zhi Huangd2248f82018-04-10 14:41:03 -0700819 const cricket::ContentInfo& content_info,
820 const cricket::SessionDescription* description) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800821 // If the content is rejected, let the
822 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700823 // then destroy the cricket::JsepTransport.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700824 RemoveTransportForMid(content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700825 if (content_info.name == bundled_mid()) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100826 for (const auto& content_name : bundle_group_->content_names()) {
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700827 RemoveTransportForMid(content_name);
Zhi Huange830e682018-03-30 10:48:35 -0700828 }
829 bundle_group_.reset();
830 } else if (IsBundled(content_info.name)) {
831 // Remove the rejected content from the |bundle_group_|.
Zhi Huange818b6e2018-02-22 15:26:27 -0800832 bundle_group_->RemoveContentName(content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700833 // Reset the bundle group if nothing left.
834 if (!bundle_group_->FirstContentName()) {
835 bundle_group_.reset();
836 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800837 }
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700838 MaybeDestroyJsepTransport(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800839}
840
Zhi Huang365381f2018-04-13 16:44:34 -0700841bool JsepTransportController::HandleBundledContent(
Zhi Huange818b6e2018-02-22 15:26:27 -0800842 const cricket::ContentInfo& content_info) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700843 auto jsep_transport = GetJsepTransportByName(*bundled_mid());
844 RTC_DCHECK(jsep_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800845 // If the content is bundled, let the
846 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700847 // then destroy the cricket::JsepTransport.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700848 if (SetTransportForMid(content_info.name, jsep_transport)) {
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -0800849 // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
850 // because it means that we first create media transport and start
851 // connecting it, and then we destroy it. We will need to address it before
852 // video path is enabled.
Zhi Huang365381f2018-04-13 16:44:34 -0700853 MaybeDestroyJsepTransport(content_info.name);
854 return true;
855 }
856 return false;
Zhi Huange818b6e2018-02-22 15:26:27 -0800857}
858
Zhi Huang365381f2018-04-13 16:44:34 -0700859bool JsepTransportController::SetTransportForMid(
Zhi Huangd2248f82018-04-10 14:41:03 -0700860 const std::string& mid,
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700861 cricket::JsepTransport* jsep_transport) {
Zhi Huang365381f2018-04-13 16:44:34 -0700862 RTC_DCHECK(jsep_transport);
Zhi Huangd2248f82018-04-10 14:41:03 -0700863 if (mid_to_transport_[mid] == jsep_transport) {
Zhi Huang365381f2018-04-13 16:44:34 -0700864 return true;
Zhi Huangd2248f82018-04-10 14:41:03 -0700865 }
866
867 mid_to_transport_[mid] = jsep_transport;
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700868 return config_.transport_observer->OnTransportChanged(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100869 mid, jsep_transport->rtp_transport(), jsep_transport->RtpDtlsTransport(),
870 jsep_transport->media_transport());
Zhi Huangd2248f82018-04-10 14:41:03 -0700871}
872
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700873void JsepTransportController::RemoveTransportForMid(const std::string& mid) {
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -0800874 bool ret = config_.transport_observer->OnTransportChanged(mid, nullptr,
875 nullptr, nullptr);
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700876 // Calling OnTransportChanged with nullptr should always succeed, since it is
877 // only expected to fail when adding media to a transport (not removing).
878 RTC_DCHECK(ret);
Zhi Huangd2248f82018-04-10 14:41:03 -0700879 mid_to_transport_.erase(mid);
880}
881
Zhi Huange818b6e2018-02-22 15:26:27 -0800882cricket::JsepTransportDescription
883JsepTransportController::CreateJsepTransportDescription(
Harald Alvestrand1716d392019-06-03 20:35:45 +0200884 const cricket::ContentInfo& content_info,
885 const cricket::TransportInfo& transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700886 const std::vector<int>& encrypted_extension_ids,
887 int rtp_abs_sendtime_extn_id) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800888 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200889 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800890 RTC_DCHECK(content_desc);
891 bool rtcp_mux_enabled = content_info.type == cricket::MediaProtocolType::kSctp
892 ? true
893 : content_desc->rtcp_mux();
894
895 return cricket::JsepTransportDescription(
896 rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
Zhi Huange830e682018-03-30 10:48:35 -0700897 rtp_abs_sendtime_extn_id, transport_info.description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800898}
899
900bool JsepTransportController::ShouldUpdateBundleGroup(
901 SdpType type,
902 const cricket::SessionDescription* description) {
903 if (config_.bundle_policy ==
904 PeerConnectionInterface::kBundlePolicyMaxBundle) {
905 return true;
906 }
907
908 if (type != SdpType::kAnswer) {
909 return false;
910 }
911
912 RTC_DCHECK(local_desc_ && remote_desc_);
913 const cricket::ContentGroup* local_bundle =
914 local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
915 const cricket::ContentGroup* remote_bundle =
916 remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
917 return local_bundle && remote_bundle;
918}
919
920std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
921 const cricket::ContentInfo& content_info) {
922 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200923 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800924
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700925 if (!config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800926 return std::vector<int>();
927 }
928
929 std::vector<int> encrypted_header_extension_ids;
Mirko Bonadei739baf02019-01-27 17:29:42 +0100930 for (const auto& extension : content_desc->rtp_header_extensions()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800931 if (!extension.encrypt) {
932 continue;
933 }
Steve Anton64b626b2019-01-28 17:25:26 -0800934 if (!absl::c_linear_search(encrypted_header_extension_ids, extension.id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800935 encrypted_header_extension_ids.push_back(extension.id);
936 }
937 }
938 return encrypted_header_extension_ids;
939}
940
941std::vector<int>
942JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundle(
943 const cricket::SessionDescription* description) {
944 RTC_DCHECK(description);
945 RTC_DCHECK(bundle_group_);
946
947 std::vector<int> merged_ids;
948 // Union the encrypted header IDs in the group when bundle is enabled.
949 for (const cricket::ContentInfo& content_info : description->contents()) {
950 if (bundle_group_->HasContentName(content_info.name)) {
951 std::vector<int> extension_ids =
952 GetEncryptedHeaderExtensionIds(content_info);
953 for (int id : extension_ids) {
Steve Anton64b626b2019-01-28 17:25:26 -0800954 if (!absl::c_linear_search(merged_ids, id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800955 merged_ids.push_back(id);
956 }
957 }
958 }
959 }
960 return merged_ids;
961}
962
Zhi Huange830e682018-03-30 10:48:35 -0700963int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
Zhi Huange818b6e2018-02-22 15:26:27 -0800964 const cricket::ContentInfo& content_info) {
Zhi Huange830e682018-03-30 10:48:35 -0700965 if (!config_.enable_external_auth) {
966 return -1;
Zhi Huange818b6e2018-02-22 15:26:27 -0800967 }
968
969 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200970 content_info.media_description();
Zhi Huange830e682018-03-30 10:48:35 -0700971
972 const webrtc::RtpExtension* send_time_extension =
973 webrtc::RtpExtension::FindHeaderExtensionByUri(
974 content_desc->rtp_header_extensions(),
975 webrtc::RtpExtension::kAbsSendTimeUri);
976 return send_time_extension ? send_time_extension->id : -1;
977}
978
Zhi Huang365381f2018-04-13 16:44:34 -0700979const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -0700980 const std::string& mid) const {
Zhi Huangd2248f82018-04-10 14:41:03 -0700981 auto it = mid_to_transport_.find(mid);
982 return it == mid_to_transport_.end() ? nullptr : it->second;
Zhi Huange830e682018-03-30 10:48:35 -0700983}
984
Zhi Huang365381f2018-04-13 16:44:34 -0700985cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -0700986 const std::string& mid) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700987 auto it = mid_to_transport_.find(mid);
988 return it == mid_to_transport_.end() ? nullptr : it->second;
Zhi Huange830e682018-03-30 10:48:35 -0700989}
990
Zhi Huang365381f2018-04-13 16:44:34 -0700991const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -0700992 const std::string& transport_name) const {
993 auto it = jsep_transports_by_name_.find(transport_name);
994 return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
995}
996
Zhi Huang365381f2018-04-13 16:44:34 -0700997cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -0700998 const std::string& transport_name) {
999 auto it = jsep_transports_by_name_.find(transport_name);
1000 return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
1001}
1002
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001003std::unique_ptr<webrtc::MediaTransportInterface>
1004JsepTransportController::MaybeCreateMediaTransport(
1005 const cricket::ContentInfo& content_info,
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001006 const cricket::SessionDescription& description,
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001007 bool local) {
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001008 if (config_.media_transport_factory == nullptr) {
1009 return nullptr;
1010 }
1011
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -08001012 if (!config_.use_media_transport_for_media &&
1013 !config_.use_media_transport_for_data_channels) {
1014 return nullptr;
1015 }
1016
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001017 // Caller (offerer) media transport.
1018 if (local) {
1019 if (offer_media_transport_) {
1020 RTC_LOG(LS_INFO) << "Offered media transport has now been activated.";
1021 return std::move(offer_media_transport_);
1022 } else {
1023 RTC_LOG(LS_INFO)
1024 << "Not returning media transport. Either SDES wasn't enabled, or "
1025 "media transport didn't return an offer earlier.";
1026 // Offer wasn't generated. Either because media transport didn't want it,
1027 // or because SDES wasn't enabled.
1028 return nullptr;
1029 }
Piotr (Peter) Slatala9f956252018-10-31 08:25:26 -07001030 }
1031
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001032 // Remote offer. If no x-mt lines, do not create media transport.
1033 if (description.MediaTransportSettings().empty()) {
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001034 return nullptr;
Anton Sukhanov7940da02018-10-10 10:34:49 -07001035 }
1036
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001037 // When bundle is enabled, two JsepTransports are created, and then
1038 // the second transport is destroyed (right away).
1039 // For media transport, we don't want to create the second
1040 // media transport in the first place.
1041 RTC_LOG(LS_INFO) << "Returning new, client media transport.";
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001042
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001043 RTC_DCHECK(!local)
1044 << "If media transport is used, you must call "
1045 "GenerateOrGetLastMediaTransportOffer before SetLocalDescription. You "
1046 "also "
1047 "must use kRtcpMuxPolicyRequire and kBundlePolicyMaxBundle with media "
1048 "transport.";
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001049 MediaTransportSettings settings;
1050 settings.is_caller = local;
Piotr (Peter) Slatala01fe3092019-02-15 12:05:50 -08001051 if (config_.use_media_transport_for_media) {
1052 settings.event_log = config_.event_log;
1053 }
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001054
1055 // Assume there is only one media transport (or if more, use the first one).
1056 if (!local && !description.MediaTransportSettings().empty() &&
1057 config_.media_transport_factory->GetTransportName() ==
1058 description.MediaTransportSettings()[0].transport_name) {
1059 settings.remote_transport_parameters =
1060 description.MediaTransportSettings()[0].transport_setting;
1061 }
1062
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001063 auto media_transport_result =
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001064 config_.media_transport_factory->CreateMediaTransport(network_thread_,
1065 settings);
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001066
1067 // TODO(sukhanov): Proper error handling.
1068 RTC_CHECK(media_transport_result.ok());
1069
1070 return media_transport_result.MoveValue();
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001071}
1072
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001073// TODO(sukhanov): Refactor to avoid code duplication for Media and Datagram
1074// transports setup.
1075std::unique_ptr<webrtc::DatagramTransportInterface>
1076JsepTransportController::MaybeCreateDatagramTransport(
1077 const cricket::ContentInfo& content_info,
1078 const cricket::SessionDescription& description,
1079 bool local) {
1080 if (config_.media_transport_factory == nullptr) {
1081 return nullptr;
1082 }
1083
1084 if (!config_.use_datagram_transport) {
1085 return nullptr;
1086 }
1087
1088 // Caller (offerer) datagram transport.
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001089 if (offer_datagram_transport_) {
1090 RTC_DCHECK(local);
1091 RTC_LOG(LS_INFO) << "Offered datagram transport has now been activated.";
1092 return std::move(offer_datagram_transport_);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001093 }
1094
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001095 const cricket::TransportDescription* transport_description =
1096 description.GetTransportDescriptionByName(content_info.mid());
1097 RTC_DCHECK(transport_description)
1098 << "Missing transport description for mid=" << content_info.mid();
1099
1100 if (!transport_description->opaque_parameters) {
1101 RTC_LOG(LS_INFO)
1102 << "No opaque transport parameters, not creating datagram transport";
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001103 return nullptr;
1104 }
1105
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001106 if (transport_description->opaque_parameters->protocol !=
1107 config_.media_transport_factory->GetTransportName()) {
1108 RTC_LOG(LS_INFO) << "Opaque transport parameters for protocol="
1109 << transport_description->opaque_parameters->protocol
1110 << ", which does not match supported protocol="
1111 << config_.media_transport_factory->GetTransportName();
1112 return nullptr;
1113 }
1114
1115 RTC_DCHECK(!local);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001116 // When bundle is enabled, two JsepTransports are created, and then
1117 // the second transport is destroyed (right away).
1118 // For datagram transport, we don't want to create the second
1119 // datagram transport in the first place.
1120 RTC_LOG(LS_INFO) << "Returning new, client datagram transport.";
1121
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001122 MediaTransportSettings settings;
1123 settings.is_caller = local;
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001124 settings.remote_transport_parameters =
1125 transport_description->opaque_parameters->parameters;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001126 settings.event_log = config_.event_log;
1127
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001128 auto datagram_transport_result =
1129 config_.media_transport_factory->CreateDatagramTransport(network_thread_,
1130 settings);
1131
1132 // TODO(sukhanov): Proper error handling.
1133 RTC_CHECK(datagram_transport_result.ok());
1134
1135 return datagram_transport_result.MoveValue();
1136}
1137
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001138RTCError JsepTransportController::MaybeCreateJsepTransport(
1139 bool local,
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001140 const cricket::ContentInfo& content_info,
1141 const cricket::SessionDescription& description) {
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001142 RTC_DCHECK(network_thread_->IsCurrent());
1143 cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
1144 if (transport) {
1145 return RTCError::OK();
1146 }
1147
1148 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +02001149 content_info.media_description();
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001150 if (certificate_ && !content_desc->cryptos().empty()) {
1151 return RTCError(RTCErrorType::INVALID_PARAMETER,
1152 "SDES and DTLS-SRTP cannot be enabled at the same time.");
1153 }
1154
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001155 std::unique_ptr<cricket::IceTransportInternal> ice =
1156 CreateIceTransport(content_info.name, /*rtcp=*/false);
1157
1158 std::unique_ptr<MediaTransportInterface> media_transport =
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001159 MaybeCreateMediaTransport(content_info, description, local);
1160 if (media_transport) {
1161 media_transport_created_once_ = true;
1162 media_transport->Connect(ice.get());
1163 }
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001164
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001165 std::unique_ptr<DatagramTransportInterface> datagram_transport =
1166 MaybeCreateDatagramTransport(content_info, description, local);
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001167 std::unique_ptr<cricket::DtlsTransportInternal> datagram_dtls_transport;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001168 if (datagram_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001169 datagram_transport->Connect(ice.get());
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001170 datagram_dtls_transport =
Anton Sukhanovac6c0962019-07-10 15:44:56 -07001171 CreateDtlsTransport(content_info, ice.get(), datagram_transport.get());
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 =
Anton Sukhanovac6c0962019-07-10 15:44:56 -07001175 CreateDtlsTransport(content_info, ice.get(), 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 Mellemc85ebbe2019-06-07 10:28:06 -07001181 std::unique_ptr<RtpTransport> datagram_rtp_transport;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001182
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001183 std::unique_ptr<cricket::IceTransportInternal> 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) {
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001187 RTC_DCHECK(media_transport == nullptr);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001188 RTC_DCHECK(datagram_transport == nullptr);
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001189 rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
Anton Sukhanovac6c0962019-07-10 15:44:56 -07001190 rtcp_dtls_transport = CreateDtlsTransport(content_info, rtcp_ice.get(),
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001191 /*datagram_transport=*/nullptr);
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001192 }
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001193
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001194 if (datagram_transport) {
1195 // TODO(sukhanov): We use unencrypted RTP transport over DatagramTransport,
1196 // because MediaTransport encrypts. In the future we may want to
1197 // implement our own version of RtpTransport over MediaTransport, because
1198 // it will give us more control over things like:
1199 // - Fusing
1200 // - Rtp header compression
1201 // - Handling Rtcp feedback.
1202 RTC_LOG(LS_INFO) << "Creating UnencryptedRtpTransport, because datagram "
1203 "transport is used.";
1204 RTC_DCHECK(!rtcp_dtls_transport);
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001205 datagram_rtp_transport = CreateUnencryptedRtpTransport(
1206 content_info.name, datagram_dtls_transport.get(), nullptr);
1207 }
1208
1209 if (config_.disable_encryption) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001210 RTC_LOG(LS_INFO)
1211 << "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001212 unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
Zhi Huangd2248f82018-04-10 14:41:03 -07001213 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001214 } else if (!content_desc->cryptos().empty()) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001215 sdes_transport = CreateSdesTransport(
1216 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001217 RTC_LOG(LS_INFO) << "Creating SdesTransport.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001218 } else {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001219 RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
Zhi Huangd2248f82018-04-10 14:41:03 -07001220 dtls_srtp_transport = CreateDtlsSrtpTransport(
1221 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001222 }
1223
Zhi Huang365381f2018-04-13 16:44:34 -07001224 std::unique_ptr<cricket::JsepTransport> jsep_transport =
Karl Wiberg918f50c2018-07-05 11:40:33 +02001225 absl::make_unique<cricket::JsepTransport>(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001226 content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
1227 std::move(unencrypted_rtp_transport), std::move(sdes_transport),
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001228 std::move(dtls_srtp_transport), std::move(datagram_rtp_transport),
1229 std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport),
1230 std::move(datagram_dtls_transport), std::move(media_transport),
Anton Sukhanov292ce4e2019-06-03 13:00:24 -07001231 std::move(datagram_transport));
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001232
Zhi Huange818b6e2018-02-22 15:26:27 -08001233 jsep_transport->SignalRtcpMuxActive.connect(
1234 this, &JsepTransportController::UpdateAggregateStates_n);
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -07001235 jsep_transport->SignalMediaTransportStateChanged.connect(
Bjorn Mellem175aa2e2018-11-08 11:23:22 -08001236 this, &JsepTransportController::OnMediaTransportStateChanged_n);
Taylor Brandstettercbaa2542018-04-16 16:42:14 -07001237 SetTransportForMid(content_info.name, jsep_transport.get());
Zhi Huange830e682018-03-30 10:48:35 -07001238
Zhi Huangd2248f82018-04-10 14:41:03 -07001239 jsep_transports_by_name_[content_info.name] = std::move(jsep_transport);
1240 UpdateAggregateStates_n();
Zhi Huange830e682018-03-30 10:48:35 -07001241 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -08001242}
1243
1244void JsepTransportController::MaybeDestroyJsepTransport(
1245 const std::string& mid) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001246 auto jsep_transport = GetJsepTransportByName(mid);
1247 if (!jsep_transport) {
1248 return;
1249 }
1250
1251 // Don't destroy the JsepTransport if there are still media sections referring
1252 // to it.
1253 for (const auto& kv : mid_to_transport_) {
1254 if (kv.second == jsep_transport) {
1255 return;
1256 }
1257 }
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001258
Zhi Huange830e682018-03-30 10:48:35 -07001259 jsep_transports_by_name_.erase(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -08001260 UpdateAggregateStates_n();
1261}
1262
1263void JsepTransportController::DestroyAllJsepTransports_n() {
1264 RTC_DCHECK(network_thread_->IsCurrent());
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001265
1266 for (const auto& jsep_transport : jsep_transports_by_name_) {
1267 config_.transport_observer->OnTransportChanged(jsep_transport.first,
1268 nullptr, nullptr, nullptr);
1269 }
1270
Zhi Huange830e682018-03-30 10:48:35 -07001271 jsep_transports_by_name_.clear();
Zhi Huange818b6e2018-02-22 15:26:27 -08001272}
1273
1274void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
1275 RTC_DCHECK(network_thread_->IsCurrent());
1276
1277 ice_role_ = ice_role;
1278 for (auto& dtls : GetDtlsTransports()) {
1279 dtls->ice_transport()->SetIceRole(ice_role_);
1280 }
1281}
1282
1283cricket::IceRole JsepTransportController::DetermineIceRole(
Zhi Huang365381f2018-04-13 16:44:34 -07001284 cricket::JsepTransport* jsep_transport,
Zhi Huange818b6e2018-02-22 15:26:27 -08001285 const cricket::TransportInfo& transport_info,
1286 SdpType type,
1287 bool local) {
1288 cricket::IceRole ice_role = ice_role_;
1289 auto tdesc = transport_info.description;
1290 if (local) {
1291 // The initial offer side may use ICE Lite, in which case, per RFC5245
1292 // Section 5.1.1, the answer side should take the controlling role if it is
1293 // in the full ICE mode.
1294 //
1295 // When both sides use ICE Lite, the initial offer side must take the
1296 // controlling role, and this is the default logic implemented in
1297 // SetLocalDescription in JsepTransportController.
1298 if (jsep_transport->remote_description() &&
1299 jsep_transport->remote_description()->transport_desc.ice_mode ==
1300 cricket::ICEMODE_LITE &&
1301 ice_role_ == cricket::ICEROLE_CONTROLLED &&
1302 tdesc.ice_mode == cricket::ICEMODE_FULL) {
1303 ice_role = cricket::ICEROLE_CONTROLLING;
1304 }
1305
1306 // Older versions of Chrome expect the ICE role to be re-determined when an
1307 // ICE restart occurs, and also don't perform conflict resolution correctly,
1308 // so for now we can't safely stop doing this, unless the application opts
1309 // in by setting |config_.redetermine_role_on_ice_restart_| to false. See:
1310 // https://bugs.chromium.org/p/chromium/issues/detail?id=628676
1311 // TODO(deadbeef): Remove this when these old versions of Chrome reach a low
1312 // enough population.
1313 if (config_.redetermine_role_on_ice_restart &&
1314 jsep_transport->local_description() &&
1315 cricket::IceCredentialsChanged(
1316 jsep_transport->local_description()->transport_desc.ice_ufrag,
1317 jsep_transport->local_description()->transport_desc.ice_pwd,
1318 tdesc.ice_ufrag, tdesc.ice_pwd) &&
1319 // Don't change the ICE role if the remote endpoint is ICE lite; we
1320 // should always be controlling in that case.
1321 (!jsep_transport->remote_description() ||
1322 jsep_transport->remote_description()->transport_desc.ice_mode !=
1323 cricket::ICEMODE_LITE)) {
1324 ice_role = (type == SdpType::kOffer) ? cricket::ICEROLE_CONTROLLING
1325 : cricket::ICEROLE_CONTROLLED;
1326 }
1327 } else {
1328 // If our role is cricket::ICEROLE_CONTROLLED and the remote endpoint
1329 // supports only ice_lite, this local endpoint should take the CONTROLLING
1330 // role.
1331 // TODO(deadbeef): This is a session-level attribute, so it really shouldn't
1332 // be in a TransportDescription in the first place...
1333 if (ice_role_ == cricket::ICEROLE_CONTROLLED &&
1334 tdesc.ice_mode == cricket::ICEMODE_LITE) {
1335 ice_role = cricket::ICEROLE_CONTROLLING;
1336 }
1337
1338 // If we use ICE Lite and the remote endpoint uses the full implementation
1339 // of ICE, the local endpoint must take the controlled role, and the other
1340 // side must be the controlling role.
1341 if (jsep_transport->local_description() &&
1342 jsep_transport->local_description()->transport_desc.ice_mode ==
1343 cricket::ICEMODE_LITE &&
1344 ice_role_ == cricket::ICEROLE_CONTROLLING &&
Zhi Huange830e682018-03-30 10:48:35 -07001345 tdesc.ice_mode == cricket::ICEMODE_FULL) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001346 ice_role = cricket::ICEROLE_CONTROLLED;
1347 }
1348 }
1349
1350 return ice_role;
1351}
1352
1353void JsepTransportController::OnTransportWritableState_n(
1354 rtc::PacketTransportInternal* transport) {
1355 RTC_DCHECK(network_thread_->IsCurrent());
1356 RTC_LOG(LS_INFO) << " Transport " << transport->transport_name()
1357 << " writability changed to " << transport->writable()
1358 << ".";
1359 UpdateAggregateStates_n();
1360}
1361
1362void JsepTransportController::OnTransportReceivingState_n(
1363 rtc::PacketTransportInternal* transport) {
1364 RTC_DCHECK(network_thread_->IsCurrent());
1365 UpdateAggregateStates_n();
1366}
1367
1368void JsepTransportController::OnTransportGatheringState_n(
1369 cricket::IceTransportInternal* transport) {
1370 RTC_DCHECK(network_thread_->IsCurrent());
1371 UpdateAggregateStates_n();
1372}
1373
1374void JsepTransportController::OnTransportCandidateGathered_n(
1375 cricket::IceTransportInternal* transport,
1376 const cricket::Candidate& candidate) {
1377 RTC_DCHECK(network_thread_->IsCurrent());
1378
1379 // We should never signal peer-reflexive candidates.
1380 if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
1381 RTC_NOTREACHED();
1382 return;
1383 }
Steve Antond25828a2018-08-31 13:06:05 -07001384 std::string transport_name = transport->transport_name();
1385 invoker_.AsyncInvoke<void>(
1386 RTC_FROM_HERE, signaling_thread_, [this, transport_name, candidate] {
1387 SignalIceCandidatesGathered(transport_name, {candidate});
1388 });
Zhi Huange818b6e2018-02-22 15:26:27 -08001389}
1390
Eldar Relloda13ea22019-06-01 12:23:43 +03001391void JsepTransportController::OnTransportCandidateError_n(
1392 cricket::IceTransportInternal* transport,
1393 const cricket::IceCandidateErrorEvent& event) {
1394 RTC_DCHECK(network_thread_->IsCurrent());
1395
1396 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1397 [this, event] { SignalIceCandidateError(event); });
1398}
Zhi Huange818b6e2018-02-22 15:26:27 -08001399void JsepTransportController::OnTransportCandidatesRemoved_n(
1400 cricket::IceTransportInternal* transport,
1401 const cricket::Candidates& candidates) {
1402 invoker_.AsyncInvoke<void>(
1403 RTC_FROM_HERE, signaling_thread_,
Steve Antond25828a2018-08-31 13:06:05 -07001404 [this, candidates] { SignalIceCandidatesRemoved(candidates); });
Zhi Huange818b6e2018-02-22 15:26:27 -08001405}
Alex Drake00c7ecf2019-08-06 10:54:47 -07001406void JsepTransportController::OnTransportCandidatePairChanged_n(
1407 const cricket::CandidatePairChangeEvent& event) {
1408 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, [this, event] {
1409 SignalIceCandidatePairChanged(event);
1410 });
1411}
Zhi Huange818b6e2018-02-22 15:26:27 -08001412
1413void JsepTransportController::OnTransportRoleConflict_n(
1414 cricket::IceTransportInternal* transport) {
1415 RTC_DCHECK(network_thread_->IsCurrent());
1416 // Note: since the role conflict is handled entirely on the network thread,
1417 // we don't need to worry about role conflicts occurring on two ports at
1418 // once. The first one encountered should immediately reverse the role.
1419 cricket::IceRole reversed_role = (ice_role_ == cricket::ICEROLE_CONTROLLING)
1420 ? cricket::ICEROLE_CONTROLLED
1421 : cricket::ICEROLE_CONTROLLING;
1422 RTC_LOG(LS_INFO) << "Got role conflict; switching to "
1423 << (reversed_role == cricket::ICEROLE_CONTROLLING
1424 ? "controlling"
1425 : "controlled")
1426 << " role.";
1427 SetIceRole_n(reversed_role);
1428}
1429
1430void JsepTransportController::OnTransportStateChanged_n(
1431 cricket::IceTransportInternal* transport) {
1432 RTC_DCHECK(network_thread_->IsCurrent());
1433 RTC_LOG(LS_INFO) << transport->transport_name() << " Transport "
1434 << transport->component()
1435 << " state changed. Check if state is complete.";
1436 UpdateAggregateStates_n();
1437}
1438
Bjorn Mellem175aa2e2018-11-08 11:23:22 -08001439void JsepTransportController::OnMediaTransportStateChanged_n() {
1440 SignalMediaTransportStateChanged();
1441 UpdateAggregateStates_n();
1442}
1443
Zhi Huange818b6e2018-02-22 15:26:27 -08001444void JsepTransportController::UpdateAggregateStates_n() {
1445 RTC_DCHECK(network_thread_->IsCurrent());
1446
1447 auto dtls_transports = GetDtlsTransports();
Alex Loiko9289eda2018-11-23 16:18:59 +00001448 cricket::IceConnectionState new_connection_state =
1449 cricket::kIceConnectionConnecting;
Jonas Olsson635474e2018-10-18 15:58:17 +02001450 PeerConnectionInterface::IceConnectionState new_ice_connection_state =
1451 PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
1452 PeerConnectionInterface::PeerConnectionState new_combined_state =
1453 PeerConnectionInterface::PeerConnectionState::kNew;
Zhi Huange818b6e2018-02-22 15:26:27 -08001454 cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
Alex Loiko9289eda2018-11-23 16:18:59 +00001455 bool any_failed = false;
1456
1457 // TODO(http://bugs.webrtc.org/9719) If(when) media_transport disables
1458 // dtls_transports entirely, the below line will have to be changed to account
1459 // for the fact that dtls transports might be absent.
1460 bool all_connected = !dtls_transports.empty();
1461 bool all_completed = !dtls_transports.empty();
Zhi Huange818b6e2018-02-22 15:26:27 -08001462 bool any_gathering = false;
1463 bool all_done_gathering = !dtls_transports.empty();
Jonas Olsson635474e2018-10-18 15:58:17 +02001464
1465 std::map<IceTransportState, int> ice_state_counts;
1466 std::map<cricket::DtlsTransportState, int> dtls_state_counts;
1467
Zhi Huange818b6e2018-02-22 15:26:27 -08001468 for (const auto& dtls : dtls_transports) {
Alex Loiko9289eda2018-11-23 16:18:59 +00001469 any_failed = any_failed || dtls->ice_transport()->GetState() ==
1470 cricket::IceTransportState::STATE_FAILED;
1471 all_connected = all_connected && dtls->writable();
1472 all_completed =
1473 all_completed && dtls->writable() &&
1474 dtls->ice_transport()->GetState() ==
1475 cricket::IceTransportState::STATE_COMPLETED &&
1476 dtls->ice_transport()->GetIceRole() == cricket::ICEROLE_CONTROLLING &&
1477 dtls->ice_transport()->gathering_state() ==
1478 cricket::kIceGatheringComplete;
Zhi Huange818b6e2018-02-22 15:26:27 -08001479 any_gathering = any_gathering || dtls->ice_transport()->gathering_state() !=
1480 cricket::kIceGatheringNew;
1481 all_done_gathering =
1482 all_done_gathering && dtls->ice_transport()->gathering_state() ==
1483 cricket::kIceGatheringComplete;
Jonas Olsson635474e2018-10-18 15:58:17 +02001484
1485 dtls_state_counts[dtls->dtls_state()]++;
1486 ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
Zhi Huange818b6e2018-02-22 15:26:27 -08001487 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -07001488
Alex Loiko9289eda2018-11-23 16:18:59 +00001489 for (auto it = jsep_transports_by_name_.begin();
1490 it != jsep_transports_by_name_.end(); ++it) {
1491 auto jsep_transport = it->second.get();
1492 if (!jsep_transport->media_transport()) {
1493 continue;
1494 }
1495
1496 // There is no 'kIceConnectionDisconnected', so we only need to handle
1497 // connected and completed.
1498 // We treat kClosed as failed, because if it happens before shutting down
1499 // media transports it means that there was a failure.
1500 // MediaTransportInterface allows to flip back and forth between kWritable
1501 // and kPending, but there does not exist an implementation that does that,
1502 // and the contract of jsep transport controller doesn't quite expect that.
1503 // When this happens, we would go from connected to connecting state, but
1504 // this may change in future.
1505 any_failed |= jsep_transport->media_transport_state() ==
1506 webrtc::MediaTransportState::kClosed;
1507 all_completed &= jsep_transport->media_transport_state() ==
1508 webrtc::MediaTransportState::kWritable;
1509 all_connected &= jsep_transport->media_transport_state() ==
1510 webrtc::MediaTransportState::kWritable;
1511 }
1512
1513 if (any_failed) {
1514 new_connection_state = cricket::kIceConnectionFailed;
1515 } else if (all_completed) {
1516 new_connection_state = cricket::kIceConnectionCompleted;
1517 } else if (all_connected) {
1518 new_connection_state = cricket::kIceConnectionConnected;
1519 }
1520 if (ice_connection_state_ != new_connection_state) {
1521 ice_connection_state_ = new_connection_state;
1522 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1523 [this, new_connection_state] {
1524 SignalIceConnectionState(new_connection_state);
1525 });
1526 }
1527
Jonas Olsson635474e2018-10-18 15:58:17 +02001528 // Compute the current RTCIceConnectionState as described in
1529 // https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
1530 // The PeerConnection is responsible for handling the "closed" state.
1531 int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
1532 int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
1533 int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
1534 int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
1535 int total_ice_disconnected =
1536 ice_state_counts[IceTransportState::kDisconnected];
1537 int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
1538 int total_ice_new = ice_state_counts[IceTransportState::kNew];
1539 int total_ice = dtls_transports.size();
1540
1541 if (total_ice_failed > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001542 // Any RTCIceTransports are in the "failed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001543 new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
Alex Loiko9289eda2018-11-23 16:18:59 +00001544 } else if (total_ice_disconnected > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001545 // None of the previous states apply and any RTCIceTransports are in the
1546 // "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001547 new_ice_connection_state =
1548 PeerConnectionInterface::kIceConnectionDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001549 } else if (total_ice_new + total_ice_closed == total_ice) {
1550 // None of the previous states apply and all RTCIceTransports are in the
1551 // "new" or "closed" state, or there are no transports.
1552 new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
1553 } else if (total_ice_new + total_ice_checking > 0) {
1554 // None of the previous states apply and any RTCIceTransports are in the
1555 // "new" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001556 new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001557 } else if (total_ice_completed + total_ice_closed == total_ice ||
1558 all_completed) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001559 // None of the previous states apply and all RTCIceTransports are in the
1560 // "completed" or "closed" state.
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001561 //
1562 // TODO(https://bugs.webrtc.org/10356): The all_completed condition is added
1563 // to mimic the behavior of the old ICE connection state, and should be
1564 // removed once we get end-of-candidates signaling in place.
Jonas Olsson635474e2018-10-18 15:58:17 +02001565 new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
1566 } else if (total_ice_connected + total_ice_completed + total_ice_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001567 total_ice) {
1568 // None of the previous states apply and all RTCIceTransports are in the
1569 // "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001570 new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001571 } else {
1572 RTC_NOTREACHED();
1573 }
1574
Alex Loiko9289eda2018-11-23 16:18:59 +00001575 if (standardized_ice_connection_state_ != new_ice_connection_state) {
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001576 if (standardized_ice_connection_state_ ==
1577 PeerConnectionInterface::kIceConnectionChecking &&
1578 new_ice_connection_state ==
1579 PeerConnectionInterface::kIceConnectionCompleted) {
1580 // Ensure that we never skip over the "connected" state.
1581 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, [this] {
1582 SignalStandardizedIceConnectionState(
1583 PeerConnectionInterface::kIceConnectionConnected);
1584 });
1585 }
Alex Loiko9289eda2018-11-23 16:18:59 +00001586 standardized_ice_connection_state_ = new_ice_connection_state;
Jonas Olsson635474e2018-10-18 15:58:17 +02001587 invoker_.AsyncInvoke<void>(
1588 RTC_FROM_HERE, signaling_thread_, [this, new_ice_connection_state] {
Alex Loiko9289eda2018-11-23 16:18:59 +00001589 SignalStandardizedIceConnectionState(new_ice_connection_state);
Jonas Olsson635474e2018-10-18 15:58:17 +02001590 });
1591 }
1592
1593 // Compute the current RTCPeerConnectionState as described in
1594 // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
1595 // The PeerConnection is responsible for handling the "closed" state.
1596 // Note that "connecting" is only a valid state for DTLS transports while
1597 // "checking", "completed" and "disconnected" are only valid for ICE
1598 // transports.
1599 int total_connected = total_ice_connected +
1600 dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTED];
1601 int total_dtls_connecting =
1602 dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTING];
1603 int total_failed =
1604 total_ice_failed + dtls_state_counts[cricket::DTLS_TRANSPORT_FAILED];
1605 int total_closed =
1606 total_ice_closed + dtls_state_counts[cricket::DTLS_TRANSPORT_CLOSED];
1607 int total_new =
1608 total_ice_new + dtls_state_counts[cricket::DTLS_TRANSPORT_NEW];
1609 int total_transports = total_ice * 2;
1610
1611 if (total_failed > 0) {
1612 // Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
1613 new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001614 } else if (total_ice_disconnected > 0) {
1615 // None of the previous states apply and any RTCIceTransports or
1616 // RTCDtlsTransports are in the "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001617 new_combined_state =
1618 PeerConnectionInterface::PeerConnectionState::kDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001619 } else if (total_new + total_closed == total_transports) {
1620 // None of the previous states apply and all RTCIceTransports and
1621 // RTCDtlsTransports are in the "new" or "closed" state, or there are no
1622 // transports.
1623 new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
1624 } else if (total_new + total_dtls_connecting + total_ice_checking > 0) {
1625 // None of the previous states apply and all RTCIceTransports or
1626 // RTCDtlsTransports are in the "new", "connecting" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001627 new_combined_state =
1628 PeerConnectionInterface::PeerConnectionState::kConnecting;
1629 } else if (total_connected + total_ice_completed + total_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001630 total_transports) {
1631 // None of the previous states apply and all RTCIceTransports and
1632 // RTCDtlsTransports are in the "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001633 new_combined_state =
1634 PeerConnectionInterface::PeerConnectionState::kConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001635 } else {
1636 RTC_NOTREACHED();
1637 }
1638
1639 if (combined_connection_state_ != new_combined_state) {
1640 combined_connection_state_ = new_combined_state;
1641 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1642 [this, new_combined_state] {
1643 SignalConnectionState(new_combined_state);
1644 });
1645 }
1646
Zhi Huange818b6e2018-02-22 15:26:27 -08001647 if (all_done_gathering) {
1648 new_gathering_state = cricket::kIceGatheringComplete;
1649 } else if (any_gathering) {
1650 new_gathering_state = cricket::kIceGatheringGathering;
1651 }
1652 if (ice_gathering_state_ != new_gathering_state) {
1653 ice_gathering_state_ = new_gathering_state;
Steve Antond25828a2018-08-31 13:06:05 -07001654 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1655 [this, new_gathering_state] {
1656 SignalIceGatheringState(new_gathering_state);
1657 });
Zhi Huange818b6e2018-02-22 15:26:27 -08001658 }
1659}
1660
1661void JsepTransportController::OnDtlsHandshakeError(
1662 rtc::SSLHandshakeError error) {
1663 SignalDtlsHandshakeError(error);
1664}
1665
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001666absl::optional<cricket::SessionDescription::MediaTransportSetting>
1667JsepTransportController::GenerateOrGetLastMediaTransportOffer() {
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001668 if (media_transport_created_once_) {
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001669 RTC_LOG(LS_INFO) << "Not regenerating media transport for the new offer in "
1670 "existing session.";
1671 return media_transport_offer_settings_;
1672 }
1673
1674 RTC_LOG(LS_INFO) << "Generating media transport offer!";
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001675
1676 absl::optional<std::string> transport_parameters;
1677
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001678 // Check that media transport is supposed to be used.
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001679 // Note that ICE is not available when media transport is created. It will
1680 // only be available in 'Connect'. This may be a potential server config, if
1681 // we decide to use this peer connection as a caller, not as a callee.
1682 // TODO(sukhanov): Avoid code duplication with CreateMedia/MediaTransport.
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001683 if (config_.use_media_transport_for_media ||
1684 config_.use_media_transport_for_data_channels) {
1685 RTC_DCHECK(config_.media_transport_factory != nullptr);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001686 RTC_DCHECK(!config_.use_datagram_transport);
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001687 webrtc::MediaTransportSettings settings;
1688 settings.is_caller = true;
1689 settings.pre_shared_key = rtc::CreateRandomString(32);
Bjorn A Mellemb073f1c2019-07-02 09:50:35 -07001690 if (config_.use_media_transport_for_media) {
1691 settings.event_log = config_.event_log;
1692 }
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001693 auto media_transport_or_error =
1694 config_.media_transport_factory->CreateMediaTransport(network_thread_,
1695 settings);
1696
1697 if (media_transport_or_error.ok()) {
1698 offer_media_transport_ = std::move(media_transport_or_error.value());
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001699 transport_parameters =
1700 offer_media_transport_->GetTransportParametersOffer();
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001701 } else {
1702 RTC_LOG(LS_INFO) << "Unable to create media transport, error="
1703 << media_transport_or_error.error().message();
1704 }
1705 }
1706
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001707 if (!offer_media_transport_) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001708 RTC_LOG(LS_INFO) << "Media and data transports do not exist";
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001709 return absl::nullopt;
1710 }
1711
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001712 if (!transport_parameters) {
1713 RTC_LOG(LS_INFO) << "Media transport didn't generate the offer";
1714 // Media transport didn't generate the offer, and is not supposed to be
1715 // used. Destroy the temporary media transport.
1716 offer_media_transport_ = nullptr;
1717 return absl::nullopt;
1718 }
1719
1720 cricket::SessionDescription::MediaTransportSetting setting;
1721 setting.transport_name = config_.media_transport_factory->GetTransportName();
1722 setting.transport_setting = *transport_parameters;
1723 media_transport_offer_settings_ = setting;
1724 return setting;
1725}
1726
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001727absl::optional<cricket::OpaqueTransportParameters>
1728JsepTransportController::GetTransportParameters(const std::string& mid) {
1729 if (!config_.use_datagram_transport) {
1730 return absl::nullopt;
1731 }
1732
1733 cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
1734 if (transport) {
1735 absl::optional<cricket::OpaqueTransportParameters> params =
1736 transport->GetTransportParameters();
1737 if (params) {
1738 params->protocol = config_.media_transport_factory->GetTransportName();
1739 }
1740 return params;
1741 }
1742
1743 RTC_DCHECK(!local_desc_ && !remote_desc_)
1744 << "JsepTransport should exist for every mid once any description is set";
1745
1746 // Need to generate a transport for the offer.
1747 if (!offer_datagram_transport_) {
1748 webrtc::MediaTransportSettings settings;
1749 settings.is_caller = true;
1750 settings.pre_shared_key = rtc::CreateRandomString(32);
1751 settings.event_log = config_.event_log;
1752 auto datagram_transport_or_error =
1753 config_.media_transport_factory->CreateDatagramTransport(
1754 network_thread_, settings);
1755
1756 if (datagram_transport_or_error.ok()) {
1757 offer_datagram_transport_ =
1758 std::move(datagram_transport_or_error.value());
1759 } else {
1760 RTC_LOG(LS_INFO) << "Unable to create datagram transport, error="
1761 << datagram_transport_or_error.error().message();
1762 }
1763 }
1764
1765 // We have prepared a transport for the offer, and can now use its parameters.
1766 cricket::OpaqueTransportParameters params;
1767 params.parameters = offer_datagram_transport_->GetTransportParameters();
1768 params.protocol = config_.media_transport_factory->GetTransportName();
1769 return params;
1770}
1771
Zhi Huange818b6e2018-02-22 15:26:27 -08001772} // namespace webrtc