blob: a4a03487bd9164544def05f8cc3186d4779da3f3 [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
11#include "pc/jseptransport2.h"
12
13#include <memory>
14#include <utility> // for std::pair
15
16#include "api/candidate.h"
17#include "p2p/base/p2pconstants.h"
18#include "p2p/base/p2ptransportchannel.h"
19#include "p2p/base/port.h"
20#include "rtc_base/bind.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/logging.h"
23#include "rtc_base/ptr_util.h"
24
25using webrtc::SdpType;
26
27namespace cricket {
28
29static bool VerifyIceParams(const JsepTransportDescription& jsep_description) {
30 // For legacy protocols.
31 // TODO(zhihuang): Remove this once the legacy protocol is no longer
32 // supported.
33 if (jsep_description.transport_desc.ice_ufrag.empty() &&
34 jsep_description.transport_desc.ice_pwd.empty()) {
35 return true;
36 }
37
38 if (jsep_description.transport_desc.ice_ufrag.length() <
39 ICE_UFRAG_MIN_LENGTH ||
40 jsep_description.transport_desc.ice_ufrag.length() >
41 ICE_UFRAG_MAX_LENGTH) {
42 return false;
43 }
44 if (jsep_description.transport_desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH ||
45 jsep_description.transport_desc.ice_pwd.length() > ICE_PWD_MAX_LENGTH) {
46 return false;
47 }
48 return true;
49}
50
51JsepTransportDescription::JsepTransportDescription() {}
52
53JsepTransportDescription::JsepTransportDescription(
54 bool rtcp_mux_enabled,
55 const std::vector<CryptoParams>& cryptos,
56 const std::vector<int>& encrypted_header_extension_ids,
Zhi Huange830e682018-03-30 10:48:35 -070057 int rtp_abs_sendtime_extn_id,
Zhi Huange818b6e2018-02-22 15:26:27 -080058 const TransportDescription& transport_desc)
59 : rtcp_mux_enabled(rtcp_mux_enabled),
60 cryptos(cryptos),
61 encrypted_header_extension_ids(encrypted_header_extension_ids),
Zhi Huange830e682018-03-30 10:48:35 -070062 rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
Zhi Huange818b6e2018-02-22 15:26:27 -080063 transport_desc(transport_desc) {}
64
65JsepTransportDescription::JsepTransportDescription(
66 const JsepTransportDescription& from)
67 : rtcp_mux_enabled(from.rtcp_mux_enabled),
68 cryptos(from.cryptos),
69 encrypted_header_extension_ids(from.encrypted_header_extension_ids),
Zhi Huange830e682018-03-30 10:48:35 -070070 rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
Zhi Huange818b6e2018-02-22 15:26:27 -080071 transport_desc(from.transport_desc) {}
72
73JsepTransportDescription::~JsepTransportDescription() = default;
74
75JsepTransportDescription& JsepTransportDescription::operator=(
76 const JsepTransportDescription& from) {
77 if (this == &from) {
78 return *this;
79 }
80 rtcp_mux_enabled = from.rtcp_mux_enabled;
81 cryptos = from.cryptos;
82 encrypted_header_extension_ids = from.encrypted_header_extension_ids;
Zhi Huange830e682018-03-30 10:48:35 -070083 rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
Zhi Huange818b6e2018-02-22 15:26:27 -080084 transport_desc = from.transport_desc;
85
86 return *this;
87}
88
89JsepTransport2::JsepTransport2(
90 const std::string& mid,
91 const rtc::scoped_refptr<rtc::RTCCertificate>& local_certificate,
92 std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
93 std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
94 std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
95 std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
96 std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport)
97 : mid_(mid),
98 local_certificate_(local_certificate),
99 rtp_dtls_transport_(std::move(rtp_dtls_transport)),
100 rtcp_dtls_transport_(std::move(rtcp_dtls_transport)) {
101 RTC_DCHECK(rtp_dtls_transport_);
102 if (unencrypted_rtp_transport) {
103 RTC_DCHECK(!sdes_transport);
104 RTC_DCHECK(!dtls_srtp_transport);
105 unencrypted_rtp_transport_ = std::move(unencrypted_rtp_transport);
106 } else if (sdes_transport) {
107 RTC_DCHECK(!unencrypted_rtp_transport);
108 RTC_DCHECK(!dtls_srtp_transport);
109 sdes_transport_ = std::move(sdes_transport);
110 } else {
111 RTC_DCHECK(dtls_srtp_transport);
112 RTC_DCHECK(!unencrypted_rtp_transport);
113 RTC_DCHECK(!sdes_transport);
114 dtls_srtp_transport_ = std::move(dtls_srtp_transport);
115 }
116}
117
118JsepTransport2::~JsepTransport2() {}
119
120webrtc::RTCError JsepTransport2::SetLocalJsepTransportDescription(
121 const JsepTransportDescription& jsep_description,
122 SdpType type) {
123 webrtc::RTCError error;
124
125 if (!VerifyIceParams(jsep_description)) {
126 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
127 "Invalid ice-ufrag or ice-pwd length.");
128 }
129
130 if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
131 ContentSource::CS_LOCAL)) {
132 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
133 "Failed to setup RTCP mux.");
134 }
135
136 // If doing SDES, setup the SDES crypto parameters.
137 if (sdes_transport_) {
138 RTC_DCHECK(!unencrypted_rtp_transport_);
139 RTC_DCHECK(!dtls_srtp_transport_);
140 if (!SetSdes(jsep_description.cryptos,
141 jsep_description.encrypted_header_extension_ids, type,
142 ContentSource::CS_LOCAL)) {
143 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
144 "Failed to setup SDES crypto parameters.");
145 }
146 } else if (dtls_srtp_transport_) {
147 RTC_DCHECK(!unencrypted_rtp_transport_);
148 RTC_DCHECK(!sdes_transport_);
149 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
150 jsep_description.encrypted_header_extension_ids);
151 }
152
153 bool ice_restarting =
154 local_description_ != nullptr &&
155 IceCredentialsChanged(local_description_->transport_desc.ice_ufrag,
156 local_description_->transport_desc.ice_pwd,
157 jsep_description.transport_desc.ice_ufrag,
158 jsep_description.transport_desc.ice_pwd);
159 local_description_.reset(new JsepTransportDescription(jsep_description));
160
161 rtc::SSLFingerprint* local_fp =
162 local_description_->transport_desc.identity_fingerprint.get();
163
164 if (!local_fp) {
165 local_certificate_ = nullptr;
166 } else {
167 error = VerifyCertificateFingerprint(local_certificate_.get(), local_fp);
168 if (!error.ok()) {
169 local_description_.reset();
170 return error;
171 }
172 }
173
174 SetLocalIceParameters(rtp_dtls_transport_->ice_transport());
175
176 if (rtcp_dtls_transport_) {
177 SetLocalIceParameters(rtcp_dtls_transport_->ice_transport());
178 }
179
180 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
181 if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
182 error = NegotiateAndSetDtlsParameters(type);
183 }
184 if (!error.ok()) {
185 local_description_.reset();
186 return error;
187 }
188
189 if (needs_ice_restart_ && ice_restarting) {
190 needs_ice_restart_ = false;
191 RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag cleared for transport "
192 << mid();
193 }
194
195 return webrtc::RTCError::OK();
196}
197
198webrtc::RTCError JsepTransport2::SetRemoteJsepTransportDescription(
199 const JsepTransportDescription& jsep_description,
200 webrtc::SdpType type) {
201 webrtc::RTCError error;
202
203 if (!VerifyIceParams(jsep_description)) {
204 remote_description_.reset();
205 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
206 "Invalid ice-ufrag or ice-pwd length.");
207 }
208
209 if (!SetRtcpMux(jsep_description.rtcp_mux_enabled, type,
210 ContentSource::CS_REMOTE)) {
211 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
212 "Failed to setup RTCP mux.");
213 }
214
215 // If doing SDES, setup the SDES crypto parameters.
216 if (sdes_transport_) {
217 RTC_DCHECK(!unencrypted_rtp_transport_);
218 RTC_DCHECK(!dtls_srtp_transport_);
219 if (!SetSdes(jsep_description.cryptos,
220 jsep_description.encrypted_header_extension_ids, type,
221 ContentSource::CS_REMOTE)) {
222 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
223 "Failed to setup SDES crypto parameters.");
224 }
Zhi Huange830e682018-03-30 10:48:35 -0700225 sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
226 jsep_description.rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800227 } else if (dtls_srtp_transport_) {
228 RTC_DCHECK(!unencrypted_rtp_transport_);
229 RTC_DCHECK(!sdes_transport_);
230 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
231 jsep_description.encrypted_header_extension_ids);
Zhi Huange830e682018-03-30 10:48:35 -0700232 dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
233 jsep_description.rtp_abs_sendtime_extn_id);
Zhi Huange818b6e2018-02-22 15:26:27 -0800234 }
235
236 remote_description_.reset(new JsepTransportDescription(jsep_description));
237 SetRemoteIceParameters(rtp_dtls_transport_->ice_transport());
238
239 if (rtcp_dtls_transport_) {
240 SetRemoteIceParameters(rtcp_dtls_transport_->ice_transport());
241 }
242
243 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
244 if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
245 error = NegotiateAndSetDtlsParameters(SdpType::kOffer);
246 }
247 if (!error.ok()) {
248 remote_description_.reset();
249 return error;
250 }
251 return webrtc::RTCError::OK();
252}
253
254webrtc::RTCError JsepTransport2::AddRemoteCandidates(
255 const Candidates& candidates) {
256 if (!local_description_ || !remote_description_) {
257 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
258 mid() +
259 " is not ready to use the remote candidate "
260 "because the local or remote description is "
261 "not set.");
262 }
263
264 for (const cricket::Candidate& candidate : candidates) {
265 auto transport =
266 candidate.component() == cricket::ICE_CANDIDATE_COMPONENT_RTP
267 ? rtp_dtls_transport_.get()
268 : rtcp_dtls_transport_.get();
269 if (!transport) {
270 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
271 "Candidate has an unknown component: " +
272 candidate.ToString() + " for mid " + mid());
273 }
274 transport->ice_transport()->AddRemoteCandidate(candidate);
275 }
276 return webrtc::RTCError::OK();
277}
278
279void JsepTransport2::SetNeedsIceRestartFlag() {
280 if (!needs_ice_restart_) {
281 needs_ice_restart_ = true;
282 RTC_LOG(LS_VERBOSE) << "needs-ice-restart flag set for transport " << mid();
283 }
284}
285
286rtc::Optional<rtc::SSLRole> JsepTransport2::GetDtlsRole() const {
287 RTC_DCHECK(rtp_dtls_transport_);
288 rtc::SSLRole dtls_role;
289 if (!rtp_dtls_transport_->GetDtlsRole(&dtls_role)) {
290 return rtc::Optional<rtc::SSLRole>();
291 }
292
293 return rtc::Optional<rtc::SSLRole>(dtls_role);
294}
295
296bool JsepTransport2::GetStats(TransportStats* stats) {
297 stats->transport_name = mid();
298 stats->channel_stats.clear();
299 bool ret = GetTransportStats(rtp_dtls_transport_.get(), stats);
300 if (rtcp_dtls_transport_) {
301 ret &= GetTransportStats(rtcp_dtls_transport_.get(), stats);
302 }
303 return ret;
304}
305
306webrtc::RTCError JsepTransport2::VerifyCertificateFingerprint(
307 const rtc::RTCCertificate* certificate,
308 const rtc::SSLFingerprint* fingerprint) const {
309 if (!fingerprint) {
310 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
311 "No fingerprint");
312 }
313 if (!certificate) {
314 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
315 "Fingerprint provided but no identity available.");
316 }
317 std::unique_ptr<rtc::SSLFingerprint> fp_tmp(rtc::SSLFingerprint::Create(
318 fingerprint->algorithm, certificate->identity()));
319 RTC_DCHECK(fp_tmp.get() != NULL);
320 if (*fp_tmp == *fingerprint) {
321 return webrtc::RTCError::OK();
322 }
323 std::ostringstream desc;
324 desc << "Local fingerprint does not match identity. Expected: ";
325 desc << fp_tmp->ToString();
326 desc << " Got: " << fingerprint->ToString();
327 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER, desc.str());
328}
329
330void JsepTransport2::SetLocalIceParameters(
331 IceTransportInternal* ice_transport) {
332 RTC_DCHECK(ice_transport);
333 RTC_DCHECK(local_description_);
334 ice_transport->SetIceParameters(
335 local_description_->transport_desc.GetIceParameters());
336}
337
338void JsepTransport2::SetRemoteIceParameters(
339 IceTransportInternal* ice_transport) {
340 RTC_DCHECK(ice_transport);
341 RTC_DCHECK(remote_description_);
342 ice_transport->SetRemoteIceParameters(
343 remote_description_->transport_desc.GetIceParameters());
344 ice_transport->SetRemoteIceMode(remote_description_->transport_desc.ice_mode);
345}
346
347webrtc::RTCError JsepTransport2::SetNegotiatedDtlsParameters(
348 DtlsTransportInternal* dtls_transport,
349 rtc::Optional<rtc::SSLRole> dtls_role,
350 rtc::SSLFingerprint* remote_fingerprint) {
351 RTC_DCHECK(dtls_transport);
352 // Set SSL role. Role must be set before fingerprint is applied, which
353 // initiates DTLS setup.
354 if (dtls_role && !dtls_transport->SetDtlsRole(*dtls_role)) {
355 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
356 "Failed to set SSL role for the transport.");
357 }
358 // Apply remote fingerprint.
359 if (!remote_fingerprint ||
360 !dtls_transport->SetRemoteFingerprint(
361 remote_fingerprint->algorithm,
362 reinterpret_cast<const uint8_t*>(remote_fingerprint->digest.data()),
363 remote_fingerprint->digest.size())) {
364 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
365 "Failed to apply remote fingerprint.");
366 }
367 return webrtc::RTCError::OK();
368}
369
370bool JsepTransport2::SetRtcpMux(bool enable,
371 webrtc::SdpType type,
372 ContentSource source) {
373 bool ret = false;
374 switch (type) {
375 case SdpType::kOffer:
376 ret = rtcp_mux_negotiator_.SetOffer(enable, source);
377 break;
378 case SdpType::kPrAnswer:
379 // This may activate RTCP muxing, but we don't yet destroy the transport
380 // because the final answer may deactivate it.
381 ret = rtcp_mux_negotiator_.SetProvisionalAnswer(enable, source);
382 break;
383 case SdpType::kAnswer:
384 ret = rtcp_mux_negotiator_.SetAnswer(enable, source);
385 if (ret && rtcp_mux_negotiator_.IsActive()) {
386 ActivateRtcpMux();
387 }
388 break;
389 default:
390 RTC_NOTREACHED();
391 }
392
393 if (!ret) {
394 return false;
395 }
396
397 auto transport = rtp_transport();
398 transport->SetRtcpMuxEnabled(rtcp_mux_negotiator_.IsActive());
399 return ret;
400}
401
402void JsepTransport2::ActivateRtcpMux() {
403 if (unencrypted_rtp_transport_) {
404 RTC_DCHECK(!sdes_transport_);
405 RTC_DCHECK(!dtls_srtp_transport_);
406 unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
407 } else if (sdes_transport_) {
408 RTC_DCHECK(!unencrypted_rtp_transport_);
409 RTC_DCHECK(!dtls_srtp_transport_);
410 sdes_transport_->SetRtcpPacketTransport(nullptr);
411 } else {
412 RTC_DCHECK(dtls_srtp_transport_);
413 RTC_DCHECK(!unencrypted_rtp_transport_);
414 RTC_DCHECK(!sdes_transport_);
415 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
416 /*rtcp_dtls_transport=*/nullptr);
417 }
418 rtcp_dtls_transport_.reset();
419 // Notify the JsepTransportController to update the aggregate states.
420 SignalRtcpMuxActive();
421}
422
423bool JsepTransport2::SetSdes(const std::vector<CryptoParams>& cryptos,
424 const std::vector<int>& encrypted_extension_ids,
425 webrtc::SdpType type,
426 ContentSource source) {
427 bool ret = false;
428 ret = sdes_negotiator_.Process(cryptos, type, source);
429 if (!ret) {
430 return ret;
431 }
432
433 if (source == ContentSource::CS_LOCAL) {
434 recv_extension_ids_ = std::move(encrypted_extension_ids);
435 } else {
436 send_extension_ids_ = std::move(encrypted_extension_ids);
437 }
438
439 // If setting an SDES answer succeeded, apply the negotiated parameters
440 // to the SRTP transport.
441 if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
442 if (sdes_negotiator_.send_cipher_suite() &&
443 sdes_negotiator_.recv_cipher_suite()) {
444 RTC_DCHECK(send_extension_ids_);
445 RTC_DCHECK(recv_extension_ids_);
446 ret = sdes_transport_->SetRtpParams(
447 *(sdes_negotiator_.send_cipher_suite()),
448 sdes_negotiator_.send_key().data(),
449 static_cast<int>(sdes_negotiator_.send_key().size()),
450 *(send_extension_ids_), *(sdes_negotiator_.recv_cipher_suite()),
451 sdes_negotiator_.recv_key().data(),
452 static_cast<int>(sdes_negotiator_.recv_key().size()),
453 *(recv_extension_ids_));
454 } else {
455 RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
456 if (type == SdpType::kAnswer) {
457 // Explicitly reset the |sdes_transport_| if no crypto param is
458 // provided in the answer. No need to call |ResetParams()| for
459 // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
460 sdes_transport_->ResetParams();
461 }
462 }
463 }
464 return ret;
465}
466
467webrtc::RTCError JsepTransport2::NegotiateAndSetDtlsParameters(
468 SdpType local_description_type) {
469 if (!local_description_ || !remote_description_) {
470 return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE,
471 "Applying an answer transport description "
472 "without applying any offer.");
473 }
474 std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
475 rtc::Optional<rtc::SSLRole> negotiated_dtls_role;
476
477 rtc::SSLFingerprint* local_fp =
478 local_description_->transport_desc.identity_fingerprint.get();
479 rtc::SSLFingerprint* remote_fp =
480 remote_description_->transport_desc.identity_fingerprint.get();
481 if (remote_fp && local_fp) {
482 remote_fingerprint = rtc::MakeUnique<rtc::SSLFingerprint>(*remote_fp);
483 webrtc::RTCError error =
484 NegotiateDtlsRole(local_description_type,
485 local_description_->transport_desc.connection_role,
486 remote_description_->transport_desc.connection_role,
487 &negotiated_dtls_role);
488 if (!error.ok()) {
489 return error;
490 }
491 } else if (local_fp && (local_description_type == SdpType::kAnswer)) {
492 return webrtc::RTCError(
493 webrtc::RTCErrorType::INVALID_PARAMETER,
494 "Local fingerprint supplied when caller didn't offer DTLS.");
495 } else {
496 // We are not doing DTLS
497 remote_fingerprint = rtc::MakeUnique<rtc::SSLFingerprint>("", nullptr, 0);
498 }
499 // Now that we have negotiated everything, push it downward.
500 // Note that we cache the result so that if we have race conditions
501 // between future SetRemote/SetLocal invocations and new transport
502 // creation, we have the negotiation state saved until a new
503 // negotiation happens.
504 webrtc::RTCError error = SetNegotiatedDtlsParameters(
505 rtp_dtls_transport_.get(), negotiated_dtls_role,
506 remote_fingerprint.get());
507 if (!error.ok()) {
508 return error;
509 }
510
511 if (rtcp_dtls_transport_) {
512 error = SetNegotiatedDtlsParameters(rtcp_dtls_transport_.get(),
513 negotiated_dtls_role,
514 remote_fingerprint.get());
515 }
516 return error;
517}
518
519webrtc::RTCError JsepTransport2::NegotiateDtlsRole(
520 SdpType local_description_type,
521 ConnectionRole local_connection_role,
522 ConnectionRole remote_connection_role,
523 rtc::Optional<rtc::SSLRole>* negotiated_dtls_role) {
524 // From RFC 4145, section-4.1, The following are the values that the
525 // 'setup' attribute can take in an offer/answer exchange:
526 // Offer Answer
527 // ________________
528 // active passive / holdconn
529 // passive active / holdconn
530 // actpass active / passive / holdconn
531 // holdconn holdconn
532 //
533 // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
534 // The endpoint MUST use the setup attribute defined in [RFC4145].
535 // The endpoint that is the offerer MUST use the setup attribute
536 // value of setup:actpass and be prepared to receive a client_hello
537 // before it receives the answer. The answerer MUST use either a
538 // setup attribute value of setup:active or setup:passive. Note that
539 // if the answerer uses setup:passive, then the DTLS handshake will
540 // not begin until the answerer is received, which adds additional
541 // latency. setup:active allows the answer and the DTLS handshake to
542 // occur in parallel. Thus, setup:active is RECOMMENDED. Whichever
543 // party is active MUST initiate a DTLS handshake by sending a
544 // ClientHello over each flow (host/port quartet).
545 // IOW - actpass and passive modes should be treated as server and
546 // active as client.
547 bool is_remote_server = false;
548 if (local_description_type == SdpType::kOffer) {
549 if (local_connection_role != CONNECTIONROLE_ACTPASS) {
550 return webrtc::RTCError(
551 webrtc::RTCErrorType::INVALID_PARAMETER,
552 "Offerer must use actpass value for setup attribute.");
553 }
554
555 if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
556 remote_connection_role == CONNECTIONROLE_PASSIVE ||
557 remote_connection_role == CONNECTIONROLE_NONE) {
558 is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
559 } else {
560 return webrtc::RTCError(
561 webrtc::RTCErrorType::INVALID_PARAMETER,
562 "Answerer must use either active or passive value "
563 "for setup attribute.");
564 }
565 // If remote is NONE or ACTIVE it will act as client.
566 } else {
567 if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
568 remote_connection_role != CONNECTIONROLE_NONE) {
569 // Accept a remote role attribute that's not "actpass", but matches the
570 // current negotiated role. This is allowed by dtls-sdp, though our
571 // implementation will never generate such an offer as it's not
572 // recommended.
573 //
574 // See https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-dtls-sdp,
575 // section 5.5.
576 auto current_dtls_role = GetDtlsRole();
577 if (!current_dtls_role ||
578 (*current_dtls_role == rtc::SSL_CLIENT &&
579 remote_connection_role == CONNECTIONROLE_ACTIVE) ||
580 (*current_dtls_role == rtc::SSL_SERVER &&
581 remote_connection_role == CONNECTIONROLE_PASSIVE)) {
582 return webrtc::RTCError(
583 webrtc::RTCErrorType::INVALID_PARAMETER,
584 "Offerer must use actpass value or current negotiated role for "
585 "setup attribute.");
586 }
587 }
588
589 if (local_connection_role == CONNECTIONROLE_ACTIVE ||
590 local_connection_role == CONNECTIONROLE_PASSIVE) {
591 is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
592 } else {
593 return webrtc::RTCError(
594 webrtc::RTCErrorType::INVALID_PARAMETER,
595 "Answerer must use either active or passive value "
596 "for setup attribute.");
597 }
598
599 // If local is passive, local will act as server.
600 }
601
602 *negotiated_dtls_role = (is_remote_server ? std::move(rtc::SSL_CLIENT)
603 : std::move(rtc::SSL_SERVER));
604 return webrtc::RTCError::OK();
605}
606
607bool JsepTransport2::GetTransportStats(DtlsTransportInternal* dtls_transport,
608 TransportStats* stats) {
609 RTC_DCHECK(dtls_transport);
610 TransportChannelStats substats;
611 substats.component = dtls_transport == rtcp_dtls_transport_.get()
612 ? ICE_CANDIDATE_COMPONENT_RTCP
613 : ICE_CANDIDATE_COMPONENT_RTP;
614 dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
615 dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite);
616 substats.dtls_state = dtls_transport->dtls_state();
617 if (!dtls_transport->ice_transport()->GetStats(
618 &substats.connection_infos, &substats.candidate_stats_list)) {
619 return false;
620 }
621 stats->channel_stats.push_back(substats);
622 return true;
623}
624
625} // namespace cricket