blob: 8c614a9db552cee6d46ae750b579215dd53c744b [file] [log] [blame]
Zhi Huange818b6e2018-02-22 15:26:27 -08001/*
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 09:11:00 -080011#include "pc/jsep_transport.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stddef.h>
14#include <stdint.h>
Zhi Huange818b6e2018-02-22 15:26:27 -080015#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010016#include <type_traits>
Zhi Huange818b6e2018-02-22 15:26:27 -080017#include <utility> // for std::pair
18
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "absl/memory/memory.h"
20#include "api/array_view.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080021#include "api/candidate.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "p2p/base/p2p_constants.h"
23#include "p2p/base/p2p_transport_channel.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080024#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/copy_on_write_buffer.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080026#include "rtc_base/logging.h"
Zhi Huang365381f2018-04-13 16:44:34 -070027#include "rtc_base/strings/string_builder.h"
Zhi Huange818b6e2018-02-22 15:26:27 -080028
29using webrtc::SdpType;
30
31namespace cricket {
32
33static bool VerifyIceParams(const JsepTransportDescription& jsep_description) {
34 // For legacy protocols.
35 // TODO(zhihuang): Remove this once the legacy protocol is no longer
36 // supported.
37 if (jsep_description.transport_desc.ice_ufrag.empty() &&
38 jsep_description.transport_desc.ice_pwd.empty()) {
39 return true;
40 }
41
42 if (jsep_description.transport_desc.ice_ufrag.length() <
43 ICE_UFRAG_MIN_LENGTH ||
44 jsep_description.transport_desc.ice_ufrag.length() >
45 ICE_UFRAG_MAX_LENGTH) {
46 return false;
47 }
48 if (jsep_description.transport_desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH ||
49 jsep_description.transport_desc.ice_pwd.length() > ICE_PWD_MAX_LENGTH) {
50 return false;
51 }
52 return true;
53}
54
55JsepTransportDescription::JsepTransportDescription() {}
56
57JsepTransportDescription::JsepTransportDescription(
58 bool rtcp_mux_enabled,
59 const std::vector<CryptoParams>& cryptos,
60 const std::vector<int>& encrypted_header_extension_ids,
Zhi Huange830e682018-03-30 10:48:35 -070061 int rtp_abs_sendtime_extn_id,
Zhi Huange818b6e2018-02-22 15:26:27 -080062 const TransportDescription& transport_desc)
63 : rtcp_mux_enabled(rtcp_mux_enabled),
64 cryptos(cryptos),
65 encrypted_header_extension_ids(encrypted_header_extension_ids),
Zhi Huange830e682018-03-30 10:48:35 -070066 rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
Zhi Huange818b6e2018-02-22 15:26:27 -080067 transport_desc(transport_desc) {}
68
69JsepTransportDescription::JsepTransportDescription(
70 const JsepTransportDescription& from)
71 : rtcp_mux_enabled(from.rtcp_mux_enabled),
72 cryptos(from.cryptos),
73 encrypted_header_extension_ids(from.encrypted_header_extension_ids),
Zhi Huange830e682018-03-30 10:48:35 -070074 rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
Zhi Huange818b6e2018-02-22 15:26:27 -080075 transport_desc(from.transport_desc) {}
76
77JsepTransportDescription::~JsepTransportDescription() = default;
78
79JsepTransportDescription& JsepTransportDescription::operator=(
80 const JsepTransportDescription& from) {
81 if (this == &from) {
82 return *this;
83 }
84 rtcp_mux_enabled = from.rtcp_mux_enabled;
85 cryptos = from.cryptos;
86 encrypted_header_extension_ids = from.encrypted_header_extension_ids;
Zhi Huange830e682018-03-30 10:48:35 -070087 rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
Zhi Huange818b6e2018-02-22 15:26:27 -080088 transport_desc = from.transport_desc;
89
90 return *this;
91}
92
Zhi Huang365381f2018-04-13 16:44:34 -070093JsepTransport::JsepTransport(
Zhi Huange818b6e2018-02-22 15:26:27 -080094 const std::string& mid,
95 const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -070096 std::unique_ptr<cricket::IceTransportInternal> ice_transport,
97 std::unique_ptr<cricket::IceTransportInternal> rtcp_ice_transport,
Zhi Huange818b6e2018-02-22 15:26:27 -080098 std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
99 std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
100 std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
101 std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
Anton Sukhanov7940da02018-10-10 10:34:49 -0700102 std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700103 std::unique_ptr<webrtc::MediaTransportInterface> media_transport,
104 std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport)
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200105 : network_thread_(rtc::Thread::Current()),
106 mid_(mid),
Zhi Huange818b6e2018-02-22 15:26:27 -0800107 local_certificate_(local_certificate),
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700108 ice_transport_(std::move(ice_transport)),
109 rtcp_ice_transport_(std::move(rtcp_ice_transport)),
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200110 unencrypted_rtp_transport_(std::move(unencrypted_rtp_transport)),
111 sdes_transport_(std::move(sdes_transport)),
112 dtls_srtp_transport_(std::move(dtls_srtp_transport)),
Harald Alvestrandad88c882018-11-28 16:47:46 +0100113 rtp_dtls_transport_(
114 rtp_dtls_transport ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
115 std::move(rtp_dtls_transport))
116 : nullptr),
117 rtcp_dtls_transport_(
118 rtcp_dtls_transport
119 ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
120 std::move(rtcp_dtls_transport))
121 : nullptr),
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700122 media_transport_(std::move(media_transport)),
123 datagram_transport_(std::move(datagram_transport)) {
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700124 RTC_DCHECK(ice_transport_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800125 RTC_DCHECK(rtp_dtls_transport_);
Bjorn A Mellem0c1c1b42019-05-29 17:34:13 -0700126 // |rtcp_ice_transport_| must be present iff |rtcp_dtls_transport_| is
127 // present.
128 RTC_DCHECK_EQ((rtcp_ice_transport_ != nullptr),
129 (rtcp_dtls_transport_ != nullptr));
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700130 RTC_DCHECK(!datagram_transport_ || !media_transport_);
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200131 // Verify the "only one out of these three can be set" invariant.
132 if (unencrypted_rtp_transport_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800133 RTC_DCHECK(!sdes_transport);
134 RTC_DCHECK(!dtls_srtp_transport);
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200135 } else if (sdes_transport_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800136 RTC_DCHECK(!unencrypted_rtp_transport);
137 RTC_DCHECK(!dtls_srtp_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800138 } else {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200139 RTC_DCHECK(dtls_srtp_transport_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800140 RTC_DCHECK(!unencrypted_rtp_transport);
141 RTC_DCHECK(!sdes_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800142 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700143
144 if (media_transport_) {
145 media_transport_->SetMediaTransportStateCallback(this);
146 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800147}
148
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700149JsepTransport::~JsepTransport() {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700150 // Disconnect media transport state callbacks and make sure we delete media
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700151 // transport before ICE.
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700152 if (media_transport_) {
153 media_transport_->SetMediaTransportStateCallback(nullptr);
Anton Sukhanovd644feb2018-12-06 09:00:39 -0800154 media_transport_.reset();
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700155 }
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700156
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100157 // Clear all DtlsTransports. There may be pointers to these from
158 // other places, so we can't assume they'll be deleted by the destructor.
Harald Alvestrandd02541e2019-01-03 12:43:28 +0100159 rtp_dtls_transport_->Clear();
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100160 if (rtcp_dtls_transport_) {
Harald Alvestrandd02541e2019-01-03 12:43:28 +0100161 rtcp_dtls_transport_->Clear();
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100162 }
Anton Sukhanov292ce4e2019-06-03 13:00:24 -0700163
164 // Delete datagram transport before ICE, but after DTLS transport.
165 datagram_transport_.reset();
166
167 // ICE will be the last transport to be deleted.
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700168}
Zhi Huange818b6e2018-02-22 15:26:27 -0800169
Zhi Huang365381f2018-04-13 16:44:34 -0700170webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
Zhi Huange818b6e2018-02-22 15:26:27 -0800171 const JsepTransportDescription& jsep_description,
172 SdpType type) {
173 webrtc::RTCError error;
174
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200175 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800176 if (!VerifyIceParams(jsep_description)) {
177 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
178 "Invalid ice-ufrag or ice-pwd length.");
179 }
180
181 if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
182 ContentSource::CS_LOCAL)) {
183 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
184 "Failed to setup RTCP mux.");
185 }
186
187 // If doing SDES, setup the SDES crypto parameters.
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000188 if (sdes_transport_) {
189 RTC_DCHECK(!unencrypted_rtp_transport_);
190 RTC_DCHECK(!dtls_srtp_transport_);
191 if (!SetSdes(jsep_description.cryptos,
192 jsep_description.encrypted_header_extension_ids, type,
193 ContentSource::CS_LOCAL)) {
194 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
195 "Failed to setup SDES crypto parameters.");
Zhi Huange818b6e2018-02-22 15:26:27 -0800196 }
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000197 } else if (dtls_srtp_transport_) {
198 RTC_DCHECK(!unencrypted_rtp_transport_);
199 RTC_DCHECK(!sdes_transport_);
200 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
201 jsep_description.encrypted_header_extension_ids);
Zhi Huange818b6e2018-02-22 15:26:27 -0800202 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800203 bool ice_restarting =
204 local_description_ != nullptr &&
205 IceCredentialsChanged(local_description_->transport_desc.ice_ufrag,
206 local_description_->transport_desc.ice_pwd,
207 jsep_description.transport_desc.ice_ufrag,
208 jsep_description.transport_desc.ice_pwd);
209 local_description_.reset(new JsepTransportDescription(jsep_description));
210
211 rtc::SSLFingerprint* local_fp =
212 local_description_->transport_desc.identity_fingerprint.get();
213
214 if (!local_fp) {
215 local_certificate_ = nullptr;
216 } else {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200217 error = VerifyCertificateFingerprint(local_certificate_, local_fp);
Zhi Huange818b6e2018-02-22 15:26:27 -0800218 if (!error.ok()) {
219 local_description_.reset();
220 return error;
221 }
222 }
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200223 {
224 rtc::CritScope scope(&accessor_lock_);
225 RTC_DCHECK(rtp_dtls_transport_->internal());
226 SetLocalIceParameters(rtp_dtls_transport_->internal()->ice_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800227
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200228 if (rtcp_dtls_transport_) {
229 RTC_DCHECK(rtcp_dtls_transport_->internal());
230 SetLocalIceParameters(rtcp_dtls_transport_->internal()->ice_transport());
231 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800232 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800233 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
234 if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
235 error = NegotiateAndSetDtlsParameters(type);
236 }
237 if (!error.ok()) {
238 local_description_.reset();
239 return error;
240 }
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200241 {
242 rtc::CritScope scope(&accessor_lock_);
243 if (needs_ice_restart_ && ice_restarting) {
244 needs_ice_restart_ = false;
245 RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag cleared for transport "
246 << mid();
247 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800248 }
249
250 return webrtc::RTCError::OK();
251}
252
Zhi Huang365381f2018-04-13 16:44:34 -0700253webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
Zhi Huange818b6e2018-02-22 15:26:27 -0800254 const JsepTransportDescription& jsep_description,
255 webrtc::SdpType type) {
256 webrtc::RTCError error;
257
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200258 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800259 if (!VerifyIceParams(jsep_description)) {
260 remote_description_.reset();
261 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
262 "Invalid ice-ufrag or ice-pwd length.");
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.
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000272 if (sdes_transport_) {
273 RTC_DCHECK(!unencrypted_rtp_transport_);
274 RTC_DCHECK(!dtls_srtp_transport_);
275 if (!SetSdes(jsep_description.cryptos,
276 jsep_description.encrypted_header_extension_ids, type,
277 ContentSource::CS_REMOTE)) {
278 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
279 "Failed to setup SDES crypto parameters.");
Zhi Huange818b6e2018-02-22 15:26:27 -0800280 }
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000281 sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
282 jsep_description.rtp_abs_sendtime_extn_id);
283 } else if (dtls_srtp_transport_) {
284 RTC_DCHECK(!unencrypted_rtp_transport_);
285 RTC_DCHECK(!sdes_transport_);
286 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
287 jsep_description.encrypted_header_extension_ids);
288 dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
289 jsep_description.rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800290 }
291
292 remote_description_.reset(new JsepTransportDescription(jsep_description));
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200293 RTC_DCHECK(rtp_dtls_transport());
294 SetRemoteIceParameters(rtp_dtls_transport()->ice_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800295
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200296 if (rtcp_dtls_transport()) {
297 SetRemoteIceParameters(rtcp_dtls_transport()->ice_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800298 }
299
300 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
301 if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
302 error = NegotiateAndSetDtlsParameters(SdpType::kOffer);
303 }
304 if (!error.ok()) {
305 remote_description_.reset();
306 return error;
307 }
308 return webrtc::RTCError::OK();
309}
310
Zhi Huang365381f2018-04-13 16:44:34 -0700311webrtc::RTCError JsepTransport::AddRemoteCandidates(
Zhi Huange818b6e2018-02-22 15:26:27 -0800312 const Candidates& candidates) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200313 RTC_DCHECK_RUN_ON(network_thread_);
Henrik Boström5d8f8fa2018-04-13 15:22:50 +0000314 if (!local_description_ || !remote_description_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800315 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
316 mid() +
317 " is not ready to use the remote candidate "
Henrik Boström5d8f8fa2018-04-13 15:22:50 +0000318 "because the local or remote description is "
319 "not set.");
Zhi Huange818b6e2018-02-22 15:26:27 -0800320 }
321
322 for (const cricket::Candidate& candidate : candidates) {
323 auto transport =
324 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
Harald Alvestrandad88c882018-11-28 16:47:46 +0100325 ? rtp_dtls_transport_
326 : rtcp_dtls_transport_;
Zhi Huange818b6e2018-02-22 15:26:27 -0800327 if (!transport) {
328 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
329 "Candidate has an unknown component: " +
330 candidate.ToString() + " for mid " + mid());
331 }
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100332 RTC_DCHECK(transport->internal() && transport->internal()->ice_transport());
Harald Alvestrandad88c882018-11-28 16:47:46 +0100333 transport->internal()->ice_transport()->AddRemoteCandidate(candidate);
Zhi Huange818b6e2018-02-22 15:26:27 -0800334 }
335 return webrtc::RTCError::OK();
336}
337
Zhi Huang365381f2018-04-13 16:44:34 -0700338void JsepTransport::SetNeedsIceRestartFlag() {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200339 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800340 if (!needs_ice_restart_) {
341 needs_ice_restart_ = true;
342 RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag set for transport " << mid();
343 }
344}
345
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200346absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200347 RTC_DCHECK_RUN_ON(network_thread_);
348 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800349 RTC_DCHECK(rtp_dtls_transport_);
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100350 RTC_DCHECK(rtp_dtls_transport_->internal());
Zhi Huange818b6e2018-02-22 15:26:27 -0800351 rtc::SSLRole dtls_role;
Harald Alvestrandad88c882018-11-28 16:47:46 +0100352 if (!rtp_dtls_transport_->internal()->GetDtlsRole(&dtls_role)) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200353 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 15:26:27 -0800354 }
355
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200356 return absl::optional<rtc::SSLRole>(dtls_role);
Zhi Huange818b6e2018-02-22 15:26:27 -0800357}
358
Zhi Huang365381f2018-04-13 16:44:34 -0700359bool JsepTransport::GetStats(TransportStats* stats) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200360 RTC_DCHECK_RUN_ON(network_thread_);
361 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800362 stats->transport_name = mid();
363 stats->channel_stats.clear();
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100364 RTC_DCHECK(rtp_dtls_transport_->internal());
Harald Alvestrandad88c882018-11-28 16:47:46 +0100365 bool ret = GetTransportStats(rtp_dtls_transport_->internal(), stats);
Zhi Huange818b6e2018-02-22 15:26:27 -0800366 if (rtcp_dtls_transport_) {
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100367 RTC_DCHECK(rtcp_dtls_transport_->internal());
Harald Alvestrandad88c882018-11-28 16:47:46 +0100368 ret &= GetTransportStats(rtcp_dtls_transport_->internal(), stats);
Zhi Huange818b6e2018-02-22 15:26:27 -0800369 }
370 return ret;
371}
372
Zhi Huang365381f2018-04-13 16:44:34 -0700373webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
Zhi Huange818b6e2018-02-22 15:26:27 -0800374 const rtc::RTCCertificate* certificate,
375 const rtc::SSLFingerprint* fingerprint) const {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200376 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800377 if (!fingerprint) {
378 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
379 "No fingerprint");
380 }
381 if (!certificate) {
382 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
383 "Fingerprint provided but no identity available.");
384 }
Steve Anton4905edb2018-10-15 19:27:44 -0700385 std::unique_ptr<rtc::SSLFingerprint> fp_tmp =
386 rtc::SSLFingerprint::CreateUnique(fingerprint->algorithm,
387 *certificate->identity());
Zhi Huange818b6e2018-02-22 15:26:27 -0800388 RTC_DCHECK(fp_tmp.get() != NULL);
389 if (*fp_tmp == *fingerprint) {
390 return webrtc::RTCError::OK();
391 }
Zhi Huang365381f2018-04-13 16:44:34 -0700392 char ss_buf[1024];
393 rtc::SimpleStringBuilder desc(ss_buf);
Zhi Huange818b6e2018-02-22 15:26:27 -0800394 desc << "Local fingerprint does not match identity. Expected: ";
395 desc << fp_tmp->ToString();
396 desc << " Got: " << fingerprint->ToString();
Zhi Huang365381f2018-04-13 16:44:34 -0700397 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
398 std::string(desc.str()));
Zhi Huange818b6e2018-02-22 15:26:27 -0800399}
400
Zhi Huangb57e1692018-06-12 11:41:11 -0700401void JsepTransport::SetActiveResetSrtpParams(bool active_reset_srtp_params) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200402 RTC_DCHECK_RUN_ON(network_thread_);
403 rtc::CritScope scope(&accessor_lock_);
Zhi Huangb57e1692018-06-12 11:41:11 -0700404 if (dtls_srtp_transport_) {
405 RTC_LOG(INFO)
406 << "Setting active_reset_srtp_params of DtlsSrtpTransport to: "
407 << active_reset_srtp_params;
408 dtls_srtp_transport_->SetActiveResetSrtpParams(active_reset_srtp_params);
409 }
410}
411
Zhi Huang365381f2018-04-13 16:44:34 -0700412void JsepTransport::SetLocalIceParameters(IceTransportInternal* ice_transport) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200413 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800414 RTC_DCHECK(ice_transport);
415 RTC_DCHECK(local_description_);
416 ice_transport->SetIceParameters(
417 local_description_->transport_desc.GetIceParameters());
418}
419
Zhi Huang365381f2018-04-13 16:44:34 -0700420void JsepTransport::SetRemoteIceParameters(
Zhi Huange818b6e2018-02-22 15:26:27 -0800421 IceTransportInternal* ice_transport) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200422 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800423 RTC_DCHECK(ice_transport);
424 RTC_DCHECK(remote_description_);
425 ice_transport->SetRemoteIceParameters(
426 remote_description_->transport_desc.GetIceParameters());
427 ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
428}
429
Zhi Huang365381f2018-04-13 16:44:34 -0700430webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters(
Zhi Huange818b6e2018-02-22 15:26:27 -0800431 DtlsTransportInternal* dtls_transport,
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200432 absl::optional<rtc::SSLRole> dtls_role,
Zhi Huange818b6e2018-02-22 15:26:27 -0800433 rtc::SSLFingerprint* remote_fingerprint) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200434 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800435 RTC_DCHECK(dtls_transport);
436 // Set SSL role. Role must be set before fingerprint is applied, which
437 // initiates DTLS setup.
438 if (dtls_role && !dtls_transport->SetDtlsRole(*dtls_role)) {
439 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
440 "Failed to set SSL role for the transport.");
441 }
442 // Apply remote fingerprint.
443 if (!remote_fingerprint ||
444 !dtls_transport->SetRemoteFingerprint(
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700445 remote_fingerprint->algorithm, remote_fingerprint->digest.cdata(),
Zhi Huange818b6e2018-02-22 15:26:27 -0800446 remote_fingerprint->digest.size())) {
447 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
448 "Failed to apply remote fingerprint.");
449 }
450 return webrtc::RTCError::OK();
451}
452
Zhi Huang365381f2018-04-13 16:44:34 -0700453bool JsepTransport::SetRtcpMux(bool enable,
454 webrtc::SdpType type,
455 ContentSource source) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200456 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800457 bool ret = false;
458 switch (type) {
459 case SdpType::kOffer:
460 ret = rtcp_mux_negotiator_.SetOffer(enable, source);
461 break;
462 case SdpType::kPrAnswer:
463 // This may activate RTCP muxing, but we don't yet destroy the transport
464 // because the final answer may deactivate it.
465 ret = rtcp_mux_negotiator_.SetProvisionalAnswer(enable, source);
466 break;
467 case SdpType::kAnswer:
468 ret = rtcp_mux_negotiator_.SetAnswer(enable, source);
469 if (ret && rtcp_mux_negotiator_.IsActive()) {
470 ActivateRtcpMux();
471 }
472 break;
473 default:
474 RTC_NOTREACHED();
475 }
476
477 if (!ret) {
478 return false;
479 }
480
481 auto transport = rtp_transport();
482 transport->SetRtcpMuxEnabled(rtcp_mux_negotiator_.IsActive());
483 return ret;
484}
485
Zhi Huang365381f2018-04-13 16:44:34 -0700486void JsepTransport::ActivateRtcpMux() {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200487 {
488 // Don't hold the network_thread_ lock while calling other functions,
489 // since they might call other functions that call RTC_DCHECK_RUN_ON.
490 // TODO(https://crbug.com/webrtc/10318): Simplify when possible.
491 RTC_DCHECK_RUN_ON(network_thread_);
492 }
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000493 if (unencrypted_rtp_transport_) {
494 RTC_DCHECK(!sdes_transport_);
495 RTC_DCHECK(!dtls_srtp_transport_);
496 unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
497 } else if (sdes_transport_) {
498 RTC_DCHECK(!unencrypted_rtp_transport_);
499 RTC_DCHECK(!dtls_srtp_transport_);
500 sdes_transport_->SetRtcpPacketTransport(nullptr);
501 } else {
502 RTC_DCHECK(dtls_srtp_transport_);
503 RTC_DCHECK(!unencrypted_rtp_transport_);
504 RTC_DCHECK(!sdes_transport_);
505 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
506 /*rtcp_dtls_transport=*/nullptr);
507 }
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200508 {
509 rtc::CritScope scope(&accessor_lock_);
510 rtcp_dtls_transport_ = nullptr; // Destroy this reference.
511 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800512 // Notify the JsepTransportController to update the aggregate states.
513 SignalRtcpMuxActive();
514}
515
Zhi Huang365381f2018-04-13 16:44:34 -0700516bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos,
517 const std::vector<int>& encrypted_extension_ids,
518 webrtc::SdpType type,
519 ContentSource source) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200520 RTC_DCHECK_RUN_ON(network_thread_);
521 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800522 bool ret = false;
523 ret = sdes_negotiator_.Process(cryptos, type, source);
524 if (!ret) {
525 return ret;
526 }
527
528 if (source == ContentSource::CS_LOCAL) {
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000529 recv_extension_ids_ = std::move(encrypted_extension_ids);
Zhi Huange818b6e2018-02-22 15:26:27 -0800530 } else {
Bjorn Mellem7e8de0b2019-06-07 06:13:42 +0000531 send_extension_ids_ = std::move(encrypted_extension_ids);
Zhi Huange818b6e2018-02-22 15:26:27 -0800532 }
533
534 // If setting an SDES answer succeeded, apply the negotiated parameters
535 // to the SRTP transport.
536 if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
537 if (sdes_negotiator_.send_cipher_suite() &&
538 sdes_negotiator_.recv_cipher_suite()) {
539 RTC_DCHECK(send_extension_ids_);
540 RTC_DCHECK(recv_extension_ids_);
541 ret = sdes_transport_->SetRtpParams(
542 *(sdes_negotiator_.send_cipher_suite()),
543 sdes_negotiator_.send_key().data(),
544 static_cast<int>(sdes_negotiator_.send_key().size()),
545 *(send_extension_ids_), *(sdes_negotiator_.recv_cipher_suite()),
546 sdes_negotiator_.recv_key().data(),
547 static_cast<int>(sdes_negotiator_.recv_key().size()),
548 *(recv_extension_ids_));
549 } else {
550 RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
551 if (type == SdpType::kAnswer) {
552 // Explicitly reset the |sdes_transport_| if no crypto param is
553 // provided in the answer. No need to call |ResetParams()| for
554 // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
555 sdes_transport_->ResetParams();
556 }
557 }
558 }
559 return ret;
560}
561
Zhi Huang365381f2018-04-13 16:44:34 -0700562webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
Zhi Huange818b6e2018-02-22 15:26:27 -0800563 SdpType local_description_type) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200564 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800565 if (!local_description_ || !remote_description_) {
566 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
567 "Applying an answer transport description "
568 "without applying any offer.");
569 }
570 std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200571 absl::optional<rtc::SSLRole> negotiated_dtls_role;
Zhi Huange818b6e2018-02-22 15:26:27 -0800572
573 rtc::SSLFingerprint* local_fp =
574 local_description_->transport_desc.identity_fingerprint.get();
575 rtc::SSLFingerprint* remote_fp =
576 remote_description_->transport_desc.identity_fingerprint.get();
577 if (remote_fp && local_fp) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200578 remote_fingerprint = absl::make_unique<rtc::SSLFingerprint>(*remote_fp);
Zhi Huange818b6e2018-02-22 15:26:27 -0800579 webrtc::RTCError error =
580 NegotiateDtlsRole(local_description_type,
581 local_description_->transport_desc.connection_role,
582 remote_description_->transport_desc.connection_role,
583 &negotiated_dtls_role);
584 if (!error.ok()) {
585 return error;
586 }
587 } else if (local_fp && (local_description_type == SdpType::kAnswer)) {
588 return webrtc::RTCError(
589 webrtc::RTCErrorType::INVALID_PARAMETER,
590 "Local fingerprint supplied when caller didn't offer DTLS.");
591 } else {
592 // We are not doing DTLS
Steve Anton4905edb2018-10-15 19:27:44 -0700593 remote_fingerprint = absl::make_unique<rtc::SSLFingerprint>(
594 "", rtc::ArrayView<const uint8_t>());
Zhi Huange818b6e2018-02-22 15:26:27 -0800595 }
596 // Now that we have negotiated everything, push it downward.
597 // Note that we cache the result so that if we have race conditions
598 // between future SetRemote/SetLocal invocations and new transport
599 // creation, we have the negotiation state saved until a new
600 // negotiation happens.
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200601 RTC_DCHECK(rtp_dtls_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800602 webrtc::RTCError error = SetNegotiatedDtlsParameters(
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200603 rtp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
Zhi Huange818b6e2018-02-22 15:26:27 -0800604 if (!error.ok()) {
605 return error;
606 }
607
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200608 if (rtcp_dtls_transport()) {
609 error = SetNegotiatedDtlsParameters(
610 rtcp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
Zhi Huange818b6e2018-02-22 15:26:27 -0800611 }
612 return error;
613}
614
Zhi Huang365381f2018-04-13 16:44:34 -0700615webrtc::RTCError JsepTransport::NegotiateDtlsRole(
Zhi Huange818b6e2018-02-22 15:26:27 -0800616 SdpType local_description_type,
617 ConnectionRole local_connection_role,
618 ConnectionRole remote_connection_role,
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200619 absl::optional<rtc::SSLRole>* negotiated_dtls_role) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800620 // From RFC 4145, section-4.1, The following are the values that the
621 // 'setup' attribute can take in an offer/answer exchange:
622 // Offer Answer
623 // ________________
624 // active passive / holdconn
625 // passive active / holdconn
626 // actpass active / passive / holdconn
627 // holdconn holdconn
628 //
629 // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
630 // The endpoint MUST use the setup attribute defined in [RFC4145].
631 // The endpoint that is the offerer MUST use the setup attribute
632 // value of setup:actpass and be prepared to receive a client_hello
633 // before it receives the answer. The answerer MUST use either a
634 // setup attribute value of setup:active or setup:passive. Note that
635 // if the answerer uses setup:passive, then the DTLS handshake will
636 // not begin until the answerer is received, which adds additional
637 // latency. setup:active allows the answer and the DTLS handshake to
638 // occur in parallel. Thus, setup:active is RECOMMENDED. Whichever
639 // party is active MUST initiate a DTLS handshake by sending a
640 // ClientHello over each flow (host/port quartet).
641 // IOW - actpass and passive modes should be treated as server and
642 // active as client.
643 bool is_remote_server = false;
644 if (local_description_type == SdpType::kOffer) {
645 if (local_connection_role != CONNECTIONROLE_ACTPASS) {
646 return webrtc::RTCError(
647 webrtc::RTCErrorType::INVALID_PARAMETER,
648 "Offerer must use actpass value for setup attribute.");
649 }
650
651 if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
652 remote_connection_role == CONNECTIONROLE_PASSIVE ||
653 remote_connection_role == CONNECTIONROLE_NONE) {
654 is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
655 } else {
656 return webrtc::RTCError(
657 webrtc::RTCErrorType::INVALID_PARAMETER,
658 "Answerer must use either active or passive value "
659 "for setup attribute.");
660 }
661 // If remote is NONE or ACTIVE it will act as client.
662 } else {
663 if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
664 remote_connection_role != CONNECTIONROLE_NONE) {
665 // Accept a remote role attribute that's not "actpass", but matches the
666 // current negotiated role. This is allowed by dtls-sdp, though our
667 // implementation will never generate such an offer as it's not
668 // recommended.
669 //
670 // See https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-dtls-sdp,
671 // section 5.5.
672 auto current_dtls_role = GetDtlsRole();
673 if (!current_dtls_role ||
674 (*current_dtls_role == rtc::SSL_CLIENT &&
675 remote_connection_role == CONNECTIONROLE_ACTIVE) ||
676 (*current_dtls_role == rtc::SSL_SERVER &&
677 remote_connection_role == CONNECTIONROLE_PASSIVE)) {
678 return webrtc::RTCError(
679 webrtc::RTCErrorType::INVALID_PARAMETER,
680 "Offerer must use actpass value or current negotiated role for "
681 "setup attribute.");
682 }
683 }
684
685 if (local_connection_role == CONNECTIONROLE_ACTIVE ||
686 local_connection_role == CONNECTIONROLE_PASSIVE) {
687 is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
688 } else {
689 return webrtc::RTCError(
690 webrtc::RTCErrorType::INVALID_PARAMETER,
691 "Answerer must use either active or passive value "
692 "for setup attribute.");
693 }
694
695 // If local is passive, local will act as server.
696 }
697
Mirko Bonadei05cf6be2019-01-31 21:38:12 +0100698 *negotiated_dtls_role =
699 (is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER);
Zhi Huange818b6e2018-02-22 15:26:27 -0800700 return webrtc::RTCError::OK();
701}
702
Zhi Huang365381f2018-04-13 16:44:34 -0700703bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
704 TransportStats* stats) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200705 RTC_DCHECK_RUN_ON(network_thread_);
706 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800707 RTC_DCHECK(dtls_transport);
708 TransportChannelStats substats;
Harald Alvestrandad88c882018-11-28 16:47:46 +0100709 if (rtcp_dtls_transport_) {
710 substats.component = dtls_transport == rtcp_dtls_transport_->internal()
711 ? ICE_CANDIDATE_COMPONENT_RTCP
712 : ICE_CANDIDATE_COMPONENT_RTP;
713 } else {
714 substats.component = ICE_CANDIDATE_COMPONENT_RTP;
715 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800716 dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
717 dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
718 substats.dtls_state = dtls_transport->dtls_state();
719 if (!dtls_transport->ice_transport()->GetStats(
720 &substats.connection_infos, &substats.candidate_stats_list)) {
721 return false;
722 }
723 stats->channel_stats.push_back(substats);
724 return true;
725}
726
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700727void JsepTransport::OnStateChanged(webrtc::MediaTransportState state) {
728 // TODO(bugs.webrtc.org/9719) This method currently fires on the network
729 // thread, but media transport does not make such guarantees. We need to make
730 // sure this callback is guaranteed to be executed on the network thread.
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200731 RTC_DCHECK_RUN_ON(network_thread_);
732 {
733 rtc::CritScope scope(&accessor_lock_);
734 media_transport_state_ = state;
735 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700736 SignalMediaTransportStateChanged();
737}
Zhi Huange818b6e2018-02-22 15:26:27 -0800738} // namespace cricket