1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2017 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "pc/jsep_transport_controller.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <functional>
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/transport/enums.h"
26*d9f75844SAndroid Build Coastguard Worker #include "media/sctp/sctp_transport_internal.h"
27*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/dtls_transport.h"
28*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/ice_transport_internal.h"
29*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
30*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
35*d9f75844SAndroid Build Coastguard Worker
36*d9f75844SAndroid Build Coastguard Worker using webrtc::SdpType;
37*d9f75844SAndroid Build Coastguard Worker
38*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
39*d9f75844SAndroid Build Coastguard Worker
JsepTransportController(rtc::Thread * network_thread,cricket::PortAllocator * port_allocator,AsyncDnsResolverFactoryInterface * async_dns_resolver_factory,Config config)40*d9f75844SAndroid Build Coastguard Worker JsepTransportController::JsepTransportController(
41*d9f75844SAndroid Build Coastguard Worker rtc::Thread* network_thread,
42*d9f75844SAndroid Build Coastguard Worker cricket::PortAllocator* port_allocator,
43*d9f75844SAndroid Build Coastguard Worker AsyncDnsResolverFactoryInterface* async_dns_resolver_factory,
44*d9f75844SAndroid Build Coastguard Worker Config config)
45*d9f75844SAndroid Build Coastguard Worker : network_thread_(network_thread),
46*d9f75844SAndroid Build Coastguard Worker port_allocator_(port_allocator),
47*d9f75844SAndroid Build Coastguard Worker async_dns_resolver_factory_(async_dns_resolver_factory),
48*d9f75844SAndroid Build Coastguard Worker transports_(
49*d9f75844SAndroid Build Coastguard Worker [this](const std::string& mid, cricket::JsepTransport* transport) {
50*d9f75844SAndroid Build Coastguard Worker return OnTransportChanged(mid, transport);
51*d9f75844SAndroid Build Coastguard Worker },
__anondb67ed740202() 52*d9f75844SAndroid Build Coastguard Worker [this]() {
53*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
54*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
55*d9f75844SAndroid Build Coastguard Worker }),
56*d9f75844SAndroid Build Coastguard Worker config_(config),
57*d9f75844SAndroid Build Coastguard Worker active_reset_srtp_params_(config.active_reset_srtp_params),
58*d9f75844SAndroid Build Coastguard Worker bundles_(config.bundle_policy) {
59*d9f75844SAndroid Build Coastguard Worker // The `transport_observer` is assumed to be non-null.
60*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(config_.transport_observer);
61*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(config_.rtcp_handler);
62*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(config_.ice_transport_factory);
63*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(config_.on_dtls_handshake_error_);
64*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(config_.field_trials);
65*d9f75844SAndroid Build Coastguard Worker if (port_allocator_) {
66*d9f75844SAndroid Build Coastguard Worker port_allocator_->SetIceTiebreaker(ice_tiebreaker_);
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker }
69*d9f75844SAndroid Build Coastguard Worker
~JsepTransportController()70*d9f75844SAndroid Build Coastguard Worker JsepTransportController::~JsepTransportController() {
71*d9f75844SAndroid Build Coastguard Worker // Channel destructors may try to send packets, so this needs to happen on
72*d9f75844SAndroid Build Coastguard Worker // the network thread.
73*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
74*d9f75844SAndroid Build Coastguard Worker DestroyAllJsepTransports_n();
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker
SetLocalDescription(SdpType type,const cricket::SessionDescription * description)77*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::SetLocalDescription(
78*d9f75844SAndroid Build Coastguard Worker SdpType type,
79*d9f75844SAndroid Build Coastguard Worker const cricket::SessionDescription* description) {
80*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransportController::SetLocalDescription");
81*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
82*d9f75844SAndroid Build Coastguard Worker return network_thread_->BlockingCall(
83*d9f75844SAndroid Build Coastguard Worker [=] { return SetLocalDescription(type, description); });
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
87*d9f75844SAndroid Build Coastguard Worker if (!initial_offerer_.has_value()) {
88*d9f75844SAndroid Build Coastguard Worker initial_offerer_.emplace(type == SdpType::kOffer);
89*d9f75844SAndroid Build Coastguard Worker if (*initial_offerer_) {
90*d9f75844SAndroid Build Coastguard Worker SetIceRole_n(cricket::ICEROLE_CONTROLLING);
91*d9f75844SAndroid Build Coastguard Worker } else {
92*d9f75844SAndroid Build Coastguard Worker SetIceRole_n(cricket::ICEROLE_CONTROLLED);
93*d9f75844SAndroid Build Coastguard Worker }
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker return ApplyDescription_n(/*local=*/true, type, description);
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker
SetRemoteDescription(SdpType type,const cricket::SessionDescription * description)98*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::SetRemoteDescription(
99*d9f75844SAndroid Build Coastguard Worker SdpType type,
100*d9f75844SAndroid Build Coastguard Worker const cricket::SessionDescription* description) {
101*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransportController::SetRemoteDescription");
102*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
103*d9f75844SAndroid Build Coastguard Worker return network_thread_->BlockingCall(
104*d9f75844SAndroid Build Coastguard Worker [=] { return SetRemoteDescription(type, description); });
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker
107*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
108*d9f75844SAndroid Build Coastguard Worker return ApplyDescription_n(/*local=*/false, type, description);
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker
GetRtpTransport(absl::string_view mid) const111*d9f75844SAndroid Build Coastguard Worker RtpTransportInternal* JsepTransportController::GetRtpTransport(
112*d9f75844SAndroid Build Coastguard Worker absl::string_view mid) const {
113*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
114*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportForMid(mid);
115*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
116*d9f75844SAndroid Build Coastguard Worker return nullptr;
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker return jsep_transport->rtp_transport();
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker
GetDataChannelTransport(const std::string & mid) const121*d9f75844SAndroid Build Coastguard Worker DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
122*d9f75844SAndroid Build Coastguard Worker const std::string& mid) const {
123*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
124*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportForMid(mid);
125*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
126*d9f75844SAndroid Build Coastguard Worker return nullptr;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker return jsep_transport->data_channel_transport();
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker
GetDtlsTransport(const std::string & mid)131*d9f75844SAndroid Build Coastguard Worker cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
132*d9f75844SAndroid Build Coastguard Worker const std::string& mid) {
133*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
134*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportForMid(mid);
135*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
136*d9f75844SAndroid Build Coastguard Worker return nullptr;
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker return jsep_transport->rtp_dtls_transport();
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker const cricket::DtlsTransportInternal*
GetRtcpDtlsTransport(const std::string & mid) const142*d9f75844SAndroid Build Coastguard Worker JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
143*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
144*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportForMid(mid);
145*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
146*d9f75844SAndroid Build Coastguard Worker return nullptr;
147*d9f75844SAndroid Build Coastguard Worker }
148*d9f75844SAndroid Build Coastguard Worker return jsep_transport->rtcp_dtls_transport();
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker
151*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::DtlsTransport>
LookupDtlsTransportByMid(const std::string & mid)152*d9f75844SAndroid Build Coastguard Worker JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
153*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
154*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportForMid(mid);
155*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
156*d9f75844SAndroid Build Coastguard Worker return nullptr;
157*d9f75844SAndroid Build Coastguard Worker }
158*d9f75844SAndroid Build Coastguard Worker return jsep_transport->RtpDtlsTransport();
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker
GetSctpTransport(const std::string & mid) const161*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
162*d9f75844SAndroid Build Coastguard Worker const std::string& mid) const {
163*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
164*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportForMid(mid);
165*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
166*d9f75844SAndroid Build Coastguard Worker return nullptr;
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker return jsep_transport->SctpTransport();
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker
SetIceConfig(const cricket::IceConfig & config)171*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::SetIceConfig(const cricket::IceConfig& config) {
172*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
173*d9f75844SAndroid Build Coastguard Worker ice_config_ = config;
174*d9f75844SAndroid Build Coastguard Worker for (auto& dtls : GetDtlsTransports()) {
175*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SetIceConfig(ice_config_);
176*d9f75844SAndroid Build Coastguard Worker }
177*d9f75844SAndroid Build Coastguard Worker }
178*d9f75844SAndroid Build Coastguard Worker
SetNeedsIceRestartFlag()179*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::SetNeedsIceRestartFlag() {
180*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
181*d9f75844SAndroid Build Coastguard Worker for (auto& transport : transports_.Transports()) {
182*d9f75844SAndroid Build Coastguard Worker transport->SetNeedsIceRestartFlag();
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker }
185*d9f75844SAndroid Build Coastguard Worker
NeedsIceRestart(const std::string & transport_name) const186*d9f75844SAndroid Build Coastguard Worker bool JsepTransportController::NeedsIceRestart(
187*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name) const {
188*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
189*d9f75844SAndroid Build Coastguard Worker
190*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* transport =
191*d9f75844SAndroid Build Coastguard Worker GetJsepTransportByName(transport_name);
192*d9f75844SAndroid Build Coastguard Worker if (!transport) {
193*d9f75844SAndroid Build Coastguard Worker return false;
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker return transport->needs_ice_restart();
196*d9f75844SAndroid Build Coastguard Worker }
197*d9f75844SAndroid Build Coastguard Worker
GetDtlsRole(const std::string & mid) const198*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
199*d9f75844SAndroid Build Coastguard Worker const std::string& mid) const {
200*d9f75844SAndroid Build Coastguard Worker // TODO(tommi): Remove this hop. Currently it's called from the signaling
201*d9f75844SAndroid Build Coastguard Worker // thread during negotiations, potentially multiple times.
202*d9f75844SAndroid Build Coastguard Worker // WebRtcSessionDescriptionFactory::InternalCreateAnswer is one example.
203*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
204*d9f75844SAndroid Build Coastguard Worker return network_thread_->BlockingCall([&] { return GetDtlsRole(mid); });
205*d9f75844SAndroid Build Coastguard Worker }
206*d9f75844SAndroid Build Coastguard Worker
207*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
208*d9f75844SAndroid Build Coastguard Worker
209*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
210*d9f75844SAndroid Build Coastguard Worker if (!t) {
211*d9f75844SAndroid Build Coastguard Worker return absl::optional<rtc::SSLRole>();
212*d9f75844SAndroid Build Coastguard Worker }
213*d9f75844SAndroid Build Coastguard Worker return t->GetDtlsRole();
214*d9f75844SAndroid Build Coastguard Worker }
215*d9f75844SAndroid Build Coastguard Worker
SetLocalCertificate(const rtc::scoped_refptr<rtc::RTCCertificate> & certificate)216*d9f75844SAndroid Build Coastguard Worker bool JsepTransportController::SetLocalCertificate(
217*d9f75844SAndroid Build Coastguard Worker const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
218*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
219*d9f75844SAndroid Build Coastguard Worker return network_thread_->BlockingCall(
220*d9f75844SAndroid Build Coastguard Worker [&] { return SetLocalCertificate(certificate); });
221*d9f75844SAndroid Build Coastguard Worker }
222*d9f75844SAndroid Build Coastguard Worker
223*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
224*d9f75844SAndroid Build Coastguard Worker
225*d9f75844SAndroid Build Coastguard Worker // Can't change a certificate, or set a null certificate.
226*d9f75844SAndroid Build Coastguard Worker if (certificate_ || !certificate) {
227*d9f75844SAndroid Build Coastguard Worker return false;
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker certificate_ = certificate;
230*d9f75844SAndroid Build Coastguard Worker
231*d9f75844SAndroid Build Coastguard Worker // Set certificate for JsepTransport, which verifies it matches the
232*d9f75844SAndroid Build Coastguard Worker // fingerprint in SDP, and DTLS transport.
233*d9f75844SAndroid Build Coastguard Worker // Fallback from DTLS to SDES is not supported.
234*d9f75844SAndroid Build Coastguard Worker for (auto& transport : transports_.Transports()) {
235*d9f75844SAndroid Build Coastguard Worker transport->SetLocalCertificate(certificate_);
236*d9f75844SAndroid Build Coastguard Worker }
237*d9f75844SAndroid Build Coastguard Worker for (auto& dtls : GetDtlsTransports()) {
238*d9f75844SAndroid Build Coastguard Worker bool set_cert_success = dtls->SetLocalCertificate(certificate_);
239*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(set_cert_success);
240*d9f75844SAndroid Build Coastguard Worker }
241*d9f75844SAndroid Build Coastguard Worker return true;
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker
244*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<rtc::RTCCertificate>
GetLocalCertificate(const std::string & transport_name) const245*d9f75844SAndroid Build Coastguard Worker JsepTransportController::GetLocalCertificate(
246*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name) const {
247*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
248*d9f75844SAndroid Build Coastguard Worker
249*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* t = GetJsepTransportByName(transport_name);
250*d9f75844SAndroid Build Coastguard Worker if (!t) {
251*d9f75844SAndroid Build Coastguard Worker return nullptr;
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker return t->GetLocalCertificate();
254*d9f75844SAndroid Build Coastguard Worker }
255*d9f75844SAndroid Build Coastguard Worker
256*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLCertChain>
GetRemoteSSLCertChain(const std::string & transport_name) const257*d9f75844SAndroid Build Coastguard Worker JsepTransportController::GetRemoteSSLCertChain(
258*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name) const {
259*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
260*d9f75844SAndroid Build Coastguard Worker
261*d9f75844SAndroid Build Coastguard Worker // Get the certificate from the RTP transport's DTLS handshake. Should be
262*d9f75844SAndroid Build Coastguard Worker // identical to the RTCP transport's, since they were given the same remote
263*d9f75844SAndroid Build Coastguard Worker // fingerprint.
264*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportByName(transport_name);
265*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
266*d9f75844SAndroid Build Coastguard Worker return nullptr;
267*d9f75844SAndroid Build Coastguard Worker }
268*d9f75844SAndroid Build Coastguard Worker auto dtls = jsep_transport->rtp_dtls_transport();
269*d9f75844SAndroid Build Coastguard Worker if (!dtls) {
270*d9f75844SAndroid Build Coastguard Worker return nullptr;
271*d9f75844SAndroid Build Coastguard Worker }
272*d9f75844SAndroid Build Coastguard Worker
273*d9f75844SAndroid Build Coastguard Worker return dtls->GetRemoteSSLCertChain();
274*d9f75844SAndroid Build Coastguard Worker }
275*d9f75844SAndroid Build Coastguard Worker
MaybeStartGathering()276*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::MaybeStartGathering() {
277*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
278*d9f75844SAndroid Build Coastguard Worker network_thread_->BlockingCall([&] { MaybeStartGathering(); });
279*d9f75844SAndroid Build Coastguard Worker return;
280*d9f75844SAndroid Build Coastguard Worker }
281*d9f75844SAndroid Build Coastguard Worker
282*d9f75844SAndroid Build Coastguard Worker for (auto& dtls : GetDtlsTransports()) {
283*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->MaybeStartGathering();
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker }
286*d9f75844SAndroid Build Coastguard Worker
AddRemoteCandidates(const std::string & transport_name,const cricket::Candidates & candidates)287*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::AddRemoteCandidates(
288*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name,
289*d9f75844SAndroid Build Coastguard Worker const cricket::Candidates& candidates) {
290*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
291*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(VerifyCandidates(candidates).ok());
292*d9f75844SAndroid Build Coastguard Worker auto jsep_transport = GetJsepTransportByName(transport_name);
293*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
294*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Not adding candidate because the JsepTransport "
295*d9f75844SAndroid Build Coastguard Worker "doesn't exist. Ignore it.";
296*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
297*d9f75844SAndroid Build Coastguard Worker }
298*d9f75844SAndroid Build Coastguard Worker return jsep_transport->AddRemoteCandidates(candidates);
299*d9f75844SAndroid Build Coastguard Worker }
300*d9f75844SAndroid Build Coastguard Worker
RemoveRemoteCandidates(const cricket::Candidates & candidates)301*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::RemoveRemoteCandidates(
302*d9f75844SAndroid Build Coastguard Worker const cricket::Candidates& candidates) {
303*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
304*d9f75844SAndroid Build Coastguard Worker return network_thread_->BlockingCall(
305*d9f75844SAndroid Build Coastguard Worker [&] { return RemoveRemoteCandidates(candidates); });
306*d9f75844SAndroid Build Coastguard Worker }
307*d9f75844SAndroid Build Coastguard Worker
308*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker // Verify each candidate before passing down to the transport layer.
311*d9f75844SAndroid Build Coastguard Worker RTCError error = VerifyCandidates(candidates);
312*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
313*d9f75844SAndroid Build Coastguard Worker return error;
314*d9f75844SAndroid Build Coastguard Worker }
315*d9f75844SAndroid Build Coastguard Worker
316*d9f75844SAndroid Build Coastguard Worker std::map<std::string, cricket::Candidates> candidates_by_transport_name;
317*d9f75844SAndroid Build Coastguard Worker for (const cricket::Candidate& cand : candidates) {
318*d9f75844SAndroid Build Coastguard Worker if (!cand.transport_name().empty()) {
319*d9f75844SAndroid Build Coastguard Worker candidates_by_transport_name[cand.transport_name()].push_back(cand);
320*d9f75844SAndroid Build Coastguard Worker } else {
321*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Not removing candidate because it does not have a "
322*d9f75844SAndroid Build Coastguard Worker "transport name set: "
323*d9f75844SAndroid Build Coastguard Worker << cand.ToSensitiveString();
324*d9f75844SAndroid Build Coastguard Worker }
325*d9f75844SAndroid Build Coastguard Worker }
326*d9f75844SAndroid Build Coastguard Worker
327*d9f75844SAndroid Build Coastguard Worker for (const auto& kv : candidates_by_transport_name) {
328*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name = kv.first;
329*d9f75844SAndroid Build Coastguard Worker const cricket::Candidates& candidates = kv.second;
330*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* jsep_transport =
331*d9f75844SAndroid Build Coastguard Worker GetJsepTransportByName(transport_name);
332*d9f75844SAndroid Build Coastguard Worker if (!jsep_transport) {
333*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
334*d9f75844SAndroid Build Coastguard Worker << "Not removing candidate because the JsepTransport doesn't exist.";
335*d9f75844SAndroid Build Coastguard Worker continue;
336*d9f75844SAndroid Build Coastguard Worker }
337*d9f75844SAndroid Build Coastguard Worker for (const cricket::Candidate& candidate : candidates) {
338*d9f75844SAndroid Build Coastguard Worker cricket::DtlsTransportInternal* dtls =
339*d9f75844SAndroid Build Coastguard Worker candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
340*d9f75844SAndroid Build Coastguard Worker ? jsep_transport->rtp_dtls_transport()
341*d9f75844SAndroid Build Coastguard Worker : jsep_transport->rtcp_dtls_transport();
342*d9f75844SAndroid Build Coastguard Worker if (dtls) {
343*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->RemoveRemoteCandidate(candidate);
344*d9f75844SAndroid Build Coastguard Worker }
345*d9f75844SAndroid Build Coastguard Worker }
346*d9f75844SAndroid Build Coastguard Worker }
347*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
348*d9f75844SAndroid Build Coastguard Worker }
349*d9f75844SAndroid Build Coastguard Worker
GetStats(const std::string & transport_name,cricket::TransportStats * stats)350*d9f75844SAndroid Build Coastguard Worker bool JsepTransportController::GetStats(const std::string& transport_name,
351*d9f75844SAndroid Build Coastguard Worker cricket::TransportStats* stats) {
352*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
353*d9f75844SAndroid Build Coastguard Worker
354*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* transport = GetJsepTransportByName(transport_name);
355*d9f75844SAndroid Build Coastguard Worker if (!transport) {
356*d9f75844SAndroid Build Coastguard Worker return false;
357*d9f75844SAndroid Build Coastguard Worker }
358*d9f75844SAndroid Build Coastguard Worker return transport->GetStats(stats);
359*d9f75844SAndroid Build Coastguard Worker }
360*d9f75844SAndroid Build Coastguard Worker
SetActiveResetSrtpParams(bool active_reset_srtp_params)361*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::SetActiveResetSrtpParams(
362*d9f75844SAndroid Build Coastguard Worker bool active_reset_srtp_params) {
363*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
364*d9f75844SAndroid Build Coastguard Worker network_thread_->BlockingCall(
365*d9f75844SAndroid Build Coastguard Worker [=] { SetActiveResetSrtpParams(active_reset_srtp_params); });
366*d9f75844SAndroid Build Coastguard Worker return;
367*d9f75844SAndroid Build Coastguard Worker }
368*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
369*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO)
370*d9f75844SAndroid Build Coastguard Worker << "Updating the active_reset_srtp_params for JsepTransportController: "
371*d9f75844SAndroid Build Coastguard Worker << active_reset_srtp_params;
372*d9f75844SAndroid Build Coastguard Worker active_reset_srtp_params_ = active_reset_srtp_params;
373*d9f75844SAndroid Build Coastguard Worker for (auto& transport : transports_.Transports()) {
374*d9f75844SAndroid Build Coastguard Worker transport->SetActiveResetSrtpParams(active_reset_srtp_params);
375*d9f75844SAndroid Build Coastguard Worker }
376*d9f75844SAndroid Build Coastguard Worker }
377*d9f75844SAndroid Build Coastguard Worker
RollbackTransports()378*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::RollbackTransports() {
379*d9f75844SAndroid Build Coastguard Worker if (!network_thread_->IsCurrent()) {
380*d9f75844SAndroid Build Coastguard Worker return network_thread_->BlockingCall([=] { return RollbackTransports(); });
381*d9f75844SAndroid Build Coastguard Worker }
382*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
383*d9f75844SAndroid Build Coastguard Worker bundles_.Rollback();
384*d9f75844SAndroid Build Coastguard Worker if (!transports_.RollbackTransports()) {
385*d9f75844SAndroid Build Coastguard Worker LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
386*d9f75844SAndroid Build Coastguard Worker "Failed to roll back transport state.");
387*d9f75844SAndroid Build Coastguard Worker }
388*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
389*d9f75844SAndroid Build Coastguard Worker }
390*d9f75844SAndroid Build Coastguard Worker
391*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::IceTransportInterface>
CreateIceTransport(const std::string & transport_name,bool rtcp)392*d9f75844SAndroid Build Coastguard Worker JsepTransportController::CreateIceTransport(const std::string& transport_name,
393*d9f75844SAndroid Build Coastguard Worker bool rtcp) {
394*d9f75844SAndroid Build Coastguard Worker int component = rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
395*d9f75844SAndroid Build Coastguard Worker : cricket::ICE_CANDIDATE_COMPONENT_RTP;
396*d9f75844SAndroid Build Coastguard Worker
397*d9f75844SAndroid Build Coastguard Worker IceTransportInit init;
398*d9f75844SAndroid Build Coastguard Worker init.set_port_allocator(port_allocator_);
399*d9f75844SAndroid Build Coastguard Worker init.set_async_dns_resolver_factory(async_dns_resolver_factory_);
400*d9f75844SAndroid Build Coastguard Worker init.set_event_log(config_.event_log);
401*d9f75844SAndroid Build Coastguard Worker init.set_field_trials(config_.field_trials);
402*d9f75844SAndroid Build Coastguard Worker auto transport = config_.ice_transport_factory->CreateIceTransport(
403*d9f75844SAndroid Build Coastguard Worker transport_name, component, std::move(init));
404*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(transport);
405*d9f75844SAndroid Build Coastguard Worker transport->internal()->SetIceRole(ice_role_);
406*d9f75844SAndroid Build Coastguard Worker transport->internal()->SetIceTiebreaker(ice_tiebreaker_);
407*d9f75844SAndroid Build Coastguard Worker transport->internal()->SetIceConfig(ice_config_);
408*d9f75844SAndroid Build Coastguard Worker return transport;
409*d9f75844SAndroid Build Coastguard Worker }
410*d9f75844SAndroid Build Coastguard Worker
411*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::DtlsTransportInternal>
CreateDtlsTransport(const cricket::ContentInfo & content_info,cricket::IceTransportInternal * ice)412*d9f75844SAndroid Build Coastguard Worker JsepTransportController::CreateDtlsTransport(
413*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info,
414*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* ice) {
415*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
416*d9f75844SAndroid Build Coastguard Worker
417*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::DtlsTransportInternal> dtls;
418*d9f75844SAndroid Build Coastguard Worker
419*d9f75844SAndroid Build Coastguard Worker if (config_.dtls_transport_factory) {
420*d9f75844SAndroid Build Coastguard Worker dtls = config_.dtls_transport_factory->CreateDtlsTransport(
421*d9f75844SAndroid Build Coastguard Worker ice, config_.crypto_options, config_.ssl_max_version);
422*d9f75844SAndroid Build Coastguard Worker } else {
423*d9f75844SAndroid Build Coastguard Worker dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
424*d9f75844SAndroid Build Coastguard Worker config_.event_log,
425*d9f75844SAndroid Build Coastguard Worker config_.ssl_max_version);
426*d9f75844SAndroid Build Coastguard Worker }
427*d9f75844SAndroid Build Coastguard Worker
428*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(dtls);
429*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(ice, dtls->ice_transport());
430*d9f75844SAndroid Build Coastguard Worker
431*d9f75844SAndroid Build Coastguard Worker if (certificate_) {
432*d9f75844SAndroid Build Coastguard Worker bool set_cert_success = dtls->SetLocalCertificate(certificate_);
433*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(set_cert_success);
434*d9f75844SAndroid Build Coastguard Worker }
435*d9f75844SAndroid Build Coastguard Worker
436*d9f75844SAndroid Build Coastguard Worker // Connect to signals offered by the DTLS and ICE transport.
437*d9f75844SAndroid Build Coastguard Worker dtls->SignalWritableState.connect(
438*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportWritableState_n);
439*d9f75844SAndroid Build Coastguard Worker dtls->SignalReceivingState.connect(
440*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportReceivingState_n);
441*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalGatheringState.connect(
442*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportGatheringState_n);
443*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalCandidateGathered.connect(
444*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportCandidateGathered_n);
445*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalCandidateError.connect(
446*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportCandidateError_n);
447*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalCandidatesRemoved.connect(
448*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportCandidatesRemoved_n);
449*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalRoleConflict.connect(
450*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportRoleConflict_n);
451*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalStateChanged.connect(
452*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportStateChanged_n);
453*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalIceTransportStateChanged.connect(
454*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportStateChanged_n);
455*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SignalCandidatePairChanged.connect(
456*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnTransportCandidatePairChanged_n);
457*d9f75844SAndroid Build Coastguard Worker
458*d9f75844SAndroid Build Coastguard Worker dtls->SubscribeDtlsHandshakeError(
459*d9f75844SAndroid Build Coastguard Worker [this](rtc::SSLHandshakeError error) { OnDtlsHandshakeError(error); });
460*d9f75844SAndroid Build Coastguard Worker return dtls;
461*d9f75844SAndroid Build Coastguard Worker }
462*d9f75844SAndroid Build Coastguard Worker
463*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::RtpTransport>
CreateUnencryptedRtpTransport(const std::string & transport_name,rtc::PacketTransportInternal * rtp_packet_transport,rtc::PacketTransportInternal * rtcp_packet_transport)464*d9f75844SAndroid Build Coastguard Worker JsepTransportController::CreateUnencryptedRtpTransport(
465*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name,
466*d9f75844SAndroid Build Coastguard Worker rtc::PacketTransportInternal* rtp_packet_transport,
467*d9f75844SAndroid Build Coastguard Worker rtc::PacketTransportInternal* rtcp_packet_transport) {
468*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
469*d9f75844SAndroid Build Coastguard Worker auto unencrypted_rtp_transport =
470*d9f75844SAndroid Build Coastguard Worker std::make_unique<RtpTransport>(rtcp_packet_transport == nullptr);
471*d9f75844SAndroid Build Coastguard Worker unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport);
472*d9f75844SAndroid Build Coastguard Worker if (rtcp_packet_transport) {
473*d9f75844SAndroid Build Coastguard Worker unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
474*d9f75844SAndroid Build Coastguard Worker }
475*d9f75844SAndroid Build Coastguard Worker return unencrypted_rtp_transport;
476*d9f75844SAndroid Build Coastguard Worker }
477*d9f75844SAndroid Build Coastguard Worker
478*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::SrtpTransport>
CreateSdesTransport(const std::string & transport_name,cricket::DtlsTransportInternal * rtp_dtls_transport,cricket::DtlsTransportInternal * rtcp_dtls_transport)479*d9f75844SAndroid Build Coastguard Worker JsepTransportController::CreateSdesTransport(
480*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name,
481*d9f75844SAndroid Build Coastguard Worker cricket::DtlsTransportInternal* rtp_dtls_transport,
482*d9f75844SAndroid Build Coastguard Worker cricket::DtlsTransportInternal* rtcp_dtls_transport) {
483*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
484*d9f75844SAndroid Build Coastguard Worker auto srtp_transport = std::make_unique<webrtc::SrtpTransport>(
485*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport == nullptr, *config_.field_trials);
486*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport);
487*d9f75844SAndroid Build Coastguard Worker srtp_transport->SetRtpPacketTransport(rtp_dtls_transport);
488*d9f75844SAndroid Build Coastguard Worker if (rtcp_dtls_transport) {
489*d9f75844SAndroid Build Coastguard Worker srtp_transport->SetRtcpPacketTransport(rtcp_dtls_transport);
490*d9f75844SAndroid Build Coastguard Worker }
491*d9f75844SAndroid Build Coastguard Worker if (config_.enable_external_auth) {
492*d9f75844SAndroid Build Coastguard Worker srtp_transport->EnableExternalAuth();
493*d9f75844SAndroid Build Coastguard Worker }
494*d9f75844SAndroid Build Coastguard Worker return srtp_transport;
495*d9f75844SAndroid Build Coastguard Worker }
496*d9f75844SAndroid Build Coastguard Worker
497*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::DtlsSrtpTransport>
CreateDtlsSrtpTransport(const std::string & transport_name,cricket::DtlsTransportInternal * rtp_dtls_transport,cricket::DtlsTransportInternal * rtcp_dtls_transport)498*d9f75844SAndroid Build Coastguard Worker JsepTransportController::CreateDtlsSrtpTransport(
499*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name,
500*d9f75844SAndroid Build Coastguard Worker cricket::DtlsTransportInternal* rtp_dtls_transport,
501*d9f75844SAndroid Build Coastguard Worker cricket::DtlsTransportInternal* rtcp_dtls_transport) {
502*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
503*d9f75844SAndroid Build Coastguard Worker auto dtls_srtp_transport = std::make_unique<webrtc::DtlsSrtpTransport>(
504*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport == nullptr, *config_.field_trials);
505*d9f75844SAndroid Build Coastguard Worker if (config_.enable_external_auth) {
506*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport->EnableExternalAuth();
507*d9f75844SAndroid Build Coastguard Worker }
508*d9f75844SAndroid Build Coastguard Worker
509*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport->SetDtlsTransports(rtp_dtls_transport,
510*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport);
511*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport->SetActiveResetSrtpParams(active_reset_srtp_params_);
512*d9f75844SAndroid Build Coastguard Worker // Capturing this in the callback because JsepTransportController will always
513*d9f75844SAndroid Build Coastguard Worker // outlive the DtlsSrtpTransport.
514*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport->SetOnDtlsStateChange([this]() {
515*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(this->network_thread_);
516*d9f75844SAndroid Build Coastguard Worker this->UpdateAggregateStates_n();
517*d9f75844SAndroid Build Coastguard Worker });
518*d9f75844SAndroid Build Coastguard Worker return dtls_srtp_transport;
519*d9f75844SAndroid Build Coastguard Worker }
520*d9f75844SAndroid Build Coastguard Worker
521*d9f75844SAndroid Build Coastguard Worker std::vector<cricket::DtlsTransportInternal*>
GetDtlsTransports()522*d9f75844SAndroid Build Coastguard Worker JsepTransportController::GetDtlsTransports() {
523*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
524*d9f75844SAndroid Build Coastguard Worker std::vector<cricket::DtlsTransportInternal*> dtls_transports;
525*d9f75844SAndroid Build Coastguard Worker for (auto jsep_transport : transports_.Transports()) {
526*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(jsep_transport);
527*d9f75844SAndroid Build Coastguard Worker if (jsep_transport->rtp_dtls_transport()) {
528*d9f75844SAndroid Build Coastguard Worker dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
529*d9f75844SAndroid Build Coastguard Worker }
530*d9f75844SAndroid Build Coastguard Worker
531*d9f75844SAndroid Build Coastguard Worker if (jsep_transport->rtcp_dtls_transport()) {
532*d9f75844SAndroid Build Coastguard Worker dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
533*d9f75844SAndroid Build Coastguard Worker }
534*d9f75844SAndroid Build Coastguard Worker }
535*d9f75844SAndroid Build Coastguard Worker return dtls_transports;
536*d9f75844SAndroid Build Coastguard Worker }
537*d9f75844SAndroid Build Coastguard Worker
538*d9f75844SAndroid Build Coastguard Worker std::vector<cricket::DtlsTransportInternal*>
GetActiveDtlsTransports()539*d9f75844SAndroid Build Coastguard Worker JsepTransportController::GetActiveDtlsTransports() {
540*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
541*d9f75844SAndroid Build Coastguard Worker std::vector<cricket::DtlsTransportInternal*> dtls_transports;
542*d9f75844SAndroid Build Coastguard Worker for (auto jsep_transport : transports_.ActiveTransports()) {
543*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(jsep_transport);
544*d9f75844SAndroid Build Coastguard Worker if (jsep_transport->rtp_dtls_transport()) {
545*d9f75844SAndroid Build Coastguard Worker dtls_transports.push_back(jsep_transport->rtp_dtls_transport());
546*d9f75844SAndroid Build Coastguard Worker }
547*d9f75844SAndroid Build Coastguard Worker
548*d9f75844SAndroid Build Coastguard Worker if (jsep_transport->rtcp_dtls_transport()) {
549*d9f75844SAndroid Build Coastguard Worker dtls_transports.push_back(jsep_transport->rtcp_dtls_transport());
550*d9f75844SAndroid Build Coastguard Worker }
551*d9f75844SAndroid Build Coastguard Worker }
552*d9f75844SAndroid Build Coastguard Worker return dtls_transports;
553*d9f75844SAndroid Build Coastguard Worker }
554*d9f75844SAndroid Build Coastguard Worker
ApplyDescription_n(bool local,SdpType type,const cricket::SessionDescription * description)555*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::ApplyDescription_n(
556*d9f75844SAndroid Build Coastguard Worker bool local,
557*d9f75844SAndroid Build Coastguard Worker SdpType type,
558*d9f75844SAndroid Build Coastguard Worker const cricket::SessionDescription* description) {
559*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransportController::ApplyDescription_n");
560*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(description);
561*d9f75844SAndroid Build Coastguard Worker
562*d9f75844SAndroid Build Coastguard Worker if (local) {
563*d9f75844SAndroid Build Coastguard Worker local_desc_ = description;
564*d9f75844SAndroid Build Coastguard Worker } else {
565*d9f75844SAndroid Build Coastguard Worker remote_desc_ = description;
566*d9f75844SAndroid Build Coastguard Worker }
567*d9f75844SAndroid Build Coastguard Worker
568*d9f75844SAndroid Build Coastguard Worker RTCError error;
569*d9f75844SAndroid Build Coastguard Worker error = ValidateAndMaybeUpdateBundleGroups(local, type, description);
570*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
571*d9f75844SAndroid Build Coastguard Worker return error;
572*d9f75844SAndroid Build Coastguard Worker }
573*d9f75844SAndroid Build Coastguard Worker
574*d9f75844SAndroid Build Coastguard Worker std::map<const cricket::ContentGroup*, std::vector<int>>
575*d9f75844SAndroid Build Coastguard Worker merged_encrypted_extension_ids_by_bundle;
576*d9f75844SAndroid Build Coastguard Worker if (!bundles_.bundle_groups().empty()) {
577*d9f75844SAndroid Build Coastguard Worker merged_encrypted_extension_ids_by_bundle =
578*d9f75844SAndroid Build Coastguard Worker MergeEncryptedHeaderExtensionIdsForBundles(description);
579*d9f75844SAndroid Build Coastguard Worker }
580*d9f75844SAndroid Build Coastguard Worker
581*d9f75844SAndroid Build Coastguard Worker for (const cricket::ContentInfo& content_info : description->contents()) {
582*d9f75844SAndroid Build Coastguard Worker // Don't create transports for rejected m-lines and bundled m-lines.
583*d9f75844SAndroid Build Coastguard Worker if (content_info.rejected ||
584*d9f75844SAndroid Build Coastguard Worker !bundles_.IsFirstMidInGroup(content_info.name)) {
585*d9f75844SAndroid Build Coastguard Worker continue;
586*d9f75844SAndroid Build Coastguard Worker }
587*d9f75844SAndroid Build Coastguard Worker error = MaybeCreateJsepTransport(local, content_info, *description);
588*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
589*d9f75844SAndroid Build Coastguard Worker return error;
590*d9f75844SAndroid Build Coastguard Worker }
591*d9f75844SAndroid Build Coastguard Worker }
592*d9f75844SAndroid Build Coastguard Worker
593*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(description->contents().size() ==
594*d9f75844SAndroid Build Coastguard Worker description->transport_infos().size());
595*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < description->contents().size(); ++i) {
596*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info = description->contents()[i];
597*d9f75844SAndroid Build Coastguard Worker const cricket::TransportInfo& transport_info =
598*d9f75844SAndroid Build Coastguard Worker description->transport_infos()[i];
599*d9f75844SAndroid Build Coastguard Worker
600*d9f75844SAndroid Build Coastguard Worker if (content_info.rejected) {
601*d9f75844SAndroid Build Coastguard Worker // This may cause groups to be removed from |bundles_.bundle_groups()|.
602*d9f75844SAndroid Build Coastguard Worker HandleRejectedContent(content_info);
603*d9f75844SAndroid Build Coastguard Worker continue;
604*d9f75844SAndroid Build Coastguard Worker }
605*d9f75844SAndroid Build Coastguard Worker
606*d9f75844SAndroid Build Coastguard Worker const cricket::ContentGroup* established_bundle_group =
607*d9f75844SAndroid Build Coastguard Worker bundles_.LookupGroupByMid(content_info.name);
608*d9f75844SAndroid Build Coastguard Worker
609*d9f75844SAndroid Build Coastguard Worker // For bundle members that are not BUNDLE-tagged (not first in the group),
610*d9f75844SAndroid Build Coastguard Worker // configure their transport to be the same as the BUNDLE-tagged transport.
611*d9f75844SAndroid Build Coastguard Worker if (established_bundle_group &&
612*d9f75844SAndroid Build Coastguard Worker content_info.name != *established_bundle_group->FirstContentName()) {
613*d9f75844SAndroid Build Coastguard Worker if (!HandleBundledContent(content_info, *established_bundle_group)) {
614*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
615*d9f75844SAndroid Build Coastguard Worker "Failed to process the bundled m= section with "
616*d9f75844SAndroid Build Coastguard Worker "mid='" +
617*d9f75844SAndroid Build Coastguard Worker content_info.name + "'.");
618*d9f75844SAndroid Build Coastguard Worker }
619*d9f75844SAndroid Build Coastguard Worker continue;
620*d9f75844SAndroid Build Coastguard Worker }
621*d9f75844SAndroid Build Coastguard Worker
622*d9f75844SAndroid Build Coastguard Worker error = ValidateContent(content_info);
623*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
624*d9f75844SAndroid Build Coastguard Worker return error;
625*d9f75844SAndroid Build Coastguard Worker }
626*d9f75844SAndroid Build Coastguard Worker
627*d9f75844SAndroid Build Coastguard Worker std::vector<int> extension_ids;
628*d9f75844SAndroid Build Coastguard Worker // Is BUNDLE-tagged (first in the group)?
629*d9f75844SAndroid Build Coastguard Worker if (established_bundle_group &&
630*d9f75844SAndroid Build Coastguard Worker content_info.name == *established_bundle_group->FirstContentName()) {
631*d9f75844SAndroid Build Coastguard Worker auto it = merged_encrypted_extension_ids_by_bundle.find(
632*d9f75844SAndroid Build Coastguard Worker established_bundle_group);
633*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(it != merged_encrypted_extension_ids_by_bundle.end());
634*d9f75844SAndroid Build Coastguard Worker extension_ids = it->second;
635*d9f75844SAndroid Build Coastguard Worker } else {
636*d9f75844SAndroid Build Coastguard Worker extension_ids = GetEncryptedHeaderExtensionIds(content_info);
637*d9f75844SAndroid Build Coastguard Worker }
638*d9f75844SAndroid Build Coastguard Worker
639*d9f75844SAndroid Build Coastguard Worker int rtp_abs_sendtime_extn_id =
640*d9f75844SAndroid Build Coastguard Worker GetRtpAbsSendTimeHeaderExtensionId(content_info);
641*d9f75844SAndroid Build Coastguard Worker
642*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* transport =
643*d9f75844SAndroid Build Coastguard Worker GetJsepTransportForMid(content_info.name);
644*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(transport);
645*d9f75844SAndroid Build Coastguard Worker
646*d9f75844SAndroid Build Coastguard Worker SetIceRole_n(DetermineIceRole(transport, transport_info, type, local));
647*d9f75844SAndroid Build Coastguard Worker
648*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransportDescription jsep_description =
649*d9f75844SAndroid Build Coastguard Worker CreateJsepTransportDescription(content_info, transport_info,
650*d9f75844SAndroid Build Coastguard Worker extension_ids, rtp_abs_sendtime_extn_id);
651*d9f75844SAndroid Build Coastguard Worker if (local) {
652*d9f75844SAndroid Build Coastguard Worker error =
653*d9f75844SAndroid Build Coastguard Worker transport->SetLocalJsepTransportDescription(jsep_description, type);
654*d9f75844SAndroid Build Coastguard Worker } else {
655*d9f75844SAndroid Build Coastguard Worker error =
656*d9f75844SAndroid Build Coastguard Worker transport->SetRemoteJsepTransportDescription(jsep_description, type);
657*d9f75844SAndroid Build Coastguard Worker }
658*d9f75844SAndroid Build Coastguard Worker
659*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
660*d9f75844SAndroid Build Coastguard Worker LOG_AND_RETURN_ERROR(
661*d9f75844SAndroid Build Coastguard Worker RTCErrorType::INVALID_PARAMETER,
662*d9f75844SAndroid Build Coastguard Worker "Failed to apply the description for m= section with mid='" +
663*d9f75844SAndroid Build Coastguard Worker content_info.name + "': " + error.message());
664*d9f75844SAndroid Build Coastguard Worker }
665*d9f75844SAndroid Build Coastguard Worker }
666*d9f75844SAndroid Build Coastguard Worker if (type == SdpType::kAnswer) {
667*d9f75844SAndroid Build Coastguard Worker transports_.CommitTransports();
668*d9f75844SAndroid Build Coastguard Worker bundles_.Commit();
669*d9f75844SAndroid Build Coastguard Worker }
670*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
671*d9f75844SAndroid Build Coastguard Worker }
672*d9f75844SAndroid Build Coastguard Worker
ValidateAndMaybeUpdateBundleGroups(bool local,SdpType type,const cricket::SessionDescription * description)673*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroups(
674*d9f75844SAndroid Build Coastguard Worker bool local,
675*d9f75844SAndroid Build Coastguard Worker SdpType type,
676*d9f75844SAndroid Build Coastguard Worker const cricket::SessionDescription* description) {
677*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(description);
678*d9f75844SAndroid Build Coastguard Worker
679*d9f75844SAndroid Build Coastguard Worker std::vector<const cricket::ContentGroup*> new_bundle_groups =
680*d9f75844SAndroid Build Coastguard Worker description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
681*d9f75844SAndroid Build Coastguard Worker // Verify `new_bundle_groups`.
682*d9f75844SAndroid Build Coastguard Worker std::map<std::string, const cricket::ContentGroup*> new_bundle_groups_by_mid;
683*d9f75844SAndroid Build Coastguard Worker for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
684*d9f75844SAndroid Build Coastguard Worker for (const std::string& content_name : new_bundle_group->content_names()) {
685*d9f75844SAndroid Build Coastguard Worker // The BUNDLE group must not contain a MID that is a member of a different
686*d9f75844SAndroid Build Coastguard Worker // BUNDLE group, or that contains the same MID multiple times.
687*d9f75844SAndroid Build Coastguard Worker if (new_bundle_groups_by_mid.find(content_name) !=
688*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_mid.end()) {
689*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
690*d9f75844SAndroid Build Coastguard Worker "A BUNDLE group contains a MID='" + content_name +
691*d9f75844SAndroid Build Coastguard Worker "' that is already in a BUNDLE group.");
692*d9f75844SAndroid Build Coastguard Worker }
693*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_mid.insert(
694*d9f75844SAndroid Build Coastguard Worker std::make_pair(content_name, new_bundle_group));
695*d9f75844SAndroid Build Coastguard Worker // The BUNDLE group must not contain a MID that no m= section has.
696*d9f75844SAndroid Build Coastguard Worker if (!description->GetContentByName(content_name)) {
697*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
698*d9f75844SAndroid Build Coastguard Worker "A BUNDLE group contains a MID='" + content_name +
699*d9f75844SAndroid Build Coastguard Worker "' matching no m= section.");
700*d9f75844SAndroid Build Coastguard Worker }
701*d9f75844SAndroid Build Coastguard Worker }
702*d9f75844SAndroid Build Coastguard Worker }
703*d9f75844SAndroid Build Coastguard Worker
704*d9f75844SAndroid Build Coastguard Worker if (type == SdpType::kOffer) {
705*d9f75844SAndroid Build Coastguard Worker // For an offer, we need to verify that there is not a conflicting mapping
706*d9f75844SAndroid Build Coastguard Worker // between existing and new bundle groups. For example, if the existing
707*d9f75844SAndroid Build Coastguard Worker // groups are [[1,2],[3,4]] and new are [[1,3],[2,4]] or [[1,2,3,4]], or
708*d9f75844SAndroid Build Coastguard Worker // vice versa. Switching things around like this requires a separate offer
709*d9f75844SAndroid Build Coastguard Worker // that removes the relevant sections from their group, as per RFC 8843,
710*d9f75844SAndroid Build Coastguard Worker // section 7.5.2.
711*d9f75844SAndroid Build Coastguard Worker std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
712*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_existing_bundle_groups;
713*d9f75844SAndroid Build Coastguard Worker std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
714*d9f75844SAndroid Build Coastguard Worker existing_bundle_groups_by_new_bundle_groups;
715*d9f75844SAndroid Build Coastguard Worker for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
716*d9f75844SAndroid Build Coastguard Worker for (const std::string& mid : new_bundle_group->content_names()) {
717*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup* existing_bundle_group =
718*d9f75844SAndroid Build Coastguard Worker bundles_.LookupGroupByMid(mid);
719*d9f75844SAndroid Build Coastguard Worker if (!existing_bundle_group) {
720*d9f75844SAndroid Build Coastguard Worker continue;
721*d9f75844SAndroid Build Coastguard Worker }
722*d9f75844SAndroid Build Coastguard Worker auto it = new_bundle_groups_by_existing_bundle_groups.find(
723*d9f75844SAndroid Build Coastguard Worker existing_bundle_group);
724*d9f75844SAndroid Build Coastguard Worker if (it != new_bundle_groups_by_existing_bundle_groups.end() &&
725*d9f75844SAndroid Build Coastguard Worker it->second != new_bundle_group) {
726*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
727*d9f75844SAndroid Build Coastguard Worker "MID " + mid + " in the offer has changed group.");
728*d9f75844SAndroid Build Coastguard Worker }
729*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_existing_bundle_groups.insert(
730*d9f75844SAndroid Build Coastguard Worker std::make_pair(existing_bundle_group, new_bundle_group));
731*d9f75844SAndroid Build Coastguard Worker it = existing_bundle_groups_by_new_bundle_groups.find(new_bundle_group);
732*d9f75844SAndroid Build Coastguard Worker if (it != existing_bundle_groups_by_new_bundle_groups.end() &&
733*d9f75844SAndroid Build Coastguard Worker it->second != existing_bundle_group) {
734*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
735*d9f75844SAndroid Build Coastguard Worker "MID " + mid + " in the offer has changed group.");
736*d9f75844SAndroid Build Coastguard Worker }
737*d9f75844SAndroid Build Coastguard Worker existing_bundle_groups_by_new_bundle_groups.insert(
738*d9f75844SAndroid Build Coastguard Worker std::make_pair(new_bundle_group, existing_bundle_group));
739*d9f75844SAndroid Build Coastguard Worker }
740*d9f75844SAndroid Build Coastguard Worker }
741*d9f75844SAndroid Build Coastguard Worker } else if (type == SdpType::kAnswer) {
742*d9f75844SAndroid Build Coastguard Worker std::vector<const cricket::ContentGroup*> offered_bundle_groups =
743*d9f75844SAndroid Build Coastguard Worker local ? remote_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)
744*d9f75844SAndroid Build Coastguard Worker : local_desc_->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
745*d9f75844SAndroid Build Coastguard Worker
746*d9f75844SAndroid Build Coastguard Worker std::map<std::string, const cricket::ContentGroup*>
747*d9f75844SAndroid Build Coastguard Worker offered_bundle_groups_by_mid;
748*d9f75844SAndroid Build Coastguard Worker for (const cricket::ContentGroup* offered_bundle_group :
749*d9f75844SAndroid Build Coastguard Worker offered_bundle_groups) {
750*d9f75844SAndroid Build Coastguard Worker for (const std::string& content_name :
751*d9f75844SAndroid Build Coastguard Worker offered_bundle_group->content_names()) {
752*d9f75844SAndroid Build Coastguard Worker offered_bundle_groups_by_mid[content_name] = offered_bundle_group;
753*d9f75844SAndroid Build Coastguard Worker }
754*d9f75844SAndroid Build Coastguard Worker }
755*d9f75844SAndroid Build Coastguard Worker
756*d9f75844SAndroid Build Coastguard Worker std::map<const cricket::ContentGroup*, const cricket::ContentGroup*>
757*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_offered_bundle_groups;
758*d9f75844SAndroid Build Coastguard Worker for (const cricket::ContentGroup* new_bundle_group : new_bundle_groups) {
759*d9f75844SAndroid Build Coastguard Worker if (!new_bundle_group->FirstContentName()) {
760*d9f75844SAndroid Build Coastguard Worker // Empty groups could be a subset of any group.
761*d9f75844SAndroid Build Coastguard Worker continue;
762*d9f75844SAndroid Build Coastguard Worker }
763*d9f75844SAndroid Build Coastguard Worker // The group in the answer (new_bundle_group) must have a corresponding
764*d9f75844SAndroid Build Coastguard Worker // group in the offer (original_group), because the answer groups may only
765*d9f75844SAndroid Build Coastguard Worker // be subsets of the offer groups.
766*d9f75844SAndroid Build Coastguard Worker auto it = offered_bundle_groups_by_mid.find(
767*d9f75844SAndroid Build Coastguard Worker *new_bundle_group->FirstContentName());
768*d9f75844SAndroid Build Coastguard Worker if (it == offered_bundle_groups_by_mid.end()) {
769*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
770*d9f75844SAndroid Build Coastguard Worker "A BUNDLE group was added in the answer that did not "
771*d9f75844SAndroid Build Coastguard Worker "exist in the offer.");
772*d9f75844SAndroid Build Coastguard Worker }
773*d9f75844SAndroid Build Coastguard Worker const cricket::ContentGroup* offered_bundle_group = it->second;
774*d9f75844SAndroid Build Coastguard Worker if (new_bundle_groups_by_offered_bundle_groups.find(
775*d9f75844SAndroid Build Coastguard Worker offered_bundle_group) !=
776*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_offered_bundle_groups.end()) {
777*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
778*d9f75844SAndroid Build Coastguard Worker "A MID in the answer has changed group.");
779*d9f75844SAndroid Build Coastguard Worker }
780*d9f75844SAndroid Build Coastguard Worker new_bundle_groups_by_offered_bundle_groups.insert(
781*d9f75844SAndroid Build Coastguard Worker std::make_pair(offered_bundle_group, new_bundle_group));
782*d9f75844SAndroid Build Coastguard Worker for (const std::string& content_name :
783*d9f75844SAndroid Build Coastguard Worker new_bundle_group->content_names()) {
784*d9f75844SAndroid Build Coastguard Worker it = offered_bundle_groups_by_mid.find(content_name);
785*d9f75844SAndroid Build Coastguard Worker // The BUNDLE group in answer should be a subset of offered group.
786*d9f75844SAndroid Build Coastguard Worker if (it == offered_bundle_groups_by_mid.end() ||
787*d9f75844SAndroid Build Coastguard Worker it->second != offered_bundle_group) {
788*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
789*d9f75844SAndroid Build Coastguard Worker "A BUNDLE group in answer contains a MID='" +
790*d9f75844SAndroid Build Coastguard Worker content_name +
791*d9f75844SAndroid Build Coastguard Worker "' that was not in the offered group.");
792*d9f75844SAndroid Build Coastguard Worker }
793*d9f75844SAndroid Build Coastguard Worker }
794*d9f75844SAndroid Build Coastguard Worker }
795*d9f75844SAndroid Build Coastguard Worker
796*d9f75844SAndroid Build Coastguard Worker for (const auto& bundle_group : bundles_.bundle_groups()) {
797*d9f75844SAndroid Build Coastguard Worker for (const std::string& content_name : bundle_group->content_names()) {
798*d9f75844SAndroid Build Coastguard Worker // An answer that removes m= sections from pre-negotiated BUNDLE group
799*d9f75844SAndroid Build Coastguard Worker // without rejecting it, is invalid.
800*d9f75844SAndroid Build Coastguard Worker auto it = new_bundle_groups_by_mid.find(content_name);
801*d9f75844SAndroid Build Coastguard Worker if (it == new_bundle_groups_by_mid.end()) {
802*d9f75844SAndroid Build Coastguard Worker auto* content_info = description->GetContentByName(content_name);
803*d9f75844SAndroid Build Coastguard Worker if (!content_info || !content_info->rejected) {
804*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
805*d9f75844SAndroid Build Coastguard Worker "Answer cannot remove m= section with mid='" +
806*d9f75844SAndroid Build Coastguard Worker content_name +
807*d9f75844SAndroid Build Coastguard Worker "' from already-established BUNDLE group.");
808*d9f75844SAndroid Build Coastguard Worker }
809*d9f75844SAndroid Build Coastguard Worker }
810*d9f75844SAndroid Build Coastguard Worker }
811*d9f75844SAndroid Build Coastguard Worker }
812*d9f75844SAndroid Build Coastguard Worker }
813*d9f75844SAndroid Build Coastguard Worker
814*d9f75844SAndroid Build Coastguard Worker if (config_.bundle_policy ==
815*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kBundlePolicyMaxBundle &&
816*d9f75844SAndroid Build Coastguard Worker !description->HasGroup(cricket::GROUP_TYPE_BUNDLE)) {
817*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
818*d9f75844SAndroid Build Coastguard Worker "max-bundle is used but no bundle group found.");
819*d9f75844SAndroid Build Coastguard Worker }
820*d9f75844SAndroid Build Coastguard Worker
821*d9f75844SAndroid Build Coastguard Worker bundles_.Update(description, type);
822*d9f75844SAndroid Build Coastguard Worker
823*d9f75844SAndroid Build Coastguard Worker for (const auto& bundle_group : bundles_.bundle_groups()) {
824*d9f75844SAndroid Build Coastguard Worker if (!bundle_group->FirstContentName())
825*d9f75844SAndroid Build Coastguard Worker continue;
826*d9f75844SAndroid Build Coastguard Worker
827*d9f75844SAndroid Build Coastguard Worker // The first MID in a BUNDLE group is BUNDLE-tagged.
828*d9f75844SAndroid Build Coastguard Worker auto bundled_content =
829*d9f75844SAndroid Build Coastguard Worker description->GetContentByName(*bundle_group->FirstContentName());
830*d9f75844SAndroid Build Coastguard Worker if (!bundled_content) {
831*d9f75844SAndroid Build Coastguard Worker return RTCError(
832*d9f75844SAndroid Build Coastguard Worker RTCErrorType::INVALID_PARAMETER,
833*d9f75844SAndroid Build Coastguard Worker "An m= section associated with the BUNDLE-tag doesn't exist.");
834*d9f75844SAndroid Build Coastguard Worker }
835*d9f75844SAndroid Build Coastguard Worker
836*d9f75844SAndroid Build Coastguard Worker // If the `bundled_content` is rejected, other contents in the bundle group
837*d9f75844SAndroid Build Coastguard Worker // must also be rejected.
838*d9f75844SAndroid Build Coastguard Worker if (bundled_content->rejected) {
839*d9f75844SAndroid Build Coastguard Worker for (const auto& content_name : bundle_group->content_names()) {
840*d9f75844SAndroid Build Coastguard Worker auto other_content = description->GetContentByName(content_name);
841*d9f75844SAndroid Build Coastguard Worker if (!other_content->rejected) {
842*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
843*d9f75844SAndroid Build Coastguard Worker "The m= section with mid='" + content_name +
844*d9f75844SAndroid Build Coastguard Worker "' should be rejected.");
845*d9f75844SAndroid Build Coastguard Worker }
846*d9f75844SAndroid Build Coastguard Worker }
847*d9f75844SAndroid Build Coastguard Worker }
848*d9f75844SAndroid Build Coastguard Worker }
849*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
850*d9f75844SAndroid Build Coastguard Worker }
851*d9f75844SAndroid Build Coastguard Worker
ValidateContent(const cricket::ContentInfo & content_info)852*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::ValidateContent(
853*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info) {
854*d9f75844SAndroid Build Coastguard Worker if (config_.rtcp_mux_policy ==
855*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kRtcpMuxPolicyRequire &&
856*d9f75844SAndroid Build Coastguard Worker content_info.type == cricket::MediaProtocolType::kRtp &&
857*d9f75844SAndroid Build Coastguard Worker !content_info.media_description()->rtcp_mux()) {
858*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
859*d9f75844SAndroid Build Coastguard Worker "The m= section with mid='" + content_info.name +
860*d9f75844SAndroid Build Coastguard Worker "' is invalid. RTCP-MUX is not "
861*d9f75844SAndroid Build Coastguard Worker "enabled when it is required.");
862*d9f75844SAndroid Build Coastguard Worker }
863*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
864*d9f75844SAndroid Build Coastguard Worker }
865*d9f75844SAndroid Build Coastguard Worker
HandleRejectedContent(const cricket::ContentInfo & content_info)866*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::HandleRejectedContent(
867*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info) {
868*d9f75844SAndroid Build Coastguard Worker // If the content is rejected, let the
869*d9f75844SAndroid Build Coastguard Worker // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
870*d9f75844SAndroid Build Coastguard Worker // then destroy the cricket::JsepTransport.
871*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup* bundle_group =
872*d9f75844SAndroid Build Coastguard Worker bundles_.LookupGroupByMid(content_info.name);
873*d9f75844SAndroid Build Coastguard Worker if (bundle_group && !bundle_group->content_names().empty() &&
874*d9f75844SAndroid Build Coastguard Worker content_info.name == *bundle_group->FirstContentName()) {
875*d9f75844SAndroid Build Coastguard Worker // Rejecting a BUNDLE group's first mid means we are rejecting the entire
876*d9f75844SAndroid Build Coastguard Worker // group.
877*d9f75844SAndroid Build Coastguard Worker for (const auto& content_name : bundle_group->content_names()) {
878*d9f75844SAndroid Build Coastguard Worker transports_.RemoveTransportForMid(content_name);
879*d9f75844SAndroid Build Coastguard Worker }
880*d9f75844SAndroid Build Coastguard Worker // Delete the BUNDLE group.
881*d9f75844SAndroid Build Coastguard Worker bundles_.DeleteGroup(bundle_group);
882*d9f75844SAndroid Build Coastguard Worker } else {
883*d9f75844SAndroid Build Coastguard Worker transports_.RemoveTransportForMid(content_info.name);
884*d9f75844SAndroid Build Coastguard Worker if (bundle_group) {
885*d9f75844SAndroid Build Coastguard Worker // Remove the rejected content from the `bundle_group`.
886*d9f75844SAndroid Build Coastguard Worker bundles_.DeleteMid(bundle_group, content_info.name);
887*d9f75844SAndroid Build Coastguard Worker }
888*d9f75844SAndroid Build Coastguard Worker }
889*d9f75844SAndroid Build Coastguard Worker }
890*d9f75844SAndroid Build Coastguard Worker
HandleBundledContent(const cricket::ContentInfo & content_info,const cricket::ContentGroup & bundle_group)891*d9f75844SAndroid Build Coastguard Worker bool JsepTransportController::HandleBundledContent(
892*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info,
893*d9f75844SAndroid Build Coastguard Worker const cricket::ContentGroup& bundle_group) {
894*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransportController::HandleBundledContent");
895*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(bundle_group.FirstContentName());
896*d9f75844SAndroid Build Coastguard Worker auto jsep_transport =
897*d9f75844SAndroid Build Coastguard Worker GetJsepTransportByName(*bundle_group.FirstContentName());
898*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(jsep_transport);
899*d9f75844SAndroid Build Coastguard Worker // If the content is bundled, let the
900*d9f75844SAndroid Build Coastguard Worker // BaseChannel/SctpTransport change the RtpTransport/DtlsTransport first,
901*d9f75844SAndroid Build Coastguard Worker // then destroy the cricket::JsepTransport.
902*d9f75844SAndroid Build Coastguard Worker // TODO(bugs.webrtc.org/9719) For media transport this is far from ideal,
903*d9f75844SAndroid Build Coastguard Worker // because it means that we first create media transport and start
904*d9f75844SAndroid Build Coastguard Worker // connecting it, and then we destroy it. We will need to address it before
905*d9f75844SAndroid Build Coastguard Worker // video path is enabled.
906*d9f75844SAndroid Build Coastguard Worker return transports_.SetTransportForMid(content_info.name, jsep_transport);
907*d9f75844SAndroid Build Coastguard Worker }
908*d9f75844SAndroid Build Coastguard Worker
909*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransportDescription
CreateJsepTransportDescription(const cricket::ContentInfo & content_info,const cricket::TransportInfo & transport_info,const std::vector<int> & encrypted_extension_ids,int rtp_abs_sendtime_extn_id)910*d9f75844SAndroid Build Coastguard Worker JsepTransportController::CreateJsepTransportDescription(
911*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info,
912*d9f75844SAndroid Build Coastguard Worker const cricket::TransportInfo& transport_info,
913*d9f75844SAndroid Build Coastguard Worker const std::vector<int>& encrypted_extension_ids,
914*d9f75844SAndroid Build Coastguard Worker int rtp_abs_sendtime_extn_id) {
915*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc",
916*d9f75844SAndroid Build Coastguard Worker "JsepTransportController::CreateJsepTransportDescription");
917*d9f75844SAndroid Build Coastguard Worker const cricket::MediaContentDescription* content_desc =
918*d9f75844SAndroid Build Coastguard Worker content_info.media_description();
919*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(content_desc);
920*d9f75844SAndroid Build Coastguard Worker bool rtcp_mux_enabled = content_info.type == cricket::MediaProtocolType::kSctp
921*d9f75844SAndroid Build Coastguard Worker ? true
922*d9f75844SAndroid Build Coastguard Worker : content_desc->rtcp_mux();
923*d9f75844SAndroid Build Coastguard Worker
924*d9f75844SAndroid Build Coastguard Worker return cricket::JsepTransportDescription(
925*d9f75844SAndroid Build Coastguard Worker rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids,
926*d9f75844SAndroid Build Coastguard Worker rtp_abs_sendtime_extn_id, transport_info.description);
927*d9f75844SAndroid Build Coastguard Worker }
928*d9f75844SAndroid Build Coastguard Worker
GetEncryptedHeaderExtensionIds(const cricket::ContentInfo & content_info)929*d9f75844SAndroid Build Coastguard Worker std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
930*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info) {
931*d9f75844SAndroid Build Coastguard Worker const cricket::MediaContentDescription* content_desc =
932*d9f75844SAndroid Build Coastguard Worker content_info.media_description();
933*d9f75844SAndroid Build Coastguard Worker
934*d9f75844SAndroid Build Coastguard Worker if (!config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions) {
935*d9f75844SAndroid Build Coastguard Worker return std::vector<int>();
936*d9f75844SAndroid Build Coastguard Worker }
937*d9f75844SAndroid Build Coastguard Worker
938*d9f75844SAndroid Build Coastguard Worker std::vector<int> encrypted_header_extension_ids;
939*d9f75844SAndroid Build Coastguard Worker for (const auto& extension : content_desc->rtp_header_extensions()) {
940*d9f75844SAndroid Build Coastguard Worker if (!extension.encrypt) {
941*d9f75844SAndroid Build Coastguard Worker continue;
942*d9f75844SAndroid Build Coastguard Worker }
943*d9f75844SAndroid Build Coastguard Worker if (!absl::c_linear_search(encrypted_header_extension_ids, extension.id)) {
944*d9f75844SAndroid Build Coastguard Worker encrypted_header_extension_ids.push_back(extension.id);
945*d9f75844SAndroid Build Coastguard Worker }
946*d9f75844SAndroid Build Coastguard Worker }
947*d9f75844SAndroid Build Coastguard Worker return encrypted_header_extension_ids;
948*d9f75844SAndroid Build Coastguard Worker }
949*d9f75844SAndroid Build Coastguard Worker
950*d9f75844SAndroid Build Coastguard Worker std::map<const cricket::ContentGroup*, std::vector<int>>
MergeEncryptedHeaderExtensionIdsForBundles(const cricket::SessionDescription * description)951*d9f75844SAndroid Build Coastguard Worker JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundles(
952*d9f75844SAndroid Build Coastguard Worker const cricket::SessionDescription* description) {
953*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(description);
954*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!bundles_.bundle_groups().empty());
955*d9f75844SAndroid Build Coastguard Worker std::map<const cricket::ContentGroup*, std::vector<int>>
956*d9f75844SAndroid Build Coastguard Worker merged_encrypted_extension_ids_by_bundle;
957*d9f75844SAndroid Build Coastguard Worker // Union the encrypted header IDs in the group when bundle is enabled.
958*d9f75844SAndroid Build Coastguard Worker for (const cricket::ContentInfo& content_info : description->contents()) {
959*d9f75844SAndroid Build Coastguard Worker auto group = bundles_.LookupGroupByMid(content_info.name);
960*d9f75844SAndroid Build Coastguard Worker if (!group)
961*d9f75844SAndroid Build Coastguard Worker continue;
962*d9f75844SAndroid Build Coastguard Worker // Get or create list of IDs for the BUNDLE group.
963*d9f75844SAndroid Build Coastguard Worker std::vector<int>& merged_ids =
964*d9f75844SAndroid Build Coastguard Worker merged_encrypted_extension_ids_by_bundle[group];
965*d9f75844SAndroid Build Coastguard Worker // Add IDs not already in the list.
966*d9f75844SAndroid Build Coastguard Worker std::vector<int> extension_ids =
967*d9f75844SAndroid Build Coastguard Worker GetEncryptedHeaderExtensionIds(content_info);
968*d9f75844SAndroid Build Coastguard Worker for (int id : extension_ids) {
969*d9f75844SAndroid Build Coastguard Worker if (!absl::c_linear_search(merged_ids, id)) {
970*d9f75844SAndroid Build Coastguard Worker merged_ids.push_back(id);
971*d9f75844SAndroid Build Coastguard Worker }
972*d9f75844SAndroid Build Coastguard Worker }
973*d9f75844SAndroid Build Coastguard Worker }
974*d9f75844SAndroid Build Coastguard Worker return merged_encrypted_extension_ids_by_bundle;
975*d9f75844SAndroid Build Coastguard Worker }
976*d9f75844SAndroid Build Coastguard Worker
GetRtpAbsSendTimeHeaderExtensionId(const cricket::ContentInfo & content_info)977*d9f75844SAndroid Build Coastguard Worker int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId(
978*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info) {
979*d9f75844SAndroid Build Coastguard Worker if (!config_.enable_external_auth) {
980*d9f75844SAndroid Build Coastguard Worker return -1;
981*d9f75844SAndroid Build Coastguard Worker }
982*d9f75844SAndroid Build Coastguard Worker
983*d9f75844SAndroid Build Coastguard Worker const cricket::MediaContentDescription* content_desc =
984*d9f75844SAndroid Build Coastguard Worker content_info.media_description();
985*d9f75844SAndroid Build Coastguard Worker
986*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* send_time_extension =
987*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::FindHeaderExtensionByUri(
988*d9f75844SAndroid Build Coastguard Worker content_desc->rtp_header_extensions(),
989*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::kAbsSendTimeUri,
990*d9f75844SAndroid Build Coastguard Worker config_.crypto_options.srtp.enable_encrypted_rtp_header_extensions
991*d9f75844SAndroid Build Coastguard Worker ? webrtc::RtpExtension::kPreferEncryptedExtension
992*d9f75844SAndroid Build Coastguard Worker : webrtc::RtpExtension::kDiscardEncryptedExtension);
993*d9f75844SAndroid Build Coastguard Worker return send_time_extension ? send_time_extension->id : -1;
994*d9f75844SAndroid Build Coastguard Worker }
995*d9f75844SAndroid Build Coastguard Worker
GetJsepTransportForMid(const std::string & mid) const996*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
997*d9f75844SAndroid Build Coastguard Worker const std::string& mid) const {
998*d9f75844SAndroid Build Coastguard Worker return transports_.GetTransportForMid(mid);
999*d9f75844SAndroid Build Coastguard Worker }
1000*d9f75844SAndroid Build Coastguard Worker
GetJsepTransportForMid(const std::string & mid)1001*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1002*d9f75844SAndroid Build Coastguard Worker const std::string& mid) {
1003*d9f75844SAndroid Build Coastguard Worker return transports_.GetTransportForMid(mid);
1004*d9f75844SAndroid Build Coastguard Worker }
GetJsepTransportForMid(absl::string_view mid) const1005*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1006*d9f75844SAndroid Build Coastguard Worker absl::string_view mid) const {
1007*d9f75844SAndroid Build Coastguard Worker return transports_.GetTransportForMid(mid);
1008*d9f75844SAndroid Build Coastguard Worker }
1009*d9f75844SAndroid Build Coastguard Worker
GetJsepTransportForMid(absl::string_view mid)1010*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* JsepTransportController::GetJsepTransportForMid(
1011*d9f75844SAndroid Build Coastguard Worker absl::string_view mid) {
1012*d9f75844SAndroid Build Coastguard Worker return transports_.GetTransportForMid(mid);
1013*d9f75844SAndroid Build Coastguard Worker }
1014*d9f75844SAndroid Build Coastguard Worker
GetJsepTransportByName(const std::string & transport_name) const1015*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
1016*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name) const {
1017*d9f75844SAndroid Build Coastguard Worker return transports_.GetTransportByName(transport_name);
1018*d9f75844SAndroid Build Coastguard Worker }
1019*d9f75844SAndroid Build Coastguard Worker
GetJsepTransportByName(const std::string & transport_name)1020*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* JsepTransportController::GetJsepTransportByName(
1021*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name) {
1022*d9f75844SAndroid Build Coastguard Worker return transports_.GetTransportByName(transport_name);
1023*d9f75844SAndroid Build Coastguard Worker }
1024*d9f75844SAndroid Build Coastguard Worker
MaybeCreateJsepTransport(bool local,const cricket::ContentInfo & content_info,const cricket::SessionDescription & description)1025*d9f75844SAndroid Build Coastguard Worker RTCError JsepTransportController::MaybeCreateJsepTransport(
1026*d9f75844SAndroid Build Coastguard Worker bool local,
1027*d9f75844SAndroid Build Coastguard Worker const cricket::ContentInfo& content_info,
1028*d9f75844SAndroid Build Coastguard Worker const cricket::SessionDescription& description) {
1029*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* transport = GetJsepTransportByName(content_info.name);
1030*d9f75844SAndroid Build Coastguard Worker if (transport) {
1031*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
1032*d9f75844SAndroid Build Coastguard Worker }
1033*d9f75844SAndroid Build Coastguard Worker const cricket::MediaContentDescription* content_desc =
1034*d9f75844SAndroid Build Coastguard Worker content_info.media_description();
1035*d9f75844SAndroid Build Coastguard Worker if (certificate_ && !content_desc->cryptos().empty()) {
1036*d9f75844SAndroid Build Coastguard Worker return RTCError(RTCErrorType::INVALID_PARAMETER,
1037*d9f75844SAndroid Build Coastguard Worker "SDES and DTLS-SRTP cannot be enabled at the same time.");
1038*d9f75844SAndroid Build Coastguard Worker }
1039*d9f75844SAndroid Build Coastguard Worker
1040*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
1041*d9f75844SAndroid Build Coastguard Worker CreateIceTransport(content_info.name, /*rtcp=*/false);
1042*d9f75844SAndroid Build Coastguard Worker
1043*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
1044*d9f75844SAndroid Build Coastguard Worker CreateDtlsTransport(content_info, ice->internal());
1045*d9f75844SAndroid Build Coastguard Worker
1046*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
1047*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
1048*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SrtpTransport> sdes_transport;
1049*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
1050*d9f75844SAndroid Build Coastguard Worker
1051*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice;
1052*d9f75844SAndroid Build Coastguard Worker if (config_.rtcp_mux_policy !=
1053*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kRtcpMuxPolicyRequire &&
1054*d9f75844SAndroid Build Coastguard Worker content_info.type == cricket::MediaProtocolType::kRtp) {
1055*d9f75844SAndroid Build Coastguard Worker rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true);
1056*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport =
1057*d9f75844SAndroid Build Coastguard Worker CreateDtlsTransport(content_info, rtcp_ice->internal());
1058*d9f75844SAndroid Build Coastguard Worker }
1059*d9f75844SAndroid Build Coastguard Worker
1060*d9f75844SAndroid Build Coastguard Worker if (config_.disable_encryption) {
1061*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO)
1062*d9f75844SAndroid Build Coastguard Worker << "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
1063*d9f75844SAndroid Build Coastguard Worker unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
1064*d9f75844SAndroid Build Coastguard Worker content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
1065*d9f75844SAndroid Build Coastguard Worker } else if (!content_desc->cryptos().empty()) {
1066*d9f75844SAndroid Build Coastguard Worker sdes_transport = CreateSdesTransport(
1067*d9f75844SAndroid Build Coastguard Worker content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
1068*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Creating SdesTransport.";
1069*d9f75844SAndroid Build Coastguard Worker } else {
1070*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
1071*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport = CreateDtlsSrtpTransport(
1072*d9f75844SAndroid Build Coastguard Worker content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
1073*d9f75844SAndroid Build Coastguard Worker }
1074*d9f75844SAndroid Build Coastguard Worker
1075*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::SctpTransportInternal> sctp_transport;
1076*d9f75844SAndroid Build Coastguard Worker if (config_.sctp_factory) {
1077*d9f75844SAndroid Build Coastguard Worker sctp_transport =
1078*d9f75844SAndroid Build Coastguard Worker config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get());
1079*d9f75844SAndroid Build Coastguard Worker }
1080*d9f75844SAndroid Build Coastguard Worker
1081*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::JsepTransport> jsep_transport =
1082*d9f75844SAndroid Build Coastguard Worker std::make_unique<cricket::JsepTransport>(
1083*d9f75844SAndroid Build Coastguard Worker content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
1084*d9f75844SAndroid Build Coastguard Worker std::move(unencrypted_rtp_transport), std::move(sdes_transport),
1085*d9f75844SAndroid Build Coastguard Worker std::move(dtls_srtp_transport), std::move(rtp_dtls_transport),
1086*d9f75844SAndroid Build Coastguard Worker std::move(rtcp_dtls_transport), std::move(sctp_transport), [&]() {
1087*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
1088*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
1089*d9f75844SAndroid Build Coastguard Worker });
1090*d9f75844SAndroid Build Coastguard Worker
1091*d9f75844SAndroid Build Coastguard Worker jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect(
1092*d9f75844SAndroid Build Coastguard Worker this, &JsepTransportController::OnRtcpPacketReceived_n);
1093*d9f75844SAndroid Build Coastguard Worker
1094*d9f75844SAndroid Build Coastguard Worker transports_.RegisterTransport(content_info.name, std::move(jsep_transport));
1095*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
1096*d9f75844SAndroid Build Coastguard Worker return RTCError::OK();
1097*d9f75844SAndroid Build Coastguard Worker }
1098*d9f75844SAndroid Build Coastguard Worker
DestroyAllJsepTransports_n()1099*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::DestroyAllJsepTransports_n() {
1100*d9f75844SAndroid Build Coastguard Worker transports_.DestroyAllTransports();
1101*d9f75844SAndroid Build Coastguard Worker }
1102*d9f75844SAndroid Build Coastguard Worker
SetIceRole_n(cricket::IceRole ice_role)1103*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::SetIceRole_n(cricket::IceRole ice_role) {
1104*d9f75844SAndroid Build Coastguard Worker ice_role_ = ice_role;
1105*d9f75844SAndroid Build Coastguard Worker auto dtls_transports = GetDtlsTransports();
1106*d9f75844SAndroid Build Coastguard Worker for (auto& dtls : dtls_transports) {
1107*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->SetIceRole(ice_role_);
1108*d9f75844SAndroid Build Coastguard Worker }
1109*d9f75844SAndroid Build Coastguard Worker }
1110*d9f75844SAndroid Build Coastguard Worker
DetermineIceRole(cricket::JsepTransport * jsep_transport,const cricket::TransportInfo & transport_info,SdpType type,bool local)1111*d9f75844SAndroid Build Coastguard Worker cricket::IceRole JsepTransportController::DetermineIceRole(
1112*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* jsep_transport,
1113*d9f75844SAndroid Build Coastguard Worker const cricket::TransportInfo& transport_info,
1114*d9f75844SAndroid Build Coastguard Worker SdpType type,
1115*d9f75844SAndroid Build Coastguard Worker bool local) {
1116*d9f75844SAndroid Build Coastguard Worker cricket::IceRole ice_role = ice_role_;
1117*d9f75844SAndroid Build Coastguard Worker auto tdesc = transport_info.description;
1118*d9f75844SAndroid Build Coastguard Worker if (local) {
1119*d9f75844SAndroid Build Coastguard Worker // The initial offer side may use ICE Lite, in which case, per RFC5245
1120*d9f75844SAndroid Build Coastguard Worker // Section 5.1.1, the answer side should take the controlling role if it is
1121*d9f75844SAndroid Build Coastguard Worker // in the full ICE mode.
1122*d9f75844SAndroid Build Coastguard Worker //
1123*d9f75844SAndroid Build Coastguard Worker // When both sides use ICE Lite, the initial offer side must take the
1124*d9f75844SAndroid Build Coastguard Worker // controlling role, and this is the default logic implemented in
1125*d9f75844SAndroid Build Coastguard Worker // SetLocalDescription in JsepTransportController.
1126*d9f75844SAndroid Build Coastguard Worker if (jsep_transport->remote_description() &&
1127*d9f75844SAndroid Build Coastguard Worker jsep_transport->remote_description()->transport_desc.ice_mode ==
1128*d9f75844SAndroid Build Coastguard Worker cricket::ICEMODE_LITE &&
1129*d9f75844SAndroid Build Coastguard Worker ice_role_ == cricket::ICEROLE_CONTROLLED &&
1130*d9f75844SAndroid Build Coastguard Worker tdesc.ice_mode == cricket::ICEMODE_FULL) {
1131*d9f75844SAndroid Build Coastguard Worker ice_role = cricket::ICEROLE_CONTROLLING;
1132*d9f75844SAndroid Build Coastguard Worker }
1133*d9f75844SAndroid Build Coastguard Worker } else {
1134*d9f75844SAndroid Build Coastguard Worker // If our role is cricket::ICEROLE_CONTROLLED and the remote endpoint
1135*d9f75844SAndroid Build Coastguard Worker // supports only ice_lite, this local endpoint should take the CONTROLLING
1136*d9f75844SAndroid Build Coastguard Worker // role.
1137*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): This is a session-level attribute, so it really shouldn't
1138*d9f75844SAndroid Build Coastguard Worker // be in a TransportDescription in the first place...
1139*d9f75844SAndroid Build Coastguard Worker if (ice_role_ == cricket::ICEROLE_CONTROLLED &&
1140*d9f75844SAndroid Build Coastguard Worker tdesc.ice_mode == cricket::ICEMODE_LITE) {
1141*d9f75844SAndroid Build Coastguard Worker ice_role = cricket::ICEROLE_CONTROLLING;
1142*d9f75844SAndroid Build Coastguard Worker }
1143*d9f75844SAndroid Build Coastguard Worker
1144*d9f75844SAndroid Build Coastguard Worker // If we use ICE Lite and the remote endpoint uses the full implementation
1145*d9f75844SAndroid Build Coastguard Worker // of ICE, the local endpoint must take the controlled role, and the other
1146*d9f75844SAndroid Build Coastguard Worker // side must be the controlling role.
1147*d9f75844SAndroid Build Coastguard Worker if (jsep_transport->local_description() &&
1148*d9f75844SAndroid Build Coastguard Worker jsep_transport->local_description()->transport_desc.ice_mode ==
1149*d9f75844SAndroid Build Coastguard Worker cricket::ICEMODE_LITE &&
1150*d9f75844SAndroid Build Coastguard Worker ice_role_ == cricket::ICEROLE_CONTROLLING &&
1151*d9f75844SAndroid Build Coastguard Worker tdesc.ice_mode == cricket::ICEMODE_FULL) {
1152*d9f75844SAndroid Build Coastguard Worker ice_role = cricket::ICEROLE_CONTROLLED;
1153*d9f75844SAndroid Build Coastguard Worker }
1154*d9f75844SAndroid Build Coastguard Worker }
1155*d9f75844SAndroid Build Coastguard Worker
1156*d9f75844SAndroid Build Coastguard Worker return ice_role;
1157*d9f75844SAndroid Build Coastguard Worker }
1158*d9f75844SAndroid Build Coastguard Worker
OnTransportWritableState_n(rtc::PacketTransportInternal * transport)1159*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportWritableState_n(
1160*d9f75844SAndroid Build Coastguard Worker rtc::PacketTransportInternal* transport) {
1161*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << " Transport " << transport->transport_name()
1162*d9f75844SAndroid Build Coastguard Worker << " writability changed to " << transport->writable()
1163*d9f75844SAndroid Build Coastguard Worker << ".";
1164*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
1165*d9f75844SAndroid Build Coastguard Worker }
1166*d9f75844SAndroid Build Coastguard Worker
OnTransportReceivingState_n(rtc::PacketTransportInternal * transport)1167*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportReceivingState_n(
1168*d9f75844SAndroid Build Coastguard Worker rtc::PacketTransportInternal* transport) {
1169*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
1170*d9f75844SAndroid Build Coastguard Worker }
1171*d9f75844SAndroid Build Coastguard Worker
OnTransportGatheringState_n(cricket::IceTransportInternal * transport)1172*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportGatheringState_n(
1173*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* transport) {
1174*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
1175*d9f75844SAndroid Build Coastguard Worker }
1176*d9f75844SAndroid Build Coastguard Worker
OnTransportCandidateGathered_n(cricket::IceTransportInternal * transport,const cricket::Candidate & candidate)1177*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportCandidateGathered_n(
1178*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* transport,
1179*d9f75844SAndroid Build Coastguard Worker const cricket::Candidate& candidate) {
1180*d9f75844SAndroid Build Coastguard Worker // We should never signal peer-reflexive candidates.
1181*d9f75844SAndroid Build Coastguard Worker if (candidate.type() == cricket::PRFLX_PORT_TYPE) {
1182*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
1183*d9f75844SAndroid Build Coastguard Worker return;
1184*d9f75844SAndroid Build Coastguard Worker }
1185*d9f75844SAndroid Build Coastguard Worker
1186*d9f75844SAndroid Build Coastguard Worker signal_ice_candidates_gathered_.Send(
1187*d9f75844SAndroid Build Coastguard Worker transport->transport_name(), std::vector<cricket::Candidate>{candidate});
1188*d9f75844SAndroid Build Coastguard Worker }
1189*d9f75844SAndroid Build Coastguard Worker
OnTransportCandidateError_n(cricket::IceTransportInternal * transport,const cricket::IceCandidateErrorEvent & event)1190*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportCandidateError_n(
1191*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* transport,
1192*d9f75844SAndroid Build Coastguard Worker const cricket::IceCandidateErrorEvent& event) {
1193*d9f75844SAndroid Build Coastguard Worker signal_ice_candidate_error_.Send(event);
1194*d9f75844SAndroid Build Coastguard Worker }
OnTransportCandidatesRemoved_n(cricket::IceTransportInternal * transport,const cricket::Candidates & candidates)1195*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportCandidatesRemoved_n(
1196*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* transport,
1197*d9f75844SAndroid Build Coastguard Worker const cricket::Candidates& candidates) {
1198*d9f75844SAndroid Build Coastguard Worker signal_ice_candidates_removed_.Send(candidates);
1199*d9f75844SAndroid Build Coastguard Worker }
OnTransportCandidatePairChanged_n(const cricket::CandidatePairChangeEvent & event)1200*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportCandidatePairChanged_n(
1201*d9f75844SAndroid Build Coastguard Worker const cricket::CandidatePairChangeEvent& event) {
1202*d9f75844SAndroid Build Coastguard Worker signal_ice_candidate_pair_changed_.Send(event);
1203*d9f75844SAndroid Build Coastguard Worker }
1204*d9f75844SAndroid Build Coastguard Worker
OnTransportRoleConflict_n(cricket::IceTransportInternal * transport)1205*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportRoleConflict_n(
1206*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* transport) {
1207*d9f75844SAndroid Build Coastguard Worker // Note: since the role conflict is handled entirely on the network thread,
1208*d9f75844SAndroid Build Coastguard Worker // we don't need to worry about role conflicts occurring on two ports at
1209*d9f75844SAndroid Build Coastguard Worker // once. The first one encountered should immediately reverse the role.
1210*d9f75844SAndroid Build Coastguard Worker cricket::IceRole reversed_role = (ice_role_ == cricket::ICEROLE_CONTROLLING)
1211*d9f75844SAndroid Build Coastguard Worker ? cricket::ICEROLE_CONTROLLED
1212*d9f75844SAndroid Build Coastguard Worker : cricket::ICEROLE_CONTROLLING;
1213*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Got role conflict; switching to "
1214*d9f75844SAndroid Build Coastguard Worker << (reversed_role == cricket::ICEROLE_CONTROLLING
1215*d9f75844SAndroid Build Coastguard Worker ? "controlling"
1216*d9f75844SAndroid Build Coastguard Worker : "controlled")
1217*d9f75844SAndroid Build Coastguard Worker << " role.";
1218*d9f75844SAndroid Build Coastguard Worker SetIceRole_n(reversed_role);
1219*d9f75844SAndroid Build Coastguard Worker }
1220*d9f75844SAndroid Build Coastguard Worker
OnTransportStateChanged_n(cricket::IceTransportInternal * transport)1221*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnTransportStateChanged_n(
1222*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportInternal* transport) {
1223*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << transport->transport_name() << " Transport "
1224*d9f75844SAndroid Build Coastguard Worker << transport->component()
1225*d9f75844SAndroid Build Coastguard Worker << " state changed. Check if state is complete.";
1226*d9f75844SAndroid Build Coastguard Worker UpdateAggregateStates_n();
1227*d9f75844SAndroid Build Coastguard Worker }
1228*d9f75844SAndroid Build Coastguard Worker
UpdateAggregateStates_n()1229*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::UpdateAggregateStates_n() {
1230*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransportController::UpdateAggregateStates_n");
1231*d9f75844SAndroid Build Coastguard Worker auto dtls_transports = GetActiveDtlsTransports();
1232*d9f75844SAndroid Build Coastguard Worker cricket::IceConnectionState new_connection_state =
1233*d9f75844SAndroid Build Coastguard Worker cricket::kIceConnectionConnecting;
1234*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::IceConnectionState new_ice_connection_state =
1235*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
1236*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::PeerConnectionState new_combined_state =
1237*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::PeerConnectionState::kNew;
1238*d9f75844SAndroid Build Coastguard Worker cricket::IceGatheringState new_gathering_state = cricket::kIceGatheringNew;
1239*d9f75844SAndroid Build Coastguard Worker bool any_failed = false;
1240*d9f75844SAndroid Build Coastguard Worker bool all_connected = !dtls_transports.empty();
1241*d9f75844SAndroid Build Coastguard Worker bool all_completed = !dtls_transports.empty();
1242*d9f75844SAndroid Build Coastguard Worker bool any_gathering = false;
1243*d9f75844SAndroid Build Coastguard Worker bool all_done_gathering = !dtls_transports.empty();
1244*d9f75844SAndroid Build Coastguard Worker
1245*d9f75844SAndroid Build Coastguard Worker std::map<IceTransportState, int> ice_state_counts;
1246*d9f75844SAndroid Build Coastguard Worker std::map<DtlsTransportState, int> dtls_state_counts;
1247*d9f75844SAndroid Build Coastguard Worker
1248*d9f75844SAndroid Build Coastguard Worker for (const auto& dtls : dtls_transports) {
1249*d9f75844SAndroid Build Coastguard Worker any_failed = any_failed || dtls->ice_transport()->GetState() ==
1250*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportState::STATE_FAILED;
1251*d9f75844SAndroid Build Coastguard Worker all_connected = all_connected && dtls->writable();
1252*d9f75844SAndroid Build Coastguard Worker all_completed =
1253*d9f75844SAndroid Build Coastguard Worker all_completed && dtls->writable() &&
1254*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->GetState() ==
1255*d9f75844SAndroid Build Coastguard Worker cricket::IceTransportState::STATE_COMPLETED &&
1256*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->GetIceRole() == cricket::ICEROLE_CONTROLLING &&
1257*d9f75844SAndroid Build Coastguard Worker dtls->ice_transport()->gathering_state() ==
1258*d9f75844SAndroid Build Coastguard Worker cricket::kIceGatheringComplete;
1259*d9f75844SAndroid Build Coastguard Worker any_gathering = any_gathering || dtls->ice_transport()->gathering_state() !=
1260*d9f75844SAndroid Build Coastguard Worker cricket::kIceGatheringNew;
1261*d9f75844SAndroid Build Coastguard Worker all_done_gathering =
1262*d9f75844SAndroid Build Coastguard Worker all_done_gathering && dtls->ice_transport()->gathering_state() ==
1263*d9f75844SAndroid Build Coastguard Worker cricket::kIceGatheringComplete;
1264*d9f75844SAndroid Build Coastguard Worker
1265*d9f75844SAndroid Build Coastguard Worker dtls_state_counts[dtls->dtls_state()]++;
1266*d9f75844SAndroid Build Coastguard Worker ice_state_counts[dtls->ice_transport()->GetIceTransportState()]++;
1267*d9f75844SAndroid Build Coastguard Worker }
1268*d9f75844SAndroid Build Coastguard Worker
1269*d9f75844SAndroid Build Coastguard Worker if (any_failed) {
1270*d9f75844SAndroid Build Coastguard Worker new_connection_state = cricket::kIceConnectionFailed;
1271*d9f75844SAndroid Build Coastguard Worker } else if (all_completed) {
1272*d9f75844SAndroid Build Coastguard Worker new_connection_state = cricket::kIceConnectionCompleted;
1273*d9f75844SAndroid Build Coastguard Worker } else if (all_connected) {
1274*d9f75844SAndroid Build Coastguard Worker new_connection_state = cricket::kIceConnectionConnected;
1275*d9f75844SAndroid Build Coastguard Worker }
1276*d9f75844SAndroid Build Coastguard Worker if (ice_connection_state_ != new_connection_state) {
1277*d9f75844SAndroid Build Coastguard Worker ice_connection_state_ = new_connection_state;
1278*d9f75844SAndroid Build Coastguard Worker
1279*d9f75844SAndroid Build Coastguard Worker signal_ice_connection_state_.Send(new_connection_state);
1280*d9f75844SAndroid Build Coastguard Worker }
1281*d9f75844SAndroid Build Coastguard Worker
1282*d9f75844SAndroid Build Coastguard Worker // Compute the current RTCIceConnectionState as described in
1283*d9f75844SAndroid Build Coastguard Worker // https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate.
1284*d9f75844SAndroid Build Coastguard Worker // The PeerConnection is responsible for handling the "closed" state.
1285*d9f75844SAndroid Build Coastguard Worker int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
1286*d9f75844SAndroid Build Coastguard Worker int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
1287*d9f75844SAndroid Build Coastguard Worker int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
1288*d9f75844SAndroid Build Coastguard Worker int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
1289*d9f75844SAndroid Build Coastguard Worker int total_ice_disconnected =
1290*d9f75844SAndroid Build Coastguard Worker ice_state_counts[IceTransportState::kDisconnected];
1291*d9f75844SAndroid Build Coastguard Worker int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
1292*d9f75844SAndroid Build Coastguard Worker int total_ice_new = ice_state_counts[IceTransportState::kNew];
1293*d9f75844SAndroid Build Coastguard Worker int total_ice = dtls_transports.size();
1294*d9f75844SAndroid Build Coastguard Worker
1295*d9f75844SAndroid Build Coastguard Worker if (total_ice_failed > 0) {
1296*d9f75844SAndroid Build Coastguard Worker // Any RTCIceTransports are in the "failed" state.
1297*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state = PeerConnectionInterface::kIceConnectionFailed;
1298*d9f75844SAndroid Build Coastguard Worker } else if (total_ice_disconnected > 0) {
1299*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and any RTCIceTransports are in the
1300*d9f75844SAndroid Build Coastguard Worker // "disconnected" state.
1301*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state =
1302*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kIceConnectionDisconnected;
1303*d9f75844SAndroid Build Coastguard Worker } else if (total_ice_new + total_ice_closed == total_ice) {
1304*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and all RTCIceTransports are in the
1305*d9f75844SAndroid Build Coastguard Worker // "new" or "closed" state, or there are no transports.
1306*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state = PeerConnectionInterface::kIceConnectionNew;
1307*d9f75844SAndroid Build Coastguard Worker } else if (total_ice_new + total_ice_checking > 0) {
1308*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and any RTCIceTransports are in the
1309*d9f75844SAndroid Build Coastguard Worker // "new" or "checking" state.
1310*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state = PeerConnectionInterface::kIceConnectionChecking;
1311*d9f75844SAndroid Build Coastguard Worker } else if (total_ice_completed + total_ice_closed == total_ice ||
1312*d9f75844SAndroid Build Coastguard Worker all_completed) {
1313*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and all RTCIceTransports are in the
1314*d9f75844SAndroid Build Coastguard Worker // "completed" or "closed" state.
1315*d9f75844SAndroid Build Coastguard Worker //
1316*d9f75844SAndroid Build Coastguard Worker // TODO(https://bugs.webrtc.org/10356): The all_completed condition is added
1317*d9f75844SAndroid Build Coastguard Worker // to mimic the behavior of the old ICE connection state, and should be
1318*d9f75844SAndroid Build Coastguard Worker // removed once we get end-of-candidates signaling in place.
1319*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state = PeerConnectionInterface::kIceConnectionCompleted;
1320*d9f75844SAndroid Build Coastguard Worker } else if (total_ice_connected + total_ice_completed + total_ice_closed ==
1321*d9f75844SAndroid Build Coastguard Worker total_ice) {
1322*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and all RTCIceTransports are in the
1323*d9f75844SAndroid Build Coastguard Worker // "connected", "completed" or "closed" state.
1324*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state = PeerConnectionInterface::kIceConnectionConnected;
1325*d9f75844SAndroid Build Coastguard Worker } else {
1326*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
1327*d9f75844SAndroid Build Coastguard Worker }
1328*d9f75844SAndroid Build Coastguard Worker
1329*d9f75844SAndroid Build Coastguard Worker if (standardized_ice_connection_state_ != new_ice_connection_state) {
1330*d9f75844SAndroid Build Coastguard Worker if (standardized_ice_connection_state_ ==
1331*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kIceConnectionChecking &&
1332*d9f75844SAndroid Build Coastguard Worker new_ice_connection_state ==
1333*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kIceConnectionCompleted) {
1334*d9f75844SAndroid Build Coastguard Worker // Ensure that we never skip over the "connected" state.
1335*d9f75844SAndroid Build Coastguard Worker signal_standardized_ice_connection_state_.Send(
1336*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::kIceConnectionConnected);
1337*d9f75844SAndroid Build Coastguard Worker }
1338*d9f75844SAndroid Build Coastguard Worker standardized_ice_connection_state_ = new_ice_connection_state;
1339*d9f75844SAndroid Build Coastguard Worker signal_standardized_ice_connection_state_.Send(new_ice_connection_state);
1340*d9f75844SAndroid Build Coastguard Worker }
1341*d9f75844SAndroid Build Coastguard Worker
1342*d9f75844SAndroid Build Coastguard Worker // Compute the current RTCPeerConnectionState as described in
1343*d9f75844SAndroid Build Coastguard Worker // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate.
1344*d9f75844SAndroid Build Coastguard Worker // The PeerConnection is responsible for handling the "closed" state.
1345*d9f75844SAndroid Build Coastguard Worker // Note that "connecting" is only a valid state for DTLS transports while
1346*d9f75844SAndroid Build Coastguard Worker // "checking", "completed" and "disconnected" are only valid for ICE
1347*d9f75844SAndroid Build Coastguard Worker // transports.
1348*d9f75844SAndroid Build Coastguard Worker int total_connected =
1349*d9f75844SAndroid Build Coastguard Worker total_ice_connected + dtls_state_counts[DtlsTransportState::kConnected];
1350*d9f75844SAndroid Build Coastguard Worker int total_dtls_connecting =
1351*d9f75844SAndroid Build Coastguard Worker dtls_state_counts[DtlsTransportState::kConnecting];
1352*d9f75844SAndroid Build Coastguard Worker int total_failed =
1353*d9f75844SAndroid Build Coastguard Worker total_ice_failed + dtls_state_counts[DtlsTransportState::kFailed];
1354*d9f75844SAndroid Build Coastguard Worker int total_closed =
1355*d9f75844SAndroid Build Coastguard Worker total_ice_closed + dtls_state_counts[DtlsTransportState::kClosed];
1356*d9f75844SAndroid Build Coastguard Worker int total_new = total_ice_new + dtls_state_counts[DtlsTransportState::kNew];
1357*d9f75844SAndroid Build Coastguard Worker int total_transports = total_ice * 2;
1358*d9f75844SAndroid Build Coastguard Worker
1359*d9f75844SAndroid Build Coastguard Worker if (total_failed > 0) {
1360*d9f75844SAndroid Build Coastguard Worker // Any of the RTCIceTransports or RTCDtlsTransports are in a "failed" state.
1361*d9f75844SAndroid Build Coastguard Worker new_combined_state = PeerConnectionInterface::PeerConnectionState::kFailed;
1362*d9f75844SAndroid Build Coastguard Worker } else if (total_ice_disconnected > 0) {
1363*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and any RTCIceTransports or
1364*d9f75844SAndroid Build Coastguard Worker // RTCDtlsTransports are in the "disconnected" state.
1365*d9f75844SAndroid Build Coastguard Worker new_combined_state =
1366*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::PeerConnectionState::kDisconnected;
1367*d9f75844SAndroid Build Coastguard Worker } else if (total_new + total_closed == total_transports) {
1368*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and all RTCIceTransports and
1369*d9f75844SAndroid Build Coastguard Worker // RTCDtlsTransports are in the "new" or "closed" state, or there are no
1370*d9f75844SAndroid Build Coastguard Worker // transports.
1371*d9f75844SAndroid Build Coastguard Worker new_combined_state = PeerConnectionInterface::PeerConnectionState::kNew;
1372*d9f75844SAndroid Build Coastguard Worker } else if (total_new + total_dtls_connecting + total_ice_checking > 0) {
1373*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and all RTCIceTransports or
1374*d9f75844SAndroid Build Coastguard Worker // RTCDtlsTransports are in the "new", "connecting" or "checking" state.
1375*d9f75844SAndroid Build Coastguard Worker new_combined_state =
1376*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::PeerConnectionState::kConnecting;
1377*d9f75844SAndroid Build Coastguard Worker } else if (total_connected + total_ice_completed + total_closed ==
1378*d9f75844SAndroid Build Coastguard Worker total_transports) {
1379*d9f75844SAndroid Build Coastguard Worker // None of the previous states apply and all RTCIceTransports and
1380*d9f75844SAndroid Build Coastguard Worker // RTCDtlsTransports are in the "connected", "completed" or "closed" state.
1381*d9f75844SAndroid Build Coastguard Worker new_combined_state =
1382*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::PeerConnectionState::kConnected;
1383*d9f75844SAndroid Build Coastguard Worker } else {
1384*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
1385*d9f75844SAndroid Build Coastguard Worker }
1386*d9f75844SAndroid Build Coastguard Worker
1387*d9f75844SAndroid Build Coastguard Worker if (combined_connection_state_ != new_combined_state) {
1388*d9f75844SAndroid Build Coastguard Worker combined_connection_state_ = new_combined_state;
1389*d9f75844SAndroid Build Coastguard Worker signal_connection_state_.Send(new_combined_state);
1390*d9f75844SAndroid Build Coastguard Worker }
1391*d9f75844SAndroid Build Coastguard Worker
1392*d9f75844SAndroid Build Coastguard Worker // Compute the gathering state.
1393*d9f75844SAndroid Build Coastguard Worker if (dtls_transports.empty()) {
1394*d9f75844SAndroid Build Coastguard Worker new_gathering_state = cricket::kIceGatheringNew;
1395*d9f75844SAndroid Build Coastguard Worker } else if (all_done_gathering) {
1396*d9f75844SAndroid Build Coastguard Worker new_gathering_state = cricket::kIceGatheringComplete;
1397*d9f75844SAndroid Build Coastguard Worker } else if (any_gathering) {
1398*d9f75844SAndroid Build Coastguard Worker new_gathering_state = cricket::kIceGatheringGathering;
1399*d9f75844SAndroid Build Coastguard Worker }
1400*d9f75844SAndroid Build Coastguard Worker if (ice_gathering_state_ != new_gathering_state) {
1401*d9f75844SAndroid Build Coastguard Worker ice_gathering_state_ = new_gathering_state;
1402*d9f75844SAndroid Build Coastguard Worker signal_ice_gathering_state_.Send(new_gathering_state);
1403*d9f75844SAndroid Build Coastguard Worker }
1404*d9f75844SAndroid Build Coastguard Worker }
1405*d9f75844SAndroid Build Coastguard Worker
OnRtcpPacketReceived_n(rtc::CopyOnWriteBuffer * packet,int64_t packet_time_us)1406*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnRtcpPacketReceived_n(
1407*d9f75844SAndroid Build Coastguard Worker rtc::CopyOnWriteBuffer* packet,
1408*d9f75844SAndroid Build Coastguard Worker int64_t packet_time_us) {
1409*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(config_.rtcp_handler);
1410*d9f75844SAndroid Build Coastguard Worker config_.rtcp_handler(*packet, packet_time_us);
1411*d9f75844SAndroid Build Coastguard Worker }
1412*d9f75844SAndroid Build Coastguard Worker
OnDtlsHandshakeError(rtc::SSLHandshakeError error)1413*d9f75844SAndroid Build Coastguard Worker void JsepTransportController::OnDtlsHandshakeError(
1414*d9f75844SAndroid Build Coastguard Worker rtc::SSLHandshakeError error) {
1415*d9f75844SAndroid Build Coastguard Worker config_.on_dtls_handshake_error_(error);
1416*d9f75844SAndroid Build Coastguard Worker }
1417*d9f75844SAndroid Build Coastguard Worker
OnTransportChanged(const std::string & mid,cricket::JsepTransport * jsep_transport)1418*d9f75844SAndroid Build Coastguard Worker bool JsepTransportController::OnTransportChanged(
1419*d9f75844SAndroid Build Coastguard Worker const std::string& mid,
1420*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* jsep_transport) {
1421*d9f75844SAndroid Build Coastguard Worker if (config_.transport_observer) {
1422*d9f75844SAndroid Build Coastguard Worker if (jsep_transport) {
1423*d9f75844SAndroid Build Coastguard Worker return config_.transport_observer->OnTransportChanged(
1424*d9f75844SAndroid Build Coastguard Worker mid, jsep_transport->rtp_transport(),
1425*d9f75844SAndroid Build Coastguard Worker jsep_transport->RtpDtlsTransport(),
1426*d9f75844SAndroid Build Coastguard Worker jsep_transport->data_channel_transport());
1427*d9f75844SAndroid Build Coastguard Worker } else {
1428*d9f75844SAndroid Build Coastguard Worker return config_.transport_observer->OnTransportChanged(mid, nullptr,
1429*d9f75844SAndroid Build Coastguard Worker nullptr, nullptr);
1430*d9f75844SAndroid Build Coastguard Worker }
1431*d9f75844SAndroid Build Coastguard Worker }
1432*d9f75844SAndroid Build Coastguard Worker return false;
1433*d9f75844SAndroid Build Coastguard Worker }
1434*d9f75844SAndroid Build Coastguard Worker
1435*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
1436