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