blob: f4c6a2ac0258a78c2fbfb60702c6bb3b49ba3ed8 [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// An integration test that covers interactions between QuicTransport client and
// server sessions.
#include <memory>
#include "url/gurl.h"
#include "url/origin.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
namespace quic {
namespace test {
namespace {
using simulator::QuicEndpointBase;
using simulator::Simulator;
using testing::_;
using testing::Return;
url::Origin GetTestOrigin() {
constexpr char kTestOrigin[] = "https://test-origin.test";
GURL origin_url(kTestOrigin);
return url::Origin::Create(origin_url);
}
ParsedQuicVersionVector GetVersions() {
return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
}
class QuicTransportEndpointBase : public QuicEndpointBase {
public:
QuicTransportEndpointBase(Simulator* simulator,
const std::string& name,
const std::string& peer_name,
Perspective perspective)
: QuicEndpointBase(simulator, name, peer_name) {
connection_ = std::make_unique<QuicConnection>(
TestConnectionId(0x10), simulator::GetAddressFromName(peer_name),
simulator, simulator->GetAlarmFactory(), &writer_,
/*owns_writer=*/false, perspective, GetVersions());
connection_->SetSelfAddress(simulator::GetAddressFromName(name));
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
}
};
class QuicTransportClientEndpoint : public QuicTransportEndpointBase {
public:
QuicTransportClientEndpoint(Simulator* simulator,
const std::string& name,
const std::string& peer_name,
url::Origin origin)
: QuicTransportEndpointBase(simulator,
name,
peer_name,
Perspective::IS_CLIENT),
crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
session_(connection_.get(),
nullptr,
DefaultQuicConfig(),
GetVersions(),
QuicServerId("test.example.com", 443),
&crypto_config_,
origin) {
session_.Initialize();
}
QuicTransportClientSession* session() { return &session_; }
private:
QuicCryptoClientConfig crypto_config_;
QuicTransportClientSession session_;
};
class MockServerVisitor : public QuicTransportServerSession::ServerVisitor {
public:
MOCK_METHOD1(CheckOrigin, bool(url::Origin));
};
class QuicTransportServerEndpoint : public QuicTransportEndpointBase {
public:
QuicTransportServerEndpoint(Simulator* simulator,
const std::string& name,
const std::string& peer_name)
: QuicTransportEndpointBase(simulator,
name,
peer_name,
Perspective::IS_SERVER),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
crypto_test_utils::ProofSourceForTesting(),
KeyExchangeSource::Default()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
session_(connection_.get(),
nullptr,
DefaultQuicConfig(),
GetVersions(),
&crypto_config_,
&compressed_certs_cache_,
&visitor_) {
session_.Initialize();
}
QuicTransportServerSession* session() { return &session_; }
MockServerVisitor* visitor() { return &visitor_; }
private:
QuicCryptoServerConfig crypto_config_;
QuicCompressedCertsCache compressed_certs_cache_;
QuicTransportServerSession session_;
MockServerVisitor visitor_;
};
constexpr QuicBandwidth kClientBandwidth =
QuicBandwidth::FromKBitsPerSecond(10000);
constexpr QuicTime::Delta kClientPropagationDelay =
QuicTime::Delta::FromMilliseconds(2);
constexpr QuicBandwidth kServerBandwidth =
QuicBandwidth::FromKBitsPerSecond(4000);
constexpr QuicTime::Delta kServerPropagationDelay =
QuicTime::Delta::FromMilliseconds(50);
const QuicTime::Delta kTransferTime =
kClientBandwidth.TransferTime(kMaxOutgoingPacketSize) +
kServerBandwidth.TransferTime(kMaxOutgoingPacketSize);
const QuicTime::Delta kRtt =
(kClientPropagationDelay + kServerPropagationDelay + kTransferTime) * 2;
const QuicByteCount kBdp = kRtt * kServerBandwidth;
constexpr QuicTime::Delta kHandshakeTimeout = QuicTime::Delta::FromSeconds(3);
class QuicTransportIntegrationTest : public QuicTest {
public:
QuicTransportIntegrationTest()
: switch_(&simulator_, "Switch", 8, 2 * kBdp) {}
void CreateDefaultEndpoints() {
client_ = std::make_unique<QuicTransportClientEndpoint>(
&simulator_, "Client", "Server", GetTestOrigin());
server_ = std::make_unique<QuicTransportServerEndpoint>(&simulator_,
"Server", "Client");
ON_CALL(*server_->visitor(), CheckOrigin(_)).WillByDefault(Return(true));
}
void WireUpEndpoints() {
client_link_ = std::make_unique<simulator::SymmetricLink>(
client_.get(), switch_.port(1), kClientBandwidth,
kClientPropagationDelay);
server_link_ = std::make_unique<simulator::SymmetricLink>(
server_.get(), switch_.port(2), kServerBandwidth,
kServerPropagationDelay);
}
void RunHandshake() {
client_->session()->CryptoConnect();
bool result = simulator_.RunUntilOrTimeout(
[this]() {
return IsHandshakeDone(client_->session()) &&
IsHandshakeDone(server_->session());
},
kHandshakeTimeout);
EXPECT_TRUE(result);
}
protected:
template <class Session>
static bool IsHandshakeDone(const Session* session) {
return session->IsSessionReady() || session->error() != QUIC_NO_ERROR;
}
Simulator simulator_;
simulator::Switch switch_;
std::unique_ptr<simulator::SymmetricLink> client_link_;
std::unique_ptr<simulator::SymmetricLink> server_link_;
std::unique_ptr<QuicTransportClientEndpoint> client_;
std::unique_ptr<QuicTransportServerEndpoint> server_;
};
TEST_F(QuicTransportIntegrationTest, SuccessfulHandshake) {
CreateDefaultEndpoints();
WireUpEndpoints();
RunHandshake();
EXPECT_TRUE(client_->session()->IsSessionReady());
EXPECT_TRUE(server_->session()->IsSessionReady());
}
TEST_F(QuicTransportIntegrationTest, OriginMismatch) {
CreateDefaultEndpoints();
WireUpEndpoints();
EXPECT_CALL(*server_->visitor(), CheckOrigin(_))
.WillRepeatedly(Return(false));
RunHandshake();
// Wait until the client receives CONNECTION_CLOSE.
simulator_.RunUntilOrTimeout(
[this]() { return !client_->session()->connection()->connected(); },
kHandshakeTimeout);
EXPECT_TRUE(client_->session()->IsSessionReady());
EXPECT_FALSE(server_->session()->IsSessionReady());
EXPECT_FALSE(client_->session()->connection()->connected());
EXPECT_FALSE(server_->session()->connection()->connected());
EXPECT_EQ(client_->session()->error(),
QUIC_TRANSPORT_INVALID_CLIENT_INDICATION);
EXPECT_EQ(server_->session()->error(),
QUIC_TRANSPORT_INVALID_CLIENT_INDICATION);
}
} // namespace
} // namespace test
} // namespace quic