1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2018 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.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker #include <functional>
17*d9f75844SAndroid Build Coastguard Worker #include <memory>
18*d9f75844SAndroid Build Coastguard Worker #include <string>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/candidate.h"
23*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
24*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_transport_channel.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/copy_on_write_buffer.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker using webrtc::SdpType;
32*d9f75844SAndroid Build Coastguard Worker
33*d9f75844SAndroid Build Coastguard Worker namespace cricket {
34*d9f75844SAndroid Build Coastguard Worker
JsepTransportDescription()35*d9f75844SAndroid Build Coastguard Worker JsepTransportDescription::JsepTransportDescription() {}
36*d9f75844SAndroid Build Coastguard Worker
JsepTransportDescription(bool rtcp_mux_enabled,const std::vector<CryptoParams> & cryptos,const std::vector<int> & encrypted_header_extension_ids,int rtp_abs_sendtime_extn_id,const TransportDescription & transport_desc)37*d9f75844SAndroid Build Coastguard Worker JsepTransportDescription::JsepTransportDescription(
38*d9f75844SAndroid Build Coastguard Worker bool rtcp_mux_enabled,
39*d9f75844SAndroid Build Coastguard Worker const std::vector<CryptoParams>& cryptos,
40*d9f75844SAndroid Build Coastguard Worker const std::vector<int>& encrypted_header_extension_ids,
41*d9f75844SAndroid Build Coastguard Worker int rtp_abs_sendtime_extn_id,
42*d9f75844SAndroid Build Coastguard Worker const TransportDescription& transport_desc)
43*d9f75844SAndroid Build Coastguard Worker : rtcp_mux_enabled(rtcp_mux_enabled),
44*d9f75844SAndroid Build Coastguard Worker cryptos(cryptos),
45*d9f75844SAndroid Build Coastguard Worker encrypted_header_extension_ids(encrypted_header_extension_ids),
46*d9f75844SAndroid Build Coastguard Worker rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
47*d9f75844SAndroid Build Coastguard Worker transport_desc(transport_desc) {}
48*d9f75844SAndroid Build Coastguard Worker
JsepTransportDescription(const JsepTransportDescription & from)49*d9f75844SAndroid Build Coastguard Worker JsepTransportDescription::JsepTransportDescription(
50*d9f75844SAndroid Build Coastguard Worker const JsepTransportDescription& from)
51*d9f75844SAndroid Build Coastguard Worker : rtcp_mux_enabled(from.rtcp_mux_enabled),
52*d9f75844SAndroid Build Coastguard Worker cryptos(from.cryptos),
53*d9f75844SAndroid Build Coastguard Worker encrypted_header_extension_ids(from.encrypted_header_extension_ids),
54*d9f75844SAndroid Build Coastguard Worker rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
55*d9f75844SAndroid Build Coastguard Worker transport_desc(from.transport_desc) {}
56*d9f75844SAndroid Build Coastguard Worker
57*d9f75844SAndroid Build Coastguard Worker JsepTransportDescription::~JsepTransportDescription() = default;
58*d9f75844SAndroid Build Coastguard Worker
operator =(const JsepTransportDescription & from)59*d9f75844SAndroid Build Coastguard Worker JsepTransportDescription& JsepTransportDescription::operator=(
60*d9f75844SAndroid Build Coastguard Worker const JsepTransportDescription& from) {
61*d9f75844SAndroid Build Coastguard Worker if (this == &from) {
62*d9f75844SAndroid Build Coastguard Worker return *this;
63*d9f75844SAndroid Build Coastguard Worker }
64*d9f75844SAndroid Build Coastguard Worker rtcp_mux_enabled = from.rtcp_mux_enabled;
65*d9f75844SAndroid Build Coastguard Worker cryptos = from.cryptos;
66*d9f75844SAndroid Build Coastguard Worker encrypted_header_extension_ids = from.encrypted_header_extension_ids;
67*d9f75844SAndroid Build Coastguard Worker rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
68*d9f75844SAndroid Build Coastguard Worker transport_desc = from.transport_desc;
69*d9f75844SAndroid Build Coastguard Worker
70*d9f75844SAndroid Build Coastguard Worker return *this;
71*d9f75844SAndroid Build Coastguard Worker }
72*d9f75844SAndroid Build Coastguard Worker
JsepTransport(const std::string & mid,const rtc::scoped_refptr<rtc::RTCCertificate> & local_certificate,rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,std::unique_ptr<webrtc::SrtpTransport> sdes_transport,std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,std::unique_ptr<SctpTransportInternal> sctp_transport,std::function<void ()> rtcp_mux_active_callback)73*d9f75844SAndroid Build Coastguard Worker JsepTransport::JsepTransport(
74*d9f75844SAndroid Build Coastguard Worker const std::string& mid,
75*d9f75844SAndroid Build Coastguard Worker const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
76*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
77*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
78*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
79*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
80*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
81*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
82*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
83*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SctpTransportInternal> sctp_transport,
84*d9f75844SAndroid Build Coastguard Worker std::function<void()> rtcp_mux_active_callback)
85*d9f75844SAndroid Build Coastguard Worker : network_thread_(rtc::Thread::Current()),
86*d9f75844SAndroid Build Coastguard Worker mid_(mid),
87*d9f75844SAndroid Build Coastguard Worker local_certificate_(local_certificate),
88*d9f75844SAndroid Build Coastguard Worker ice_transport_(std::move(ice_transport)),
89*d9f75844SAndroid Build Coastguard Worker rtcp_ice_transport_(std::move(rtcp_ice_transport)),
90*d9f75844SAndroid Build Coastguard Worker unencrypted_rtp_transport_(std::move(unencrypted_rtp_transport)),
91*d9f75844SAndroid Build Coastguard Worker sdes_transport_(std::move(sdes_transport)),
92*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport_(std::move(dtls_srtp_transport)),
93*d9f75844SAndroid Build Coastguard Worker rtp_dtls_transport_(rtp_dtls_transport
94*d9f75844SAndroid Build Coastguard Worker ? rtc::make_ref_counted<webrtc::DtlsTransport>(
95*d9f75844SAndroid Build Coastguard Worker std::move(rtp_dtls_transport))
96*d9f75844SAndroid Build Coastguard Worker : nullptr),
97*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport_(rtcp_dtls_transport
98*d9f75844SAndroid Build Coastguard Worker ? rtc::make_ref_counted<webrtc::DtlsTransport>(
99*d9f75844SAndroid Build Coastguard Worker std::move(rtcp_dtls_transport))
100*d9f75844SAndroid Build Coastguard Worker : nullptr),
101*d9f75844SAndroid Build Coastguard Worker sctp_transport_(sctp_transport
102*d9f75844SAndroid Build Coastguard Worker ? rtc::make_ref_counted<webrtc::SctpTransport>(
103*d9f75844SAndroid Build Coastguard Worker std::move(sctp_transport))
104*d9f75844SAndroid Build Coastguard Worker : nullptr),
105*d9f75844SAndroid Build Coastguard Worker rtcp_mux_active_callback_(std::move(rtcp_mux_active_callback)) {
106*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::JsepTransport");
107*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(ice_transport_);
108*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport_);
109*d9f75844SAndroid Build Coastguard Worker // `rtcp_ice_transport_` must be present iff `rtcp_dtls_transport_` is
110*d9f75844SAndroid Build Coastguard Worker // present.
111*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ((rtcp_ice_transport_ != nullptr),
112*d9f75844SAndroid Build Coastguard Worker (rtcp_dtls_transport_ != nullptr));
113*d9f75844SAndroid Build Coastguard Worker // Verify the "only one out of these three can be set" invariant.
114*d9f75844SAndroid Build Coastguard Worker if (unencrypted_rtp_transport_) {
115*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sdes_transport);
116*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!dtls_srtp_transport);
117*d9f75844SAndroid Build Coastguard Worker } else if (sdes_transport_) {
118*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport);
119*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!dtls_srtp_transport);
120*d9f75844SAndroid Build Coastguard Worker } else {
121*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(dtls_srtp_transport_);
122*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport);
123*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sdes_transport);
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker
126*d9f75844SAndroid Build Coastguard Worker if (sctp_transport_) {
127*d9f75844SAndroid Build Coastguard Worker sctp_transport_->SetDtlsTransport(rtp_dtls_transport_);
128*d9f75844SAndroid Build Coastguard Worker }
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker
~JsepTransport()131*d9f75844SAndroid Build Coastguard Worker JsepTransport::~JsepTransport() {
132*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::~JsepTransport");
133*d9f75844SAndroid Build Coastguard Worker if (sctp_transport_) {
134*d9f75844SAndroid Build Coastguard Worker sctp_transport_->Clear();
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker
137*d9f75844SAndroid Build Coastguard Worker // Clear all DtlsTransports. There may be pointers to these from
138*d9f75844SAndroid Build Coastguard Worker // other places, so we can't assume they'll be deleted by the destructor.
139*d9f75844SAndroid Build Coastguard Worker rtp_dtls_transport_->Clear();
140*d9f75844SAndroid Build Coastguard Worker if (rtcp_dtls_transport_) {
141*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport_->Clear();
142*d9f75844SAndroid Build Coastguard Worker }
143*d9f75844SAndroid Build Coastguard Worker
144*d9f75844SAndroid Build Coastguard Worker // ICE will be the last transport to be deleted.
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker
SetLocalJsepTransportDescription(const JsepTransportDescription & jsep_description,SdpType type)147*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
148*d9f75844SAndroid Build Coastguard Worker const JsepTransportDescription& jsep_description,
149*d9f75844SAndroid Build Coastguard Worker SdpType type) {
150*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError error;
151*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::SetLocalJsepTransportDescription");
152*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
153*d9f75844SAndroid Build Coastguard Worker
154*d9f75844SAndroid Build Coastguard Worker IceParameters ice_parameters =
155*d9f75844SAndroid Build Coastguard Worker jsep_description.transport_desc.GetIceParameters();
156*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError ice_parameters_result = ice_parameters.Validate();
157*d9f75844SAndroid Build Coastguard Worker if (!ice_parameters_result.ok()) {
158*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder sb;
159*d9f75844SAndroid Build Coastguard Worker sb << "Invalid ICE parameters: " << ice_parameters_result.message();
160*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
161*d9f75844SAndroid Build Coastguard Worker sb.Release());
162*d9f75844SAndroid Build Coastguard Worker }
163*d9f75844SAndroid Build Coastguard Worker
164*d9f75844SAndroid Build Coastguard Worker if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
165*d9f75844SAndroid Build Coastguard Worker ContentSource::CS_LOCAL)) {
166*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
167*d9f75844SAndroid Build Coastguard Worker "Failed to setup RTCP mux.");
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker
170*d9f75844SAndroid Build Coastguard Worker // If doing SDES, setup the SDES crypto parameters.
171*d9f75844SAndroid Build Coastguard Worker if (sdes_transport_) {
172*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport_);
173*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!dtls_srtp_transport_);
174*d9f75844SAndroid Build Coastguard Worker if (!SetSdes(jsep_description.cryptos,
175*d9f75844SAndroid Build Coastguard Worker jsep_description.encrypted_header_extension_ids, type,
176*d9f75844SAndroid Build Coastguard Worker ContentSource::CS_LOCAL)) {
177*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
178*d9f75844SAndroid Build Coastguard Worker "Failed to setup SDES crypto parameters.");
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker } else if (dtls_srtp_transport_) {
181*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport_);
182*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sdes_transport_);
183*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
184*d9f75844SAndroid Build Coastguard Worker jsep_description.encrypted_header_extension_ids);
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker bool ice_restarting =
187*d9f75844SAndroid Build Coastguard Worker local_description_ != nullptr &&
188*d9f75844SAndroid Build Coastguard Worker IceCredentialsChanged(local_description_->transport_desc.ice_ufrag,
189*d9f75844SAndroid Build Coastguard Worker local_description_->transport_desc.ice_pwd,
190*d9f75844SAndroid Build Coastguard Worker ice_parameters.ufrag, ice_parameters.pwd);
191*d9f75844SAndroid Build Coastguard Worker local_description_.reset(new JsepTransportDescription(jsep_description));
192*d9f75844SAndroid Build Coastguard Worker
193*d9f75844SAndroid Build Coastguard Worker rtc::SSLFingerprint* local_fp =
194*d9f75844SAndroid Build Coastguard Worker local_description_->transport_desc.identity_fingerprint.get();
195*d9f75844SAndroid Build Coastguard Worker
196*d9f75844SAndroid Build Coastguard Worker if (!local_fp) {
197*d9f75844SAndroid Build Coastguard Worker local_certificate_ = nullptr;
198*d9f75844SAndroid Build Coastguard Worker } else {
199*d9f75844SAndroid Build Coastguard Worker error = VerifyCertificateFingerprint(local_certificate_.get(), local_fp);
200*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
201*d9f75844SAndroid Build Coastguard Worker local_description_.reset();
202*d9f75844SAndroid Build Coastguard Worker return error;
203*d9f75844SAndroid Build Coastguard Worker }
204*d9f75844SAndroid Build Coastguard Worker }
205*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport_->internal());
206*d9f75844SAndroid Build Coastguard Worker rtp_dtls_transport_->internal()->ice_transport()->SetIceParameters(
207*d9f75844SAndroid Build Coastguard Worker ice_parameters);
208*d9f75844SAndroid Build Coastguard Worker
209*d9f75844SAndroid Build Coastguard Worker if (rtcp_dtls_transport_) {
210*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtcp_dtls_transport_->internal());
211*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport_->internal()->ice_transport()->SetIceParameters(
212*d9f75844SAndroid Build Coastguard Worker ice_parameters);
213*d9f75844SAndroid Build Coastguard Worker }
214*d9f75844SAndroid Build Coastguard Worker // If PRANSWER/ANSWER is set, we should decide transport protocol type.
215*d9f75844SAndroid Build Coastguard Worker if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
216*d9f75844SAndroid Build Coastguard Worker error = NegotiateAndSetDtlsParameters(type);
217*d9f75844SAndroid Build Coastguard Worker }
218*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
219*d9f75844SAndroid Build Coastguard Worker local_description_.reset();
220*d9f75844SAndroid Build Coastguard Worker return error;
221*d9f75844SAndroid Build Coastguard Worker }
222*d9f75844SAndroid Build Coastguard Worker
223*d9f75844SAndroid Build Coastguard Worker if (needs_ice_restart_ && ice_restarting) {
224*d9f75844SAndroid Build Coastguard Worker needs_ice_restart_ = false;
225*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag cleared for transport "
226*d9f75844SAndroid Build Coastguard Worker << mid();
227*d9f75844SAndroid Build Coastguard Worker }
228*d9f75844SAndroid Build Coastguard Worker
229*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError::OK();
230*d9f75844SAndroid Build Coastguard Worker }
231*d9f75844SAndroid Build Coastguard Worker
SetRemoteJsepTransportDescription(const JsepTransportDescription & jsep_description,webrtc::SdpType type)232*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
233*d9f75844SAndroid Build Coastguard Worker const JsepTransportDescription& jsep_description,
234*d9f75844SAndroid Build Coastguard Worker webrtc::SdpType type) {
235*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::SetLocalJsepTransportDescription");
236*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError error;
237*d9f75844SAndroid Build Coastguard Worker
238*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
239*d9f75844SAndroid Build Coastguard Worker
240*d9f75844SAndroid Build Coastguard Worker IceParameters ice_parameters =
241*d9f75844SAndroid Build Coastguard Worker jsep_description.transport_desc.GetIceParameters();
242*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError ice_parameters_result = ice_parameters.Validate();
243*d9f75844SAndroid Build Coastguard Worker if (!ice_parameters_result.ok()) {
244*d9f75844SAndroid Build Coastguard Worker remote_description_.reset();
245*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder sb;
246*d9f75844SAndroid Build Coastguard Worker sb << "Invalid ICE parameters: " << ice_parameters_result.message();
247*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
248*d9f75844SAndroid Build Coastguard Worker sb.Release());
249*d9f75844SAndroid Build Coastguard Worker }
250*d9f75844SAndroid Build Coastguard Worker
251*d9f75844SAndroid Build Coastguard Worker if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
252*d9f75844SAndroid Build Coastguard Worker ContentSource::CS_REMOTE)) {
253*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
254*d9f75844SAndroid Build Coastguard Worker "Failed to setup RTCP mux.");
255*d9f75844SAndroid Build Coastguard Worker }
256*d9f75844SAndroid Build Coastguard Worker
257*d9f75844SAndroid Build Coastguard Worker // If doing SDES, setup the SDES crypto parameters.
258*d9f75844SAndroid Build Coastguard Worker if (sdes_transport_) {
259*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport_);
260*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!dtls_srtp_transport_);
261*d9f75844SAndroid Build Coastguard Worker if (!SetSdes(jsep_description.cryptos,
262*d9f75844SAndroid Build Coastguard Worker jsep_description.encrypted_header_extension_ids, type,
263*d9f75844SAndroid Build Coastguard Worker ContentSource::CS_REMOTE)) {
264*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
265*d9f75844SAndroid Build Coastguard Worker "Failed to setup SDES crypto parameters.");
266*d9f75844SAndroid Build Coastguard Worker }
267*d9f75844SAndroid Build Coastguard Worker sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
268*d9f75844SAndroid Build Coastguard Worker jsep_description.rtp_abs_sendtime_extn_id);
269*d9f75844SAndroid Build Coastguard Worker } else if (dtls_srtp_transport_) {
270*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport_);
271*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sdes_transport_);
272*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
273*d9f75844SAndroid Build Coastguard Worker jsep_description.encrypted_header_extension_ids);
274*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
275*d9f75844SAndroid Build Coastguard Worker jsep_description.rtp_abs_sendtime_extn_id);
276*d9f75844SAndroid Build Coastguard Worker }
277*d9f75844SAndroid Build Coastguard Worker
278*d9f75844SAndroid Build Coastguard Worker remote_description_.reset(new JsepTransportDescription(jsep_description));
279*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport());
280*d9f75844SAndroid Build Coastguard Worker SetRemoteIceParameters(ice_parameters, rtp_dtls_transport()->ice_transport());
281*d9f75844SAndroid Build Coastguard Worker
282*d9f75844SAndroid Build Coastguard Worker if (rtcp_dtls_transport()) {
283*d9f75844SAndroid Build Coastguard Worker SetRemoteIceParameters(ice_parameters,
284*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport()->ice_transport());
285*d9f75844SAndroid Build Coastguard Worker }
286*d9f75844SAndroid Build Coastguard Worker
287*d9f75844SAndroid Build Coastguard Worker // If PRANSWER/ANSWER is set, we should decide transport protocol type.
288*d9f75844SAndroid Build Coastguard Worker if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
289*d9f75844SAndroid Build Coastguard Worker error = NegotiateAndSetDtlsParameters(SdpType::kOffer);
290*d9f75844SAndroid Build Coastguard Worker }
291*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
292*d9f75844SAndroid Build Coastguard Worker remote_description_.reset();
293*d9f75844SAndroid Build Coastguard Worker return error;
294*d9f75844SAndroid Build Coastguard Worker }
295*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError::OK();
296*d9f75844SAndroid Build Coastguard Worker }
297*d9f75844SAndroid Build Coastguard Worker
AddRemoteCandidates(const Candidates & candidates)298*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::AddRemoteCandidates(
299*d9f75844SAndroid Build Coastguard Worker const Candidates& candidates) {
300*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
301*d9f75844SAndroid Build Coastguard Worker if (!local_description_ || !remote_description_) {
302*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
303*d9f75844SAndroid Build Coastguard Worker mid() +
304*d9f75844SAndroid Build Coastguard Worker " is not ready to use the remote candidate "
305*d9f75844SAndroid Build Coastguard Worker "because the local or remote description is "
306*d9f75844SAndroid Build Coastguard Worker "not set.");
307*d9f75844SAndroid Build Coastguard Worker }
308*d9f75844SAndroid Build Coastguard Worker
309*d9f75844SAndroid Build Coastguard Worker for (const cricket::Candidate& candidate : candidates) {
310*d9f75844SAndroid Build Coastguard Worker auto transport =
311*d9f75844SAndroid Build Coastguard Worker candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
312*d9f75844SAndroid Build Coastguard Worker ? rtp_dtls_transport_
313*d9f75844SAndroid Build Coastguard Worker : rtcp_dtls_transport_;
314*d9f75844SAndroid Build Coastguard Worker if (!transport) {
315*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
316*d9f75844SAndroid Build Coastguard Worker "Candidate has an unknown component: " +
317*d9f75844SAndroid Build Coastguard Worker candidate.ToSensitiveString() + " for mid " +
318*d9f75844SAndroid Build Coastguard Worker mid());
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(transport->internal() && transport->internal()->ice_transport());
321*d9f75844SAndroid Build Coastguard Worker transport->internal()->ice_transport()->AddRemoteCandidate(candidate);
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError::OK();
324*d9f75844SAndroid Build Coastguard Worker }
325*d9f75844SAndroid Build Coastguard Worker
SetNeedsIceRestartFlag()326*d9f75844SAndroid Build Coastguard Worker void JsepTransport::SetNeedsIceRestartFlag() {
327*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
328*d9f75844SAndroid Build Coastguard Worker if (!needs_ice_restart_) {
329*d9f75844SAndroid Build Coastguard Worker needs_ice_restart_ = true;
330*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag set for transport " << mid();
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker }
333*d9f75844SAndroid Build Coastguard Worker
GetDtlsRole() const334*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
335*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
336*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport_);
337*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport_->internal());
338*d9f75844SAndroid Build Coastguard Worker rtc::SSLRole dtls_role;
339*d9f75844SAndroid Build Coastguard Worker if (!rtp_dtls_transport_->internal()->GetDtlsRole(&dtls_role)) {
340*d9f75844SAndroid Build Coastguard Worker return absl::optional<rtc::SSLRole>();
341*d9f75844SAndroid Build Coastguard Worker }
342*d9f75844SAndroid Build Coastguard Worker
343*d9f75844SAndroid Build Coastguard Worker return absl::optional<rtc::SSLRole>(dtls_role);
344*d9f75844SAndroid Build Coastguard Worker }
345*d9f75844SAndroid Build Coastguard Worker
GetStats(TransportStats * stats)346*d9f75844SAndroid Build Coastguard Worker bool JsepTransport::GetStats(TransportStats* stats) {
347*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::GetStats");
348*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
349*d9f75844SAndroid Build Coastguard Worker stats->transport_name = mid();
350*d9f75844SAndroid Build Coastguard Worker stats->channel_stats.clear();
351*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport_->internal());
352*d9f75844SAndroid Build Coastguard Worker bool ret = GetTransportStats(rtp_dtls_transport_->internal(),
353*d9f75844SAndroid Build Coastguard Worker ICE_CANDIDATE_COMPONENT_RTP, stats);
354*d9f75844SAndroid Build Coastguard Worker
355*d9f75844SAndroid Build Coastguard Worker if (rtcp_dtls_transport_) {
356*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtcp_dtls_transport_->internal());
357*d9f75844SAndroid Build Coastguard Worker ret &= GetTransportStats(rtcp_dtls_transport_->internal(),
358*d9f75844SAndroid Build Coastguard Worker ICE_CANDIDATE_COMPONENT_RTCP, stats);
359*d9f75844SAndroid Build Coastguard Worker }
360*d9f75844SAndroid Build Coastguard Worker return ret;
361*d9f75844SAndroid Build Coastguard Worker }
362*d9f75844SAndroid Build Coastguard Worker
VerifyCertificateFingerprint(const rtc::RTCCertificate * certificate,const rtc::SSLFingerprint * fingerprint) const363*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
364*d9f75844SAndroid Build Coastguard Worker const rtc::RTCCertificate* certificate,
365*d9f75844SAndroid Build Coastguard Worker const rtc::SSLFingerprint* fingerprint) const {
366*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::VerifyCertificateFingerprint");
367*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
368*d9f75844SAndroid Build Coastguard Worker if (!fingerprint) {
369*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
370*d9f75844SAndroid Build Coastguard Worker "No fingerprint");
371*d9f75844SAndroid Build Coastguard Worker }
372*d9f75844SAndroid Build Coastguard Worker if (!certificate) {
373*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
374*d9f75844SAndroid Build Coastguard Worker "Fingerprint provided but no identity available.");
375*d9f75844SAndroid Build Coastguard Worker }
376*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLFingerprint> fp_tmp =
377*d9f75844SAndroid Build Coastguard Worker rtc::SSLFingerprint::CreateUnique(fingerprint->algorithm,
378*d9f75844SAndroid Build Coastguard Worker *certificate->identity());
379*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(fp_tmp.get() != NULL);
380*d9f75844SAndroid Build Coastguard Worker if (*fp_tmp == *fingerprint) {
381*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError::OK();
382*d9f75844SAndroid Build Coastguard Worker }
383*d9f75844SAndroid Build Coastguard Worker char ss_buf[1024];
384*d9f75844SAndroid Build Coastguard Worker rtc::SimpleStringBuilder desc(ss_buf);
385*d9f75844SAndroid Build Coastguard Worker desc << "Local fingerprint does not match identity. Expected: ";
386*d9f75844SAndroid Build Coastguard Worker desc << fp_tmp->ToString();
387*d9f75844SAndroid Build Coastguard Worker desc << " Got: " << fingerprint->ToString();
388*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
389*d9f75844SAndroid Build Coastguard Worker std::string(desc.str()));
390*d9f75844SAndroid Build Coastguard Worker }
391*d9f75844SAndroid Build Coastguard Worker
SetActiveResetSrtpParams(bool active_reset_srtp_params)392*d9f75844SAndroid Build Coastguard Worker void JsepTransport::SetActiveResetSrtpParams(bool active_reset_srtp_params) {
393*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
394*d9f75844SAndroid Build Coastguard Worker if (dtls_srtp_transport_) {
395*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO)
396*d9f75844SAndroid Build Coastguard Worker << "Setting active_reset_srtp_params of DtlsSrtpTransport to: "
397*d9f75844SAndroid Build Coastguard Worker << active_reset_srtp_params;
398*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport_->SetActiveResetSrtpParams(active_reset_srtp_params);
399*d9f75844SAndroid Build Coastguard Worker }
400*d9f75844SAndroid Build Coastguard Worker }
401*d9f75844SAndroid Build Coastguard Worker
SetRemoteIceParameters(const IceParameters & ice_parameters,IceTransportInternal * ice_transport)402*d9f75844SAndroid Build Coastguard Worker void JsepTransport::SetRemoteIceParameters(
403*d9f75844SAndroid Build Coastguard Worker const IceParameters& ice_parameters,
404*d9f75844SAndroid Build Coastguard Worker IceTransportInternal* ice_transport) {
405*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT0("webrtc", "JsepTransport::SetRemoteIceParameters");
406*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
407*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(ice_transport);
408*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(remote_description_);
409*d9f75844SAndroid Build Coastguard Worker ice_transport->SetRemoteIceParameters(ice_parameters);
410*d9f75844SAndroid Build Coastguard Worker ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
411*d9f75844SAndroid Build Coastguard Worker }
412*d9f75844SAndroid Build Coastguard Worker
SetNegotiatedDtlsParameters(DtlsTransportInternal * dtls_transport,absl::optional<rtc::SSLRole> dtls_role,rtc::SSLFingerprint * remote_fingerprint)413*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters(
414*d9f75844SAndroid Build Coastguard Worker DtlsTransportInternal* dtls_transport,
415*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole> dtls_role,
416*d9f75844SAndroid Build Coastguard Worker rtc::SSLFingerprint* remote_fingerprint) {
417*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(dtls_transport);
418*d9f75844SAndroid Build Coastguard Worker return dtls_transport->SetRemoteParameters(
419*d9f75844SAndroid Build Coastguard Worker remote_fingerprint->algorithm, remote_fingerprint->digest.cdata(),
420*d9f75844SAndroid Build Coastguard Worker remote_fingerprint->digest.size(), dtls_role);
421*d9f75844SAndroid Build Coastguard Worker }
422*d9f75844SAndroid Build Coastguard Worker
SetRtcpMux(bool enable,webrtc::SdpType type,ContentSource source)423*d9f75844SAndroid Build Coastguard Worker bool JsepTransport::SetRtcpMux(bool enable,
424*d9f75844SAndroid Build Coastguard Worker webrtc::SdpType type,
425*d9f75844SAndroid Build Coastguard Worker ContentSource source) {
426*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
427*d9f75844SAndroid Build Coastguard Worker bool ret = false;
428*d9f75844SAndroid Build Coastguard Worker switch (type) {
429*d9f75844SAndroid Build Coastguard Worker case SdpType::kOffer:
430*d9f75844SAndroid Build Coastguard Worker ret = rtcp_mux_negotiator_.SetOffer(enable, source);
431*d9f75844SAndroid Build Coastguard Worker break;
432*d9f75844SAndroid Build Coastguard Worker case SdpType::kPrAnswer:
433*d9f75844SAndroid Build Coastguard Worker // This may activate RTCP muxing, but we don't yet destroy the transport
434*d9f75844SAndroid Build Coastguard Worker // because the final answer may deactivate it.
435*d9f75844SAndroid Build Coastguard Worker ret = rtcp_mux_negotiator_.SetProvisionalAnswer(enable, source);
436*d9f75844SAndroid Build Coastguard Worker break;
437*d9f75844SAndroid Build Coastguard Worker case SdpType::kAnswer:
438*d9f75844SAndroid Build Coastguard Worker ret = rtcp_mux_negotiator_.SetAnswer(enable, source);
439*d9f75844SAndroid Build Coastguard Worker if (ret && rtcp_mux_negotiator_.IsActive()) {
440*d9f75844SAndroid Build Coastguard Worker ActivateRtcpMux();
441*d9f75844SAndroid Build Coastguard Worker }
442*d9f75844SAndroid Build Coastguard Worker break;
443*d9f75844SAndroid Build Coastguard Worker default:
444*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
445*d9f75844SAndroid Build Coastguard Worker }
446*d9f75844SAndroid Build Coastguard Worker
447*d9f75844SAndroid Build Coastguard Worker if (!ret) {
448*d9f75844SAndroid Build Coastguard Worker return false;
449*d9f75844SAndroid Build Coastguard Worker }
450*d9f75844SAndroid Build Coastguard Worker
451*d9f75844SAndroid Build Coastguard Worker auto transport = rtp_transport();
452*d9f75844SAndroid Build Coastguard Worker transport->SetRtcpMuxEnabled(rtcp_mux_negotiator_.IsActive());
453*d9f75844SAndroid Build Coastguard Worker return ret;
454*d9f75844SAndroid Build Coastguard Worker }
455*d9f75844SAndroid Build Coastguard Worker
ActivateRtcpMux()456*d9f75844SAndroid Build Coastguard Worker void JsepTransport::ActivateRtcpMux() {
457*d9f75844SAndroid Build Coastguard Worker if (unencrypted_rtp_transport_) {
458*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sdes_transport_);
459*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!dtls_srtp_transport_);
460*d9f75844SAndroid Build Coastguard Worker unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
461*d9f75844SAndroid Build Coastguard Worker } else if (sdes_transport_) {
462*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport_);
463*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!dtls_srtp_transport_);
464*d9f75844SAndroid Build Coastguard Worker sdes_transport_->SetRtcpPacketTransport(nullptr);
465*d9f75844SAndroid Build Coastguard Worker } else if (dtls_srtp_transport_) {
466*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(dtls_srtp_transport_);
467*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!unencrypted_rtp_transport_);
468*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sdes_transport_);
469*d9f75844SAndroid Build Coastguard Worker dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
470*d9f75844SAndroid Build Coastguard Worker /*rtcp_dtls_transport=*/nullptr);
471*d9f75844SAndroid Build Coastguard Worker }
472*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport_ = nullptr; // Destroy this reference.
473*d9f75844SAndroid Build Coastguard Worker // Notify the JsepTransportController to update the aggregate states.
474*d9f75844SAndroid Build Coastguard Worker rtcp_mux_active_callback_();
475*d9f75844SAndroid Build Coastguard Worker }
476*d9f75844SAndroid Build Coastguard Worker
SetSdes(const std::vector<CryptoParams> & cryptos,const std::vector<int> & encrypted_extension_ids,webrtc::SdpType type,ContentSource source)477*d9f75844SAndroid Build Coastguard Worker bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos,
478*d9f75844SAndroid Build Coastguard Worker const std::vector<int>& encrypted_extension_ids,
479*d9f75844SAndroid Build Coastguard Worker webrtc::SdpType type,
480*d9f75844SAndroid Build Coastguard Worker ContentSource source) {
481*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
482*d9f75844SAndroid Build Coastguard Worker bool ret = false;
483*d9f75844SAndroid Build Coastguard Worker ret = sdes_negotiator_.Process(cryptos, type, source);
484*d9f75844SAndroid Build Coastguard Worker if (!ret) {
485*d9f75844SAndroid Build Coastguard Worker return ret;
486*d9f75844SAndroid Build Coastguard Worker }
487*d9f75844SAndroid Build Coastguard Worker
488*d9f75844SAndroid Build Coastguard Worker if (source == ContentSource::CS_LOCAL) {
489*d9f75844SAndroid Build Coastguard Worker recv_extension_ids_ = encrypted_extension_ids;
490*d9f75844SAndroid Build Coastguard Worker } else {
491*d9f75844SAndroid Build Coastguard Worker send_extension_ids_ = encrypted_extension_ids;
492*d9f75844SAndroid Build Coastguard Worker }
493*d9f75844SAndroid Build Coastguard Worker
494*d9f75844SAndroid Build Coastguard Worker // If setting an SDES answer succeeded, apply the negotiated parameters
495*d9f75844SAndroid Build Coastguard Worker // to the SRTP transport.
496*d9f75844SAndroid Build Coastguard Worker if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
497*d9f75844SAndroid Build Coastguard Worker if (sdes_negotiator_.send_cipher_suite() &&
498*d9f75844SAndroid Build Coastguard Worker sdes_negotiator_.recv_cipher_suite()) {
499*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(send_extension_ids_);
500*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(recv_extension_ids_);
501*d9f75844SAndroid Build Coastguard Worker ret = sdes_transport_->SetRtpParams(
502*d9f75844SAndroid Build Coastguard Worker *(sdes_negotiator_.send_cipher_suite()),
503*d9f75844SAndroid Build Coastguard Worker sdes_negotiator_.send_key().data(),
504*d9f75844SAndroid Build Coastguard Worker static_cast<int>(sdes_negotiator_.send_key().size()),
505*d9f75844SAndroid Build Coastguard Worker *(send_extension_ids_), *(sdes_negotiator_.recv_cipher_suite()),
506*d9f75844SAndroid Build Coastguard Worker sdes_negotiator_.recv_key().data(),
507*d9f75844SAndroid Build Coastguard Worker static_cast<int>(sdes_negotiator_.recv_key().size()),
508*d9f75844SAndroid Build Coastguard Worker *(recv_extension_ids_));
509*d9f75844SAndroid Build Coastguard Worker } else {
510*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
511*d9f75844SAndroid Build Coastguard Worker if (type == SdpType::kAnswer) {
512*d9f75844SAndroid Build Coastguard Worker // Explicitly reset the `sdes_transport_` if no crypto param is
513*d9f75844SAndroid Build Coastguard Worker // provided in the answer. No need to call `ResetParams()` for
514*d9f75844SAndroid Build Coastguard Worker // `sdes_negotiator_` because it resets the params inside `SetAnswer`.
515*d9f75844SAndroid Build Coastguard Worker sdes_transport_->ResetParams();
516*d9f75844SAndroid Build Coastguard Worker }
517*d9f75844SAndroid Build Coastguard Worker }
518*d9f75844SAndroid Build Coastguard Worker }
519*d9f75844SAndroid Build Coastguard Worker return ret;
520*d9f75844SAndroid Build Coastguard Worker }
521*d9f75844SAndroid Build Coastguard Worker
NegotiateAndSetDtlsParameters(SdpType local_description_type)522*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
523*d9f75844SAndroid Build Coastguard Worker SdpType local_description_type) {
524*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
525*d9f75844SAndroid Build Coastguard Worker if (!local_description_ || !remote_description_) {
526*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
527*d9f75844SAndroid Build Coastguard Worker "Applying an answer transport description "
528*d9f75844SAndroid Build Coastguard Worker "without applying any offer.");
529*d9f75844SAndroid Build Coastguard Worker }
530*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
531*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole> negotiated_dtls_role;
532*d9f75844SAndroid Build Coastguard Worker
533*d9f75844SAndroid Build Coastguard Worker rtc::SSLFingerprint* local_fp =
534*d9f75844SAndroid Build Coastguard Worker local_description_->transport_desc.identity_fingerprint.get();
535*d9f75844SAndroid Build Coastguard Worker rtc::SSLFingerprint* remote_fp =
536*d9f75844SAndroid Build Coastguard Worker remote_description_->transport_desc.identity_fingerprint.get();
537*d9f75844SAndroid Build Coastguard Worker if (remote_fp && local_fp) {
538*d9f75844SAndroid Build Coastguard Worker remote_fingerprint = std::make_unique<rtc::SSLFingerprint>(*remote_fp);
539*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError error =
540*d9f75844SAndroid Build Coastguard Worker NegotiateDtlsRole(local_description_type,
541*d9f75844SAndroid Build Coastguard Worker local_description_->transport_desc.connection_role,
542*d9f75844SAndroid Build Coastguard Worker remote_description_->transport_desc.connection_role,
543*d9f75844SAndroid Build Coastguard Worker &negotiated_dtls_role);
544*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
545*d9f75844SAndroid Build Coastguard Worker return error;
546*d9f75844SAndroid Build Coastguard Worker }
547*d9f75844SAndroid Build Coastguard Worker } else if (local_fp && (local_description_type == SdpType::kAnswer)) {
548*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
549*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
550*d9f75844SAndroid Build Coastguard Worker "Local fingerprint supplied when caller didn't offer DTLS.");
551*d9f75844SAndroid Build Coastguard Worker } else {
552*d9f75844SAndroid Build Coastguard Worker // We are not doing DTLS
553*d9f75844SAndroid Build Coastguard Worker remote_fingerprint = std::make_unique<rtc::SSLFingerprint>(
554*d9f75844SAndroid Build Coastguard Worker "", rtc::ArrayView<const uint8_t>());
555*d9f75844SAndroid Build Coastguard Worker }
556*d9f75844SAndroid Build Coastguard Worker // Now that we have negotiated everything, push it downward.
557*d9f75844SAndroid Build Coastguard Worker // Note that we cache the result so that if we have race conditions
558*d9f75844SAndroid Build Coastguard Worker // between future SetRemote/SetLocal invocations and new transport
559*d9f75844SAndroid Build Coastguard Worker // creation, we have the negotiation state saved until a new
560*d9f75844SAndroid Build Coastguard Worker // negotiation happens.
561*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rtp_dtls_transport());
562*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError error = SetNegotiatedDtlsParameters(
563*d9f75844SAndroid Build Coastguard Worker rtp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
564*d9f75844SAndroid Build Coastguard Worker if (!error.ok()) {
565*d9f75844SAndroid Build Coastguard Worker return error;
566*d9f75844SAndroid Build Coastguard Worker }
567*d9f75844SAndroid Build Coastguard Worker
568*d9f75844SAndroid Build Coastguard Worker if (rtcp_dtls_transport()) {
569*d9f75844SAndroid Build Coastguard Worker error = SetNegotiatedDtlsParameters(
570*d9f75844SAndroid Build Coastguard Worker rtcp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
571*d9f75844SAndroid Build Coastguard Worker }
572*d9f75844SAndroid Build Coastguard Worker return error;
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker
NegotiateDtlsRole(SdpType local_description_type,ConnectionRole local_connection_role,ConnectionRole remote_connection_role,absl::optional<rtc::SSLRole> * negotiated_dtls_role)575*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError JsepTransport::NegotiateDtlsRole(
576*d9f75844SAndroid Build Coastguard Worker SdpType local_description_type,
577*d9f75844SAndroid Build Coastguard Worker ConnectionRole local_connection_role,
578*d9f75844SAndroid Build Coastguard Worker ConnectionRole remote_connection_role,
579*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole>* negotiated_dtls_role) {
580*d9f75844SAndroid Build Coastguard Worker // From RFC 4145, section-4.1, The following are the values that the
581*d9f75844SAndroid Build Coastguard Worker // 'setup' attribute can take in an offer/answer exchange:
582*d9f75844SAndroid Build Coastguard Worker // Offer Answer
583*d9f75844SAndroid Build Coastguard Worker // ________________
584*d9f75844SAndroid Build Coastguard Worker // active passive / holdconn
585*d9f75844SAndroid Build Coastguard Worker // passive active / holdconn
586*d9f75844SAndroid Build Coastguard Worker // actpass active / passive / holdconn
587*d9f75844SAndroid Build Coastguard Worker // holdconn holdconn
588*d9f75844SAndroid Build Coastguard Worker //
589*d9f75844SAndroid Build Coastguard Worker // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
590*d9f75844SAndroid Build Coastguard Worker // The endpoint MUST use the setup attribute defined in [RFC4145].
591*d9f75844SAndroid Build Coastguard Worker // The endpoint that is the offerer MUST use the setup attribute
592*d9f75844SAndroid Build Coastguard Worker // value of setup:actpass and be prepared to receive a client_hello
593*d9f75844SAndroid Build Coastguard Worker // before it receives the answer. The answerer MUST use either a
594*d9f75844SAndroid Build Coastguard Worker // setup attribute value of setup:active or setup:passive. Note that
595*d9f75844SAndroid Build Coastguard Worker // if the answerer uses setup:passive, then the DTLS handshake will
596*d9f75844SAndroid Build Coastguard Worker // not begin until the answerer is received, which adds additional
597*d9f75844SAndroid Build Coastguard Worker // latency. setup:active allows the answer and the DTLS handshake to
598*d9f75844SAndroid Build Coastguard Worker // occur in parallel. Thus, setup:active is RECOMMENDED. Whichever
599*d9f75844SAndroid Build Coastguard Worker // party is active MUST initiate a DTLS handshake by sending a
600*d9f75844SAndroid Build Coastguard Worker // ClientHello over each flow (host/port quartet).
601*d9f75844SAndroid Build Coastguard Worker // IOW - actpass and passive modes should be treated as server and
602*d9f75844SAndroid Build Coastguard Worker // active as client.
603*d9f75844SAndroid Build Coastguard Worker // RFC 8842 section 5.3 updates this text, so that it is mandated
604*d9f75844SAndroid Build Coastguard Worker // for the responder to handle offers with "active" and "passive"
605*d9f75844SAndroid Build Coastguard Worker // as well as "actpass"
606*d9f75844SAndroid Build Coastguard Worker bool is_remote_server = false;
607*d9f75844SAndroid Build Coastguard Worker if (local_description_type == SdpType::kOffer) {
608*d9f75844SAndroid Build Coastguard Worker if (local_connection_role != CONNECTIONROLE_ACTPASS) {
609*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
610*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
611*d9f75844SAndroid Build Coastguard Worker "Offerer must use actpass value for setup attribute.");
612*d9f75844SAndroid Build Coastguard Worker }
613*d9f75844SAndroid Build Coastguard Worker
614*d9f75844SAndroid Build Coastguard Worker if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
615*d9f75844SAndroid Build Coastguard Worker remote_connection_role == CONNECTIONROLE_PASSIVE ||
616*d9f75844SAndroid Build Coastguard Worker remote_connection_role == CONNECTIONROLE_NONE) {
617*d9f75844SAndroid Build Coastguard Worker is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
618*d9f75844SAndroid Build Coastguard Worker } else {
619*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
620*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
621*d9f75844SAndroid Build Coastguard Worker "Answerer must use either active or passive value "
622*d9f75844SAndroid Build Coastguard Worker "for setup attribute.");
623*d9f75844SAndroid Build Coastguard Worker }
624*d9f75844SAndroid Build Coastguard Worker // If remote is NONE or ACTIVE it will act as client.
625*d9f75844SAndroid Build Coastguard Worker } else {
626*d9f75844SAndroid Build Coastguard Worker if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
627*d9f75844SAndroid Build Coastguard Worker remote_connection_role != CONNECTIONROLE_NONE) {
628*d9f75844SAndroid Build Coastguard Worker // Accept a remote role attribute that's not "actpass", but matches the
629*d9f75844SAndroid Build Coastguard Worker // current negotiated role. This is allowed by dtls-sdp, though our
630*d9f75844SAndroid Build Coastguard Worker // implementation will never generate such an offer as it's not
631*d9f75844SAndroid Build Coastguard Worker // recommended.
632*d9f75844SAndroid Build Coastguard Worker //
633*d9f75844SAndroid Build Coastguard Worker // See https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-dtls-sdp,
634*d9f75844SAndroid Build Coastguard Worker // section 5.5.
635*d9f75844SAndroid Build Coastguard Worker auto current_dtls_role = GetDtlsRole();
636*d9f75844SAndroid Build Coastguard Worker if (!current_dtls_role) {
637*d9f75844SAndroid Build Coastguard Worker // Role not assigned yet. Verify that local role fits with remote role.
638*d9f75844SAndroid Build Coastguard Worker switch (remote_connection_role) {
639*d9f75844SAndroid Build Coastguard Worker case CONNECTIONROLE_ACTIVE:
640*d9f75844SAndroid Build Coastguard Worker if (local_connection_role != CONNECTIONROLE_PASSIVE) {
641*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
642*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
643*d9f75844SAndroid Build Coastguard Worker "Answerer must be passive when offerer is active");
644*d9f75844SAndroid Build Coastguard Worker }
645*d9f75844SAndroid Build Coastguard Worker break;
646*d9f75844SAndroid Build Coastguard Worker case CONNECTIONROLE_PASSIVE:
647*d9f75844SAndroid Build Coastguard Worker if (local_connection_role != CONNECTIONROLE_ACTIVE) {
648*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
649*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
650*d9f75844SAndroid Build Coastguard Worker "Answerer must be active when offerer is passive");
651*d9f75844SAndroid Build Coastguard Worker }
652*d9f75844SAndroid Build Coastguard Worker break;
653*d9f75844SAndroid Build Coastguard Worker default:
654*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
655*d9f75844SAndroid Build Coastguard Worker break;
656*d9f75844SAndroid Build Coastguard Worker }
657*d9f75844SAndroid Build Coastguard Worker } else {
658*d9f75844SAndroid Build Coastguard Worker if ((*current_dtls_role == rtc::SSL_CLIENT &&
659*d9f75844SAndroid Build Coastguard Worker remote_connection_role == CONNECTIONROLE_ACTIVE) ||
660*d9f75844SAndroid Build Coastguard Worker (*current_dtls_role == rtc::SSL_SERVER &&
661*d9f75844SAndroid Build Coastguard Worker remote_connection_role == CONNECTIONROLE_PASSIVE)) {
662*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
663*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
664*d9f75844SAndroid Build Coastguard Worker "Offerer must use current negotiated role for "
665*d9f75844SAndroid Build Coastguard Worker "setup attribute.");
666*d9f75844SAndroid Build Coastguard Worker }
667*d9f75844SAndroid Build Coastguard Worker }
668*d9f75844SAndroid Build Coastguard Worker }
669*d9f75844SAndroid Build Coastguard Worker
670*d9f75844SAndroid Build Coastguard Worker if (local_connection_role == CONNECTIONROLE_ACTIVE ||
671*d9f75844SAndroid Build Coastguard Worker local_connection_role == CONNECTIONROLE_PASSIVE) {
672*d9f75844SAndroid Build Coastguard Worker is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
673*d9f75844SAndroid Build Coastguard Worker } else {
674*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError(
675*d9f75844SAndroid Build Coastguard Worker webrtc::RTCErrorType::INVALID_PARAMETER,
676*d9f75844SAndroid Build Coastguard Worker "Answerer must use either active or passive value "
677*d9f75844SAndroid Build Coastguard Worker "for setup attribute.");
678*d9f75844SAndroid Build Coastguard Worker }
679*d9f75844SAndroid Build Coastguard Worker
680*d9f75844SAndroid Build Coastguard Worker // If local is passive, local will act as server.
681*d9f75844SAndroid Build Coastguard Worker }
682*d9f75844SAndroid Build Coastguard Worker
683*d9f75844SAndroid Build Coastguard Worker *negotiated_dtls_role =
684*d9f75844SAndroid Build Coastguard Worker (is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER);
685*d9f75844SAndroid Build Coastguard Worker return webrtc::RTCError::OK();
686*d9f75844SAndroid Build Coastguard Worker }
687*d9f75844SAndroid Build Coastguard Worker
GetTransportStats(DtlsTransportInternal * dtls_transport,int component,TransportStats * stats)688*d9f75844SAndroid Build Coastguard Worker bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
689*d9f75844SAndroid Build Coastguard Worker int component,
690*d9f75844SAndroid Build Coastguard Worker TransportStats* stats) {
691*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(network_thread_);
692*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(dtls_transport);
693*d9f75844SAndroid Build Coastguard Worker TransportChannelStats substats;
694*d9f75844SAndroid Build Coastguard Worker substats.component = component;
695*d9f75844SAndroid Build Coastguard Worker dtls_transport->GetSslVersionBytes(&substats.ssl_version_bytes);
696*d9f75844SAndroid Build Coastguard Worker dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
697*d9f75844SAndroid Build Coastguard Worker dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
698*d9f75844SAndroid Build Coastguard Worker substats.dtls_state = dtls_transport->dtls_state();
699*d9f75844SAndroid Build Coastguard Worker rtc::SSLRole dtls_role;
700*d9f75844SAndroid Build Coastguard Worker if (dtls_transport->GetDtlsRole(&dtls_role)) {
701*d9f75844SAndroid Build Coastguard Worker substats.dtls_role = dtls_role;
702*d9f75844SAndroid Build Coastguard Worker }
703*d9f75844SAndroid Build Coastguard Worker if (!dtls_transport->ice_transport()->GetStats(
704*d9f75844SAndroid Build Coastguard Worker &substats.ice_transport_stats)) {
705*d9f75844SAndroid Build Coastguard Worker return false;
706*d9f75844SAndroid Build Coastguard Worker }
707*d9f75844SAndroid Build Coastguard Worker stats->channel_stats.push_back(substats);
708*d9f75844SAndroid Build Coastguard Worker return true;
709*d9f75844SAndroid Build Coastguard Worker }
710*d9f75844SAndroid Build Coastguard Worker
711*d9f75844SAndroid Build Coastguard Worker } // namespace cricket
712