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