| Index: webrtc/p2p/base/jseptransport_unittest.cc
|
| diff --git a/webrtc/p2p/base/jseptransport_unittest.cc b/webrtc/p2p/base/jseptransport_unittest.cc
|
| index ccb7016e0531f82a2b5c8376772813a3f3484dfd..23ed4d857df70378cdc5d90eef8ca19040886cb1 100644
|
| --- a/webrtc/p2p/base/jseptransport_unittest.cc
|
| +++ b/webrtc/p2p/base/jseptransport_unittest.cc
|
| @@ -32,16 +32,21 @@ static const char kIcePwd2[] = "TESTICEPWD00000000000002";
|
|
|
| class JsepTransportTest : public testing::Test, public sigslot::has_slots<> {
|
| public:
|
| - JsepTransportTest()
|
| - : transport_(new JsepTransport("test content name", nullptr)) {}
|
| + JsepTransportTest() { RecreateTransport(); }
|
| +
|
| bool SetupChannel() {
|
| fake_ice_transport_.reset(new FakeIceTransport(transport_->mid(), 1));
|
| fake_dtls_transport_.reset(
|
| new FakeDtlsTransport(fake_ice_transport_.get()));
|
| return transport_->AddChannel(fake_dtls_transport_.get(), 1);
|
| }
|
| +
|
| void DestroyChannel() { transport_->RemoveChannel(1); }
|
|
|
| + void RecreateTransport() {
|
| + transport_.reset(new JsepTransport("test content name", nullptr));
|
| + }
|
| +
|
| protected:
|
| std::unique_ptr<FakeDtlsTransport> fake_dtls_transport_;
|
| std::unique_ptr<FakeIceTransport> fake_ice_transport_;
|
| @@ -167,10 +172,22 @@ TEST_F(JsepTransportTest, TestVerifyCertificateFingerprint) {
|
| }
|
| }
|
|
|
| -// Tests that NegotiateRole sets the SSL role correctly.
|
| -TEST_F(JsepTransportTest, TestNegotiateRole) {
|
| +// Tests the logic of DTLS role negotiation for an initial offer/answer.
|
| +TEST_F(JsepTransportTest, DtlsRoleNegotiation) {
|
| + rtc::scoped_refptr<rtc::RTCCertificate> certificate =
|
| + rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
| + rtc::SSLIdentity::Generate("testing", rtc::KT_ECDSA)));
|
| + std::unique_ptr<rtc::SSLFingerprint> fingerprint(
|
| + rtc::SSLFingerprint::CreateFromCertificate(certificate));
|
| +
|
| TransportDescription local_desc(kIceUfrag1, kIcePwd1);
|
| TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
|
| + // Just use the same fingerprint in both descriptions; the remote fingerprint
|
| + // doesn't matter in a non end-to-end test.
|
| + local_desc.identity_fingerprint.reset(
|
| + TransportDescription::CopyFingerprint(fingerprint.get()));
|
| + remote_desc.identity_fingerprint.reset(
|
| + TransportDescription::CopyFingerprint(fingerprint.get()));
|
|
|
| struct NegotiateRoleParams {
|
| cricket::ConnectionRole local_role;
|
| @@ -179,7 +196,6 @@ TEST_F(JsepTransportTest, TestNegotiateRole) {
|
| cricket::ContentAction remote_action;
|
| };
|
|
|
| - rtc::SSLRole ssl_role;
|
| std::string error_desc;
|
|
|
| // Parameters which set the SSL role to SSL_CLIENT.
|
| @@ -194,16 +210,25 @@ TEST_F(JsepTransportTest, TestNegotiateRole) {
|
| cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
|
|
| for (auto& param : valid_client_params) {
|
| + RecreateTransport();
|
| + transport_->SetLocalCertificate(certificate);
|
| +
|
| local_desc.connection_role = param.local_role;
|
| remote_desc.connection_role = param.remote_role;
|
|
|
| - ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
| - remote_desc, param.remote_action, nullptr));
|
| - ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
| - local_desc, param.local_action, nullptr));
|
| - EXPECT_TRUE(
|
| - transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
| - EXPECT_EQ(rtc::SSL_CLIENT, ssl_role);
|
| + // Set the offer first.
|
| + if (param.local_action == cricket::CA_OFFER) {
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + } else {
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + }
|
| + EXPECT_EQ(rtc::SSL_CLIENT, *transport_->GetSslRole());
|
| }
|
|
|
| // Parameters which set the SSL role to SSL_SERVER.
|
| @@ -218,16 +243,25 @@ TEST_F(JsepTransportTest, TestNegotiateRole) {
|
| cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
|
|
| for (auto& param : valid_server_params) {
|
| + RecreateTransport();
|
| + transport_->SetLocalCertificate(certificate);
|
| +
|
| local_desc.connection_role = param.local_role;
|
| remote_desc.connection_role = param.remote_role;
|
|
|
| - ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
| - remote_desc, param.remote_action, nullptr));
|
| - ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
| - local_desc, param.local_action, nullptr));
|
| - EXPECT_TRUE(
|
| - transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
| - EXPECT_EQ(rtc::SSL_SERVER, ssl_role);
|
| + // Set the offer first.
|
| + if (param.local_action == cricket::CA_OFFER) {
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + } else {
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + }
|
| + EXPECT_EQ(rtc::SSL_SERVER, *transport_->GetSslRole());
|
| }
|
|
|
| // Invalid parameters due to both peers having a duplicate role.
|
| @@ -258,15 +292,24 @@ TEST_F(JsepTransportTest, TestNegotiateRole) {
|
| cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
|
|
| for (auto& param : duplicate_params) {
|
| + RecreateTransport();
|
| + transport_->SetLocalCertificate(certificate);
|
| +
|
| local_desc.connection_role = param.local_role;
|
| remote_desc.connection_role = param.remote_role;
|
|
|
| - ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
| - remote_desc, param.remote_action, nullptr));
|
| - ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
| - local_desc, param.local_action, nullptr));
|
| - EXPECT_FALSE(
|
| - transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
| + // Set the offer first.
|
| + if (param.local_action == cricket::CA_OFFER) {
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + EXPECT_FALSE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + } else {
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + EXPECT_FALSE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + }
|
| }
|
|
|
| // Invalid parameters due to the offerer not using ACTPASS.
|
| @@ -297,14 +340,113 @@ TEST_F(JsepTransportTest, TestNegotiateRole) {
|
| cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
|
|
| for (auto& param : offerer_without_actpass_params) {
|
| + RecreateTransport();
|
| + transport_->SetLocalCertificate(certificate);
|
| +
|
| local_desc.connection_role = param.local_role;
|
| remote_desc.connection_role = param.remote_role;
|
|
|
| - ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
| - remote_desc, param.remote_action, nullptr));
|
| - ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
| - local_desc, param.local_action, nullptr));
|
| - EXPECT_FALSE(
|
| - transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
| + // Set the offer first.
|
| + // TODO(deadbeef): Really this should fail as soon as the offer is
|
| + // attempted to be applied, and not when the answer is applied.
|
| + if (param.local_action == cricket::CA_OFFER) {
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + EXPECT_FALSE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + } else {
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, param.remote_action, nullptr));
|
| + EXPECT_FALSE(transport_->SetLocalTransportDescription(
|
| + local_desc, param.local_action, nullptr));
|
| + }
|
| }
|
| }
|
| +
|
| +// Test that a remote offer with the current negotiated role can be accepted.
|
| +// This is allowed by dtls-sdp, though we'll never generate such an offer,
|
| +// since JSEP requires generating "actpass".
|
| +TEST_F(JsepTransportTest, RemoteOfferWithCurrentNegotiatedDtlsRole) {
|
| + rtc::scoped_refptr<rtc::RTCCertificate> certificate =
|
| + rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
| + rtc::SSLIdentity::Generate("testing", rtc::KT_ECDSA)));
|
| + std::unique_ptr<rtc::SSLFingerprint> fingerprint(
|
| + rtc::SSLFingerprint::CreateFromCertificate(certificate));
|
| + transport_->SetLocalCertificate(certificate);
|
| +
|
| + TransportDescription local_desc(kIceUfrag1, kIcePwd1);
|
| + TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
|
| + // Just use the same fingerprint in both descriptions; the remote fingerprint
|
| + // doesn't matter in a non end-to-end test.
|
| + local_desc.identity_fingerprint.reset(
|
| + TransportDescription::CopyFingerprint(fingerprint.get()));
|
| + remote_desc.identity_fingerprint.reset(
|
| + TransportDescription::CopyFingerprint(fingerprint.get()));
|
| +
|
| + remote_desc.connection_role = cricket::CONNECTIONROLE_ACTPASS;
|
| + local_desc.connection_role = cricket::CONNECTIONROLE_ACTIVE;
|
| +
|
| + // Normal initial offer/answer with "actpass" in the offer and "active" in
|
| + // the answer.
|
| + ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, cricket::CA_OFFER, nullptr));
|
| + ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, cricket::CA_ANSWER, nullptr));
|
| +
|
| + // Sanity check that role was actually negotiated.
|
| + rtc::Optional<rtc::SSLRole> role = transport_->GetSslRole();
|
| + ASSERT_TRUE(role);
|
| + EXPECT_EQ(rtc::SSL_CLIENT, *role);
|
| +
|
| + // Subsequent offer with current negotiated role of "passive".
|
| + remote_desc.connection_role = cricket::CONNECTIONROLE_PASSIVE;
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, cricket::CA_OFFER, nullptr));
|
| + EXPECT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, cricket::CA_ANSWER, nullptr));
|
| +}
|
| +
|
| +// Test that a remote offer with the inverse of the current negotiated DTLS
|
| +// role is rejected.
|
| +TEST_F(JsepTransportTest, RemoteOfferThatChangesNegotiatedDtlsRole) {
|
| + rtc::scoped_refptr<rtc::RTCCertificate> certificate =
|
| + rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
| + rtc::SSLIdentity::Generate("testing", rtc::KT_ECDSA)));
|
| + std::unique_ptr<rtc::SSLFingerprint> fingerprint(
|
| + rtc::SSLFingerprint::CreateFromCertificate(certificate));
|
| + transport_->SetLocalCertificate(certificate);
|
| +
|
| + TransportDescription local_desc(kIceUfrag1, kIcePwd1);
|
| + TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
|
| + // Just use the same fingerprint in both descriptions; the remote fingerprint
|
| + // doesn't matter in a non end-to-end test.
|
| + local_desc.identity_fingerprint.reset(
|
| + TransportDescription::CopyFingerprint(fingerprint.get()));
|
| + remote_desc.identity_fingerprint.reset(
|
| + TransportDescription::CopyFingerprint(fingerprint.get()));
|
| +
|
| + remote_desc.connection_role = cricket::CONNECTIONROLE_ACTPASS;
|
| + local_desc.connection_role = cricket::CONNECTIONROLE_ACTIVE;
|
| +
|
| + // Normal initial offer/answer with "actpass" in the offer and "active" in
|
| + // the answer.
|
| + ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, cricket::CA_OFFER, nullptr));
|
| + ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
| + local_desc, cricket::CA_ANSWER, nullptr));
|
| +
|
| + // Sanity check that role was actually negotiated.
|
| + rtc::Optional<rtc::SSLRole> role = transport_->GetSslRole();
|
| + ASSERT_TRUE(role);
|
| + EXPECT_EQ(rtc::SSL_CLIENT, *role);
|
| +
|
| + // Subsequent offer with "active", which is the opposite of the remote
|
| + // endpoint's negotiated role.
|
| + // TODO(deadbeef): Really this should fail as soon as the offer is
|
| + // attempted to be applied, and not when the answer is applied.
|
| + remote_desc.connection_role = cricket::CONNECTIONROLE_ACTIVE;
|
| + EXPECT_TRUE(transport_->SetRemoteTransportDescription(
|
| + remote_desc, cricket::CA_OFFER, nullptr));
|
| + EXPECT_FALSE(transport_->SetLocalTransportDescription(
|
| + local_desc, cricket::CA_ANSWER, nullptr));
|
| +}
|
|
|