• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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