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}
This commit is contained in:
parent
97a9f76bce
commit
6b63cd5e54
@ -391,6 +391,7 @@ if (rtc_include_tests) {
|
||||
"localaudiosource_unittest.cc",
|
||||
"mediaconstraintsinterface_unittest.cc",
|
||||
"mediastream_unittest.cc",
|
||||
"peerconnection_crypto_unittest.cc",
|
||||
"peerconnection_integrationtest.cc",
|
||||
"peerconnectionendtoend_unittest.cc",
|
||||
"peerconnectionfactory_unittest.cc",
|
||||
|
||||
@ -185,9 +185,6 @@ class BaseChannel
|
||||
|
||||
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.
|
||||
|
||||
605
pc/peerconnection_crypto_unittest.cc
Normal file
605
pc/peerconnection_crypto_unittest.cc
Normal file
@ -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
|
||||
@ -125,16 +125,21 @@ class FakeRTCCertificateGenerator
|
||||
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 @@ class FakeRTCCertificateGenerator
|
||||
|
||||
// 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 @@ class FakeRTCCertificateGenerator
|
||||
break;
|
||||
}
|
||||
case MSG_FAILURE:
|
||||
++generated_failures_;
|
||||
callback->OnFailure();
|
||||
break;
|
||||
}
|
||||
@ -224,8 +238,10 @@ class FakeRTCCertificateGenerator
|
||||
}
|
||||
|
||||
bool should_fail_;
|
||||
bool should_wait_;
|
||||
int key_index_ = 0;
|
||||
int generated_certificates_ = 0;
|
||||
int generated_failures_ = 0;
|
||||
};
|
||||
|
||||
#endif // PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_
|
||||
|
||||
@ -667,10 +667,6 @@ cricket::BaseChannel* WebRtcSession::GetChannel(
|
||||
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 "
|
||||
|
||||
@ -241,8 +241,6 @@ class WebRtcSession :
|
||||
|
||||
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).
|
||||
|
||||
@ -81,10 +81,6 @@ static const char kClientIPv6AddrHost1[] =
|
||||
"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 char kMediaContentName1[] = "video";
|
||||
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 @@ class WebRtcSessionCreateSDPObserverForTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ class WebRtcSessionTest
|
||||
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 @@ TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
|
||||
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 @@ TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
|
||||
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 @@ TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
|
||||
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 @@ TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
|
||||
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 @@ TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
|
||||
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 @@ TEST_P(WebRtcSessionTest, TestSctpDataChannelOpenMessage) {
|
||||
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();
|
||||
|
||||
@ -4,4 +4,5 @@ DtmfSenderTest.*
|
||||
PeerConnectionIntegrationTest.*
|
||||
PeerConnectionEndToEndTest.*
|
||||
PeerConnectionInterfaceTest.*
|
||||
PeerConnectionCryptoUnitTest.*
|
||||
RTCStatsIntegrationTest.*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user