/* * Copyright 2016 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 "webrtc/p2p/quic/quictransport.h" #include #include #include #include "webrtc/base/gunit.h" #include "webrtc/base/rtccertificate.h" #include "webrtc/base/sslidentity.h" using cricket::TransportChannelImpl; using cricket::QuicTransport; using cricket::Transport; using cricket::TransportDescription; static const char kIceUfrag1[] = "TESTICEUFRAG0001"; static const char kIcePwd1[] = "TESTICEPWD00000000000001"; static const char kIceUfrag2[] = "TESTICEUFRAG0002"; static const char kIcePwd2[] = "TESTICEPWD00000000000002"; static rtc::scoped_refptr CreateCertificate( std::string name) { return rtc::RTCCertificate::Create(std::unique_ptr( rtc::SSLIdentity::Generate(name, rtc::KT_DEFAULT))); } static std::unique_ptr CreateFingerprint( rtc::RTCCertificate* cert) { std::string digest_algorithm; cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm); return std::unique_ptr( rtc::SSLFingerprint::Create(digest_algorithm, cert->identity())); } class QuicTransportTest : public testing::Test { public: QuicTransportTest() : transport_("testing", nullptr, nullptr) {} void SetTransportDescription(cricket::ConnectionRole local_role, cricket::ConnectionRole remote_role, cricket::ContentAction local_action, cricket::ContentAction remote_action, rtc::SSLRole expected_ssl_role) { TransportChannelImpl* channel = transport_.CreateChannel(1); ASSERT_NE(nullptr, channel); rtc::scoped_refptr local_certificate( CreateCertificate("local")); ASSERT_NE(nullptr, local_certificate); transport_.SetLocalCertificate(local_certificate); std::unique_ptr local_fingerprint = CreateFingerprint(local_certificate.get()); ASSERT_NE(nullptr, local_fingerprint); TransportDescription local_desc(std::vector(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, local_role, local_fingerprint.get()); ASSERT_TRUE(transport_.SetLocalTransportDescription(local_desc, local_action, nullptr)); // The certificate is applied to QuicTransportChannel when the local // description is set. rtc::scoped_refptr channel_local_certificate = channel->GetLocalCertificate(); ASSERT_NE(nullptr, channel_local_certificate); EXPECT_EQ(local_certificate, channel_local_certificate); std::unique_ptr remote_fingerprint = CreateFingerprint(CreateCertificate("remote").get()); // NegotiateTransportDescription was not called yet. The SSL role should // not be set and neither should the remote fingerprint. std::unique_ptr role(new rtc::SSLRole()); EXPECT_FALSE(channel->GetSslRole(role.get())); // Setting the remote description should set the SSL role. ASSERT_NE(nullptr, remote_fingerprint); TransportDescription remote_desc(std::vector(), kIceUfrag2, kIcePwd2, cricket::ICEMODE_FULL, remote_role, remote_fingerprint.get()); ASSERT_TRUE(transport_.SetRemoteTransportDescription( remote_desc, remote_action, nullptr)); ASSERT_TRUE(channel->GetSslRole(role.get())); // SSL role should be client because the remote description is an ANSWER. EXPECT_EQ(expected_ssl_role, *role); } protected: QuicTransport transport_; }; // Test setting the local certificate. TEST_F(QuicTransportTest, SetLocalCertificate) { rtc::scoped_refptr local_certificate( CreateCertificate("local")); ASSERT_NE(nullptr, local_certificate); rtc::scoped_refptr transport_local_certificate; EXPECT_FALSE(transport_.GetLocalCertificate(&transport_local_certificate)); transport_.SetLocalCertificate(local_certificate); ASSERT_TRUE(transport_.GetLocalCertificate(&transport_local_certificate)); ASSERT_NE(nullptr, transport_local_certificate); EXPECT_EQ(local_certificate, transport_local_certificate); } // Test setting the ICE role. TEST_F(QuicTransportTest, SetIceRole) { TransportChannelImpl* channel1 = transport_.CreateChannel(1); ASSERT_NE(nullptr, channel1); transport_.SetIceRole(cricket::ICEROLE_CONTROLLING); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_.ice_role()); TransportChannelImpl* channel2 = transport_.CreateChannel(2); ASSERT_NE(nullptr, channel2); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole()); EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole()); } // Test setting the ICE tie breaker. TEST_F(QuicTransportTest, SetIceTiebreaker) { transport_.SetIceTiebreaker(1u); EXPECT_EQ(1u, transport_.IceTiebreaker()); } // Test setting the local and remote descriptions for a SSL client. TEST_F(QuicTransportTest, SetLocalAndRemoteTransportDescriptionClient) { SetTransportDescription(cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE, cricket::CA_OFFER, cricket::CA_ANSWER, rtc::SSL_CLIENT); } // Test setting the local and remote descriptions for a SSL server. TEST_F(QuicTransportTest, SetLocalAndRemoteTransportDescriptionServer) { SetTransportDescription(cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTIVE, cricket::CA_OFFER, cricket::CA_ANSWER, rtc::SSL_SERVER); } // Test creation and destruction of channels. TEST_F(QuicTransportTest, CreateAndDestroyChannels) { TransportChannelImpl* channel1 = transport_.CreateChannel(1); ASSERT_NE(nullptr, channel1); EXPECT_TRUE(transport_.HasChannel(1)); EXPECT_EQ(channel1, transport_.GetChannel(1)); TransportChannelImpl* channel2 = transport_.CreateChannel(2); ASSERT_NE(nullptr, channel2); EXPECT_TRUE(transport_.HasChannel(2)); EXPECT_EQ(channel2, transport_.GetChannel(2)); transport_.DestroyChannel(1); EXPECT_FALSE(transport_.HasChannel(1)); EXPECT_EQ(nullptr, transport_.GetChannel(1)); transport_.DestroyChannel(2); EXPECT_FALSE(transport_.HasChannel(2)); EXPECT_EQ(nullptr, transport_.GetChannel(2)); }