blob: 26311d19db773a74930c428aeabbf17fe4bb767a [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,
96 std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
97 std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
98 std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
99 std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
Anton Sukhanov7940da02018-10-10 10:34:49 -0700100 std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
101 std::unique_ptr<webrtc::MediaTransportInterface> media_transport)
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200102 : network_thread_(rtc::Thread::Current()),
103 mid_(mid),
Zhi Huange818b6e2018-02-22 15:26:27 -0800104 local_certificate_(local_certificate),
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200105 unencrypted_rtp_transport_(std::move(unencrypted_rtp_transport)),
106 sdes_transport_(std::move(sdes_transport)),
107 dtls_srtp_transport_(std::move(dtls_srtp_transport)),
Harald Alvestrandad88c882018-11-28 16:47:46 +0100108 rtp_dtls_transport_(
109 rtp_dtls_transport ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
110 std::move(rtp_dtls_transport))
111 : nullptr),
112 rtcp_dtls_transport_(
113 rtcp_dtls_transport
114 ? new rtc::RefCountedObject<webrtc::DtlsTransport>(
115 std::move(rtcp_dtls_transport))
116 : nullptr),
Anton Sukhanov7940da02018-10-10 10:34:49 -0700117 media_transport_(std::move(media_transport)) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800118 RTC_DCHECK(rtp_dtls_transport_);
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700119 RTC_DCHECK(!datagram_transport() || !media_transport_);
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200120 // Verify the "only one out of these three can be set" invariant.
121 if (unencrypted_rtp_transport_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800122 RTC_DCHECK(!sdes_transport);
123 RTC_DCHECK(!dtls_srtp_transport);
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200124 } else if (sdes_transport_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800125 RTC_DCHECK(!unencrypted_rtp_transport);
126 RTC_DCHECK(!dtls_srtp_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800127 } else {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200128 RTC_DCHECK(dtls_srtp_transport_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800129 RTC_DCHECK(!unencrypted_rtp_transport);
130 RTC_DCHECK(!sdes_transport);
Zhi Huange818b6e2018-02-22 15:26:27 -0800131 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700132
133 if (media_transport_) {
134 media_transport_->SetMediaTransportStateCallback(this);
135 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800136}
137
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700138JsepTransport::~JsepTransport() {
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700139 // Disconnect media transport state callbacks and make sure we delete media
140 // transports before ICE.
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700141 if (media_transport_) {
142 media_transport_->SetMediaTransportStateCallback(nullptr);
Anton Sukhanovd644feb2018-12-06 09:00:39 -0800143 media_transport_.reset();
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700144 }
Anton Sukhanov316f3ac2019-05-23 15:50:38 -0700145
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100146 // Clear all DtlsTransports. There may be pointers to these from
147 // other places, so we can't assume they'll be deleted by the destructor.
Harald Alvestrandd02541e2019-01-03 12:43:28 +0100148 rtp_dtls_transport_->Clear();
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100149 if (rtcp_dtls_transport_) {
Harald Alvestrandd02541e2019-01-03 12:43:28 +0100150 rtcp_dtls_transport_->Clear();
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100151 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700152}
Zhi Huange818b6e2018-02-22 15:26:27 -0800153
Zhi Huang365381f2018-04-13 16:44:34 -0700154webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
Zhi Huange818b6e2018-02-22 15:26:27 -0800155 const JsepTransportDescription& jsep_description,
156 SdpType type) {
157 webrtc::RTCError error;
158
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200159 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800160 if (!VerifyIceParams(jsep_description)) {
161 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
162 "Invalid ice-ufrag or ice-pwd length.");
163 }
164
165 if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
166 ContentSource::CS_LOCAL)) {
167 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
168 "Failed to setup RTCP mux.");
169 }
170
171 // If doing SDES, setup the SDES crypto parameters.
172 if (sdes_transport_) {
173 RTC_DCHECK(!unencrypted_rtp_transport_);
174 RTC_DCHECK(!dtls_srtp_transport_);
175 if (!SetSdes(jsep_description.cryptos,
176 jsep_description.encrypted_header_extension_ids, type,
177 ContentSource::CS_LOCAL)) {
178 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
179 "Failed to setup SDES crypto parameters.");
180 }
181 } else if (dtls_srtp_transport_) {
182 RTC_DCHECK(!unencrypted_rtp_transport_);
183 RTC_DCHECK(!sdes_transport_);
184 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
185 jsep_description.encrypted_header_extension_ids);
186 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800187 bool ice_restarting =
188 local_description_ != nullptr &&
189 IceCredentialsChanged(local_description_->transport_desc.ice_ufrag,
190 local_description_->transport_desc.ice_pwd,
191 jsep_description.transport_desc.ice_ufrag,
192 jsep_description.transport_desc.ice_pwd);
193 local_description_.reset(new JsepTransportDescription(jsep_description));
194
195 rtc::SSLFingerprint* local_fp =
196 local_description_->transport_desc.identity_fingerprint.get();
197
198 if (!local_fp) {
199 local_certificate_ = nullptr;
200 } else {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200201 error = VerifyCertificateFingerprint(local_certificate_, local_fp);
Zhi Huange818b6e2018-02-22 15:26:27 -0800202 if (!error.ok()) {
203 local_description_.reset();
204 return error;
205 }
206 }
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200207 {
208 rtc::CritScope scope(&accessor_lock_);
209 RTC_DCHECK(rtp_dtls_transport_->internal());
210 SetLocalIceParameters(rtp_dtls_transport_->internal()->ice_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800211
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200212 if (rtcp_dtls_transport_) {
213 RTC_DCHECK(rtcp_dtls_transport_->internal());
214 SetLocalIceParameters(rtcp_dtls_transport_->internal()->ice_transport());
215 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800216 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800217 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
218 if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
219 error = NegotiateAndSetDtlsParameters(type);
220 }
221 if (!error.ok()) {
222 local_description_.reset();
223 return error;
224 }
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200225 {
226 rtc::CritScope scope(&accessor_lock_);
227 if (needs_ice_restart_ && ice_restarting) {
228 needs_ice_restart_ = false;
229 RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag cleared for transport "
230 << mid();
231 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800232 }
233
234 return webrtc::RTCError::OK();
235}
236
Zhi Huang365381f2018-04-13 16:44:34 -0700237webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
Zhi Huange818b6e2018-02-22 15:26:27 -0800238 const JsepTransportDescription& jsep_description,
239 webrtc::SdpType type) {
240 webrtc::RTCError error;
241
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200242 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800243 if (!VerifyIceParams(jsep_description)) {
244 remote_description_.reset();
245 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
246 "Invalid ice-ufrag or ice-pwd length.");
247 }
248
249 if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
250 ContentSource::CS_REMOTE)) {
251 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
252 "Failed to setup RTCP mux.");
253 }
254
255 // If doing SDES, setup the SDES crypto parameters.
256 if (sdes_transport_) {
257 RTC_DCHECK(!unencrypted_rtp_transport_);
258 RTC_DCHECK(!dtls_srtp_transport_);
259 if (!SetSdes(jsep_description.cryptos,
260 jsep_description.encrypted_header_extension_ids, type,
261 ContentSource::CS_REMOTE)) {
262 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
263 "Failed to setup SDES crypto parameters.");
264 }
Zhi Huange830e682018-03-30 10:48:35 -0700265 sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
266 jsep_description.rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800267 } else if (dtls_srtp_transport_) {
268 RTC_DCHECK(!unencrypted_rtp_transport_);
269 RTC_DCHECK(!sdes_transport_);
270 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
271 jsep_description.encrypted_header_extension_ids);
Zhi Huange830e682018-03-30 10:48:35 -0700272 dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
273 jsep_description.rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800274 }
275
276 remote_description_.reset(new JsepTransportDescription(jsep_description));
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200277 RTC_DCHECK(rtp_dtls_transport());
278 SetRemoteIceParameters(rtp_dtls_transport()->ice_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800279
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200280 if (rtcp_dtls_transport()) {
281 SetRemoteIceParameters(rtcp_dtls_transport()->ice_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800282 }
283
284 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
285 if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
286 error = NegotiateAndSetDtlsParameters(SdpType::kOffer);
287 }
288 if (!error.ok()) {
289 remote_description_.reset();
290 return error;
291 }
292 return webrtc::RTCError::OK();
293}
294
Zhi Huang365381f2018-04-13 16:44:34 -0700295webrtc::RTCError JsepTransport::AddRemoteCandidates(
Zhi Huange818b6e2018-02-22 15:26:27 -0800296 const Candidates& candidates) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200297 RTC_DCHECK_RUN_ON(network_thread_);
Henrik Boström5d8f8fa2018-04-13 15:22:50 +0000298 if (!local_description_ || !remote_description_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800299 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
300 mid() +
301 " is not ready to use the remote candidate "
Henrik Boström5d8f8fa2018-04-13 15:22:50 +0000302 "because the local or remote description is "
303 "not set.");
Zhi Huange818b6e2018-02-22 15:26:27 -0800304 }
305
306 for (const cricket::Candidate& candidate : candidates) {
307 auto transport =
308 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
Harald Alvestrandad88c882018-11-28 16:47:46 +0100309 ? rtp_dtls_transport_
310 : rtcp_dtls_transport_;
Zhi Huange818b6e2018-02-22 15:26:27 -0800311 if (!transport) {
312 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
313 "Candidate has an unknown component: " +
314 candidate.ToString() + " for mid " + mid());
315 }
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100316 RTC_DCHECK(transport->internal() && transport->internal()->ice_transport());
Harald Alvestrandad88c882018-11-28 16:47:46 +0100317 transport->internal()->ice_transport()->AddRemoteCandidate(candidate);
Zhi Huange818b6e2018-02-22 15:26:27 -0800318 }
319 return webrtc::RTCError::OK();
320}
321
Zhi Huang365381f2018-04-13 16:44:34 -0700322void JsepTransport::SetNeedsIceRestartFlag() {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200323 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800324 if (!needs_ice_restart_) {
325 needs_ice_restart_ = true;
326 RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag set for transport " << mid();
327 }
328}
329
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200330absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200331 RTC_DCHECK_RUN_ON(network_thread_);
332 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800333 RTC_DCHECK(rtp_dtls_transport_);
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100334 RTC_DCHECK(rtp_dtls_transport_->internal());
Zhi Huange818b6e2018-02-22 15:26:27 -0800335 rtc::SSLRole dtls_role;
Harald Alvestrandad88c882018-11-28 16:47:46 +0100336 if (!rtp_dtls_transport_->internal()->GetDtlsRole(&dtls_role)) {
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200337 return absl::optional<rtc::SSLRole>();
Zhi Huange818b6e2018-02-22 15:26:27 -0800338 }
339
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200340 return absl::optional<rtc::SSLRole>(dtls_role);
Zhi Huange818b6e2018-02-22 15:26:27 -0800341}
342
Zhi Huang365381f2018-04-13 16:44:34 -0700343bool JsepTransport::GetStats(TransportStats* stats) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200344 RTC_DCHECK_RUN_ON(network_thread_);
345 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800346 stats->transport_name = mid();
347 stats->channel_stats.clear();
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100348 RTC_DCHECK(rtp_dtls_transport_->internal());
Harald Alvestrandad88c882018-11-28 16:47:46 +0100349 bool ret = GetTransportStats(rtp_dtls_transport_->internal(), stats);
Zhi Huange818b6e2018-02-22 15:26:27 -0800350 if (rtcp_dtls_transport_) {
Harald Alvestrand628f37a2018-12-06 10:55:20 +0100351 RTC_DCHECK(rtcp_dtls_transport_->internal());
Harald Alvestrandad88c882018-11-28 16:47:46 +0100352 ret &= GetTransportStats(rtcp_dtls_transport_->internal(), stats);
Zhi Huange818b6e2018-02-22 15:26:27 -0800353 }
354 return ret;
355}
356
Zhi Huang365381f2018-04-13 16:44:34 -0700357webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
Zhi Huange818b6e2018-02-22 15:26:27 -0800358 const rtc::RTCCertificate* certificate,
359 const rtc::SSLFingerprint* fingerprint) const {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200360 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800361 if (!fingerprint) {
362 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
363 "No fingerprint");
364 }
365 if (!certificate) {
366 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
367 "Fingerprint provided but no identity available.");
368 }
Steve Anton4905edb2018-10-15 19:27:44 -0700369 std::unique_ptr<rtc::SSLFingerprint> fp_tmp =
370 rtc::SSLFingerprint::CreateUnique(fingerprint->algorithm,
371 *certificate->identity());
Zhi Huange818b6e2018-02-22 15:26:27 -0800372 RTC_DCHECK(fp_tmp.get() != NULL);
373 if (*fp_tmp == *fingerprint) {
374 return webrtc::RTCError::OK();
375 }
Zhi Huang365381f2018-04-13 16:44:34 -0700376 char ss_buf[1024];
377 rtc::SimpleStringBuilder desc(ss_buf);
Zhi Huange818b6e2018-02-22 15:26:27 -0800378 desc << "Local fingerprint does not match identity. Expected: ";
379 desc << fp_tmp->ToString();
380 desc << " Got: " << fingerprint->ToString();
Zhi Huang365381f2018-04-13 16:44:34 -0700381 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
382 std::string(desc.str()));
Zhi Huange818b6e2018-02-22 15:26:27 -0800383}
384
Zhi Huangb57e1692018-06-12 11:41:11 -0700385void JsepTransport::SetActiveResetSrtpParams(bool active_reset_srtp_params) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200386 RTC_DCHECK_RUN_ON(network_thread_);
387 rtc::CritScope scope(&accessor_lock_);
Zhi Huangb57e1692018-06-12 11:41:11 -0700388 if (dtls_srtp_transport_) {
389 RTC_LOG(INFO)
390 << "Setting active_reset_srtp_params of DtlsSrtpTransport to: "
391 << active_reset_srtp_params;
392 dtls_srtp_transport_->SetActiveResetSrtpParams(active_reset_srtp_params);
393 }
394}
395
Zhi Huang365381f2018-04-13 16:44:34 -0700396void JsepTransport::SetLocalIceParameters(IceTransportInternal* ice_transport) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200397 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800398 RTC_DCHECK(ice_transport);
399 RTC_DCHECK(local_description_);
400 ice_transport->SetIceParameters(
401 local_description_->transport_desc.GetIceParameters());
402}
403
Zhi Huang365381f2018-04-13 16:44:34 -0700404void JsepTransport::SetRemoteIceParameters(
Zhi Huange818b6e2018-02-22 15:26:27 -0800405 IceTransportInternal* ice_transport) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200406 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800407 RTC_DCHECK(ice_transport);
408 RTC_DCHECK(remote_description_);
409 ice_transport->SetRemoteIceParameters(
410 remote_description_->transport_desc.GetIceParameters());
411 ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
412}
413
Zhi Huang365381f2018-04-13 16:44:34 -0700414webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters(
Zhi Huange818b6e2018-02-22 15:26:27 -0800415 DtlsTransportInternal* dtls_transport,
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200416 absl::optional<rtc::SSLRole> dtls_role,
Zhi Huange818b6e2018-02-22 15:26:27 -0800417 rtc::SSLFingerprint* remote_fingerprint) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200418 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800419 RTC_DCHECK(dtls_transport);
420 // Set SSL role. Role must be set before fingerprint is applied, which
421 // initiates DTLS setup.
422 if (dtls_role && !dtls_transport->SetDtlsRole(*dtls_role)) {
423 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
424 "Failed to set SSL role for the transport.");
425 }
426 // Apply remote fingerprint.
427 if (!remote_fingerprint ||
428 !dtls_transport->SetRemoteFingerprint(
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700429 remote_fingerprint->algorithm, remote_fingerprint->digest.cdata(),
Zhi Huange818b6e2018-02-22 15:26:27 -0800430 remote_fingerprint->digest.size())) {
431 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
432 "Failed to apply remote fingerprint.");
433 }
434 return webrtc::RTCError::OK();
435}
436
Zhi Huang365381f2018-04-13 16:44:34 -0700437bool JsepTransport::SetRtcpMux(bool enable,
438 webrtc::SdpType type,
439 ContentSource source) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200440 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800441 bool ret = false;
442 switch (type) {
443 case SdpType::kOffer:
444 ret = rtcp_mux_negotiator_.SetOffer(enable, source);
445 break;
446 case SdpType::kPrAnswer:
447 // This may activate RTCP muxing, but we don't yet destroy the transport
448 // because the final answer may deactivate it.
449 ret = rtcp_mux_negotiator_.SetProvisionalAnswer(enable, source);
450 break;
451 case SdpType::kAnswer:
452 ret = rtcp_mux_negotiator_.SetAnswer(enable, source);
453 if (ret && rtcp_mux_negotiator_.IsActive()) {
454 ActivateRtcpMux();
455 }
456 break;
457 default:
458 RTC_NOTREACHED();
459 }
460
461 if (!ret) {
462 return false;
463 }
464
465 auto transport = rtp_transport();
466 transport->SetRtcpMuxEnabled(rtcp_mux_negotiator_.IsActive());
467 return ret;
468}
469
Zhi Huang365381f2018-04-13 16:44:34 -0700470void JsepTransport::ActivateRtcpMux() {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200471 {
472 // Don't hold the network_thread_ lock while calling other functions,
473 // since they might call other functions that call RTC_DCHECK_RUN_ON.
474 // TODO(https://crbug.com/webrtc/10318): Simplify when possible.
475 RTC_DCHECK_RUN_ON(network_thread_);
476 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800477 if (unencrypted_rtp_transport_) {
478 RTC_DCHECK(!sdes_transport_);
479 RTC_DCHECK(!dtls_srtp_transport_);
480 unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
481 } else if (sdes_transport_) {
482 RTC_DCHECK(!unencrypted_rtp_transport_);
483 RTC_DCHECK(!dtls_srtp_transport_);
484 sdes_transport_->SetRtcpPacketTransport(nullptr);
485 } else {
486 RTC_DCHECK(dtls_srtp_transport_);
487 RTC_DCHECK(!unencrypted_rtp_transport_);
488 RTC_DCHECK(!sdes_transport_);
489 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
490 /*rtcp_dtls_transport=*/nullptr);
491 }
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200492 {
493 rtc::CritScope scope(&accessor_lock_);
494 rtcp_dtls_transport_ = nullptr; // Destroy this reference.
495 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800496 // Notify the JsepTransportController to update the aggregate states.
497 SignalRtcpMuxActive();
498}
499
Zhi Huang365381f2018-04-13 16:44:34 -0700500bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos,
501 const std::vector<int>& encrypted_extension_ids,
502 webrtc::SdpType type,
503 ContentSource source) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200504 RTC_DCHECK_RUN_ON(network_thread_);
505 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800506 bool ret = false;
507 ret = sdes_negotiator_.Process(cryptos, type, source);
508 if (!ret) {
509 return ret;
510 }
511
512 if (source == ContentSource::CS_LOCAL) {
513 recv_extension_ids_ = std::move(encrypted_extension_ids);
514 } else {
515 send_extension_ids_ = std::move(encrypted_extension_ids);
516 }
517
518 // If setting an SDES answer succeeded, apply the negotiated parameters
519 // to the SRTP transport.
520 if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
521 if (sdes_negotiator_.send_cipher_suite() &&
522 sdes_negotiator_.recv_cipher_suite()) {
523 RTC_DCHECK(send_extension_ids_);
524 RTC_DCHECK(recv_extension_ids_);
525 ret = sdes_transport_->SetRtpParams(
526 *(sdes_negotiator_.send_cipher_suite()),
527 sdes_negotiator_.send_key().data(),
528 static_cast<int>(sdes_negotiator_.send_key().size()),
529 *(send_extension_ids_), *(sdes_negotiator_.recv_cipher_suite()),
530 sdes_negotiator_.recv_key().data(),
531 static_cast<int>(sdes_negotiator_.recv_key().size()),
532 *(recv_extension_ids_));
533 } else {
534 RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
535 if (type == SdpType::kAnswer) {
536 // Explicitly reset the |sdes_transport_| if no crypto param is
537 // provided in the answer. No need to call |ResetParams()| for
538 // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
539 sdes_transport_->ResetParams();
540 }
541 }
542 }
543 return ret;
544}
545
Zhi Huang365381f2018-04-13 16:44:34 -0700546webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
Zhi Huange818b6e2018-02-22 15:26:27 -0800547 SdpType local_description_type) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200548 RTC_DCHECK_RUN_ON(network_thread_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800549 if (!local_description_ || !remote_description_) {
550 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
551 "Applying an answer transport description "
552 "without applying any offer.");
553 }
554 std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200555 absl::optional<rtc::SSLRole> negotiated_dtls_role;
Zhi Huange818b6e2018-02-22 15:26:27 -0800556
557 rtc::SSLFingerprint* local_fp =
558 local_description_->transport_desc.identity_fingerprint.get();
559 rtc::SSLFingerprint* remote_fp =
560 remote_description_->transport_desc.identity_fingerprint.get();
561 if (remote_fp && local_fp) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200562 remote_fingerprint = absl::make_unique<rtc::SSLFingerprint>(*remote_fp);
Zhi Huange818b6e2018-02-22 15:26:27 -0800563 webrtc::RTCError error =
564 NegotiateDtlsRole(local_description_type,
565 local_description_->transport_desc.connection_role,
566 remote_description_->transport_desc.connection_role,
567 &negotiated_dtls_role);
568 if (!error.ok()) {
569 return error;
570 }
571 } else if (local_fp && (local_description_type == SdpType::kAnswer)) {
572 return webrtc::RTCError(
573 webrtc::RTCErrorType::INVALID_PARAMETER,
574 "Local fingerprint supplied when caller didn't offer DTLS.");
575 } else {
576 // We are not doing DTLS
Steve Anton4905edb2018-10-15 19:27:44 -0700577 remote_fingerprint = absl::make_unique<rtc::SSLFingerprint>(
578 "", rtc::ArrayView<const uint8_t>());
Zhi Huange818b6e2018-02-22 15:26:27 -0800579 }
580 // Now that we have negotiated everything, push it downward.
581 // Note that we cache the result so that if we have race conditions
582 // between future SetRemote/SetLocal invocations and new transport
583 // creation, we have the negotiation state saved until a new
584 // negotiation happens.
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200585 RTC_DCHECK(rtp_dtls_transport());
Zhi Huange818b6e2018-02-22 15:26:27 -0800586 webrtc::RTCError error = SetNegotiatedDtlsParameters(
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200587 rtp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
Zhi Huange818b6e2018-02-22 15:26:27 -0800588 if (!error.ok()) {
589 return error;
590 }
591
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200592 if (rtcp_dtls_transport()) {
593 error = SetNegotiatedDtlsParameters(
594 rtcp_dtls_transport(), negotiated_dtls_role, remote_fingerprint.get());
Zhi Huange818b6e2018-02-22 15:26:27 -0800595 }
596 return error;
597}
598
Zhi Huang365381f2018-04-13 16:44:34 -0700599webrtc::RTCError JsepTransport::NegotiateDtlsRole(
Zhi Huange818b6e2018-02-22 15:26:27 -0800600 SdpType local_description_type,
601 ConnectionRole local_connection_role,
602 ConnectionRole remote_connection_role,
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200603 absl::optional<rtc::SSLRole>* negotiated_dtls_role) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800604 // From RFC 4145, section-4.1, The following are the values that the
605 // 'setup' attribute can take in an offer/answer exchange:
606 // Offer Answer
607 // ________________
608 // active passive / holdconn
609 // passive active / holdconn
610 // actpass active / passive / holdconn
611 // holdconn holdconn
612 //
613 // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
614 // The endpoint MUST use the setup attribute defined in [RFC4145].
615 // The endpoint that is the offerer MUST use the setup attribute
616 // value of setup:actpass and be prepared to receive a client_hello
617 // before it receives the answer. The answerer MUST use either a
618 // setup attribute value of setup:active or setup:passive. Note that
619 // if the answerer uses setup:passive, then the DTLS handshake will
620 // not begin until the answerer is received, which adds additional
621 // latency. setup:active allows the answer and the DTLS handshake to
622 // occur in parallel. Thus, setup:active is RECOMMENDED. Whichever
623 // party is active MUST initiate a DTLS handshake by sending a
624 // ClientHello over each flow (host/port quartet).
625 // IOW - actpass and passive modes should be treated as server and
626 // active as client.
627 bool is_remote_server = false;
628 if (local_description_type == SdpType::kOffer) {
629 if (local_connection_role != CONNECTIONROLE_ACTPASS) {
630 return webrtc::RTCError(
631 webrtc::RTCErrorType::INVALID_PARAMETER,
632 "Offerer must use actpass value for setup attribute.");
633 }
634
635 if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
636 remote_connection_role == CONNECTIONROLE_PASSIVE ||
637 remote_connection_role == CONNECTIONROLE_NONE) {
638 is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
639 } else {
640 return webrtc::RTCError(
641 webrtc::RTCErrorType::INVALID_PARAMETER,
642 "Answerer must use either active or passive value "
643 "for setup attribute.");
644 }
645 // If remote is NONE or ACTIVE it will act as client.
646 } else {
647 if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
648 remote_connection_role != CONNECTIONROLE_NONE) {
649 // Accept a remote role attribute that's not "actpass", but matches the
650 // current negotiated role. This is allowed by dtls-sdp, though our
651 // implementation will never generate such an offer as it's not
652 // recommended.
653 //
654 // See https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-dtls-sdp,
655 // section 5.5.
656 auto current_dtls_role = GetDtlsRole();
657 if (!current_dtls_role ||
658 (*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 actpass value or current negotiated role for "
665 "setup attribute.");
666 }
667 }
668
669 if (local_connection_role == CONNECTIONROLE_ACTIVE ||
670 local_connection_role == CONNECTIONROLE_PASSIVE) {
671 is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
672 } else {
673 return webrtc::RTCError(
674 webrtc::RTCErrorType::INVALID_PARAMETER,
675 "Answerer must use either active or passive value "
676 "for setup attribute.");
677 }
678
679 // If local is passive, local will act as server.
680 }
681
Mirko Bonadei05cf6be2019-01-31 21:38:12 +0100682 *negotiated_dtls_role =
683 (is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER);
Zhi Huange818b6e2018-02-22 15:26:27 -0800684 return webrtc::RTCError::OK();
685}
686
Zhi Huang365381f2018-04-13 16:44:34 -0700687bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport,
688 TransportStats* stats) {
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200689 RTC_DCHECK_RUN_ON(network_thread_);
690 rtc::CritScope scope(&accessor_lock_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800691 RTC_DCHECK(dtls_transport);
692 TransportChannelStats substats;
Harald Alvestrandad88c882018-11-28 16:47:46 +0100693 if (rtcp_dtls_transport_) {
694 substats.component = dtls_transport == rtcp_dtls_transport_->internal()
695 ? ICE_CANDIDATE_COMPONENT_RTCP
696 : ICE_CANDIDATE_COMPONENT_RTP;
697 } else {
698 substats.component = ICE_CANDIDATE_COMPONENT_RTP;
699 }
Zhi Huange818b6e2018-02-22 15:26:27 -0800700 dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
701 dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
702 substats.dtls_state = dtls_transport->dtls_state();
703 if (!dtls_transport->ice_transport()->GetStats(
704 &substats.connection_infos, &substats.candidate_stats_list)) {
705 return false;
706 }
707 stats->channel_stats.push_back(substats);
708 return true;
709}
710
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700711void JsepTransport::OnStateChanged(webrtc::MediaTransportState state) {
712 // TODO(bugs.webrtc.org/9719) This method currently fires on the network
713 // thread, but media transport does not make such guarantees. We need to make
714 // sure this callback is guaranteed to be executed on the network thread.
Harald Alvestrand78a5e962019-04-03 10:42:39 +0200715 RTC_DCHECK_RUN_ON(network_thread_);
716 {
717 rtc::CritScope scope(&accessor_lock_);
718 media_transport_state_ = state;
719 }
Piotr (Peter) Slatala4eb41122018-11-01 07:26:03 -0700720 SignalMediaTransportStateChanged();
721}
Zhi Huange818b6e2018-02-22 15:26:27 -0800722} // namespace cricket