Rewrite WebRtcSession DTLS/SDES crypto tests as PeerConnection tests
Bug: webrtc:8222
Change-Id: I6be2c5a5735b77a5c577472b88ff830204dd69eb
Reviewed-on: https://webrtc-review.googlesource.com/1160
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20193}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 1bfa37c..6e95bf8 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -391,6 +391,7 @@
"localaudiosource_unittest.cc",
"mediaconstraintsinterface_unittest.cc",
"mediastream_unittest.cc",
+ "peerconnection_crypto_unittest.cc",
"peerconnection_integrationtest.cc",
"peerconnectionendtoend_unittest.cc",
"peerconnectionfactory_unittest.cc",
diff --git a/pc/channel.h b/pc/channel.h
index d9b149c..c5888db 100644
--- a/pc/channel.h
+++ b/pc/channel.h
@@ -185,9 +185,6 @@
virtual cricket::MediaType media_type() = 0;
- // This function returns true if we require SRTP for call setup.
- bool srtp_required_for_testing() const { return srtp_required_; }
-
// Public for testing.
// TODO(zstein): Remove this once channels register themselves with
// an RtpTransport in a more explicit way.
diff --git a/pc/peerconnection_crypto_unittest.cc b/pc/peerconnection_crypto_unittest.cc
new file mode 100644
index 0000000..0f54995
--- /dev/null
+++ b/pc/peerconnection_crypto_unittest.cc
@@ -0,0 +1,605 @@
+/*
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "p2p/base/fakeportallocator.h"
+#include "pc/mediasession.h"
+#include "pc/peerconnectionwrapper.h"
+#include "pc/sdputils.h"
+#ifdef WEBRTC_ANDROID
+#include "pc/test/androidtestinitializer.h"
+#endif
+#include "pc/test/fakeaudiocapturemodule.h"
+#include "pc/test/fakertccertificategenerator.h"
+#include "rtc_base/gunit.h"
+#include "rtc_base/ptr_util.h"
+#include "rtc_base/virtualsocketserver.h"
+
+namespace webrtc {
+
+using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
+using ::testing::Values;
+using ::testing::Combine;
+
+constexpr int kGenerateCertTimeout = 1000;
+
+class PeerConnectionCryptoUnitTest : public ::testing::Test {
+ protected:
+ typedef std::unique_ptr<PeerConnectionWrapper> WrapperPtr;
+
+ PeerConnectionCryptoUnitTest()
+ : vss_(new rtc::VirtualSocketServer()), main_(vss_.get()) {
+#ifdef WEBRTC_ANDROID
+ InitializeAndroidObjects();
+#endif
+ pc_factory_ = CreatePeerConnectionFactory(
+ rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
+ FakeAudioCaptureModule::Create(), nullptr, nullptr);
+ }
+
+ WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
+ return CreatePeerConnection(config, nullptr);
+ }
+
+ WrapperPtr CreatePeerConnection(
+ const RTCConfiguration& config,
+ std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_gen) {
+ auto fake_port_allocator = rtc::MakeUnique<cricket::FakePortAllocator>(
+ rtc::Thread::Current(), nullptr);
+ auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
+ auto pc = pc_factory_->CreatePeerConnection(
+ config, std::move(fake_port_allocator), std::move(cert_gen),
+ observer.get());
+ if (!pc) {
+ return nullptr;
+ }
+
+ return rtc::MakeUnique<PeerConnectionWrapper>(pc_factory_, pc,
+ std::move(observer));
+ }
+
+ // Accepts the same arguments as CreatePeerConnection and adds default audio
+ // and video tracks.
+ template <typename... Args>
+ WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
+ auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
+ if (!wrapper) {
+ return nullptr;
+ }
+ wrapper->AddAudioVideoStream("s", "a", "v");
+ return wrapper;
+ }
+
+ std::unique_ptr<rtc::VirtualSocketServer> vss_;
+ rtc::AutoSocketServerThread main_;
+ rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
+};
+
+SdpContentPredicate HaveDtlsFingerprint() {
+ return [](const cricket::ContentInfo* content,
+ const cricket::TransportInfo* transport) {
+ return transport->description.identity_fingerprint != nullptr;
+ };
+}
+
+SdpContentPredicate HaveSdesCryptos() {
+ return [](const cricket::ContentInfo* content,
+ const cricket::TransportInfo* transport) {
+ const auto* media_desc =
+ static_cast<const cricket::MediaContentDescription*>(
+ content->description);
+ return !media_desc->cryptos().empty();
+ };
+}
+
+SdpContentPredicate HaveProtocol(const std::string& protocol) {
+ return [protocol](const cricket::ContentInfo* content,
+ const cricket::TransportInfo* transport) {
+ const auto* media_desc =
+ static_cast<const cricket::MediaContentDescription*>(
+ content->description);
+ return media_desc->protocol() == protocol;
+ };
+}
+
+SdpContentPredicate HaveSdesGcmCryptos(size_t num_crypto_suites) {
+ return [num_crypto_suites](const cricket::ContentInfo* content,
+ const cricket::TransportInfo* transport) {
+ const auto* media_desc =
+ static_cast<const cricket::MediaContentDescription*>(
+ content->description);
+ if (media_desc->cryptos().size() != num_crypto_suites) {
+ return false;
+ }
+ const cricket::CryptoParams first_params = media_desc->cryptos()[0];
+ return first_params.key_params.size() == 67U &&
+ first_params.cipher_suite == "AEAD_AES_256_GCM";
+ };
+}
+
+SdpContentMutator RemoveSdesCryptos() {
+ return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
+ auto* media_desc =
+ static_cast<cricket::MediaContentDescription*>(content->description);
+ media_desc->set_cryptos({});
+ };
+}
+
+SdpContentMutator RemoveDtlsFingerprint() {
+ return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
+ transport->description.identity_fingerprint.reset();
+ };
+}
+
+// When DTLS is enabled, the SDP offer/answer should have a DTLS fingerprint and
+// no SDES cryptos.
+TEST_F(PeerConnectionCryptoUnitTest, CorrectCryptoInOfferWhenDtlsEnabled) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ ASSERT_TRUE(offer);
+
+ ASSERT_FALSE(offer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsAll(HaveDtlsFingerprint(), offer->description()));
+ EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), offer->description()));
+ EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolDtlsSavpf),
+ offer->description()));
+}
+TEST_F(PeerConnectionCryptoUnitTest, CorrectCryptoInAnswerWhenDtlsEnabled) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOffer());
+ auto answer = callee->CreateAnswer();
+ ASSERT_TRUE(answer);
+
+ ASSERT_FALSE(answer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsAll(HaveDtlsFingerprint(), answer->description()));
+ EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), answer->description()));
+ EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolDtlsSavpf),
+ answer->description()));
+}
+
+// When DTLS is disabled, the SDP offer/answer should include SDES cryptos and
+// should not have a DTLS fingerprint.
+TEST_F(PeerConnectionCryptoUnitTest, CorrectCryptoInOfferWhenDtlsDisabled) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ ASSERT_TRUE(offer);
+
+ ASSERT_FALSE(offer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsAll(HaveSdesCryptos(), offer->description()));
+ EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), offer->description()));
+ EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolSavpf),
+ offer->description()));
+}
+TEST_F(PeerConnectionCryptoUnitTest, CorrectCryptoInAnswerWhenDtlsDisabled) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOffer());
+ auto answer = callee->CreateAnswer();
+ ASSERT_TRUE(answer);
+
+ ASSERT_FALSE(answer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsAll(HaveSdesCryptos(), answer->description()));
+ EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), answer->description()));
+ EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolSavpf),
+ answer->description()));
+}
+
+// When encryption is disabled, the SDP offer/answer should have neither a DTLS
+// fingerprint nor any SDES crypto options.
+TEST_F(PeerConnectionCryptoUnitTest,
+ CorrectCryptoInOfferWhenEncryptionDisabled) {
+ PeerConnectionFactoryInterface::Options options;
+ options.disable_encryption = true;
+ pc_factory_->SetOptions(options);
+
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ ASSERT_TRUE(offer);
+
+ ASSERT_FALSE(offer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), offer->description()));
+ EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), offer->description()));
+ EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolAvpf),
+ offer->description()));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ CorrectCryptoInAnswerWhenEncryptionDisabled) {
+ PeerConnectionFactoryInterface::Options options;
+ options.disable_encryption = true;
+ pc_factory_->SetOptions(options);
+
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOffer());
+ auto answer = callee->CreateAnswer();
+ ASSERT_TRUE(answer);
+
+ ASSERT_FALSE(answer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsNone(HaveSdesCryptos(), answer->description()));
+ EXPECT_TRUE(SdpContentsNone(HaveDtlsFingerprint(), answer->description()));
+ EXPECT_TRUE(SdpContentsAll(HaveProtocol(cricket::kMediaProtocolAvpf),
+ answer->description()));
+}
+
+// When DTLS is disabled and GCM cipher suites are enabled, the SDP offer/answer
+// should have the correct ciphers in the SDES crypto options.
+// With GCM cipher suites enabled, there will be 3 cryptos in the offer and 1
+// in the answer.
+TEST_F(PeerConnectionCryptoUnitTest, CorrectCryptoInOfferWithSdesAndGcm) {
+ PeerConnectionFactoryInterface::Options options;
+ options.crypto_options.enable_gcm_crypto_suites = true;
+ pc_factory_->SetOptions(options);
+
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ ASSERT_TRUE(offer);
+
+ ASSERT_FALSE(offer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsAll(HaveSdesGcmCryptos(3), offer->description()));
+}
+TEST_F(PeerConnectionCryptoUnitTest, CorrectCryptoInAnswerWithSdesAndGcm) {
+ PeerConnectionFactoryInterface::Options options;
+ options.crypto_options.enable_gcm_crypto_suites = true;
+ pc_factory_->SetOptions(options);
+
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOffer());
+ auto answer = callee->CreateAnswer();
+ ASSERT_TRUE(answer);
+
+ ASSERT_FALSE(answer->description()->contents().empty());
+ EXPECT_TRUE(SdpContentsAll(HaveSdesGcmCryptos(1), answer->description()));
+}
+
+TEST_F(PeerConnectionCryptoUnitTest, CanSetSdesGcmRemoteOfferAndLocalAnswer) {
+ PeerConnectionFactoryInterface::Options options;
+ options.crypto_options.enable_gcm_crypto_suites = true;
+ pc_factory_->SetOptions(options);
+
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ ASSERT_TRUE(offer);
+ ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+
+ auto answer = callee->CreateAnswer();
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
+}
+
+// The following group tests that two PeerConnections can successfully exchange
+// an offer/answer when DTLS is off and that they will refuse any offer/answer
+// applied locally/remotely if it does not include SDES cryptos.
+TEST_F(PeerConnectionCryptoUnitTest, ExchangeOfferAnswerWhenSdesOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOfferAndSetAsLocal();
+ ASSERT_TRUE(offer);
+ ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+
+ auto answer = callee->CreateAnswerAndSetAsLocal();
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetLocalOfferWithNoCryptosWhenSdesOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ SdpContentsForEach(RemoveSdesCryptos(), offer->description());
+
+ EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetRemoteOfferWithNoCryptosWhenSdesOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ SdpContentsForEach(RemoveSdesCryptos(), offer->description());
+
+ EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetLocalAnswerWithNoCryptosWhenSdesOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
+ auto answer = callee->CreateAnswer();
+ SdpContentsForEach(RemoveSdesCryptos(), answer->description());
+
+ EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetRemoteAnswerWithNoCryptosWhenSdesOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
+ auto answer = callee->CreateAnswerAndSetAsLocal();
+ SdpContentsForEach(RemoveSdesCryptos(), answer->description());
+
+ EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));
+}
+
+// The following group tests that two PeerConnections can successfully exchange
+// an offer/answer when DTLS is on and that they will refuse any offer/answer
+// applied locally/remotely if it does not include a DTLS fingerprint.
+TEST_F(PeerConnectionCryptoUnitTest, ExchangeOfferAnswerWhenDtlsOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOfferAndSetAsLocal();
+ ASSERT_TRUE(offer);
+ ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+
+ auto answer = callee->CreateAnswerAndSetAsLocal();
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetLocalOfferWithNoFingerprintWhenDtlsOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ SdpContentsForEach(RemoveDtlsFingerprint(), offer->description());
+
+ EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetRemoteOfferWithNoFingerprintWhenDtlsOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOffer();
+ SdpContentsForEach(RemoveDtlsFingerprint(), offer->description());
+
+ EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetLocalAnswerWithNoFingerprintWhenDtlsOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
+ auto answer = callee->CreateAnswer();
+ SdpContentsForEach(RemoveDtlsFingerprint(), answer->description());
+}
+TEST_F(PeerConnectionCryptoUnitTest,
+ FailToSetRemoteAnswerWithNoFingerprintWhenDtlsOn) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
+ auto answer = callee->CreateAnswerAndSetAsLocal();
+ SdpContentsForEach(RemoveDtlsFingerprint(), answer->description());
+
+ EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));
+}
+
+// Test that an offer/answer can be exchanged when encryption is disabled.
+TEST_F(PeerConnectionCryptoUnitTest, ExchangeOfferAnswerWhenNoEncryption) {
+ PeerConnectionFactoryInterface::Options options;
+ options.disable_encryption = true;
+ pc_factory_->SetOptions(options);
+
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(false);
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ auto callee = CreatePeerConnectionWithAudioVideo(config);
+
+ auto offer = caller->CreateOfferAndSetAsLocal();
+ ASSERT_TRUE(offer);
+ ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+
+ auto answer = callee->CreateAnswerAndSetAsLocal();
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
+}
+
+// Tests that a DTLS call can be established when the certificate is specified
+// in the PeerConnection config and no certificate generator is specified.
+TEST_F(PeerConnectionCryptoUnitTest,
+ ExchangeOfferAnswerWhenDtlsCertificateInConfig) {
+ RTCConfiguration caller_config;
+ caller_config.enable_dtls_srtp.emplace(true);
+ caller_config.certificates.push_back(
+ FakeRTCCertificateGenerator::GenerateCertificate());
+ auto caller = CreatePeerConnectionWithAudioVideo(caller_config);
+
+ RTCConfiguration callee_config;
+ callee_config.enable_dtls_srtp.emplace(true);
+ callee_config.certificates.push_back(
+ FakeRTCCertificateGenerator::GenerateCertificate());
+ auto callee = CreatePeerConnectionWithAudioVideo(callee_config);
+
+ auto offer = caller->CreateOfferAndSetAsLocal();
+ ASSERT_TRUE(offer);
+ ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
+
+ auto answer = callee->CreateAnswerAndSetAsLocal();
+ ASSERT_TRUE(answer);
+ ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
+}
+
+// The following parameterized test verifies that CreateOffer/CreateAnswer
+// returns successfully (or with failure if the underlying certificate generator
+// fails) no matter when the DTLS certificate is generated. If multiple
+// CreateOffer/CreateAnswer calls are made while waiting for the certificate,
+// they all finish after the certificate is generated.
+
+// Whether the test will call CreateOffer or CreateAnswer.
+enum class SdpType { kOffer, kAnswer };
+std::ostream& operator<<(std::ostream& out, SdpType value) {
+ switch (value) {
+ case SdpType::kOffer:
+ return out << "offer";
+ case SdpType::kAnswer:
+ return out << "answer";
+ default:
+ return out << "unknown";
+ }
+}
+
+// Whether the certificate will be generated before calling CreateOffer or
+// while CreateOffer is executing.
+enum class CertGenTime { kBefore, kDuring };
+std::ostream& operator<<(std::ostream& out, CertGenTime value) {
+ switch (value) {
+ case CertGenTime::kBefore:
+ return out << "before";
+ case CertGenTime::kDuring:
+ return out << "during";
+ default:
+ return out << "unknown";
+ }
+}
+
+// Whether the fake certificate generator will produce a certificate or fail.
+enum class CertGenResult { kSucceed, kFail };
+std::ostream& operator<<(std::ostream& out, CertGenResult value) {
+ switch (value) {
+ case CertGenResult::kSucceed:
+ return out << "succeed";
+ case CertGenResult::kFail:
+ return out << "fail";
+ default:
+ return out << "unknown";
+ }
+}
+
+class PeerConnectionCryptoDtlsCertGenUnitTest
+ : public PeerConnectionCryptoUnitTest,
+ public ::testing::WithParamInterface<
+ ::testing::tuple<SdpType, CertGenTime, CertGenResult, size_t>> {
+ protected:
+ PeerConnectionCryptoDtlsCertGenUnitTest() {
+ sdp_type_ = ::testing::get<0>(GetParam());
+ cert_gen_time_ = ::testing::get<1>(GetParam());
+ cert_gen_result_ = ::testing::get<2>(GetParam());
+ concurrent_calls_ = ::testing::get<3>(GetParam());
+ }
+
+ SdpType sdp_type_;
+ CertGenTime cert_gen_time_;
+ CertGenResult cert_gen_result_;
+ size_t concurrent_calls_;
+};
+
+TEST_P(PeerConnectionCryptoDtlsCertGenUnitTest, TestCertificateGeneration) {
+ RTCConfiguration config;
+ config.enable_dtls_srtp.emplace(true);
+ auto owned_fake_certificate_generator =
+ rtc::MakeUnique<FakeRTCCertificateGenerator>();
+ auto* fake_certificate_generator = owned_fake_certificate_generator.get();
+ fake_certificate_generator->set_should_fail(cert_gen_result_ ==
+ CertGenResult::kFail);
+ fake_certificate_generator->set_should_wait(cert_gen_time_ ==
+ CertGenTime::kDuring);
+ WrapperPtr pc;
+ if (sdp_type_ == SdpType::kOffer) {
+ pc = CreatePeerConnectionWithAudioVideo(
+ config, std::move(owned_fake_certificate_generator));
+ } else {
+ auto caller = CreatePeerConnectionWithAudioVideo(config);
+ pc = CreatePeerConnectionWithAudioVideo(
+ config, std::move(owned_fake_certificate_generator));
+ pc->SetRemoteDescription(caller->CreateOfferAndSetAsLocal());
+ }
+ if (cert_gen_time_ == CertGenTime::kBefore) {
+ ASSERT_TRUE_WAIT(fake_certificate_generator->generated_certificates() +
+ fake_certificate_generator->generated_failures() >
+ 0,
+ kGenerateCertTimeout);
+ } else {
+ ASSERT_EQ(fake_certificate_generator->generated_certificates(), 0);
+ fake_certificate_generator->set_should_wait(false);
+ }
+ std::vector<rtc::scoped_refptr<MockCreateSessionDescriptionObserver>>
+ observers;
+ for (size_t i = 0; i < concurrent_calls_; i++) {
+ rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observer =
+ new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>();
+ observers.push_back(observer);
+ if (sdp_type_ == SdpType::kOffer) {
+ pc->pc()->CreateOffer(observer, nullptr);
+ } else {
+ pc->pc()->CreateAnswer(observer, nullptr);
+ }
+ }
+ for (auto& observer : observers) {
+ EXPECT_TRUE_WAIT(observer->called(), 1000);
+ if (cert_gen_result_ == CertGenResult::kSucceed) {
+ EXPECT_TRUE(observer->result());
+ } else {
+ EXPECT_FALSE(observer->result());
+ }
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(
+ PeerConnectionCryptoUnitTest,
+ PeerConnectionCryptoDtlsCertGenUnitTest,
+ Combine(Values(SdpType::kOffer, SdpType::kAnswer),
+ Values(CertGenTime::kBefore, CertGenTime::kDuring),
+ Values(CertGenResult::kSucceed, CertGenResult::kFail),
+ Values(1, 3)));
+
+} // namespace webrtc
diff --git a/pc/test/fakertccertificategenerator.h b/pc/test/fakertccertificategenerator.h
index cac33e4..9cc7928 100644
--- a/pc/test/fakertccertificategenerator.h
+++ b/pc/test/fakertccertificategenerator.h
@@ -125,16 +125,21 @@
typedef rtc::TypedMessageData<rtc::scoped_refptr<
rtc::RTCCertificateGeneratorCallback> > MessageData;
- FakeRTCCertificateGenerator() : should_fail_(false) {}
+ FakeRTCCertificateGenerator() : should_fail_(false), should_wait_(false) {}
void set_should_fail(bool should_fail) {
should_fail_ = should_fail;
}
+ // If set to true, stalls the generation of the fake certificate until it is
+ // set to false.
+ void set_should_wait(bool should_wait) { should_wait_ = should_wait; }
+
void use_original_key() { key_index_ = 0; }
void use_alternate_key() { key_index_ = 1; }
int generated_certificates() { return generated_certificates_; }
+ int generated_failures() { return generated_failures_; }
void GenerateCertificateAsync(
const rtc::KeyParams& key_params,
@@ -201,6 +206,14 @@
// rtc::MessageHandler implementation.
void OnMessage(rtc::Message* msg) override {
+ // If the certificate generation should be stalled, re-post this same
+ // message to the queue with a small delay so as to wait in a loop until
+ // set_should_wait(false) is called.
+ if (should_wait_) {
+ rtc::Thread::Current()->PostDelayed(RTC_FROM_HERE, 1, this,
+ msg->message_id, msg->pdata);
+ return;
+ }
MessageData* message_data = static_cast<MessageData*>(msg->pdata);
rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback> callback =
message_data->data();
@@ -217,6 +230,7 @@
break;
}
case MSG_FAILURE:
+ ++generated_failures_;
callback->OnFailure();
break;
}
@@ -224,8 +238,10 @@
}
bool should_fail_;
+ bool should_wait_;
int key_index_ = 0;
int generated_certificates_ = 0;
+ int generated_failures_ = 0;
};
#endif // PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_
diff --git a/pc/webrtcsession.cc b/pc/webrtcsession.cc
index 86015a7..f556204 100644
--- a/pc/webrtcsession.cc
+++ b/pc/webrtcsession.cc
@@ -667,10 +667,6 @@
return nullptr;
}
-cricket::SecurePolicy WebRtcSession::SdesPolicy() const {
- return webrtc_session_desc_factory_->SdesPolicy();
-}
-
bool WebRtcSession::GetSctpSslRole(rtc::SSLRole* role) {
if (!local_description() || !remote_description()) {
LOG(LS_INFO) << "Local and Remote descriptions must be applied to get the "
diff --git a/pc/webrtcsession.h b/pc/webrtcsession.h
index 284c601..16c3931 100644
--- a/pc/webrtcsession.h
+++ b/pc/webrtcsession.h
@@ -241,8 +241,6 @@
cricket::BaseChannel* GetChannel(const std::string& content_name);
- cricket::SecurePolicy SdesPolicy() const;
-
// Get current SSL role used by SCTP's underlying transport.
bool GetSctpSslRole(rtc::SSLRole* role);
// Get SSL role for an arbitrary m= section (handles bundling correctly).
diff --git a/pc/webrtcsession_unittest.cc b/pc/webrtcsession_unittest.cc
index fe0049d..e3a9e92 100644
--- a/pc/webrtcsession_unittest.cc
+++ b/pc/webrtcsession_unittest.cc
@@ -81,10 +81,6 @@
"2620:0:aaaa:bbbb:cccc:dddd:eeee:ffff";
static const char kClientAddrHost2[] = "22.22.22.22";
static const char kStunAddrHost[] = "99.99.99.1";
-static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478);
-static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0);
-static const char kTurnUsername[] = "test";
-static const char kTurnPassword[] = "test";
static const char kSessionVersion[] = "1";
@@ -99,10 +95,6 @@
static const int kDefaultTimeout = 10000; // 10 seconds.
static const int kIceCandidatesTimeout = 10000;
-static const char kFakeDtlsFingerprint[] =
- "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
- "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
-
static const char kTooLongIceUfragPwd[] =
"IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
"IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
@@ -343,22 +335,6 @@
State state_;
};
-class FakeAudioSource : public cricket::AudioSource {
- public:
- FakeAudioSource() : sink_(NULL) {}
- virtual ~FakeAudioSource() {
- if (sink_)
- sink_->OnClose();
- }
-
- void SetSink(Sink* sink) override { sink_ = sink; }
-
- const cricket::AudioSource::Sink* sink() const { return sink_; }
-
- private:
- cricket::AudioSource::Sink* sink_;
-};
-
class WebRtcSessionTest
: public testing::TestWithParam<RTCCertificateGenerationMethod>,
public sigslot::has_slots<> {
@@ -384,7 +360,6 @@
rtc::SocketAddress(kStunAddrHost, cricket::STUN_SERVER_PORT)),
stun_server_(cricket::TestStunServer::Create(Thread::Current(),
stun_socket_addr_)),
- turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
metrics_observer_(new rtc::RefCountedObject<FakeMetricsObserver>()) {
cricket::ServerAddresses stun_servers;
stun_servers.insert(stun_socket_addr_);
@@ -464,11 +439,6 @@
Init(nullptr, rtcp_mux_policy, rtc::CryptoOptions());
}
- void InitWithCryptoOptions(const rtc::CryptoOptions& crypto_options) {
- Init(nullptr, PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
- crypto_options);
- }
-
// Successfully init with DTLS; with a certificate generated and supplied or
// with a store that generates it for us.
void InitWithDtls(RTCCertificateGenerationMethod cert_gen_method) {
@@ -487,22 +457,6 @@
rtc::CryptoOptions());
}
- // Init with DTLS with a store that will fail to generate a certificate.
- void InitWithDtlsIdentityGenFail() {
- std::unique_ptr<FakeRTCCertificateGenerator> cert_generator(
- new FakeRTCCertificateGenerator());
- cert_generator->set_should_fail(true);
- Init(std::move(cert_generator),
- PeerConnectionInterface::kRtcpMuxPolicyNegotiate,
- rtc::CryptoOptions());
- }
-
- void InitWithGcm() {
- rtc::CryptoOptions crypto_options;
- crypto_options.enable_gcm_crypto_suites = true;
- InitWithCryptoOptions(crypto_options);
- }
-
// The following convenience functions can be applied for both local side and
// remote side. The flags can be overwritten for different use cases.
void SendAudioVideoStream1() {
@@ -818,95 +772,6 @@
return CreateAnswer(options);
}
- bool ChannelsExist() const {
- return (session_->voice_channel() != NULL &&
- session_->video_channel() != NULL);
- }
-
- void VerifyCryptoParams(const cricket::SessionDescription* sdp,
- bool gcm_enabled = false) {
- ASSERT_TRUE(session_.get() != NULL);
- const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
- ASSERT_TRUE(content != NULL);
- const cricket::AudioContentDescription* audio_content =
- static_cast<const cricket::AudioContentDescription*>(
- content->description);
- ASSERT_TRUE(audio_content != NULL);
- if (!gcm_enabled) {
- ASSERT_EQ(1U, audio_content->cryptos().size());
- ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
- audio_content->cryptos()[0].cipher_suite);
- EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
- audio_content->protocol());
- } else {
- // The offer contains 3 possible crypto suites, the answer 1.
- EXPECT_LE(1U, audio_content->cryptos().size());
- EXPECT_NE(2U, audio_content->cryptos().size());
- EXPECT_GE(3U, audio_content->cryptos().size());
- ASSERT_EQ(67U, audio_content->cryptos()[0].key_params.size());
- ASSERT_EQ("AEAD_AES_256_GCM",
- audio_content->cryptos()[0].cipher_suite);
- EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
- audio_content->protocol());
- }
-
- content = cricket::GetFirstVideoContent(sdp);
- ASSERT_TRUE(content != NULL);
- const cricket::VideoContentDescription* video_content =
- static_cast<const cricket::VideoContentDescription*>(
- content->description);
- ASSERT_TRUE(video_content != NULL);
- if (!gcm_enabled) {
- ASSERT_EQ(1U, video_content->cryptos().size());
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
- video_content->cryptos()[0].cipher_suite);
- ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
- EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
- video_content->protocol());
- } else {
- // The offer contains 3 possible crypto suites, the answer 1.
- EXPECT_LE(1U, video_content->cryptos().size());
- EXPECT_NE(2U, video_content->cryptos().size());
- EXPECT_GE(3U, video_content->cryptos().size());
- ASSERT_EQ("AEAD_AES_256_GCM",
- video_content->cryptos()[0].cipher_suite);
- ASSERT_EQ(67U, video_content->cryptos()[0].key_params.size());
- EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
- video_content->protocol());
- }
- }
-
- void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
- const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
- ASSERT_TRUE(content != NULL);
- const cricket::AudioContentDescription* audio_content =
- static_cast<const cricket::AudioContentDescription*>(
- content->description);
- ASSERT_TRUE(audio_content != NULL);
- ASSERT_EQ(0U, audio_content->cryptos().size());
-
- content = cricket::GetFirstVideoContent(sdp);
- ASSERT_TRUE(content != NULL);
- const cricket::VideoContentDescription* video_content =
- static_cast<const cricket::VideoContentDescription*>(
- content->description);
- ASSERT_TRUE(video_content != NULL);
- ASSERT_EQ(0U, video_content->cryptos().size());
-
- if (dtls) {
- EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
- audio_content->protocol());
- EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
- video_content->protocol());
- } else {
- EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
- audio_content->protocol());
- EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
- video_content->protocol());
- }
- }
-
// Set the internal fake description factories to do DTLS-SRTP.
void SetFactoryDtlsSrtp() {
desc_factory_->set_secure(cricket::SEC_DISABLED);
@@ -919,45 +784,6 @@
tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
}
- void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
- bool expected) {
- const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
- ASSERT_TRUE(audio != NULL);
- ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
- const TransportInfo* video = sdp->GetTransportInfoByName("video");
- ASSERT_TRUE(video != NULL);
- ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
- }
-
- void VerifyAnswerFromNonCryptoOffer() {
- // Create an SDP without Crypto.
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- JsepSessionDescription* offer(
- CreateRemoteOffer(options, cricket::SEC_DISABLED));
- ASSERT_TRUE(offer != NULL);
- VerifyNoCryptoParams(offer->description(), false);
- SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
- offer);
- const webrtc::SessionDescriptionInterface* answer = CreateAnswer();
- // Answer should be NULL as no crypto params in offer.
- ASSERT_TRUE(answer == NULL);
- }
-
- void VerifyAnswerFromCryptoOffer() {
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- options.bundle_enabled = true;
- std::unique_ptr<JsepSessionDescription> offer(
- CreateRemoteOffer(options, cricket::SEC_REQUIRED));
- ASSERT_TRUE(offer.get() != NULL);
- VerifyCryptoParams(offer->description());
- SetRemoteDescriptionWithoutError(offer.release());
- std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
- ASSERT_TRUE(answer.get() != NULL);
- VerifyCryptoParams(answer->description());
- }
-
bool IceUfragPwdEqual(const cricket::SessionDescription* desc1,
const cricket::SessionDescription* desc2) {
if (desc1->contents().size() != desc2->contents().size()) {
@@ -1120,59 +946,12 @@
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
expected_error, desc);
}
- void SetRemoteDescriptionPranswerExpectError(
- const std::string& expected_error, SessionDescriptionInterface* desc) {
- SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
- expected_error, desc);
- }
void SetRemoteDescriptionAnswerExpectError(
const std::string& expected_error, SessionDescriptionInterface* desc) {
SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
expected_error, desc);
}
- void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
- SessionDescriptionInterface** nocrypto_answer) {
- // Create a SDP without Crypto.
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- options.bundle_enabled = true;
- *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
- ASSERT_TRUE(*offer != NULL);
- VerifyCryptoParams((*offer)->description());
-
- cricket::MediaSessionOptions answer_options;
- GetOptionsForRemoteAnswer(&answer_options);
- *nocrypto_answer =
- CreateRemoteAnswer(*offer, answer_options, cricket::SEC_DISABLED);
- EXPECT_TRUE(*nocrypto_answer != NULL);
- }
-
- void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
- SessionDescriptionInterface** nodtls_answer) {
- cricket::MediaSessionOptions options;
- AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
- cricket::MD_RECVONLY, kActive, &options);
- AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::MD_RECVONLY, kActive, &options);
- options.bundle_enabled = true;
-
- std::unique_ptr<SessionDescriptionInterface> temp_offer(
- CreateRemoteOffer(options, cricket::SEC_ENABLED));
-
- *nodtls_answer =
- CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
- EXPECT_TRUE(*nodtls_answer != NULL);
- VerifyFingerprintStatus((*nodtls_answer)->description(), false);
- VerifyCryptoParams((*nodtls_answer)->description());
-
- SetFactoryDtlsSrtp();
- *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
- ASSERT_TRUE(*offer != NULL);
- VerifyFingerprintStatus((*offer)->description(), true);
- VerifyCryptoParams((*offer)->description());
- }
-
JsepSessionDescription* CreateRemoteOfferWithVersion(
cricket::MediaSessionOptions options,
cricket::SecurePolicy secure_policy,
@@ -1585,74 +1364,6 @@
SetLocalDescriptionWithoutError(offer);
}
- void VerifyMultipleAsyncCreateDescription(
- RTCCertificateGenerationMethod cert_gen_method,
- CreateSessionDescriptionRequest::Type type) {
- InitWithDtls(cert_gen_method);
- VerifyMultipleAsyncCreateDescriptionAfterInit(true, type);
- }
-
- void VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
- CreateSessionDescriptionRequest::Type type) {
- InitWithDtlsIdentityGenFail();
- VerifyMultipleAsyncCreateDescriptionAfterInit(false, type);
- }
-
- void VerifyMultipleAsyncCreateDescriptionAfterInit(
- bool success, CreateSessionDescriptionRequest::Type type) {
- RTC_CHECK(session_);
- SetFactoryDtlsSrtp();
- if (type == CreateSessionDescriptionRequest::kAnswer) {
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- std::unique_ptr<JsepSessionDescription> offer(
- CreateRemoteOffer(options, cricket::SEC_DISABLED));
- ASSERT_TRUE(offer.get() != NULL);
- SetRemoteDescriptionWithoutError(offer.release());
- }
-
- PeerConnectionInterface::RTCOfferAnswerOptions options;
- cricket::MediaSessionOptions offer_session_options;
- cricket::MediaSessionOptions answer_session_options;
- GetOptionsForOffer(options, &offer_session_options);
- GetOptionsForAnswer(&answer_session_options);
- const int kNumber = 3;
- rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
- observers[kNumber];
- for (int i = 0; i < kNumber; ++i) {
- observers[i] = new WebRtcSessionCreateSDPObserverForTest();
- if (type == CreateSessionDescriptionRequest::kOffer) {
- session_->CreateOffer(observers[i], options, offer_session_options);
- } else {
- session_->CreateAnswer(observers[i], answer_session_options);
- }
- }
-
- WebRtcSessionCreateSDPObserverForTest::State expected_state =
- success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
- WebRtcSessionCreateSDPObserverForTest::kFailed;
-
- for (int i = 0; i < kNumber; ++i) {
- EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
- if (success) {
- EXPECT_TRUE(observers[i]->description() != NULL);
- } else {
- EXPECT_TRUE(observers[i]->description() == NULL);
- }
- }
- }
-
- void ConfigureAllocatorWithTurn() {
- cricket::RelayServerConfig turn_server(cricket::RELAY_TURN);
- cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
- turn_server.credentials = credentials;
- turn_server.ports.push_back(
- cricket::ProtocolAddress(kTurnUdpIntAddr, cricket::PROTO_UDP));
- allocator_->AddTurnServer(turn_server);
- allocator_->set_step_delay(cricket::kMinimumStepDelay);
- allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP);
- }
-
webrtc::RtcEventLogNullImpl event_log_;
std::unique_ptr<rtc::VirtualSocketServer> vss_;
std::unique_ptr<rtc::FirewallSocketServer> fss_;
@@ -1669,7 +1380,6 @@
std::unique_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
rtc::SocketAddress stun_socket_addr_;
std::unique_ptr<cricket::TestStunServer> stun_server_;
- cricket::TestTurnServer turn_server_;
rtc::FakeNetworkManager network_manager_;
std::unique_ptr<cricket::BasicPortAllocator> allocator_;
PeerConnectionFactoryInterface::Options options_;
@@ -1698,18 +1408,6 @@
rtc::CryptoOptions crypto_options_;
};
-TEST_P(WebRtcSessionTest, TestInitializeWithDtls) {
- InitWithDtls(GetParam());
- // SDES is disabled when DTLS is on.
- EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
-}
-
-TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
- Init();
- // SDES is required if DTLS is off.
- EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
-}
-
TEST_F(WebRtcSessionTest, TestSessionCandidates) {
TestSessionCandidatesWithBundleRtcpMux(false, false);
}
@@ -1827,12 +1525,10 @@
Init();
SendAudioVideoStream2();
SessionDescriptionInterface* offer = CreateOffer();
- VerifyCryptoParams(offer->description());
SetRemoteDescriptionWithoutError(offer);
SendAudioVideoStream1();
SessionDescriptionInterface* answer = CreateAnswer();
- VerifyCryptoParams(answer->description());
SetLocalDescriptionWithoutError(answer);
const std::string session_id_orig = answer->session_id();
@@ -1895,255 +1591,6 @@
SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
}
-//
-// Tests for creating/setting SDP under different SDES/DTLS polices:
-//
-// --DTLS off and SDES on
-// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
-// set local/remote offer/answer with crypto --> success
-// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
-// failure
-// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
-// failure
-// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
-// failure
-//
-// --DTLS on and SDES off
-// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
-// set local/remote offer/answer with DTLS fingerprint --> success
-// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
-// fingerprint --> failure
-// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
-// --> failure
-// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
-// --> failure
-//
-// --Encryption disabled: DTLS off and SDES off
-// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
-// answer without SDES or DTLS --> success
-// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
-// answer without SDES or DTLS --> success
-//
-
-// Test that we return a failure when applying a remote/local offer that doesn't
-// have cryptos enabled when DTLS is off.
-TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
- Init();
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- JsepSessionDescription* offer = CreateRemoteOffer(
- options, cricket::SEC_DISABLED);
- ASSERT_TRUE(offer != NULL);
- VerifyNoCryptoParams(offer->description(), false);
- // SetRemoteDescription and SetLocalDescription will take the ownership of
- // the offer.
- SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
- offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
- ASSERT_TRUE(offer != NULL);
- SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
-}
-
-// Test that we return a failure when applying a local answer that doesn't have
-// cryptos enabled when DTLS is off.
-TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
- Init();
- SessionDescriptionInterface* offer = NULL;
- SessionDescriptionInterface* answer = NULL;
- CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
- // SetRemoteDescription and SetLocalDescription will take the ownership of
- // the offer.
- SetRemoteDescriptionWithoutError(offer);
- SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
-}
-
-// Test we will return fail when apply an remote answer that doesn't have
-// crypto enabled when DTLS is off.
-TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
- Init();
- SessionDescriptionInterface* offer = NULL;
- SessionDescriptionInterface* answer = NULL;
- CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
- // SetRemoteDescription and SetLocalDescription will take the ownership of
- // the offer.
- SetLocalDescriptionWithoutError(offer);
- SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
-}
-
-// Test that we accept an offer with a DTLS fingerprint when DTLS is on
-// and that we return an answer with a DTLS fingerprint.
-TEST_P(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
- SendAudioVideoStream1();
- InitWithDtls(GetParam());
- SetFactoryDtlsSrtp();
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- JsepSessionDescription* offer =
- CreateRemoteOffer(options, cricket::SEC_DISABLED);
- ASSERT_TRUE(offer != NULL);
- VerifyFingerprintStatus(offer->description(), true);
- VerifyNoCryptoParams(offer->description(), true);
-
- // SetRemoteDescription will take the ownership of the offer.
- SetRemoteDescriptionWithoutError(offer);
-
- // Verify that we get a crypto fingerprint in the answer.
- SessionDescriptionInterface* answer = CreateAnswer();
- ASSERT_TRUE(answer != NULL);
- VerifyFingerprintStatus(answer->description(), true);
- // Check that we don't have an a=crypto line in the answer.
- VerifyNoCryptoParams(answer->description(), true);
-
- // Now set the local description, which should work, even without a=crypto.
- SetLocalDescriptionWithoutError(answer);
-}
-
-// Test that we set a local offer with a DTLS fingerprint when DTLS is on
-// and then we accept a remote answer with a DTLS fingerprint successfully.
-TEST_P(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
- SendAudioVideoStream1();
- InitWithDtls(GetParam());
- SetFactoryDtlsSrtp();
-
- // Verify that we get a crypto fingerprint in the answer.
- SessionDescriptionInterface* offer = CreateOffer();
- ASSERT_TRUE(offer != NULL);
- VerifyFingerprintStatus(offer->description(), true);
- // Check that we don't have an a=crypto line in the offer.
- VerifyNoCryptoParams(offer->description(), true);
-
- // Now set the local description, which should work, even without a=crypto.
- SetLocalDescriptionWithoutError(offer);
-
- cricket::MediaSessionOptions options;
- GetOptionsForAnswer(&options);
- JsepSessionDescription* answer =
- CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
- ASSERT_TRUE(answer != NULL);
- VerifyFingerprintStatus(answer->description(), true);
- VerifyNoCryptoParams(answer->description(), true);
-
- // SetRemoteDescription will take the ownership of the answer.
- SetRemoteDescriptionWithoutError(answer);
-}
-
-// Test that if we support DTLS and the other side didn't offer a fingerprint,
-// we will fail to set the remote description.
-TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
- InitWithDtls(GetParam());
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- options.bundle_enabled = true;
- JsepSessionDescription* offer = CreateRemoteOffer(
- options, cricket::SEC_REQUIRED);
- ASSERT_TRUE(offer != NULL);
- VerifyFingerprintStatus(offer->description(), false);
- VerifyCryptoParams(offer->description());
-
- // SetRemoteDescription will take the ownership of the offer.
- SetRemoteDescriptionOfferExpectError(
- kSdpWithoutDtlsFingerprint, offer);
-
- offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
- // SetLocalDescription will take the ownership of the offer.
- SetLocalDescriptionOfferExpectError(
- kSdpWithoutDtlsFingerprint, offer);
-}
-
-// Test that we return a failure when applying a local answer that doesn't have
-// a DTLS fingerprint when DTLS is required.
-TEST_P(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
- InitWithDtls(GetParam());
- SessionDescriptionInterface* offer = NULL;
- SessionDescriptionInterface* answer = NULL;
- CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
-
- // SetRemoteDescription and SetLocalDescription will take the ownership of
- // the offer and answer.
- SetRemoteDescriptionWithoutError(offer);
- SetLocalDescriptionAnswerExpectError(
- kSdpWithoutDtlsFingerprint, answer);
-}
-
-// Test that we return a failure when applying a remote answer that doesn't have
-// a DTLS fingerprint when DTLS is required.
-TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
- InitWithDtls(GetParam());
- SessionDescriptionInterface* offer = CreateOffer();
- cricket::MediaSessionOptions offer_options;
- GetOptionsForRemoteOffer(&offer_options);
-
- std::unique_ptr<SessionDescriptionInterface> temp_offer(
- CreateRemoteOffer(offer_options, cricket::SEC_ENABLED));
-
- cricket::MediaSessionOptions answer_options;
- GetOptionsForAnswer(&answer_options);
- JsepSessionDescription* answer = CreateRemoteAnswer(
- temp_offer.get(), answer_options, cricket::SEC_ENABLED);
-
- // SetRemoteDescription and SetLocalDescription will take the ownership of
- // the offer and answer.
- SetLocalDescriptionWithoutError(offer);
- SetRemoteDescriptionAnswerExpectError(
- kSdpWithoutDtlsFingerprint, answer);
-}
-
-// Test that we create a local offer without SDES or DTLS and accept a remote
-// answer without SDES or DTLS when encryption is disabled.
-TEST_P(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
- SendAudioVideoStream1();
- options_.disable_encryption = true;
- InitWithDtls(GetParam());
-
- // Verify that we get a crypto fingerprint in the answer.
- SessionDescriptionInterface* offer = CreateOffer();
- ASSERT_TRUE(offer != NULL);
- VerifyFingerprintStatus(offer->description(), false);
- // Check that we don't have an a=crypto line in the offer.
- VerifyNoCryptoParams(offer->description(), false);
-
- // Now set the local description, which should work, even without a=crypto.
- SetLocalDescriptionWithoutError(offer);
-
- cricket::MediaSessionOptions options;
- GetOptionsForAnswer(&options);
- JsepSessionDescription* answer =
- CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
- ASSERT_TRUE(answer != NULL);
- VerifyFingerprintStatus(answer->description(), false);
- VerifyNoCryptoParams(answer->description(), false);
-
- // SetRemoteDescription will take the ownership of the answer.
- SetRemoteDescriptionWithoutError(answer);
-}
-
-// Test that we create a local answer without SDES or DTLS and accept a remote
-// offer without SDES or DTLS when encryption is disabled.
-TEST_P(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
- options_.disable_encryption = true;
- InitWithDtls(GetParam());
-
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- JsepSessionDescription* offer =
- CreateRemoteOffer(options, cricket::SEC_DISABLED);
- ASSERT_TRUE(offer != NULL);
- VerifyFingerprintStatus(offer->description(), false);
- VerifyNoCryptoParams(offer->description(), false);
-
- // SetRemoteDescription will take the ownership of the offer.
- SetRemoteDescriptionWithoutError(offer);
-
- // Verify that we get a crypto fingerprint in the answer.
- SessionDescriptionInterface* answer = CreateAnswer();
- ASSERT_TRUE(answer != NULL);
- VerifyFingerprintStatus(answer->description(), false);
- // Check that we don't have an a=crypto line in the answer.
- VerifyNoCryptoParams(answer->description(), false);
-
- // Now set the local description, which should work, even without a=crypto.
- SetLocalDescriptionWithoutError(answer);
-}
-
// Test that we can create and set an answer correctly when different
// SSL roles have been negotiated for different transports.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4525
@@ -3041,44 +2488,6 @@
EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
}
-TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
- Init();
- SendAudioVideoStream1();
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
- VerifyCryptoParams(offer->description());
- SetRemoteDescriptionWithoutError(offer.release());
- std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
- VerifyCryptoParams(answer->description());
-}
-
-TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDPGcm) {
- InitWithGcm();
- SendAudioVideoStream1();
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
- VerifyCryptoParams(offer->description(), true);
- SetRemoteDescriptionWithoutError(offer.release());
- std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
- VerifyCryptoParams(answer->description(), true);
-}
-
-TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
- options_.disable_encryption = true;
- Init();
- SendAudioVideoStream1();
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
- VerifyNoCryptoParams(offer->description(), false);
-}
-
-TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
- Init();
- VerifyAnswerFromNonCryptoOffer();
-}
-
-TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
- Init();
- VerifyAnswerFromCryptoOffer();
-}
-
// This test verifies that setLocalDescription fails if
// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
@@ -3692,12 +3101,6 @@
SetLocalDescriptionWithoutError(offer);
}
-TEST_F(WebRtcSessionTest, SetSetupGcm) {
- InitWithGcm();
- SendAudioVideoStream1();
- CreateAndSetRemoteOfferAndLocalAnswer();
-}
-
// This test verifies the |initial_offerer| flag when session initiates the
// call.
TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
@@ -3825,44 +3228,6 @@
EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
}
-// This test verifies that crypto parameter is updated in local session
-// description as per security policy set in MediaSessionDescriptionFactory.
-TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
- Init();
- SendAudioVideoStream1();
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
-
- // Making sure SetLocalDescription correctly sets crypto value in
- // SessionDescription object after de-serialization of sdp string. The value
- // will be set as per MediaSessionDescriptionFactory.
- std::string offer_str;
- offer->ToString(&offer_str);
- SessionDescriptionInterface* jsep_offer_str =
- CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
- SetLocalDescriptionWithoutError(jsep_offer_str);
- EXPECT_TRUE(session_->voice_channel()->srtp_required_for_testing());
- EXPECT_TRUE(session_->video_channel()->srtp_required_for_testing());
-}
-
-// This test verifies the crypto parameter when security is disabled.
-TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
- options_.disable_encryption = true;
- Init();
- SendAudioVideoStream1();
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
-
- // Making sure SetLocalDescription correctly sets crypto value in
- // SessionDescription object after de-serialization of sdp string. The value
- // will be set as per MediaSessionDescriptionFactory.
- std::string offer_str;
- offer->ToString(&offer_str);
- SessionDescriptionInterface* jsep_offer_str =
- CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
- SetLocalDescriptionWithoutError(jsep_offer_str);
- EXPECT_FALSE(session_->voice_channel()->srtp_required_for_testing());
- EXPECT_FALSE(session_->video_channel()->srtp_required_for_testing());
-}
-
// This test verifies that an answer contains new ufrag and password if an offer
// with new ufrag and password is received.
TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
@@ -4243,129 +3608,6 @@
last_data_channel_config_.open_handshake_role);
}
-TEST_P(WebRtcSessionTest, TestUsesProvidedCertificate) {
- rtc::scoped_refptr<rtc::RTCCertificate> certificate =
- FakeRTCCertificateGenerator::GenerateCertificate();
-
- configuration_.certificates.push_back(certificate);
- Init();
- EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
-
- EXPECT_EQ(session_->certificate_for_testing(), certificate);
-}
-
-// Verifies that CreateOffer succeeds when CreateOffer is called before async
-// identity generation is finished (even if a certificate is provided this is
-// an async op).
-TEST_P(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
- InitWithDtls(GetParam());
-
- EXPECT_TRUE(session_->waiting_for_certificate_for_testing());
- SendAudioVideoStream1();
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
-
- EXPECT_TRUE(offer != NULL);
- VerifyNoCryptoParams(offer->description(), true);
- VerifyFingerprintStatus(offer->description(), true);
-}
-
-// Verifies that CreateAnswer succeeds when CreateOffer is called before async
-// identity generation is finished (even if a certificate is provided this is
-// an async op).
-TEST_P(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
- InitWithDtls(GetParam());
- SetFactoryDtlsSrtp();
-
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- std::unique_ptr<JsepSessionDescription> offer(
- CreateRemoteOffer(options, cricket::SEC_DISABLED));
- ASSERT_TRUE(offer.get() != NULL);
- SetRemoteDescriptionWithoutError(offer.release());
-
- std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer());
- EXPECT_TRUE(answer != NULL);
- VerifyNoCryptoParams(answer->description(), true);
- VerifyFingerprintStatus(answer->description(), true);
-}
-
-// Verifies that CreateOffer succeeds when CreateOffer is called after async
-// identity generation is finished (even if a certificate is provided this is
-// an async op).
-TEST_P(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
- InitWithDtls(GetParam());
-
- EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
-
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
- EXPECT_TRUE(offer != NULL);
-}
-
-// Verifies that CreateOffer fails when CreateOffer is called after async
-// identity generation fails.
-TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
- InitWithDtlsIdentityGenFail();
-
- EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
-
- std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer());
- EXPECT_TRUE(offer == NULL);
-}
-
-// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
-// before async identity generation is finished.
-TEST_P(WebRtcSessionTest,
- TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
- VerifyMultipleAsyncCreateDescription(GetParam(),
- CreateSessionDescriptionRequest::kOffer);
-}
-
-// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
-// before async identity generation fails.
-TEST_F(WebRtcSessionTest,
- TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
- VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
- CreateSessionDescriptionRequest::kOffer);
-}
-
-// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
-// before async identity generation is finished.
-TEST_P(WebRtcSessionTest,
- TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
- VerifyMultipleAsyncCreateDescription(
- GetParam(), CreateSessionDescriptionRequest::kAnswer);
-}
-
-// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
-// before async identity generation fails.
-TEST_F(WebRtcSessionTest,
- TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
- VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
- CreateSessionDescriptionRequest::kAnswer);
-}
-
-// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
-// offer has no SDES crypto but only DTLS fingerprint.
-TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
- // Init without DTLS.
- Init();
- // Create a remote offer with secured transport disabled.
- cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
- JsepSessionDescription* offer(CreateRemoteOffer(
- options, cricket::SEC_DISABLED));
- // Adds a DTLS fingerprint to the remote offer.
- cricket::SessionDescription* sdp = offer->description();
- TransportInfo* audio = sdp->GetTransportInfoByName("audio");
- ASSERT_TRUE(audio != NULL);
- ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
- audio->description.identity_fingerprint.reset(
- rtc::SSLFingerprint::CreateFromRfc4572(
- rtc::DIGEST_SHA_256, kFakeDtlsFingerprint));
- SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
- offer);
-}
-
TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) {
configuration_.combined_audio_video_bwe = rtc::Optional<bool>(true);
Init();