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