blob: 75f5d9db8c6325276c77d4dd4135109d5a564fc3 [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"
Niels Möller65f17ca2019-09-12 13:59:36 +020017#include "api/transport/datagram_transport_interface.h"
18#include "api/transport/media/media_transport_interface.h"
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -080019#include "p2p/base/ice_transport_internal.h"
20#include "p2p/base/no_op_dtls_transport.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
62 return webrtc::RTCError::OK();
63}
64
65webrtc::RTCError VerifyCandidates(const cricket::Candidates& candidates) {
66 for (const cricket::Candidate& candidate : candidates) {
67 webrtc::RTCError error = VerifyCandidate(candidate);
68 if (!error.ok()) {
69 return error;
70 }
71 }
72 return webrtc::RTCError::OK();
73}
74
75} // namespace
76
77namespace webrtc {
78
79JsepTransportController::JsepTransportController(
80 rtc::Thread* signaling_thread,
81 rtc::Thread* network_thread,
82 cricket::PortAllocator* port_allocator,
Zach Steine20867f2018-08-02 13:20:15 -070083 AsyncResolverFactory* async_resolver_factory,
Zhi Huange818b6e2018-02-22 15:26:27 -080084 Config config)
85 : signaling_thread_(signaling_thread),
86 network_thread_(network_thread),
87 port_allocator_(port_allocator),
Zach Steine20867f2018-08-02 13:20:15 -070088 async_resolver_factory_(async_resolver_factory),
Zhi Huang365381f2018-04-13 16:44:34 -070089 config_(config) {
90 // The |transport_observer| is assumed to be non-null.
91 RTC_DCHECK(config_.transport_observer);
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +020092 RTC_DCHECK(config_.rtcp_handler);
Zhi Huang365381f2018-04-13 16:44:34 -070093}
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
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700154 DatagramTransportInterface* datagram_transport = nullptr;
155 if (config_.use_datagram_transport) {
156 datagram_transport = jsep_transport->datagram_transport();
157 }
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700158
159 // Media transport and datagram transports can not be used together.
160 RTC_DCHECK(!media_transport || !datagram_transport);
161
162 if (media_transport) {
163 return MediaTransportConfig(media_transport);
164 } else if (datagram_transport) {
165 return MediaTransportConfig(
166 /*rtp_max_packet_size=*/datagram_transport->GetLargestDatagramSize());
167 } else {
168 return MediaTransportConfig();
169 }
170}
171
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700172DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700173 const std::string& mid) const {
174 auto jsep_transport = GetJsepTransportForMid(mid);
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700175 if (!jsep_transport) {
Anton Sukhanov7940da02018-10-10 10:34:49 -0700176 return nullptr;
177 }
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700178 return jsep_transport->data_channel_transport();
Anton Sukhanov7940da02018-10-10 10:34:49 -0700179}
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
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700217rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
218 const std::string& mid) const {
219 auto jsep_transport = GetJsepTransportForMid(mid);
220 if (!jsep_transport) {
221 return nullptr;
222 }
223 return jsep_transport->SctpTransport();
224}
225
Zhi Huange818b6e2018-02-22 15:26:27 -0800226void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
227 if (!network_thread_->IsCurrent()) {
228 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] { SetIceConfig(config); });
229 return;
230 }
231
232 ice_config_ = config;
233 for (auto& dtls : GetDtlsTransports()) {
234 dtls->ice_transport()->SetIceConfig(ice_config_);
235 }
236}
237
238void JsepTransportController::SetNeedsIceRestartFlag() {
Zhi Huange830e682018-03-30 10:48:35 -0700239 for (auto& kv : jsep_transports_by_name_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800240 kv.second->SetNeedsIceRestartFlag();
241 }
242}
243
244bool JsepTransportController::NeedsIceRestart(
245 const std::string& transport_name) const {
Zhi Huang365381f2018-04-13 16:44:34 -0700246 const cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700247 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800248 if (!transport) {
249 return false;
250 }
251 return transport->needs_ice_restart();
252}
253
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200254absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
Zhi Huange830e682018-03-30 10:48:35 -0700255 const std::string& mid) const {
Zhi Huange818b6e2018-02-22 15:26:27 -0800256 if (!network_thread_->IsCurrent()) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200257 return network_thread_->Invoke<absl::optional<rtc::SSLRole>>(
Zhi Huange830e682018-03-30 10:48:35 -0700258 RTC_FROM_HERE, [&] { return GetDtlsRole(mid); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800259 }
260
Zhi Huang365381f2018-04-13 16:44:34 -0700261 const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -0800262 if (!t) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200263 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 15:26:27 -0800264 }
265 return t->GetDtlsRole();
266}
267
268bool JsepTransportController::SetLocalCertificate(
269 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
270 if (!network_thread_->IsCurrent()) {
271 return network_thread_->Invoke<bool>(
272 RTC_FROM_HERE, [&] { return SetLocalCertificate(certificate); });
273 }
274
275 // Can't change a certificate, or set a null certificate.
276 if (certificate_ || !certificate) {
277 return false;
278 }
279 certificate_ = certificate;
280
281 // Set certificate for JsepTransport, which verifies it matches the
282 // fingerprint in SDP, and DTLS transport.
283 // Fallback from DTLS to SDES is not supported.
Zhi Huange830e682018-03-30 10:48:35 -0700284 for (auto& kv : jsep_transports_by_name_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800285 kv.second->SetLocalCertificate(certificate_);
286 }
287 for (auto& dtls : GetDtlsTransports()) {
288 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
289 RTC_DCHECK(set_cert_success);
290 }
291 return true;
292}
293
294rtc::scoped_refptr<rtc::RTCCertificate>
295JsepTransportController::GetLocalCertificate(
296 const std::string& transport_name) const {
297 if (!network_thread_->IsCurrent()) {
298 return network_thread_->Invoke<rtc::scoped_refptr<rtc::RTCCertificate>>(
299 RTC_FROM_HERE, [&] { return GetLocalCertificate(transport_name); });
300 }
301
Zhi Huang365381f2018-04-13 16:44:34 -0700302 const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800303 if (!t) {
304 return nullptr;
305 }
306 return t->GetLocalCertificate();
307}
308
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800309std::unique_ptr<rtc::SSLCertChain>
310JsepTransportController::GetRemoteSSLCertChain(
Zhi Huange818b6e2018-02-22 15:26:27 -0800311 const std::string& transport_name) const {
312 if (!network_thread_->IsCurrent()) {
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800313 return network_thread_->Invoke<std::unique_ptr<rtc::SSLCertChain>>(
314 RTC_FROM_HERE, [&] { return GetRemoteSSLCertChain(transport_name); });
Zhi Huange818b6e2018-02-22 15:26:27 -0800315 }
316
Zhi Huange830e682018-03-30 10:48:35 -0700317 // Get the certificate from the RTP transport's DTLS handshake. Should be
318 // identical to the RTCP transport's, since they were given the same remote
Zhi Huange818b6e2018-02-22 15:26:27 -0800319 // fingerprint.
Zhi Huange830e682018-03-30 10:48:35 -0700320 auto jsep_transport = GetJsepTransportByName(transport_name);
321 if (!jsep_transport) {
322 return nullptr;
323 }
324 auto dtls = jsep_transport->rtp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800325 if (!dtls) {
326 return nullptr;
327 }
328
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800329 return dtls->GetRemoteSSLCertChain();
Zhi Huange818b6e2018-02-22 15:26:27 -0800330}
331
332void JsepTransportController::MaybeStartGathering() {
333 if (!network_thread_->IsCurrent()) {
334 network_thread_->Invoke<void>(RTC_FROM_HERE,
335 [&] { MaybeStartGathering(); });
336 return;
337 }
338
339 for (auto& dtls : GetDtlsTransports()) {
340 dtls->ice_transport()->MaybeStartGathering();
341 }
342}
343
344RTCError JsepTransportController::AddRemoteCandidates(
345 const std::string& transport_name,
346 const cricket::Candidates& candidates) {
347 if (!network_thread_->IsCurrent()) {
348 return network_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
349 return AddRemoteCandidates(transport_name, candidates);
350 });
351 }
352
353 // Verify each candidate before passing down to the transport layer.
354 RTCError error = VerifyCandidates(candidates);
355 if (!error.ok()) {
356 return error;
357 }
Zhi Huange830e682018-03-30 10:48:35 -0700358 auto jsep_transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800359 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700360 RTC_LOG(LS_WARNING) << "Not adding candidate because the JsepTransport "
361 "doesn't exist. Ignore it.";
362 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -0800363 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800364 return jsep_transport->AddRemoteCandidates(candidates);
365}
366
367RTCError JsepTransportController::RemoveRemoteCandidates(
368 const cricket::Candidates& candidates) {
369 if (!network_thread_->IsCurrent()) {
370 return network_thread_->Invoke<RTCError>(
371 RTC_FROM_HERE, [&] { return RemoveRemoteCandidates(candidates); });
372 }
373
374 // Verify each candidate before passing down to the transport layer.
375 RTCError error = VerifyCandidates(candidates);
376 if (!error.ok()) {
377 return error;
378 }
379
380 std::map<std::string, cricket::Candidates> candidates_by_transport_name;
381 for (const cricket::Candidate& cand : candidates) {
382 if (!cand.transport_name().empty()) {
383 candidates_by_transport_name[cand.transport_name()].push_back(cand);
384 } else {
385 RTC_LOG(LS_ERROR) << "Not removing candidate because it does not have a "
386 "transport name set: "
Qingsi Wang20232a92019-09-06 12:51:17 -0700387 << cand.ToSensitiveString();
Zhi Huange818b6e2018-02-22 15:26:27 -0800388 }
389 }
390
391 for (const auto& kv : candidates_by_transport_name) {
392 const std::string& transport_name = kv.first;
393 const cricket::Candidates& candidates = kv.second;
Zhi Huang365381f2018-04-13 16:44:34 -0700394 cricket::JsepTransport* jsep_transport =
Zhi Huange830e682018-03-30 10:48:35 -0700395 GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800396 if (!jsep_transport) {
Zhi Huange830e682018-03-30 10:48:35 -0700397 RTC_LOG(LS_WARNING)
398 << "Not removing candidate because the JsepTransport doesn't exist.";
399 continue;
Zhi Huange818b6e2018-02-22 15:26:27 -0800400 }
401 for (const cricket::Candidate& candidate : candidates) {
Harald Alvestrandad88c882018-11-28 16:47:46 +0100402 cricket::DtlsTransportInternal* dtls =
403 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
404 ? jsep_transport->rtp_dtls_transport()
405 : jsep_transport->rtcp_dtls_transport();
Zhi Huange818b6e2018-02-22 15:26:27 -0800406 if (dtls) {
407 dtls->ice_transport()->RemoveRemoteCandidate(candidate);
408 }
409 }
410 }
411 return RTCError::OK();
412}
413
414bool JsepTransportController::GetStats(const std::string& transport_name,
415 cricket::TransportStats* stats) {
416 if (!network_thread_->IsCurrent()) {
417 return network_thread_->Invoke<bool>(
418 RTC_FROM_HERE, [=] { return GetStats(transport_name, stats); });
419 }
420
Zhi Huang365381f2018-04-13 16:44:34 -0700421 cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800422 if (!transport) {
423 return false;
424 }
425 return transport->GetStats(stats);
426}
427
Zhi Huangb57e1692018-06-12 11:41:11 -0700428void JsepTransportController::SetActiveResetSrtpParams(
429 bool active_reset_srtp_params) {
430 if (!network_thread_->IsCurrent()) {
431 network_thread_->Invoke<void>(RTC_FROM_HERE, [=] {
432 SetActiveResetSrtpParams(active_reset_srtp_params);
433 });
434 return;
435 }
436
437 RTC_LOG(INFO)
438 << "Updating the active_reset_srtp_params for JsepTransportController: "
439 << active_reset_srtp_params;
440 config_.active_reset_srtp_params = active_reset_srtp_params;
441 for (auto& kv : jsep_transports_by_name_) {
442 kv.second->SetActiveResetSrtpParams(active_reset_srtp_params);
443 }
444}
445
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800446void JsepTransportController::SetMediaTransportSettings(
447 bool use_media_transport_for_media,
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700448 bool use_media_transport_for_data_channels,
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700449 bool use_datagram_transport,
450 bool use_datagram_transport_for_data_channels) {
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800451 RTC_DCHECK(use_media_transport_for_media ==
452 config_.use_media_transport_for_media ||
Piotr (Peter) Slatala97fc11f2018-10-18 12:57:59 -0700453 jsep_transports_by_name_.empty())
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -0800454 << "You can only change media transport configuration before creating "
455 "the first transport.";
456
457 RTC_DCHECK(use_media_transport_for_data_channels ==
458 config_.use_media_transport_for_data_channels ||
459 jsep_transports_by_name_.empty())
460 << "You can only change media transport configuration before creating "
461 "the first transport.";
462
463 config_.use_media_transport_for_media = use_media_transport_for_media;
464 config_.use_media_transport_for_data_channels =
465 use_media_transport_for_data_channels;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700466 config_.use_datagram_transport = use_datagram_transport;
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700467 config_.use_datagram_transport_for_data_channels =
468 use_datagram_transport_for_data_channels;
Piotr (Peter) Slatala97fc11f2018-10-18 12:57:59 -0700469}
470
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800471std::unique_ptr<cricket::IceTransportInternal>
472JsepTransportController::CreateIceTransport(const std::string transport_name,
473 bool rtcp) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800474 int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
475 : cricket::ICE_CANDIDATE_COMPONENT_RTP;
476
Zhi Huange818b6e2018-02-22 15:26:27 -0800477 if (config_.external_transport_factory) {
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800478 return config_.external_transport_factory->CreateIceTransport(
Zhi Huange818b6e2018-02-22 15:26:27 -0800479 transport_name, component);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800480 } else {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200481 return std::make_unique<cricket::P2PTransportChannel>(
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800482 transport_name, component, port_allocator_, async_resolver_factory_,
483 config_.event_log);
484 }
485}
486
487std::unique_ptr<cricket::DtlsTransportInternal>
488JsepTransportController::CreateDtlsTransport(
Anton Sukhanovac6c0962019-07-10 15:44:56 -0700489 const cricket::ContentInfo& content_info,
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700490 cricket::IceTransportInternal* ice,
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700491 DatagramTransportInterface* datagram_transport) {
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800492 RTC_DCHECK(network_thread_->IsCurrent());
493
494 std::unique_ptr<cricket::DtlsTransportInternal> dtls;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700495
496 if (datagram_transport) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700497 RTC_DCHECK(config_.use_datagram_transport ||
498 config_.use_datagram_transport_for_data_channels);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700499 } else if (config_.media_transport_factory &&
500 config_.use_media_transport_for_media &&
501 config_.use_media_transport_for_data_channels) {
502 // If media transport is used for both media and data channels,
503 // then we don't need to create DTLS.
504 // Otherwise, DTLS is still created.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200505 dtls = std::make_unique<cricket::NoOpDtlsTransport>(ice,
506 config_.crypto_options);
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -0800507 } else if (config_.external_transport_factory) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800508 dtls = config_.external_transport_factory->CreateDtlsTransport(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700509 ice, config_.crypto_options);
Zhi Huange818b6e2018-02-22 15:26:27 -0800510 } else {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200511 dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
512 config_.event_log);
Zhi Huange818b6e2018-02-22 15:26:27 -0800513 }
514
515 RTC_DCHECK(dtls);
516 dtls->SetSslMaxProtocolVersion(config_.ssl_max_version);
Zhi Huange818b6e2018-02-22 15:26:27 -0800517 dtls->ice_transport()->SetIceRole(ice_role_);
518 dtls->ice_transport()->SetIceTiebreaker(ice_tiebreaker_);
519 dtls->ice_transport()->SetIceConfig(ice_config_);
520 if (certificate_) {
521 bool set_cert_success = dtls->SetLocalCertificate(certificate_);
522 RTC_DCHECK(set_cert_success);
523 }
524
525 // Connect to signals offered by the DTLS and ICE transport.
526 dtls->SignalWritableState.connect(
527 this, &JsepTransportController::OnTransportWritableState_n);
528 dtls->SignalReceivingState.connect(
529 this, &JsepTransportController::OnTransportReceivingState_n);
530 dtls->SignalDtlsHandshakeError.connect(
531 this, &JsepTransportController::OnDtlsHandshakeError);
532 dtls->ice_transport()->SignalGatheringState.connect(
533 this, &JsepTransportController::OnTransportGatheringState_n);
534 dtls->ice_transport()->SignalCandidateGathered.connect(
535 this, &JsepTransportController::OnTransportCandidateGathered_n);
Eldar Relloda13ea22019-06-01 12:23:43 +0300536 dtls->ice_transport()->SignalCandidateError.connect(
537 this, &JsepTransportController::OnTransportCandidateError_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800538 dtls->ice_transport()->SignalCandidatesRemoved.connect(
539 this, &JsepTransportController::OnTransportCandidatesRemoved_n);
540 dtls->ice_transport()->SignalRoleConflict.connect(
541 this, &JsepTransportController::OnTransportRoleConflict_n);
542 dtls->ice_transport()->SignalStateChanged.connect(
543 this, &JsepTransportController::OnTransportStateChanged_n);
Jonas Olsson7a6739e2019-01-15 16:31:55 +0100544 dtls->ice_transport()->SignalIceTransportStateChanged.connect(
545 this, &JsepTransportController::OnTransportStateChanged_n);
Alex Drake00c7ecf2019-08-06 10:54:47 -0700546 dtls->ice_transport()->SignalCandidatePairChanged.connect(
547 this, &JsepTransportController::OnTransportCandidatePairChanged_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800548 return dtls;
549}
550
551std::unique_ptr<webrtc::RtpTransport>
552JsepTransportController::CreateUnencryptedRtpTransport(
553 const std::string& transport_name,
554 rtc::PacketTransportInternal* rtp_packet_transport,
555 rtc::PacketTransportInternal* rtcp_packet_transport) {
556 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange830e682018-03-30 10:48:35 -0700557 auto unencrypted_rtp_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200558 std::make_unique<RtpTransport>(rtcp_packet_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700559 unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
560 if (rtcp_packet_transport) {
561 unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
562 }
563 return unencrypted_rtp_transport;
Zhi Huange818b6e2018-02-22 15:26:27 -0800564}
565
566std::unique_ptr<webrtc::SrtpTransport>
567JsepTransportController::CreateSdesTransport(
568 const std::string& transport_name,
Zhi Huange830e682018-03-30 10:48:35 -0700569 cricket::DtlsTransportInternal* rtp_dtls_transport,
570 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800571 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange818b6e2018-02-22 15:26:27 -0800572 auto srtp_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200573 std::make_unique<webrtc::SrtpTransport>(rtcp_dtls_transport == nullptr);
Zhi Huange830e682018-03-30 10:48:35 -0700574 RTC_DCHECK(rtp_dtls_transport);
575 srtp_transport->SetRtpPacketTransport(rtp_dtls_transport);
576 if (rtcp_dtls_transport) {
577 srtp_transport->SetRtcpPacketTransport(rtcp_dtls_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800578 }
579 if (config_.enable_external_auth) {
580 srtp_transport->EnableExternalAuth();
581 }
582 return srtp_transport;
583}
584
585std::unique_ptr<webrtc::DtlsSrtpTransport>
586JsepTransportController::CreateDtlsSrtpTransport(
587 const std::string& transport_name,
588 cricket::DtlsTransportInternal* rtp_dtls_transport,
589 cricket::DtlsTransportInternal* rtcp_dtls_transport) {
590 RTC_DCHECK(network_thread_->IsCurrent());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200591 auto dtls_srtp_transport = std::make_unique<webrtc::DtlsSrtpTransport>(
Zhi Huang365381f2018-04-13 16:44:34 -0700592 rtcp_dtls_transport == nullptr);
Zhi Huang27f3bf52018-03-26 21:37:23 -0700593 if (config_.enable_external_auth) {
Zhi Huang365381f2018-04-13 16:44:34 -0700594 dtls_srtp_transport->EnableExternalAuth();
Zhi Huang27f3bf52018-03-26 21:37:23 -0700595 }
Zhi Huang97d5e5b2018-03-27 00:09:01 +0000596
Zhi Huange818b6e2018-02-22 15:26:27 -0800597 dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
598 rtcp_dtls_transport);
Zhi Huangb57e1692018-06-12 11:41:11 -0700599 dtls_srtp_transport->SetActiveResetSrtpParams(
600 config_.active_reset_srtp_params);
Jonas Olsson635474e2018-10-18 15:58:17 +0200601 dtls_srtp_transport->SignalDtlsStateChange.connect(
602 this, &JsepTransportController::UpdateAggregateStates_n);
Zhi Huange818b6e2018-02-22 15:26:27 -0800603 return dtls_srtp_transport;
604}
605
606std::vector<cricket::DtlsTransportInternal*>
607JsepTransportController::GetDtlsTransports() {
608 std::vector<cricket::DtlsTransportInternal*> dtls_transports;
Zhi Huange830e682018-03-30 10:48:35 -0700609 for (auto it = jsep_transports_by_name_.begin();
610 it != jsep_transports_by_name_.end(); ++it) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800611 auto jsep_transport = it->second.get();
612 RTC_DCHECK(jsep_transport);
613 if (jsep_transport->rtp_dtls_transport()) {
614 dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
615 }
616
617 if (jsep_transport->rtcp_dtls_transport()) {
618 dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
619 }
620 }
621 return dtls_transports;
622}
623
Zhi Huange818b6e2018-02-22 15:26:27 -0800624RTCError JsepTransportController::ApplyDescription_n(
625 bool local,
626 SdpType type,
627 const cricket::SessionDescription* description) {
628 RTC_DCHECK(network_thread_->IsCurrent());
629 RTC_DCHECK(description);
630
631 if (local) {
632 local_desc_ = description;
633 } else {
634 remote_desc_ = description;
635 }
636
Zhi Huange830e682018-03-30 10:48:35 -0700637 RTCError error;
Zhi Huangd2248f82018-04-10 14:41:03 -0700638 error = ValidateAndMaybeUpdateBundleGroup(local, type, description);
Zhi Huange830e682018-03-30 10:48:35 -0700639 if (!error.ok()) {
640 return error;
Zhi Huange818b6e2018-02-22 15:26:27 -0800641 }
642
643 std::vector<int> merged_encrypted_extension_ids;
644 if (bundle_group_) {
645 merged_encrypted_extension_ids =
646 MergeEncryptedHeaderExtensionIdsForBundle(description);
647 }
648
649 for (const cricket::ContentInfo& content_info : description->contents()) {
650 // Don't create transports for rejected m-lines and bundled m-lines."
651 if (content_info.rejected ||
652 (IsBundled(content_info.name) && content_info.name != *bundled_mid())) {
653 continue;
654 }
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -0800655 error = MaybeCreateJsepTransport(local, content_info, *description);
Zhi Huange830e682018-03-30 10:48:35 -0700656 if (!error.ok()) {
657 return error;
658 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800659 }
660
661 RTC_DCHECK(description->contents().size() ==
662 description->transport_infos().size());
663 for (size_t i = 0; i < description->contents().size(); ++i) {
664 const cricket::ContentInfo& content_info = description->contents()[i];
665 const cricket::TransportInfo& transport_info =
666 description->transport_infos()[i];
667 if (content_info.rejected) {
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700668 HandleRejectedContent(content_info, description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800669 continue;
670 }
671
672 if (IsBundled(content_info.name) && content_info.name != *bundled_mid()) {
Zhi Huang365381f2018-04-13 16:44:34 -0700673 if (!HandleBundledContent(content_info)) {
674 return RTCError(RTCErrorType::INVALID_PARAMETER,
675 "Failed to process the bundled m= section.");
676 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800677 continue;
678 }
679
Zhi Huange830e682018-03-30 10:48:35 -0700680 error = ValidateContent(content_info);
681 if (!error.ok()) {
682 return error;
683 }
684
Zhi Huange818b6e2018-02-22 15:26:27 -0800685 std::vector<int> extension_ids;
Taylor Brandstetter0ab56512018-04-12 10:30:48 -0700686 if (bundled_mid() && content_info.name == *bundled_mid()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800687 extension_ids = merged_encrypted_extension_ids;
688 } else {
689 extension_ids = GetEncryptedHeaderExtensionIds(content_info);
690 }
691
Zhi Huange830e682018-03-30 10:48:35 -0700692 int rtp_abs_sendtime_extn_id =
693 GetRtpAbsSendTimeHeaderExtensionId(content_info);
694
Zhi Huang365381f2018-04-13 16:44:34 -0700695 cricket::JsepTransport* transport =
Zhi Huange830e682018-03-30 10:48:35 -0700696 GetJsepTransportForMid(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800697 RTC_DCHECK(transport);
698
699 SetIceRole_n(DetermineIceRole(transport, transport_info, type, local));
700
Zhi Huange818b6e2018-02-22 15:26:27 -0800701 cricket::JsepTransportDescription jsep_description =
702 CreateJsepTransportDescription(content_info, transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700703 extension_ids, rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800704 if (local) {
705 error =
706 transport->SetLocalJsepTransportDescription(jsep_description, type);
707 } else {
708 error =
709 transport->SetRemoteJsepTransportDescription(jsep_description, type);
710 }
711
712 if (!error.ok()) {
713 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
714 "Failed to apply the description for " +
715 content_info.name + ": " + error.message());
716 }
717 }
718 return RTCError::OK();
719}
720
Zhi Huangd2248f82018-04-10 14:41:03 -0700721RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup(
722 bool local,
723 SdpType type,
Zhi Huange830e682018-03-30 10:48:35 -0700724 const cricket::SessionDescription* description) {
725 RTC_DCHECK(description);
Zhi Huangd2248f82018-04-10 14:41:03 -0700726 const cricket::ContentGroup* new_bundle_group =
727 description->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
728
729 // The BUNDLE group containing a MID that no m= section has is invalid.
730 if (new_bundle_group) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100731 for (const auto& content_name : new_bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700732 if (!description->GetContentByName(content_name)) {
733 return RTCError(RTCErrorType::INVALID_PARAMETER,
734 "The BUNDLE group contains MID:" + content_name +
735 " matching no m= section.");
736 }
737 }
738 }
739
740 if (type == SdpType::kAnswer) {
741 const cricket::ContentGroup* offered_bundle_group =
742 local ? remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE)
743 : local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
744
745 if (new_bundle_group) {
746 // The BUNDLE group in answer should be a subset of offered group.
Mirko Bonadei739baf02019-01-27 17:29:42 +0100747 for (const auto& content_name : new_bundle_group->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700748 if (!offered_bundle_group ||
749 !offered_bundle_group->HasContentName(content_name)) {
750 return RTCError(RTCErrorType::INVALID_PARAMETER,
751 "The BUNDLE group in answer contains a MID that was "
752 "not in the offered group.");
753 }
754 }
755 }
756
757 if (bundle_group_) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100758 for (const auto& content_name : bundle_group_->content_names()) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700759 // An answer that removes m= sections from pre-negotiated BUNDLE group
760 // without rejecting it, is invalid.
761 if (!new_bundle_group ||
762 !new_bundle_group->HasContentName(content_name)) {
763 auto* content_info = description->GetContentByName(content_name);
764 if (!content_info || !content_info->rejected) {
765 return RTCError(RTCErrorType::INVALID_PARAMETER,
766 "Answer cannot remove m= section " + content_name +
767 " from already-established BUNDLE group.");
768 }
769 }
770 }
771 }
772 }
773
774 if (config_.bundle_policy ==
775 PeerConnectionInterface::kBundlePolicyMaxBundle &&
776 !description->HasGroup(cricket::GROUP_TYPE_BUNDLE)) {
777 return RTCError(RTCErrorType::INVALID_PARAMETER,
778 "max-bundle is used but no bundle group found.");
779 }
780
781 if (ShouldUpdateBundleGroup(type, description)) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700782 bundle_group_ = *new_bundle_group;
783 }
Zhi Huange830e682018-03-30 10:48:35 -0700784
785 if (!bundled_mid()) {
786 return RTCError::OK();
787 }
788
789 auto bundled_content = description->GetContentByName(*bundled_mid());
790 if (!bundled_content) {
791 return RTCError(
792 RTCErrorType::INVALID_PARAMETER,
793 "An m= section associated with the BUNDLE-tag doesn't exist.");
794 }
795
796 // If the |bundled_content| is rejected, other contents in the bundle group
797 // should be rejected.
798 if (bundled_content->rejected) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100799 for (const auto& content_name : bundle_group_->content_names()) {
Zhi Huange830e682018-03-30 10:48:35 -0700800 auto other_content = description->GetContentByName(content_name);
801 if (!other_content->rejected) {
802 return RTCError(
803 RTCErrorType::INVALID_PARAMETER,
804 "The m= section:" + content_name + " should be rejected.");
805 }
806 }
807 }
808
809 return RTCError::OK();
810}
811
812RTCError JsepTransportController::ValidateContent(
813 const cricket::ContentInfo& content_info) {
814 if (config_.rtcp_mux_policy ==
815 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
816 content_info.type == cricket::MediaProtocolType::kRtp &&
817 !content_info.media_description()->rtcp_mux()) {
818 return RTCError(RTCErrorType::INVALID_PARAMETER,
819 "The m= section:" + content_info.name +
820 " is invalid. RTCP-MUX is not "
821 "enabled when it is required.");
822 }
823 return RTCError::OK();
824}
825
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700826void JsepTransportController::HandleRejectedContent(
Zhi Huangd2248f82018-04-10 14:41:03 -0700827 const cricket::ContentInfo& content_info,
828 const cricket::SessionDescription* description) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800829 // If the content is rejected, let the
830 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700831 // then destroy the cricket::JsepTransport.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700832 RemoveTransportForMid(content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700833 if (content_info.name == bundled_mid()) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100834 for (const auto& content_name : bundle_group_->content_names()) {
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700835 RemoveTransportForMid(content_name);
Zhi Huange830e682018-03-30 10:48:35 -0700836 }
837 bundle_group_.reset();
838 } else if (IsBundled(content_info.name)) {
839 // Remove the rejected content from the |bundle_group_|.
Zhi Huange818b6e2018-02-22 15:26:27 -0800840 bundle_group_->RemoveContentName(content_info.name);
Zhi Huange830e682018-03-30 10:48:35 -0700841 // Reset the bundle group if nothing left.
842 if (!bundle_group_->FirstContentName()) {
843 bundle_group_.reset();
844 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800845 }
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700846 MaybeDestroyJsepTransport(content_info.name);
Zhi Huange818b6e2018-02-22 15:26:27 -0800847}
848
Zhi Huang365381f2018-04-13 16:44:34 -0700849bool JsepTransportController::HandleBundledContent(
Zhi Huange818b6e2018-02-22 15:26:27 -0800850 const cricket::ContentInfo& content_info) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700851 auto jsep_transport = GetJsepTransportByName(*bundled_mid());
852 RTC_DCHECK(jsep_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800853 // If the content is bundled, let the
854 // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
Zhi Huang365381f2018-04-13 16:44:34 -0700855 // then destroy the cricket::JsepTransport.
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700856 if (SetTransportForMid(content_info.name, jsep_transport)) {
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -0800857 // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
858 // because it means that we first create media transport and start
859 // connecting it, and then we destroy it. We will need to address it before
860 // video path is enabled.
Zhi Huang365381f2018-04-13 16:44:34 -0700861 MaybeDestroyJsepTransport(content_info.name);
862 return true;
863 }
864 return false;
Zhi Huange818b6e2018-02-22 15:26:27 -0800865}
866
Zhi Huang365381f2018-04-13 16:44:34 -0700867bool JsepTransportController::SetTransportForMid(
Zhi Huangd2248f82018-04-10 14:41:03 -0700868 const std::string& mid,
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700869 cricket::JsepTransport* jsep_transport) {
Zhi Huang365381f2018-04-13 16:44:34 -0700870 RTC_DCHECK(jsep_transport);
Zhi Huangd2248f82018-04-10 14:41:03 -0700871 if (mid_to_transport_[mid] == jsep_transport) {
Zhi Huang365381f2018-04-13 16:44:34 -0700872 return true;
Zhi Huangd2248f82018-04-10 14:41:03 -0700873 }
874
875 mid_to_transport_[mid] = jsep_transport;
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700876 return config_.transport_observer->OnTransportChanged(
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100877 mid, jsep_transport->rtp_transport(), jsep_transport->RtpDtlsTransport(),
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700878 jsep_transport->media_transport(),
879 jsep_transport->data_channel_transport());
Zhi Huangd2248f82018-04-10 14:41:03 -0700880}
881
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700882void JsepTransportController::RemoveTransportForMid(const std::string& mid) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -0700883 bool ret = config_.transport_observer->OnTransportChanged(
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -0700884 mid, nullptr, nullptr, nullptr, nullptr);
Taylor Brandstettercbaa2542018-04-16 16:42:14 -0700885 // Calling OnTransportChanged with nullptr should always succeed, since it is
886 // only expected to fail when adding media to a transport (not removing).
887 RTC_DCHECK(ret);
Zhi Huangd2248f82018-04-10 14:41:03 -0700888 mid_to_transport_.erase(mid);
889}
890
Zhi Huange818b6e2018-02-22 15:26:27 -0800891cricket::JsepTransportDescription
892JsepTransportController::CreateJsepTransportDescription(
Harald Alvestrand1716d392019-06-03 20:35:45 +0200893 const cricket::ContentInfo& content_info,
894 const cricket::TransportInfo& transport_info,
Zhi Huange830e682018-03-30 10:48:35 -0700895 const std::vector<int>& encrypted_extension_ids,
896 int rtp_abs_sendtime_extn_id) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800897 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200898 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800899 RTC_DCHECK(content_desc);
900 bool rtcp_mux_enabled = content_info.type == cricket::MediaProtocolType::kSctp
901 ? true
902 : content_desc->rtcp_mux();
903
904 return cricket::JsepTransportDescription(
905 rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
Zhi Huange830e682018-03-30 10:48:35 -0700906 rtp_abs_sendtime_extn_id, transport_info.description);
Zhi Huange818b6e2018-02-22 15:26:27 -0800907}
908
909bool JsepTransportController::ShouldUpdateBundleGroup(
910 SdpType type,
911 const cricket::SessionDescription* description) {
912 if (config_.bundle_policy ==
913 PeerConnectionInterface::kBundlePolicyMaxBundle) {
914 return true;
915 }
916
917 if (type != SdpType::kAnswer) {
918 return false;
919 }
920
921 RTC_DCHECK(local_desc_ && remote_desc_);
922 const cricket::ContentGroup* local_bundle =
923 local_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
924 const cricket::ContentGroup* remote_bundle =
925 remote_desc_->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
926 return local_bundle && remote_bundle;
927}
928
929std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
930 const cricket::ContentInfo& content_info) {
931 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200932 content_info.media_description();
Zhi Huange818b6e2018-02-22 15:26:27 -0800933
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700934 if (!config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800935 return std::vector<int>();
936 }
937
938 std::vector<int> encrypted_header_extension_ids;
Mirko Bonadei739baf02019-01-27 17:29:42 +0100939 for (const auto& extension : content_desc->rtp_header_extensions()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800940 if (!extension.encrypt) {
941 continue;
942 }
Steve Anton64b626b2019-01-28 17:25:26 -0800943 if (!absl::c_linear_search(encrypted_header_extension_ids, extension.id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800944 encrypted_header_extension_ids.push_back(extension.id);
945 }
946 }
947 return encrypted_header_extension_ids;
948}
949
950std::vector<int>
951JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundle(
952 const cricket::SessionDescription* description) {
953 RTC_DCHECK(description);
954 RTC_DCHECK(bundle_group_);
955
956 std::vector<int> merged_ids;
957 // Union the encrypted header IDs in the group when bundle is enabled.
958 for (const cricket::ContentInfo& content_info : description->contents()) {
959 if (bundle_group_->HasContentName(content_info.name)) {
960 std::vector<int> extension_ids =
961 GetEncryptedHeaderExtensionIds(content_info);
962 for (int id : extension_ids) {
Steve Anton64b626b2019-01-28 17:25:26 -0800963 if (!absl::c_linear_search(merged_ids, id)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800964 merged_ids.push_back(id);
965 }
966 }
967 }
968 }
969 return merged_ids;
970}
971
Zhi Huange830e682018-03-30 10:48:35 -0700972int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
Zhi Huange818b6e2018-02-22 15:26:27 -0800973 const cricket::ContentInfo& content_info) {
Zhi Huange830e682018-03-30 10:48:35 -0700974 if (!config_.enable_external_auth) {
975 return -1;
Zhi Huange818b6e2018-02-22 15:26:27 -0800976 }
977
978 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +0200979 content_info.media_description();
Zhi Huange830e682018-03-30 10:48:35 -0700980
981 const webrtc::RtpExtension* send_time_extension =
982 webrtc::RtpExtension::FindHeaderExtensionByUri(
983 content_desc->rtp_header_extensions(),
984 webrtc::RtpExtension::kAbsSendTimeUri);
985 return send_time_extension ? send_time_extension->id : -1;
986}
987
Zhi Huang365381f2018-04-13 16:44:34 -0700988const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -0700989 const std::string& mid) const {
Zhi Huangd2248f82018-04-10 14:41:03 -0700990 auto it = mid_to_transport_.find(mid);
991 return it == mid_to_transport_.end() ? nullptr : it->second;
Zhi Huange830e682018-03-30 10:48:35 -0700992}
993
Zhi Huang365381f2018-04-13 16:44:34 -0700994cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
Zhi Huange830e682018-03-30 10:48:35 -0700995 const std::string& mid) {
Zhi Huangd2248f82018-04-10 14:41:03 -0700996 auto it = mid_to_transport_.find(mid);
997 return it == mid_to_transport_.end() ? nullptr : it->second;
Zhi Huange830e682018-03-30 10:48:35 -0700998}
999
Zhi Huang365381f2018-04-13 16:44:34 -07001000const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -07001001 const std::string& transport_name) const {
1002 auto it = jsep_transports_by_name_.find(transport_name);
1003 return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
1004}
1005
Zhi Huang365381f2018-04-13 16:44:34 -07001006cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
Zhi Huange830e682018-03-30 10:48:35 -07001007 const std::string& transport_name) {
1008 auto it = jsep_transports_by_name_.find(transport_name);
1009 return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
1010}
1011
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001012std::unique_ptr<webrtc::MediaTransportInterface>
1013JsepTransportController::MaybeCreateMediaTransport(
1014 const cricket::ContentInfo& content_info,
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001015 const cricket::SessionDescription& description,
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001016 bool local) {
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001017 if (config_.media_transport_factory == nullptr) {
1018 return nullptr;
1019 }
1020
Piotr (Peter) Slatala55b91b92019-01-25 13:31:15 -08001021 if (!config_.use_media_transport_for_media &&
1022 !config_.use_media_transport_for_data_channels) {
1023 return nullptr;
1024 }
1025
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001026 // Caller (offerer) media transport.
1027 if (local) {
1028 if (offer_media_transport_) {
1029 RTC_LOG(LS_INFO) << "Offered media transport has now been activated.";
1030 return std::move(offer_media_transport_);
1031 } else {
1032 RTC_LOG(LS_INFO)
1033 << "Not returning media transport. Either SDES wasn't enabled, or "
1034 "media transport didn't return an offer earlier.";
1035 // Offer wasn't generated. Either because media transport didn't want it,
1036 // or because SDES wasn't enabled.
1037 return nullptr;
1038 }
Piotr (Peter) Slatala9f956252018-10-31 08:25:26 -07001039 }
1040
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001041 // Remote offer. If no x-mt lines, do not create media transport.
1042 if (description.MediaTransportSettings().empty()) {
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001043 return nullptr;
Anton Sukhanov7940da02018-10-10 10:34:49 -07001044 }
1045
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001046 // When bundle is enabled, two JsepTransports are created, and then
1047 // the second transport is destroyed (right away).
1048 // For media transport, we don't want to create the second
1049 // media transport in the first place.
1050 RTC_LOG(LS_INFO) << "Returning new, client media transport.";
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001051
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001052 RTC_DCHECK(!local)
1053 << "If media transport is used, you must call "
1054 "GenerateOrGetLastMediaTransportOffer before SetLocalDescription. You "
1055 "also "
1056 "must use kRtcpMuxPolicyRequire and kBundlePolicyMaxBundle with media "
1057 "transport.";
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001058 MediaTransportSettings settings;
1059 settings.is_caller = local;
Piotr (Peter) Slatala01fe3092019-02-15 12:05:50 -08001060 if (config_.use_media_transport_for_media) {
1061 settings.event_log = config_.event_log;
1062 }
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001063
1064 // Assume there is only one media transport (or if more, use the first one).
1065 if (!local && !description.MediaTransportSettings().empty() &&
1066 config_.media_transport_factory->GetTransportName() ==
1067 description.MediaTransportSettings()[0].transport_name) {
1068 settings.remote_transport_parameters =
1069 description.MediaTransportSettings()[0].transport_setting;
1070 }
1071
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001072 auto media_transport_result =
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001073 config_.media_transport_factory->CreateMediaTransport(network_thread_,
1074 settings);
Piotr (Peter) Slatala63a176b2019-01-25 08:25:33 -08001075
1076 // TODO(sukhanov): Proper error handling.
1077 RTC_CHECK(media_transport_result.ok());
1078
1079 return media_transport_result.MoveValue();
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001080}
1081
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001082// TODO(sukhanov): Refactor to avoid code duplication for Media and Datagram
1083// transports setup.
1084std::unique_ptr<webrtc::DatagramTransportInterface>
1085JsepTransportController::MaybeCreateDatagramTransport(
1086 const cricket::ContentInfo& content_info,
1087 const cricket::SessionDescription& description,
1088 bool local) {
1089 if (config_.media_transport_factory == nullptr) {
1090 return nullptr;
1091 }
1092
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001093 if (!(config_.use_datagram_transport ||
1094 config_.use_datagram_transport_for_data_channels)) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001095 return nullptr;
1096 }
1097
1098 // Caller (offerer) datagram transport.
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001099 if (offer_datagram_transport_) {
1100 RTC_DCHECK(local);
1101 RTC_LOG(LS_INFO) << "Offered datagram transport has now been activated.";
1102 return std::move(offer_datagram_transport_);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001103 }
1104
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001105 const cricket::TransportDescription* transport_description =
1106 description.GetTransportDescriptionByName(content_info.mid());
1107 RTC_DCHECK(transport_description)
1108 << "Missing transport description for mid=" << content_info.mid();
1109
1110 if (!transport_description->opaque_parameters) {
1111 RTC_LOG(LS_INFO)
1112 << "No opaque transport parameters, not creating datagram transport";
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001113 return nullptr;
1114 }
1115
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001116 if (transport_description->opaque_parameters->protocol !=
1117 config_.media_transport_factory->GetTransportName()) {
1118 RTC_LOG(LS_INFO) << "Opaque transport parameters for protocol="
1119 << transport_description->opaque_parameters->protocol
1120 << ", which does not match supported protocol="
1121 << config_.media_transport_factory->GetTransportName();
1122 return nullptr;
1123 }
1124
1125 RTC_DCHECK(!local);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001126 // When bundle is enabled, two JsepTransports are created, and then
1127 // the second transport is destroyed (right away).
1128 // For datagram transport, we don't want to create the second
1129 // datagram transport in the first place.
1130 RTC_LOG(LS_INFO) << "Returning new, client datagram transport.";
1131
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001132 MediaTransportSettings settings;
1133 settings.is_caller = local;
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001134 settings.remote_transport_parameters =
1135 transport_description->opaque_parameters->parameters;
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001136 settings.event_log = config_.event_log;
1137
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001138 auto datagram_transport_result =
1139 config_.media_transport_factory->CreateDatagramTransport(network_thread_,
1140 settings);
1141
1142 // TODO(sukhanov): Proper error handling.
1143 RTC_CHECK(datagram_transport_result.ok());
1144
1145 return datagram_transport_result.MoveValue();
1146}
1147
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001148RTCError JsepTransportController::MaybeCreateJsepTransport(
1149 bool local,
Piotr (Peter) Slatala105ded32019-02-27 14:26:15 -08001150 const cricket::ContentInfo& content_info,
1151 const cricket::SessionDescription& description) {
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001152 RTC_DCHECK(network_thread_->IsCurrent());
1153 cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
1154 if (transport) {
1155 return RTCError::OK();
1156 }
1157
1158 const cricket::MediaContentDescription* content_desc =
Harald Alvestrand1716d392019-06-03 20:35:45 +02001159 content_info.media_description();
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001160 if (certificate_ && !content_desc->cryptos().empty()) {
1161 return RTCError(RTCErrorType::INVALID_PARAMETER,
1162 "SDES and DTLS-SRTP cannot be enabled at the same time.");
1163 }
1164
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001165 std::unique_ptr<cricket::IceTransportInternal> ice =
1166 CreateIceTransport(content_info.name, /*rtcp=*/false);
1167
1168 std::unique_ptr<MediaTransportInterface> media_transport =
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001169 MaybeCreateMediaTransport(content_info, description, local);
1170 if (media_transport) {
1171 media_transport_created_once_ = true;
1172 media_transport->Connect(ice.get());
1173 }
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001174
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001175 std::unique_ptr<DatagramTransportInterface> datagram_transport =
1176 MaybeCreateDatagramTransport(content_info, description, local);
1177 if (datagram_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001178 datagram_transport->Connect(ice.get());
1179 }
1180
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001181 std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
Anton Sukhanovac6c0962019-07-10 15:44:56 -07001182 CreateDtlsTransport(content_info, ice.get(), nullptr);
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001183
1184 std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
1185 std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
1186 std::unique_ptr<SrtpTransport> sdes_transport;
1187 std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
Bjorn A Mellem364b2672019-08-20 16:58:03 -07001188 std::unique_ptr<RtpTransportInternal> datagram_rtp_transport;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001189
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001190 std::unique_ptr<cricket::IceTransportInternal> rtcp_ice;
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001191 if (config_.rtcp_mux_policy !=
1192 PeerConnectionInterface::kRtcpMuxPolicyRequire &&
1193 content_info.type == cricket::MediaProtocolType::kRtp) {
Piotr (Peter) Slatala2b5baee2019-01-16 08:25:21 -08001194 RTC_DCHECK(media_transport == nullptr);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001195 RTC_DCHECK(datagram_transport == nullptr);
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001196 rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
Anton Sukhanovac6c0962019-07-10 15:44:56 -07001197 rtcp_dtls_transport = CreateDtlsTransport(content_info, rtcp_ice.get(),
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001198 /*datagram_transport=*/nullptr);
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001199 }
Piotr (Peter) Slatala47dfdca2018-11-16 14:13:58 -08001200
Bjorn A Mellem703ea952019-08-23 10:31:11 -07001201 // Only create a datagram RTP transport if the datagram transport should be
1202 // used for RTP.
1203 if (datagram_transport && config_.use_datagram_transport) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001204 // TODO(sukhanov): We use unencrypted RTP transport over DatagramTransport,
1205 // because MediaTransport encrypts. In the future we may want to
1206 // implement our own version of RtpTransport over MediaTransport, because
1207 // it will give us more control over things like:
1208 // - Fusing
1209 // - Rtp header compression
1210 // - Handling Rtcp feedback.
1211 RTC_LOG(LS_INFO) << "Creating UnencryptedRtpTransport, because datagram "
1212 "transport is used.";
1213 RTC_DCHECK(!rtcp_dtls_transport);
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001214 datagram_rtp_transport = std::make_unique<DatagramRtpTransport>(
Bjorn A Mellem364b2672019-08-20 16:58:03 -07001215 content_info.media_description()->rtp_header_extensions(), ice.get(),
1216 datagram_transport.get());
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001217 }
1218
1219 if (config_.disable_encryption) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001220 RTC_LOG(LS_INFO)
1221 << "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001222 unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
Zhi Huangd2248f82018-04-10 14:41:03 -07001223 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001224 } else if (!content_desc->cryptos().empty()) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001225 sdes_transport = CreateSdesTransport(
1226 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001227 RTC_LOG(LS_INFO) << "Creating SdesTransport.";
Zhi Huange818b6e2018-02-22 15:26:27 -08001228 } else {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001229 RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
Zhi Huangd2248f82018-04-10 14:41:03 -07001230 dtls_srtp_transport = CreateDtlsSrtpTransport(
1231 content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
Zhi Huange818b6e2018-02-22 15:26:27 -08001232 }
1233
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001234 std::unique_ptr<cricket::SctpTransportInternal> sctp_transport;
1235 if (config_.sctp_factory) {
1236 sctp_transport =
1237 config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
1238 }
1239
1240 DataChannelTransportInterface* data_channel_transport = nullptr;
1241 if (config_.use_datagram_transport_for_data_channels) {
1242 data_channel_transport = datagram_transport.get();
1243 } else if (config_.use_media_transport_for_data_channels) {
1244 data_channel_transport = media_transport.get();
1245 }
1246
Zhi Huang365381f2018-04-13 16:44:34 -07001247 std::unique_ptr<cricket::JsepTransport> jsep_transport =
Mirko Bonadei317a1f02019-09-17 17:06:18 +02001248 std::make_unique<cricket::JsepTransport>(
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -07001249 content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
1250 std::move(unencrypted_rtp_transport), std::move(sdes_transport),
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001251 std::move(dtls_srtp_transport), std::move(datagram_rtp_transport),
1252 std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport),
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001253 std::move(sctp_transport), std::move(media_transport),
1254 std::move(datagram_transport), data_channel_transport);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001255
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +02001256 jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect(
1257 this, &JsepTransportController::OnRtcpPacketReceived_n);
1258
Zhi Huange818b6e2018-02-22 15:26:27 -08001259 jsep_transport->SignalRtcpMuxActive.connect(
1260 this, &JsepTransportController::UpdateAggregateStates_n);
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -07001261 jsep_transport->SignalMediaTransportStateChanged.connect(
Bjorn Mellem175aa2e2018-11-08 11:23:22 -08001262 this, &JsepTransportController::OnMediaTransportStateChanged_n);
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001263 jsep_transport->SignalDataChannelTransportNegotiated.connect(
1264 this, &JsepTransportController::OnDataChannelTransportNegotiated_n);
Taylor Brandstettercbaa2542018-04-16 16:42:14 -07001265 SetTransportForMid(content_info.name, jsep_transport.get());
Zhi Huange830e682018-03-30 10:48:35 -07001266
Zhi Huangd2248f82018-04-10 14:41:03 -07001267 jsep_transports_by_name_[content_info.name] = std::move(jsep_transport);
1268 UpdateAggregateStates_n();
Zhi Huange830e682018-03-30 10:48:35 -07001269 return RTCError::OK();
Zhi Huange818b6e2018-02-22 15:26:27 -08001270}
1271
1272void JsepTransportController::MaybeDestroyJsepTransport(
1273 const std::string& mid) {
Zhi Huangd2248f82018-04-10 14:41:03 -07001274 auto jsep_transport = GetJsepTransportByName(mid);
1275 if (!jsep_transport) {
1276 return;
1277 }
1278
1279 // Don't destroy the JsepTransport if there are still media sections referring
1280 // to it.
1281 for (const auto& kv : mid_to_transport_) {
1282 if (kv.second == jsep_transport) {
1283 return;
1284 }
1285 }
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001286
Zhi Huange830e682018-03-30 10:48:35 -07001287 jsep_transports_by_name_.erase(mid);
Zhi Huange818b6e2018-02-22 15:26:27 -08001288 UpdateAggregateStates_n();
1289}
1290
1291void JsepTransportController::DestroyAllJsepTransports_n() {
1292 RTC_DCHECK(network_thread_->IsCurrent());
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001293
1294 for (const auto& jsep_transport : jsep_transports_by_name_) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001295 config_.transport_observer->OnTransportChanged(
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001296 jsep_transport.first, nullptr, nullptr, nullptr, nullptr);
Piotr (Peter) Slatalacc8e8bb2018-11-15 08:26:19 -08001297 }
1298
Zhi Huange830e682018-03-30 10:48:35 -07001299 jsep_transports_by_name_.clear();
Zhi Huange818b6e2018-02-22 15:26:27 -08001300}
1301
1302void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
1303 RTC_DCHECK(network_thread_->IsCurrent());
1304
1305 ice_role_ = ice_role;
1306 for (auto& dtls : GetDtlsTransports()) {
1307 dtls->ice_transport()->SetIceRole(ice_role_);
1308 }
1309}
1310
1311cricket::IceRole JsepTransportController::DetermineIceRole(
Zhi Huang365381f2018-04-13 16:44:34 -07001312 cricket::JsepTransport* jsep_transport,
Zhi Huange818b6e2018-02-22 15:26:27 -08001313 const cricket::TransportInfo& transport_info,
1314 SdpType type,
1315 bool local) {
1316 cricket::IceRole ice_role = ice_role_;
1317 auto tdesc = transport_info.description;
1318 if (local) {
1319 // The initial offer side may use ICE Lite, in which case, per RFC5245
1320 // Section 5.1.1, the answer side should take the controlling role if it is
1321 // in the full ICE mode.
1322 //
1323 // When both sides use ICE Lite, the initial offer side must take the
1324 // controlling role, and this is the default logic implemented in
1325 // SetLocalDescription in JsepTransportController.
1326 if (jsep_transport->remote_description() &&
1327 jsep_transport->remote_description()->transport_desc.ice_mode ==
1328 cricket::ICEMODE_LITE &&
1329 ice_role_ == cricket::ICEROLE_CONTROLLED &&
1330 tdesc.ice_mode == cricket::ICEMODE_FULL) {
1331 ice_role = cricket::ICEROLE_CONTROLLING;
1332 }
1333
1334 // Older versions of Chrome expect the ICE role to be re-determined when an
1335 // ICE restart occurs, and also don't perform conflict resolution correctly,
1336 // so for now we can't safely stop doing this, unless the application opts
1337 // in by setting |config_.redetermine_role_on_ice_restart_| to false. See:
1338 // https://bugs.chromium.org/p/chromium/issues/detail?id=628676
1339 // TODO(deadbeef): Remove this when these old versions of Chrome reach a low
1340 // enough population.
1341 if (config_.redetermine_role_on_ice_restart &&
1342 jsep_transport->local_description() &&
1343 cricket::IceCredentialsChanged(
1344 jsep_transport->local_description()->transport_desc.ice_ufrag,
1345 jsep_transport->local_description()->transport_desc.ice_pwd,
1346 tdesc.ice_ufrag, tdesc.ice_pwd) &&
1347 // Don't change the ICE role if the remote endpoint is ICE lite; we
1348 // should always be controlling in that case.
1349 (!jsep_transport->remote_description() ||
1350 jsep_transport->remote_description()->transport_desc.ice_mode !=
1351 cricket::ICEMODE_LITE)) {
1352 ice_role = (type == SdpType::kOffer) ? cricket::ICEROLE_CONTROLLING
1353 : cricket::ICEROLE_CONTROLLED;
1354 }
1355 } else {
1356 // If our role is cricket::ICEROLE_CONTROLLED and the remote endpoint
1357 // supports only ice_lite, this local endpoint should take the CONTROLLING
1358 // role.
1359 // TODO(deadbeef): This is a session-level attribute, so it really shouldn't
1360 // be in a TransportDescription in the first place...
1361 if (ice_role_ == cricket::ICEROLE_CONTROLLED &&
1362 tdesc.ice_mode == cricket::ICEMODE_LITE) {
1363 ice_role = cricket::ICEROLE_CONTROLLING;
1364 }
1365
1366 // If we use ICE Lite and the remote endpoint uses the full implementation
1367 // of ICE, the local endpoint must take the controlled role, and the other
1368 // side must be the controlling role.
1369 if (jsep_transport->local_description() &&
1370 jsep_transport->local_description()->transport_desc.ice_mode ==
1371 cricket::ICEMODE_LITE &&
1372 ice_role_ == cricket::ICEROLE_CONTROLLING &&
Zhi Huange830e682018-03-30 10:48:35 -07001373 tdesc.ice_mode == cricket::ICEMODE_FULL) {
Zhi Huange818b6e2018-02-22 15:26:27 -08001374 ice_role = cricket::ICEROLE_CONTROLLED;
1375 }
1376 }
1377
1378 return ice_role;
1379}
1380
1381void JsepTransportController::OnTransportWritableState_n(
1382 rtc::PacketTransportInternal* transport) {
1383 RTC_DCHECK(network_thread_->IsCurrent());
1384 RTC_LOG(LS_INFO) << " Transport " << transport->transport_name()
1385 << " writability changed to " << transport->writable()
1386 << ".";
1387 UpdateAggregateStates_n();
1388}
1389
1390void JsepTransportController::OnTransportReceivingState_n(
1391 rtc::PacketTransportInternal* transport) {
1392 RTC_DCHECK(network_thread_->IsCurrent());
1393 UpdateAggregateStates_n();
1394}
1395
1396void JsepTransportController::OnTransportGatheringState_n(
1397 cricket::IceTransportInternal* transport) {
1398 RTC_DCHECK(network_thread_->IsCurrent());
1399 UpdateAggregateStates_n();
1400}
1401
1402void JsepTransportController::OnTransportCandidateGathered_n(
1403 cricket::IceTransportInternal* transport,
1404 const cricket::Candidate& candidate) {
1405 RTC_DCHECK(network_thread_->IsCurrent());
1406
1407 // We should never signal peer-reflexive candidates.
1408 if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
1409 RTC_NOTREACHED();
1410 return;
1411 }
Steve Antond25828a2018-08-31 13:06:05 -07001412 std::string transport_name = transport->transport_name();
1413 invoker_.AsyncInvoke<void>(
1414 RTC_FROM_HERE, signaling_thread_, [this, transport_name, candidate] {
1415 SignalIceCandidatesGathered(transport_name, {candidate});
1416 });
Zhi Huange818b6e2018-02-22 15:26:27 -08001417}
1418
Eldar Relloda13ea22019-06-01 12:23:43 +03001419void JsepTransportController::OnTransportCandidateError_n(
1420 cricket::IceTransportInternal* transport,
1421 const cricket::IceCandidateErrorEvent& event) {
1422 RTC_DCHECK(network_thread_->IsCurrent());
1423
1424 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1425 [this, event] { SignalIceCandidateError(event); });
1426}
Zhi Huange818b6e2018-02-22 15:26:27 -08001427void JsepTransportController::OnTransportCandidatesRemoved_n(
1428 cricket::IceTransportInternal* transport,
1429 const cricket::Candidates& candidates) {
1430 invoker_.AsyncInvoke<void>(
1431 RTC_FROM_HERE, signaling_thread_,
Steve Antond25828a2018-08-31 13:06:05 -07001432 [this, candidates] { SignalIceCandidatesRemoved(candidates); });
Zhi Huange818b6e2018-02-22 15:26:27 -08001433}
Alex Drake00c7ecf2019-08-06 10:54:47 -07001434void JsepTransportController::OnTransportCandidatePairChanged_n(
1435 const cricket::CandidatePairChangeEvent& event) {
1436 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, [this, event] {
1437 SignalIceCandidatePairChanged(event);
1438 });
1439}
Zhi Huange818b6e2018-02-22 15:26:27 -08001440
1441void JsepTransportController::OnTransportRoleConflict_n(
1442 cricket::IceTransportInternal* transport) {
1443 RTC_DCHECK(network_thread_->IsCurrent());
1444 // Note: since the role conflict is handled entirely on the network thread,
1445 // we don't need to worry about role conflicts occurring on two ports at
1446 // once. The first one encountered should immediately reverse the role.
1447 cricket::IceRole reversed_role = (ice_role_ == cricket::ICEROLE_CONTROLLING)
1448 ? cricket::ICEROLE_CONTROLLED
1449 : cricket::ICEROLE_CONTROLLING;
1450 RTC_LOG(LS_INFO) << "Got role conflict; switching to "
1451 << (reversed_role == cricket::ICEROLE_CONTROLLING
1452 ? "controlling"
1453 : "controlled")
1454 << " role.";
1455 SetIceRole_n(reversed_role);
1456}
1457
1458void JsepTransportController::OnTransportStateChanged_n(
1459 cricket::IceTransportInternal* transport) {
1460 RTC_DCHECK(network_thread_->IsCurrent());
1461 RTC_LOG(LS_INFO) << transport->transport_name() << " Transport "
1462 << transport->component()
1463 << " state changed. Check if state is complete.";
1464 UpdateAggregateStates_n();
1465}
1466
Bjorn Mellem175aa2e2018-11-08 11:23:22 -08001467void JsepTransportController::OnMediaTransportStateChanged_n() {
Bjorn Mellem175aa2e2018-11-08 11:23:22 -08001468 UpdateAggregateStates_n();
1469}
1470
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001471void JsepTransportController::OnDataChannelTransportNegotiated_n(
1472 cricket::JsepTransport* transport,
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001473 DataChannelTransportInterface* data_channel_transport) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001474 for (auto it : mid_to_transport_) {
1475 if (it.second == transport) {
1476 config_.transport_observer->OnTransportChanged(
1477 it.first, transport->rtp_transport(), transport->RtpDtlsTransport(),
Bjorn A Mellembc3eebc2019-09-23 14:53:54 -07001478 transport->media_transport(), data_channel_transport);
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001479 }
1480 }
1481}
1482
Zhi Huange818b6e2018-02-22 15:26:27 -08001483void JsepTransportController::UpdateAggregateStates_n() {
1484 RTC_DCHECK(network_thread_->IsCurrent());
1485
1486 auto dtls_transports = GetDtlsTransports();
Alex Loiko9289eda2018-11-23 16:18:59 +00001487 cricket::IceConnectionState new_connection_state =
1488 cricket::kIceConnectionConnecting;
Jonas Olsson635474e2018-10-18 15:58:17 +02001489 PeerConnectionInterface::IceConnectionState new_ice_connection_state =
1490 PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
1491 PeerConnectionInterface::PeerConnectionState new_combined_state =
1492 PeerConnectionInterface::PeerConnectionState::kNew;
Zhi Huange818b6e2018-02-22 15:26:27 -08001493 cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
Alex Loiko9289eda2018-11-23 16:18:59 +00001494 bool any_failed = false;
1495
1496 // TODO(http://bugs.webrtc.org/9719) If(when) media_transport disables
1497 // dtls_transports entirely, the below line will have to be changed to account
1498 // for the fact that dtls transports might be absent.
1499 bool all_connected = !dtls_transports.empty();
1500 bool all_completed = !dtls_transports.empty();
Zhi Huange818b6e2018-02-22 15:26:27 -08001501 bool any_gathering = false;
1502 bool all_done_gathering = !dtls_transports.empty();
Jonas Olsson635474e2018-10-18 15:58:17 +02001503
1504 std::map<IceTransportState, int> ice_state_counts;
1505 std::map<cricket::DtlsTransportState, int> dtls_state_counts;
1506
Zhi Huange818b6e2018-02-22 15:26:27 -08001507 for (const auto& dtls : dtls_transports) {
Alex Loiko9289eda2018-11-23 16:18:59 +00001508 any_failed = any_failed || dtls->ice_transport()->GetState() ==
1509 cricket::IceTransportState::STATE_FAILED;
1510 all_connected = all_connected && dtls->writable();
1511 all_completed =
1512 all_completed && dtls->writable() &&
1513 dtls->ice_transport()->GetState() ==
1514 cricket::IceTransportState::STATE_COMPLETED &&
1515 dtls->ice_transport()->GetIceRole() == cricket::ICEROLE_CONTROLLING &&
1516 dtls->ice_transport()->gathering_state() ==
1517 cricket::kIceGatheringComplete;
Zhi Huange818b6e2018-02-22 15:26:27 -08001518 any_gathering = any_gathering || dtls->ice_transport()->gathering_state() !=
1519 cricket::kIceGatheringNew;
1520 all_done_gathering =
1521 all_done_gathering && dtls->ice_transport()->gathering_state() ==
1522 cricket::kIceGatheringComplete;
Jonas Olsson635474e2018-10-18 15:58:17 +02001523
1524 dtls_state_counts[dtls->dtls_state()]++;
1525 ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
Zhi Huange818b6e2018-02-22 15:26:27 -08001526 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -07001527
Bjorn A Mellemfa8f4ee2019-08-16 15:47:45 -07001528 // Don't indicate that the call failed or isn't connected due to media
1529 // transport state unless the media transport is used for media. If it's only
1530 // used for data channels, it will signal those separately.
1531 if (config_.use_media_transport_for_media || config_.use_datagram_transport) {
1532 for (auto it = jsep_transports_by_name_.begin();
1533 it != jsep_transports_by_name_.end(); ++it) {
1534 auto jsep_transport = it->second.get();
1535 if (!jsep_transport->media_transport()) {
1536 continue;
1537 }
Alex Loiko9289eda2018-11-23 16:18:59 +00001538
Bjorn A Mellemfa8f4ee2019-08-16 15:47:45 -07001539 // There is no 'kIceConnectionDisconnected', so we only need to handle
1540 // connected and completed.
1541 // We treat kClosed as failed, because if it happens before shutting down
1542 // media transports it means that there was a failure.
1543 // MediaTransportInterface allows to flip back and forth between kWritable
1544 // and kPending, but there does not exist an implementation that does
1545 // that, and the contract of jsep transport controller doesn't quite
1546 // expect that. When this happens, we would go from connected to
1547 // connecting state, but this may change in future.
1548 any_failed |= jsep_transport->media_transport_state() ==
1549 webrtc::MediaTransportState::kClosed;
1550 all_completed &= jsep_transport->media_transport_state() ==
1551 webrtc::MediaTransportState::kWritable;
1552 all_connected &= jsep_transport->media_transport_state() ==
1553 webrtc::MediaTransportState::kWritable;
1554 }
Alex Loiko9289eda2018-11-23 16:18:59 +00001555 }
1556
1557 if (any_failed) {
1558 new_connection_state = cricket::kIceConnectionFailed;
1559 } else if (all_completed) {
1560 new_connection_state = cricket::kIceConnectionCompleted;
1561 } else if (all_connected) {
1562 new_connection_state = cricket::kIceConnectionConnected;
1563 }
1564 if (ice_connection_state_ != new_connection_state) {
1565 ice_connection_state_ = new_connection_state;
1566 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1567 [this, new_connection_state] {
1568 SignalIceConnectionState(new_connection_state);
1569 });
1570 }
1571
Jonas Olsson635474e2018-10-18 15:58:17 +02001572 // Compute the current RTCIceConnectionState as described in
1573 // https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
1574 // The PeerConnection is responsible for handling the "closed" state.
1575 int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
1576 int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
1577 int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
1578 int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
1579 int total_ice_disconnected =
1580 ice_state_counts[IceTransportState::kDisconnected];
1581 int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
1582 int total_ice_new = ice_state_counts[IceTransportState::kNew];
1583 int total_ice = dtls_transports.size();
1584
1585 if (total_ice_failed > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001586 // Any RTCIceTransports are in the "failed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001587 new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
Alex Loiko9289eda2018-11-23 16:18:59 +00001588 } else if (total_ice_disconnected > 0) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001589 // None of the previous states apply and any RTCIceTransports are in the
1590 // "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001591 new_ice_connection_state =
1592 PeerConnectionInterface::kIceConnectionDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001593 } else if (total_ice_new + total_ice_closed == total_ice) {
1594 // None of the previous states apply and all RTCIceTransports are in the
1595 // "new" or "closed" state, or there are no transports.
1596 new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
1597 } else if (total_ice_new + total_ice_checking > 0) {
1598 // None of the previous states apply and any RTCIceTransports are in the
1599 // "new" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001600 new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001601 } else if (total_ice_completed + total_ice_closed == total_ice ||
1602 all_completed) {
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001603 // None of the previous states apply and all RTCIceTransports are in the
1604 // "completed" or "closed" state.
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001605 //
1606 // TODO(https://bugs.webrtc.org/10356): The all_completed condition is added
1607 // to mimic the behavior of the old ICE connection state, and should be
1608 // removed once we get end-of-candidates signaling in place.
Jonas Olsson635474e2018-10-18 15:58:17 +02001609 new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
1610 } else if (total_ice_connected + total_ice_completed + total_ice_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001611 total_ice) {
1612 // None of the previous states apply and all RTCIceTransports are in the
1613 // "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001614 new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001615 } else {
1616 RTC_NOTREACHED();
1617 }
1618
Alex Loiko9289eda2018-11-23 16:18:59 +00001619 if (standardized_ice_connection_state_ != new_ice_connection_state) {
Jonas Olssonacd8ae72019-02-25 15:26:24 +01001620 if (standardized_ice_connection_state_ ==
1621 PeerConnectionInterface::kIceConnectionChecking &&
1622 new_ice_connection_state ==
1623 PeerConnectionInterface::kIceConnectionCompleted) {
1624 // Ensure that we never skip over the "connected" state.
1625 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, [this] {
1626 SignalStandardizedIceConnectionState(
1627 PeerConnectionInterface::kIceConnectionConnected);
1628 });
1629 }
Alex Loiko9289eda2018-11-23 16:18:59 +00001630 standardized_ice_connection_state_ = new_ice_connection_state;
Jonas Olsson635474e2018-10-18 15:58:17 +02001631 invoker_.AsyncInvoke<void>(
1632 RTC_FROM_HERE, signaling_thread_, [this, new_ice_connection_state] {
Alex Loiko9289eda2018-11-23 16:18:59 +00001633 SignalStandardizedIceConnectionState(new_ice_connection_state);
Jonas Olsson635474e2018-10-18 15:58:17 +02001634 });
1635 }
1636
1637 // Compute the current RTCPeerConnectionState as described in
1638 // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
1639 // The PeerConnection is responsible for handling the "closed" state.
1640 // Note that "connecting" is only a valid state for DTLS transports while
1641 // "checking", "completed" and "disconnected" are only valid for ICE
1642 // transports.
1643 int total_connected = total_ice_connected +
1644 dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTED];
1645 int total_dtls_connecting =
1646 dtls_state_counts[cricket::DTLS_TRANSPORT_CONNECTING];
1647 int total_failed =
1648 total_ice_failed + dtls_state_counts[cricket::DTLS_TRANSPORT_FAILED];
1649 int total_closed =
1650 total_ice_closed + dtls_state_counts[cricket::DTLS_TRANSPORT_CLOSED];
1651 int total_new =
1652 total_ice_new + dtls_state_counts[cricket::DTLS_TRANSPORT_NEW];
1653 int total_transports = total_ice * 2;
1654
1655 if (total_failed > 0) {
1656 // Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
1657 new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001658 } else if (total_ice_disconnected > 0) {
1659 // None of the previous states apply and any RTCIceTransports or
1660 // RTCDtlsTransports are in the "disconnected" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001661 new_combined_state =
1662 PeerConnectionInterface::PeerConnectionState::kDisconnected;
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001663 } else if (total_new + total_closed == total_transports) {
1664 // None of the previous states apply and all RTCIceTransports and
1665 // RTCDtlsTransports are in the "new" or "closed" state, or there are no
1666 // transports.
1667 new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
1668 } else if (total_new + total_dtls_connecting + total_ice_checking > 0) {
1669 // None of the previous states apply and all RTCIceTransports or
1670 // RTCDtlsTransports are in the "new", "connecting" or "checking" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001671 new_combined_state =
1672 PeerConnectionInterface::PeerConnectionState::kConnecting;
1673 } else if (total_connected + total_ice_completed + total_closed ==
Jonas Olsson6a8727b2018-12-07 13:11:44 +01001674 total_transports) {
1675 // None of the previous states apply and all RTCIceTransports and
1676 // RTCDtlsTransports are in the "connected", "completed" or "closed" state.
Jonas Olsson635474e2018-10-18 15:58:17 +02001677 new_combined_state =
1678 PeerConnectionInterface::PeerConnectionState::kConnected;
Jonas Olsson635474e2018-10-18 15:58:17 +02001679 } else {
1680 RTC_NOTREACHED();
1681 }
1682
1683 if (combined_connection_state_ != new_combined_state) {
1684 combined_connection_state_ = new_combined_state;
1685 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1686 [this, new_combined_state] {
1687 SignalConnectionState(new_combined_state);
1688 });
1689 }
1690
Zhi Huange818b6e2018-02-22 15:26:27 -08001691 if (all_done_gathering) {
1692 new_gathering_state = cricket::kIceGatheringComplete;
1693 } else if (any_gathering) {
1694 new_gathering_state = cricket::kIceGatheringGathering;
1695 }
1696 if (ice_gathering_state_ != new_gathering_state) {
1697 ice_gathering_state_ = new_gathering_state;
Steve Antond25828a2018-08-31 13:06:05 -07001698 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
1699 [this, new_gathering_state] {
1700 SignalIceGatheringState(new_gathering_state);
1701 });
Zhi Huange818b6e2018-02-22 15:26:27 -08001702 }
1703}
1704
Sebastian Jansson1b83a9e2019-09-18 18:22:12 +02001705void JsepTransportController::OnRtcpPacketReceived_n(
1706 rtc::CopyOnWriteBuffer* packet,
1707 int64_t packet_time_us) {
1708 RTC_DCHECK(config_.rtcp_handler);
1709 config_.rtcp_handler(*packet, packet_time_us);
1710}
1711
Zhi Huange818b6e2018-02-22 15:26:27 -08001712void JsepTransportController::OnDtlsHandshakeError(
1713 rtc::SSLHandshakeError error) {
1714 SignalDtlsHandshakeError(error);
1715}
1716
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001717absl::optional<cricket::SessionDescription::MediaTransportSetting>
1718JsepTransportController::GenerateOrGetLastMediaTransportOffer() {
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001719 if (media_transport_created_once_) {
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001720 RTC_LOG(LS_INFO) << "Not regenerating media transport for the new offer in "
1721 "existing session.";
1722 return media_transport_offer_settings_;
1723 }
1724
1725 RTC_LOG(LS_INFO) << "Generating media transport offer!";
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001726
1727 absl::optional<std::string> transport_parameters;
1728
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001729 // Check that media transport is supposed to be used.
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001730 // Note that ICE is not available when media transport is created. It will
1731 // only be available in 'Connect'. This may be a potential server config, if
1732 // we decide to use this peer connection as a caller, not as a callee.
1733 // TODO(sukhanov): Avoid code duplication with CreateMedia/MediaTransport.
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001734 if (config_.use_media_transport_for_media ||
1735 config_.use_media_transport_for_data_channels) {
1736 RTC_DCHECK(config_.media_transport_factory != nullptr);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001737 RTC_DCHECK(!config_.use_datagram_transport);
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001738 webrtc::MediaTransportSettings settings;
1739 settings.is_caller = true;
1740 settings.pre_shared_key = rtc::CreateRandomString(32);
Bjorn A Mellemb073f1c2019-07-02 09:50:35 -07001741 if (config_.use_media_transport_for_media) {
1742 settings.event_log = config_.event_log;
1743 }
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001744 auto media_transport_or_error =
1745 config_.media_transport_factory->CreateMediaTransport(network_thread_,
1746 settings);
1747
1748 if (media_transport_or_error.ok()) {
1749 offer_media_transport_ = std::move(media_transport_or_error.value());
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001750 transport_parameters =
1751 offer_media_transport_->GetTransportParametersOffer();
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001752 } else {
1753 RTC_LOG(LS_INFO) << "Unable to create media transport, error="
1754 << media_transport_or_error.error().message();
1755 }
1756 }
1757
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001758 if (!offer_media_transport_) {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -07001759 RTC_LOG(LS_INFO) << "Media and data transports do not exist";
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001760 return absl::nullopt;
1761 }
1762
Piotr (Peter) Slatalab1ae10b2019-03-01 11:14:05 -08001763 if (!transport_parameters) {
1764 RTC_LOG(LS_INFO) << "Media transport didn't generate the offer";
1765 // Media transport didn't generate the offer, and is not supposed to be
1766 // used. Destroy the temporary media transport.
1767 offer_media_transport_ = nullptr;
1768 return absl::nullopt;
1769 }
1770
1771 cricket::SessionDescription::MediaTransportSetting setting;
1772 setting.transport_name = config_.media_transport_factory->GetTransportName();
1773 setting.transport_setting = *transport_parameters;
1774 media_transport_offer_settings_ = setting;
1775 return setting;
1776}
1777
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001778absl::optional<cricket::OpaqueTransportParameters>
1779JsepTransportController::GetTransportParameters(const std::string& mid) {
Bjorn A Mellemb689af42019-08-21 10:44:59 -07001780 if (!(config_.use_datagram_transport ||
1781 config_.use_datagram_transport_for_data_channels)) {
Bjorn A Mellemc85ebbe2019-06-07 10:28:06 -07001782 return absl::nullopt;
1783 }
1784
1785 cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
1786 if (transport) {
1787 absl::optional<cricket::OpaqueTransportParameters> params =
1788 transport->GetTransportParameters();
1789 if (params) {
1790 params->protocol = config_.media_transport_factory->GetTransportName();
1791 }
1792 return params;
1793 }
1794
1795 RTC_DCHECK(!local_desc_ && !remote_desc_)
1796 << "JsepTransport should exist for every mid once any description is set";
1797
1798 // Need to generate a transport for the offer.
1799 if (!offer_datagram_transport_) {
1800 webrtc::MediaTransportSettings settings;
1801 settings.is_caller = true;
1802 settings.pre_shared_key = rtc::CreateRandomString(32);
1803 settings.event_log = config_.event_log;
1804 auto datagram_transport_or_error =
1805 config_.media_transport_factory->CreateDatagramTransport(
1806 network_thread_, settings);
1807
1808 if (datagram_transport_or_error.ok()) {
1809 offer_datagram_transport_ =
1810 std::move(datagram_transport_or_error.value());
1811 } else {
1812 RTC_LOG(LS_INFO) << "Unable to create datagram transport, error="
1813 << datagram_transport_or_error.error().message();
1814 }
1815 }
1816
1817 // We have prepared a transport for the offer, and can now use its parameters.
1818 cricket::OpaqueTransportParameters params;
1819 params.parameters = offer_datagram_transport_->GetTransportParameters();
1820 params.protocol = config_.media_transport_factory->GetTransportName();
1821 return params;
1822}
1823
Zhi Huange818b6e2018-02-22 15:26:27 -08001824} // namespace webrtc