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