blob: 2398a0ad2de0ea1fdd344714e9afdcd513ca2ad4 [file] [log] [blame]
Zhi Huange818b6e2018-02-22 23:26:271/*
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
Steve Anton10542f22019-01-11 17:11:0011#include "pc/jsep_transport.h"
Zhi Huange818b6e2018-02-22 23:26:2712
Yves Gerey3e707812018-11-28 15:47:4913#include <stddef.h>
14#include <stdint.h>
Jonas Olssona4d87372019-07-05 17:08:3315
Mirko Bonadei96dca922021-07-10 20:37:4016#include <functional>
Zhi Huange818b6e2018-02-22 23:26:2717#include <memory>
Harald Alvestrandc24a2182022-02-23 13:44:5918#include <string>
Mirko Bonadei96dca922021-07-10 20:37:4019#include <utility>
Zhi Huange818b6e2018-02-22 23:26:2720
Yves Gerey3e707812018-11-28 15:47:4921#include "api/array_view.h"
Zhi Huange818b6e2018-02-22 23:26:2722#include "api/candidate.h"
Steve Anton10542f22019-01-11 17:11:0023#include "p2p/base/p2p_constants.h"
24#include "p2p/base/p2p_transport_channel.h"
Zhi Huange818b6e2018-02-22 23:26:2725#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0026#include "rtc_base/copy_on_write_buffer.h"
Zhi Huange818b6e2018-02-22 23:26:2727#include "rtc_base/logging.h"
Zhi Huang365381f2018-04-13 23:44:3428#include "rtc_base/strings/string_builder.h"
Markus Handell518669d2021-06-07 11:30:4629#include "rtc_base/trace_event.h"
Zhi Huange818b6e2018-02-22 23:26:2730
31using webrtc::SdpType;
32
33namespace cricket {
34
Zhi Huange818b6e2018-02-22 23:26:2735JsepTransportDescription::JsepTransportDescription() {}
36
37JsepTransportDescription::JsepTransportDescription(
38 bool rtcp_mux_enabled,
Harald Alvestrand0d018412021-11-04 13:52:3139 const std::vector<CryptoParams>& cryptos,
Zhi Huange818b6e2018-02-22 23:26:2740 const std::vector<int>& encrypted_header_extension_ids,
Zhi Huange830e682018-03-30 17:48:3541 int rtp_abs_sendtime_extn_id,
Niels Möllerdc80aaf2020-06-18 08:10:1742 const TransportDescription& transport_desc)
Zhi Huange818b6e2018-02-22 23:26:2743 : rtcp_mux_enabled(rtcp_mux_enabled),
Harald Alvestrand0d018412021-11-04 13:52:3144 cryptos(cryptos),
Zhi Huange818b6e2018-02-22 23:26:2745 encrypted_header_extension_ids(encrypted_header_extension_ids),
Zhi Huange830e682018-03-30 17:48:3546 rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
Niels Möllerdc80aaf2020-06-18 08:10:1747 transport_desc(transport_desc) {}
Zhi Huange818b6e2018-02-22 23:26:2748
49JsepTransportDescription::JsepTransportDescription(
50 const JsepTransportDescription& from)
51 : rtcp_mux_enabled(from.rtcp_mux_enabled),
Harald Alvestrand0d018412021-11-04 13:52:3152 cryptos(from.cryptos),
Zhi Huange818b6e2018-02-22 23:26:2753 encrypted_header_extension_ids(from.encrypted_header_extension_ids),
Zhi Huange830e682018-03-30 17:48:3554 rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
Niels Möllerdc80aaf2020-06-18 08:10:1755 transport_desc(from.transport_desc) {}
Zhi Huange818b6e2018-02-22 23:26:2756
57JsepTransportDescription::~JsepTransportDescription() = default;
58
59JsepTransportDescription& JsepTransportDescription::operator=(
60 const JsepTransportDescription& from) {
61 if (this == &from) {
62 return *this;
63 }
64 rtcp_mux_enabled = from.rtcp_mux_enabled;
Harald Alvestrand0d018412021-11-04 13:52:3165 cryptos = from.cryptos;
Zhi Huange818b6e2018-02-22 23:26:2766 encrypted_header_extension_ids = from.encrypted_header_extension_ids;
Zhi Huange830e682018-03-30 17:48:3567 rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
Zhi Huange818b6e2018-02-22 23:26:2768 transport_desc = from.transport_desc;
69
70 return *this;
71}
72
Zhi Huang365381f2018-04-13 23:44:3473JsepTransport::JsepTransport(
Zhi Huange818b6e2018-02-22 23:26:2774 const std::string& mid,
75 const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
Qingsi Wang25ec8882019-11-15 20:33:0576 rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
77 rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
Zhi Huange818b6e2018-02-22 23:26:2778 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,
Anton Sukhanov7940da02018-10-10 17:34:4982 std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
Mirko Bonadei96dca922021-07-10 20:37:4083 std::unique_ptr<SctpTransportInternal> sctp_transport,
84 std::function<void()> rtcp_mux_active_callback)
Harald Alvestrand78a5e962019-04-03 08:42:3985 : network_thread_(rtc::Thread::Current()),
86 mid_(mid),
Zhi Huange818b6e2018-02-22 23:26:2787 local_certificate_(local_certificate),
Bjorn A Mellem0c1c1b42019-05-30 00:34:1388 ice_transport_(std::move(ice_transport)),
89 rtcp_ice_transport_(std::move(rtcp_ice_transport)),
Harald Alvestrand78a5e962019-04-03 08:42:3990 unencrypted_rtp_transport_(std::move(unencrypted_rtp_transport)),
Harald Alvestrand0d018412021-11-04 13:52:3191 sdes_transport_(std::move(sdes_transport)),
Harald Alvestrand78a5e962019-04-03 08:42:3992 dtls_srtp_transport_(std::move(dtls_srtp_transport)),
Tommi87f70902021-04-27 12:43:0893 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),
Bjorn A Mellembc3eebc2019-09-23 21:53:54101 sctp_transport_(sctp_transport
Tommi87f70902021-04-27 12:43:08102 ? rtc::make_ref_counted<webrtc::SctpTransport>(
Bjorn A Mellembc3eebc2019-09-23 21:53:54103 std::move(sctp_transport))
Mirko Bonadei96dca922021-07-10 20:37:40104 : nullptr),
105 rtcp_mux_active_callback_(std::move(rtcp_mux_active_callback)) {
Markus Handell518669d2021-06-07 11:30:46106 TRACE_EVENT0("webrtc", "JsepTransport::JsepTransport");
Bjorn A Mellem0c1c1b42019-05-30 00:34:13107 RTC_DCHECK(ice_transport_);
Zhi Huange818b6e2018-02-22 23:26:27108 RTC_DCHECK(rtp_dtls_transport_);
Artem Titov880fa812021-07-30 20:30:23109 // `rtcp_ice_transport_` must be present iff `rtcp_dtls_transport_` is
Bjorn A Mellem0c1c1b42019-05-30 00:34:13110 // present.
111 RTC_DCHECK_EQ((rtcp_ice_transport_ != nullptr),
112 (rtcp_dtls_transport_ != nullptr));
Harald Alvestrand78a5e962019-04-03 08:42:39113 // Verify the "only one out of these three can be set" invariant.
114 if (unencrypted_rtp_transport_) {
Harald Alvestrand0d018412021-11-04 13:52:31115 RTC_DCHECK(!sdes_transport);
116 RTC_DCHECK(!dtls_srtp_transport);
117 } else if (sdes_transport_) {
118 RTC_DCHECK(!unencrypted_rtp_transport);
Zhi Huange818b6e2018-02-22 23:26:27119 RTC_DCHECK(!dtls_srtp_transport);
Zhi Huange818b6e2018-02-22 23:26:27120 } else {
Harald Alvestrand78a5e962019-04-03 08:42:39121 RTC_DCHECK(dtls_srtp_transport_);
Zhi Huange818b6e2018-02-22 23:26:27122 RTC_DCHECK(!unencrypted_rtp_transport);
Harald Alvestrand0d018412021-11-04 13:52:31123 RTC_DCHECK(!sdes_transport);
Zhi Huange818b6e2018-02-22 23:26:27124 }
Piotr (Peter) Slatala4eb41122018-11-01 14:26:03125
Bjorn A Mellembc3eebc2019-09-23 21:53:54126 if (sctp_transport_) {
127 sctp_transport_->SetDtlsTransport(rtp_dtls_transport_);
128 }
Zhi Huange818b6e2018-02-22 23:26:27129}
130
Piotr (Peter) Slatala4eb41122018-11-01 14:26:03131JsepTransport::~JsepTransport() {
Markus Handell518669d2021-06-07 11:30:46132 TRACE_EVENT0("webrtc", "JsepTransport::~JsepTransport");
Bjorn A Mellembc3eebc2019-09-23 21:53:54133 if (sctp_transport_) {
134 sctp_transport_->Clear();
135 }
136
Harald Alvestrand628f37a2018-12-06 09:55:20137 // 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.
Harald Alvestrandd02541e2019-01-03 11:43:28139 rtp_dtls_transport_->Clear();
Harald Alvestrand628f37a2018-12-06 09:55:20140 if (rtcp_dtls_transport_) {
Harald Alvestrandd02541e2019-01-03 11:43:28141 rtcp_dtls_transport_->Clear();
Harald Alvestrand628f37a2018-12-06 09:55:20142 }
Anton Sukhanov292ce4e2019-06-03 20:00:24143
Anton Sukhanov292ce4e2019-06-03 20:00:24144 // ICE will be the last transport to be deleted.
Piotr (Peter) Slatala4eb41122018-11-01 14:26:03145}
Zhi Huange818b6e2018-02-22 23:26:27146
Zhi Huang365381f2018-04-13 23:44:34147webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
Zhi Huange818b6e2018-02-22 23:26:27148 const JsepTransportDescription& jsep_description,
149 SdpType type) {
150 webrtc::RTCError error;
Markus Handell518669d2021-06-07 11:30:46151 TRACE_EVENT0("webrtc", "JsepTransport::SetLocalJsepTransportDescription");
Harald Alvestrand78a5e962019-04-03 08:42:39152 RTC_DCHECK_RUN_ON(network_thread_);
Steve Anton71ff0732020-01-25 00:28:15153
Jonas Oreland52aea5d2020-03-03 12:21:30154 IceParameters ice_parameters =
155 jsep_description.transport_desc.GetIceParameters();
156 webrtc::RTCError ice_parameters_result = ice_parameters.Validate();
Steve Anton71ff0732020-01-25 00:28:15157 if (!ice_parameters_result.ok()) {
158 rtc::StringBuilder sb;
Jonas Oreland52aea5d2020-03-03 12:21:30159 sb << "Invalid ICE parameters: " << ice_parameters_result.message();
Zhi Huange818b6e2018-02-22 23:26:27160 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
Steve Anton71ff0732020-01-25 00:28:15161 sb.Release());
Zhi Huange818b6e2018-02-22 23:26:27162 }
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
Harald Alvestrand0d018412021-11-04 13:52:31170 // If doing SDES, setup the SDES crypto parameters.
171 if (sdes_transport_) {
Niels Möller6a48a1d2021-02-05 11:34:14172 RTC_DCHECK(!unencrypted_rtp_transport_);
Harald Alvestrand0d018412021-11-04 13:52:31173 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_);
Niels Möller6a48a1d2021-02-05 11:34:14183 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
184 jsep_description.encrypted_header_extension_ids);
Zhi Huange818b6e2018-02-22 23:26:27185 }
Zhi Huange818b6e2018-02-22 23:26:27186 bool ice_restarting =
187 local_description_ != nullptr &&
188 IceCredentialsChanged(local_description_->transport_desc.ice_ufrag,
189 local_description_->transport_desc.ice_pwd,
Steve Anton71ff0732020-01-25 00:28:15190 ice_parameters.ufrag, ice_parameters.pwd);
Zhi Huange818b6e2018-02-22 23:26:27191 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 {
Niels Möllerafb246b2022-04-20 12:26:50199 error = VerifyCertificateFingerprint(local_certificate_.get(), local_fp);
Zhi Huange818b6e2018-02-22 23:26:27200 if (!error.ok()) {
201 local_description_.reset();
202 return error;
203 }
204 }
Yaowen Guo9e138602022-01-05 09:48:33205 RTC_DCHECK(rtp_dtls_transport_->internal());
206 rtp_dtls_transport_->internal()->ice_transport()->SetIceParameters(
207 ice_parameters);
Zhi Huange818b6e2018-02-22 23:26:27208
Yaowen Guo9e138602022-01-05 09:48:33209 if (rtcp_dtls_transport_) {
210 RTC_DCHECK(rtcp_dtls_transport_->internal());
211 rtcp_dtls_transport_->internal()->ice_transport()->SetIceParameters(
212 ice_parameters);
213 }
Zhi Huange818b6e2018-02-22 23:26:27214 // 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 }
Tomas Gunnarsson20f74562021-02-04 09:22:50222
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();
Zhi Huange818b6e2018-02-22 23:26:27227 }
228
229 return webrtc::RTCError::OK();
230}
231
Zhi Huang365381f2018-04-13 23:44:34232webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
Zhi Huange818b6e2018-02-22 23:26:27233 const JsepTransportDescription& jsep_description,
234 webrtc::SdpType type) {
Markus Handell518669d2021-06-07 11:30:46235 TRACE_EVENT0("webrtc", "JsepTransport::SetLocalJsepTransportDescription");
Zhi Huange818b6e2018-02-22 23:26:27236 webrtc::RTCError error;
237
Harald Alvestrand78a5e962019-04-03 08:42:39238 RTC_DCHECK_RUN_ON(network_thread_);
Steve Anton71ff0732020-01-25 00:28:15239
Jonas Oreland52aea5d2020-03-03 12:21:30240 IceParameters ice_parameters =
241 jsep_description.transport_desc.GetIceParameters();
242 webrtc::RTCError ice_parameters_result = ice_parameters.Validate();
Steve Anton71ff0732020-01-25 00:28:15243 if (!ice_parameters_result.ok()) {
Zhi Huange818b6e2018-02-22 23:26:27244 remote_description_.reset();
Steve Anton71ff0732020-01-25 00:28:15245 rtc::StringBuilder sb;
Jonas Oreland52aea5d2020-03-03 12:21:30246 sb << "Invalid ICE parameters: " << ice_parameters_result.message();
Zhi Huange818b6e2018-02-22 23:26:27247 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
Steve Anton71ff0732020-01-25 00:28:15248 sb.Release());
Zhi Huange818b6e2018-02-22 23:26:27249 }
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
Harald Alvestrand0d018412021-11-04 13:52:31257 // If doing SDES, setup the SDES crypto parameters.
258 if (sdes_transport_) {
Niels Möller6a48a1d2021-02-05 11:34:14259 RTC_DCHECK(!unencrypted_rtp_transport_);
Harald Alvestrand0d018412021-11-04 13:52:31260 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_);
Niels Möller6a48a1d2021-02-05 11:34:14272 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
273 jsep_description.encrypted_header_extension_ids);
274 dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
275 jsep_description.rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 23:26:27276 }
277
278 remote_description_.reset(new JsepTransportDescription(jsep_description));
Harald Alvestrand78a5e962019-04-03 08:42:39279 RTC_DCHECK(rtp_dtls_transport());
Steve Anton71ff0732020-01-25 00:28:15280 SetRemoteIceParameters(ice_parameters, rtp_dtls_transport()->ice_transport());
Zhi Huange818b6e2018-02-22 23:26:27281
Harald Alvestrand78a5e962019-04-03 08:42:39282 if (rtcp_dtls_transport()) {
Steve Anton71ff0732020-01-25 00:28:15283 SetRemoteIceParameters(ice_parameters,
284 rtcp_dtls_transport()->ice_transport());
Zhi Huange818b6e2018-02-22 23:26:27285 }
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
Zhi Huang365381f2018-04-13 23:44:34298webrtc::RTCError JsepTransport::AddRemoteCandidates(
Zhi Huange818b6e2018-02-22 23:26:27299 const Candidates& candidates) {
Harald Alvestrand78a5e962019-04-03 08:42:39300 RTC_DCHECK_RUN_ON(network_thread_);
Henrik Boström5d8f8fa2018-04-13 15:22:50301 if (!local_description_ || !remote_description_) {
Zhi Huange818b6e2018-02-22 23:26:27302 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
303 mid() +
304 " is not ready to use the remote candidate "
Henrik Boström5d8f8fa2018-04-13 15:22:50305 "because the local or remote description is "
306 "not set.");
Zhi Huange818b6e2018-02-22 23:26:27307 }
308
309 for (const cricket::Candidate& candidate : candidates) {
310 auto transport =
311 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
Harald Alvestrandad88c882018-11-28 15:47:46312 ? rtp_dtls_transport_
313 : rtcp_dtls_transport_;
Zhi Huange818b6e2018-02-22 23:26:27314 if (!transport) {
315 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
316 "Candidate has an unknown component: " +
Qingsi Wang20232a92019-09-06 19:51:17317 candidate.ToSensitiveString() + " for mid " +
318 mid());
Zhi Huange818b6e2018-02-22 23:26:27319 }
Harald Alvestrand628f37a2018-12-06 09:55:20320 RTC_DCHECK(transport->internal() && transport->internal()->ice_transport());
Harald Alvestrandad88c882018-11-28 15:47:46321 transport->internal()->ice_transport()->AddRemoteCandidate(candidate);
Zhi Huange818b6e2018-02-22 23:26:27322 }
323 return webrtc::RTCError::OK();
324}
325
Zhi Huang365381f2018-04-13 23:44:34326void JsepTransport::SetNeedsIceRestartFlag() {
Tomas Gunnarsson20f74562021-02-04 09:22:50327 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27328 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
Danil Chapovalov66cadcc2018-06-19 14:47:43334absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
Harald Alvestrand78a5e962019-04-03 08:42:39335 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27336 RTC_DCHECK(rtp_dtls_transport_);
Harald Alvestrand628f37a2018-12-06 09:55:20337 RTC_DCHECK(rtp_dtls_transport_->internal());
Zhi Huange818b6e2018-02-22 23:26:27338 rtc::SSLRole dtls_role;
Harald Alvestrandad88c882018-11-28 15:47:46339 if (!rtp_dtls_transport_->internal()->GetDtlsRole(&dtls_role)) {
Danil Chapovalov66cadcc2018-06-19 14:47:43340 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 23:26:27341 }
342
Danil Chapovalov66cadcc2018-06-19 14:47:43343 return absl::optional<rtc::SSLRole>(dtls_role);
Zhi Huange818b6e2018-02-22 23:26:27344}
345
Zhi Huang365381f2018-04-13 23:44:34346bool JsepTransport::GetStats(TransportStats* stats) {
Markus Handell518669d2021-06-07 11:30:46347 TRACE_EVENT0("webrtc", "JsepTransport::GetStats");
Harald Alvestrand78a5e962019-04-03 08:42:39348 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27349 stats->transport_name = mid();
350 stats->channel_stats.clear();
Harald Alvestrand628f37a2018-12-06 09:55:20351 RTC_DCHECK(rtp_dtls_transport_->internal());
Niels Möller6a48a1d2021-02-05 11:34:14352 bool ret = GetTransportStats(rtp_dtls_transport_->internal(),
353 ICE_CANDIDATE_COMPONENT_RTP, stats);
354
Zhi Huange818b6e2018-02-22 23:26:27355 if (rtcp_dtls_transport_) {
Harald Alvestrand628f37a2018-12-06 09:55:20356 RTC_DCHECK(rtcp_dtls_transport_->internal());
Niels Möller6a48a1d2021-02-05 11:34:14357 ret &= GetTransportStats(rtcp_dtls_transport_->internal(),
358 ICE_CANDIDATE_COMPONENT_RTCP, stats);
Zhi Huange818b6e2018-02-22 23:26:27359 }
360 return ret;
361}
362
Zhi Huang365381f2018-04-13 23:44:34363webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
Zhi Huange818b6e2018-02-22 23:26:27364 const rtc::RTCCertificate* certificate,
365 const rtc::SSLFingerprint* fingerprint) const {
Markus Handell518669d2021-06-07 11:30:46366 TRACE_EVENT0("webrtc", "JsepTransport::VerifyCertificateFingerprint");
Harald Alvestrand78a5e962019-04-03 08:42:39367 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27368 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 }
Steve Anton4905edb2018-10-16 02:27:44376 std::unique_ptr<rtc::SSLFingerprint> fp_tmp =
377 rtc::SSLFingerprint::CreateUnique(fingerprint->algorithm,
378 *certificate->identity());
Zhi Huange818b6e2018-02-22 23:26:27379 RTC_DCHECK(fp_tmp.get() != NULL);
380 if (*fp_tmp == *fingerprint) {
381 return webrtc::RTCError::OK();
382 }
Zhi Huang365381f2018-04-13 23:44:34383 char ss_buf[1024];
384 rtc::SimpleStringBuilder desc(ss_buf);
Zhi Huange818b6e2018-02-22 23:26:27385 desc << "Local fingerprint does not match identity. Expected: ";
386 desc << fp_tmp->ToString();
387 desc << " Got: " << fingerprint->ToString();
Zhi Huang365381f2018-04-13 23:44:34388 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
389 std::string(desc.str()));
Zhi Huange818b6e2018-02-22 23:26:27390}
391
Zhi Huangb57e1692018-06-12 18:41:11392void JsepTransport::SetActiveResetSrtpParams(bool active_reset_srtp_params) {
Harald Alvestrand78a5e962019-04-03 08:42:39393 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huangb57e1692018-06-12 18:41:11394 if (dtls_srtp_transport_) {
Harald Alvestrand97597c02021-11-04 12:01:23395 RTC_LOG(LS_INFO)
Zhi Huangb57e1692018-06-12 18:41:11396 << "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
Zhi Huang365381f2018-04-13 23:44:34402void JsepTransport::SetRemoteIceParameters(
Steve Anton71ff0732020-01-25 00:28:15403 const IceParameters& ice_parameters,
Zhi Huange818b6e2018-02-22 23:26:27404 IceTransportInternal* ice_transport) {
Markus Handell518669d2021-06-07 11:30:46405 TRACE_EVENT0("webrtc", "JsepTransport::SetRemoteIceParameters");
Harald Alvestrand78a5e962019-04-03 08:42:39406 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27407 RTC_DCHECK(ice_transport);
408 RTC_DCHECK(remote_description_);
Steve Anton71ff0732020-01-25 00:28:15409 ice_transport->SetRemoteIceParameters(ice_parameters);
Zhi Huange818b6e2018-02-22 23:26:27410 ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
411}
412
Zhi Huang365381f2018-04-13 23:44:34413webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters(
Zhi Huange818b6e2018-02-22 23:26:27414 DtlsTransportInternal* dtls_transport,
Danil Chapovalov66cadcc2018-06-19 14:47:43415 absl::optional<rtc::SSLRole> dtls_role,
Zhi Huange818b6e2018-02-22 23:26:27416 rtc::SSLFingerprint* remote_fingerprint) {
417 RTC_DCHECK(dtls_transport);
Philipp Hancke4a3b5cc2022-08-18 12:48:21418 return dtls_transport->SetRemoteParameters(
419 remote_fingerprint->algorithm, remote_fingerprint->digest.cdata(),
420 remote_fingerprint->digest.size(), dtls_role);
Zhi Huange818b6e2018-02-22 23:26:27421}
422
Zhi Huang365381f2018-04-13 23:44:34423bool JsepTransport::SetRtcpMux(bool enable,
424 webrtc::SdpType type,
425 ContentSource source) {
Harald Alvestrand78a5e962019-04-03 08:42:39426 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27427 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:
Artem Titovd3251962021-11-15 15:57:07444 RTC_DCHECK_NOTREACHED();
Zhi Huange818b6e2018-02-22 23:26:27445 }
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
Zhi Huang365381f2018-04-13 23:44:34456void JsepTransport::ActivateRtcpMux() {
Niels Möller6a48a1d2021-02-05 11:34:14457 if (unencrypted_rtp_transport_) {
Harald Alvestrand0d018412021-11-04 13:52:31458 RTC_DCHECK(!sdes_transport_);
Niels Möller6a48a1d2021-02-05 11:34:14459 RTC_DCHECK(!dtls_srtp_transport_);
460 unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
Harald Alvestrand0d018412021-11-04 13:52:31461 } else if (sdes_transport_) {
462 RTC_DCHECK(!unencrypted_rtp_transport_);
463 RTC_DCHECK(!dtls_srtp_transport_);
464 sdes_transport_->SetRtcpPacketTransport(nullptr);
Niels Möller6a48a1d2021-02-05 11:34:14465 } else if (dtls_srtp_transport_) {
466 RTC_DCHECK(dtls_srtp_transport_);
467 RTC_DCHECK(!unencrypted_rtp_transport_);
Harald Alvestrand0d018412021-11-04 13:52:31468 RTC_DCHECK(!sdes_transport_);
Niels Möller6a48a1d2021-02-05 11:34:14469 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
470 /*rtcp_dtls_transport=*/nullptr);
Harald Alvestrand78a5e962019-04-03 08:42:39471 }
Harald Alvestrandd4ad2ef2021-02-05 23:36:39472 rtcp_dtls_transport_ = nullptr; // Destroy this reference.
Zhi Huange818b6e2018-02-22 23:26:27473 // Notify the JsepTransportController to update the aggregate states.
Mirko Bonadei96dca922021-07-10 20:37:40474 rtcp_mux_active_callback_();
Zhi Huange818b6e2018-02-22 23:26:27475}
476
Harald Alvestrand0d018412021-11-04 13:52:31477bool 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) {
Philipp Hancke55b89a82023-08-01 09:34:05497 if (sdes_negotiator_.send_crypto_suite() &&
498 sdes_negotiator_.recv_crypto_suite()) {
Harald Alvestrand0d018412021-11-04 13:52:31499 RTC_DCHECK(send_extension_ids_);
500 RTC_DCHECK(recv_extension_ids_);
501 ret = sdes_transport_->SetRtpParams(
Philipp Hancke55b89a82023-08-01 09:34:05502 *(sdes_negotiator_.send_crypto_suite()),
Harald Alvestrand0d018412021-11-04 13:52:31503 sdes_negotiator_.send_key().data(),
504 static_cast<int>(sdes_negotiator_.send_key().size()),
Philipp Hancke55b89a82023-08-01 09:34:05505 *(send_extension_ids_), *(sdes_negotiator_.recv_crypto_suite()),
Harald Alvestrand0d018412021-11-04 13:52:31506 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
Zhi Huang365381f2018-04-13 23:44:34522webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
Zhi Huange818b6e2018-02-22 23:26:27523 SdpType local_description_type) {
Harald Alvestrand78a5e962019-04-03 08:42:39524 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27525 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;
Danil Chapovalov66cadcc2018-06-19 14:47:43531 absl::optional<rtc::SSLRole> negotiated_dtls_role;
Zhi Huange818b6e2018-02-22 23:26:27532
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) {
Mirko Bonadei317a1f02019-09-17 15:06:18538 remote_fingerprint = std::make_unique<rtc::SSLFingerprint>(*remote_fp);
Zhi Huange818b6e2018-02-22 23:26:27539 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
Mirko Bonadei317a1f02019-09-17 15:06:18553 remote_fingerprint = std::make_unique<rtc::SSLFingerprint>(
Steve Anton4905edb2018-10-16 02:27:44554 "", rtc::ArrayView<const uint8_t>());
Zhi Huange818b6e2018-02-22 23:26:27555 }
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.
Harald Alvestrand78a5e962019-04-03 08:42:39561 RTC_DCHECK(rtp_dtls_transport());
Zhi Huange818b6e2018-02-22 23:26:27562 webrtc::RTCError error = SetNegotiatedDtlsParameters(
Harald Alvestrand78a5e962019-04-03 08:42:39563 rtp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
Zhi Huange818b6e2018-02-22 23:26:27564 if (!error.ok()) {
565 return error;
566 }
567
Harald Alvestrand78a5e962019-04-03 08:42:39568 if (rtcp_dtls_transport()) {
569 error = SetNegotiatedDtlsParameters(
570 rtcp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
Zhi Huange818b6e2018-02-22 23:26:27571 }
572 return error;
573}
574
Zhi Huang365381f2018-04-13 23:44:34575webrtc::RTCError JsepTransport::NegotiateDtlsRole(
Zhi Huange818b6e2018-02-22 23:26:27576 SdpType local_description_type,
577 ConnectionRole local_connection_role,
578 ConnectionRole remote_connection_role,
Danil Chapovalov66cadcc2018-06-19 14:47:43579 absl::optional<rtc::SSLRole>* negotiated_dtls_role) {
Zhi Huange818b6e2018-02-22 23:26:27580 // 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.
Harald Alvestrandefece422021-08-19 09:12:51603 // 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"
Zhi Huange818b6e2018-02-22 23:26:27606 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();
Harald Alvestrandefece422021-08-19 09:12:51636 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:
Artem Titovd3251962021-11-15 15:57:07654 RTC_DCHECK_NOTREACHED();
Harald Alvestrandefece422021-08-19 09:12:51655 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 }
Zhi Huange818b6e2018-02-22 23:26:27667 }
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
Mirko Bonadei05cf6be2019-01-31 20:38:12683 *negotiated_dtls_role =
684 (is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER);
Zhi Huange818b6e2018-02-22 23:26:27685 return webrtc::RTCError::OK();
686}
687
Zhi Huang365381f2018-04-13 23:44:34688bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
Niels Möller6a48a1d2021-02-05 11:34:14689 int component,
Zhi Huang365381f2018-04-13 23:44:34690 TransportStats* stats) {
Harald Alvestrand78a5e962019-04-03 08:42:39691 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 23:26:27692 RTC_DCHECK(dtls_transport);
693 TransportChannelStats substats;
Niels Möller6a48a1d2021-02-05 11:34:14694 substats.component = component;
Harald Alvestrand5cb78072019-10-28 08:51:17695 dtls_transport->GetSslVersionBytes(&substats.ssl_version_bytes);
Zhi Huange818b6e2018-02-22 23:26:27696 dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
697 dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
698 substats.dtls_state = dtls_transport->dtls_state();
Philipp Hancke69c1df22022-04-22 13:46:24699 rtc::SSLRole dtls_role;
700 if (dtls_transport->GetDtlsRole(&dtls_role)) {
701 substats.dtls_role = dtls_role;
702 }
Zhi Huange818b6e2018-02-22 23:26:27703 if (!dtls_transport->ice_transport()->GetStats(
Jonas Oreland149dc722019-08-28 06:10:27704 &substats.ice_transport_stats)) {
Zhi Huange818b6e2018-02-22 23:26:27705 return false;
706 }
Philipp Hancke36e4dd22023-09-28 09:02:21707 substats.ssl_peer_signature_algorithm =
708 dtls_transport->GetSslPeerSignatureAlgorithm();
Zhi Huange818b6e2018-02-22 23:26:27709 stats->channel_stats.push_back(substats);
710 return true;
711}
712
Zhi Huange818b6e2018-02-22 23:26:27713} // namespace cricket