blob: 3328556fc773190db5fa3cb95a7c070386d085a4 [file] [log] [blame]
/*
* 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 <memory>
#include <string>
#include <vector>
#include "webrtc/rtc_base/gunit.h"
#include "webrtc/rtc_base/rtccertificate.h"
#include "webrtc/rtc_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<rtc::RTCCertificate> CreateCertificate(
std::string name) {
return rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
rtc::SSLIdentity::Generate(name, rtc::KT_DEFAULT)));
}
static std::unique_ptr<rtc::SSLFingerprint> CreateFingerprint(
rtc::RTCCertificate* cert) {
std::string digest_algorithm;
cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
return std::unique_ptr<rtc::SSLFingerprint>(
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<rtc::RTCCertificate> local_certificate(
CreateCertificate("local"));
ASSERT_NE(nullptr, local_certificate);
transport_.SetLocalCertificate(local_certificate);
std::unique_ptr<rtc::SSLFingerprint> local_fingerprint =
CreateFingerprint(local_certificate.get());
ASSERT_NE(nullptr, local_fingerprint);
TransportDescription local_desc(std::vector<std::string>(), 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<rtc::RTCCertificate> channel_local_certificate =
channel->GetLocalCertificate();
ASSERT_NE(nullptr, channel_local_certificate);
EXPECT_EQ(local_certificate, channel_local_certificate);
std::unique_ptr<rtc::SSLFingerprint> 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<rtc::SSLRole> 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<std::string>(), 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<rtc::RTCCertificate> local_certificate(
CreateCertificate("local"));
ASSERT_NE(nullptr, local_certificate);
rtc::scoped_refptr<rtc::RTCCertificate> 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));
}