blob: 5f8c25d64167daf3f6c01720446400a85590393c [file] [log] [blame] [edit]
// Copyright (c) 2017 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.
#include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.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/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_fakes.h"
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
namespace quic {
namespace {
class QuartcEndpointTest : public QuicTest {
protected:
QuartcEndpointTest()
: client_transport_(&simulator_,
"client_transport",
"server_transport",
10 * kDefaultMaxPacketSize),
server_transport_(&simulator_,
"server_transport",
"client_transport",
10 * kDefaultMaxPacketSize),
client_server_link_(&client_transport_,
&server_transport_,
QuicBandwidth::FromKBitsPerSecond(10000),
QuicTime::Delta::FromMilliseconds(1)),
server_endpoint_delegate_(&server_stream_delegate_,
simulator_.GetClock()),
server_endpoint_(QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(),
simulator_.GetClock(),
simulator_.GetRandomGenerator(),
&server_endpoint_delegate_,
QuartcSessionConfig())),
client_endpoint_delegate_(&client_stream_delegate_,
simulator_.GetClock()),
client_endpoint_(QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(),
simulator_.GetClock(),
simulator_.GetRandomGenerator(),
&client_endpoint_delegate_,
QuartcSessionConfig(),
/*serialized_server_config=*/"")) {}
simulator::Simulator simulator_;
simulator::SimulatedQuartcPacketTransport client_transport_;
simulator::SimulatedQuartcPacketTransport server_transport_;
simulator::SymmetricLink client_server_link_;
FakeQuartcStreamDelegate server_stream_delegate_;
FakeQuartcEndpointDelegate server_endpoint_delegate_;
std::unique_ptr<QuartcServerEndpoint> server_endpoint_;
FakeQuartcStreamDelegate client_stream_delegate_;
FakeQuartcEndpointDelegate client_endpoint_delegate_;
std::unique_ptr<QuartcClientEndpoint> client_endpoint_;
};
// After calling Connect, the client endpoint must wait for an async callback.
// The callback occurs after a finite amount of time and produces a session.
TEST_F(QuartcEndpointTest, ClientCreatesSessionAsynchronously) {
client_endpoint_->Connect(&client_transport_);
EXPECT_EQ(client_endpoint_delegate_.session(), nullptr);
EXPECT_TRUE(simulator_.RunUntil(
[this] { return client_endpoint_delegate_.session() != nullptr; }));
}
// Tests that the server can negotiate for an older QUIC version if the client
// attempts to connect using a newer version.
TEST_F(QuartcEndpointTest,
QUIC_TEST_DISABLED_IN_CHROME(ServerNegotiatesForOldVersion)) {
// Note: for this test, we need support for two versions. Which two shouldn't
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
// Reset the client endpoint to prefer version 46 but also be capable of
// speaking version 43.
ParsedQuicVersionVector client_versions;
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
// Reset the server endpoint to only speak version 43.
ParsedQuicVersionVector server_versions;
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be able to establish a connection using version 46.
server_endpoint_->Connect(&server_transport_);
client_endpoint_->Connect(&client_transport_);
ASSERT_TRUE(simulator_.RunUntil([this] {
return client_endpoint_delegate_.session() != nullptr &&
client_endpoint_delegate_.session()->IsEncryptionEstablished() &&
server_endpoint_delegate_.session() != nullptr &&
server_endpoint_delegate_.session()->IsEncryptionEstablished();
}));
EXPECT_EQ(client_endpoint_delegate_.session()->connection()->version(),
server_versions[0]);
EXPECT_EQ(server_endpoint_delegate_.session()->connection()->version(),
server_versions[0]);
}
// Tests that the server can accept connections from clients that use older
// QUIC versions.
TEST_F(QuartcEndpointTest,
QUIC_TEST_DISABLED_IN_CHROME(ServerAcceptsOldVersion)) {
// Note: for this test, we need support for two versions. Which two shouldn't
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
// Reset the client endpoint to only speak version 43.
ParsedQuicVersionVector client_versions;
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
// Reset the server endpoint to prefer version 46 but also be capable of
// speaking version 43.
ParsedQuicVersionVector server_versions;
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be able to establish a connection using version 46.
server_endpoint_->Connect(&server_transport_);
client_endpoint_->Connect(&client_transport_);
ASSERT_TRUE(simulator_.RunUntil([this] {
return client_endpoint_delegate_.session() != nullptr &&
client_endpoint_delegate_.session()->IsEncryptionEstablished() &&
server_endpoint_delegate_.session() != nullptr &&
server_endpoint_delegate_.session()->IsEncryptionEstablished();
}));
EXPECT_EQ(client_endpoint_delegate_.session()->connection()->version(),
client_versions[0]);
EXPECT_EQ(server_endpoint_delegate_.session()->connection()->version(),
client_versions[0]);
}
// Tests that version negotiation fails when the client and server support
// completely disjoint sets of versions.
TEST_F(QuartcEndpointTest,
QUIC_TEST_DISABLED_IN_CHROME(VersionNegotiationWithDisjointVersions)) {
// Note: for this test, we need support for two versions. Which two shouldn't
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
// Reset the client endpoint to only speak version 43.
ParsedQuicVersionVector client_versions;
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
// Reset the server endpoint to only speak version 46.
ParsedQuicVersionVector server_versions;
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be unable to establish a connection.
server_endpoint_->Connect(&server_transport_);
client_endpoint_->Connect(&client_transport_);
// Note that the error is reported from the client and *not* the server. The
// server sees an invalid version, sends a version negotiation packet, and
// never gets a response, because the client stops sending when it can't find
// a mutually supported versions.
ASSERT_TRUE(simulator_.RunUntil([this] {
return client_endpoint_delegate_.session() != nullptr &&
client_endpoint_delegate_.session()->error() != QUIC_NO_ERROR;
}));
EXPECT_EQ(client_endpoint_delegate_.session()->error(), QUIC_INVALID_VERSION);
}
// Tests that the client endpoint can create a new session in order to continue
// version negotiation.
TEST_F(QuartcEndpointTest,
QUIC_TEST_DISABLED_IN_CHROME(CreatesNewSessionWhenRequired)) {
// Setting this flag to true requires the client to create a new session when
// version negotiation fails.
SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true);
// Note: for this test, we need support for two versions. Which two shouldn't
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
// Reset the client endpoint to prefer version 46 but also be capable of
// speaking version 43.
ParsedQuicVersionVector client_versions;
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
// Reset the server endpoint to only speak version 43.
ParsedQuicVersionVector server_versions;
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be able to establish a connection using version 46.
server_endpoint_->Connect(&server_transport_);
client_endpoint_->Connect(&client_transport_);
ASSERT_TRUE(simulator_.RunUntil([this] {
return client_endpoint_delegate_.session() != nullptr &&
client_endpoint_delegate_.session()->IsEncryptionEstablished() &&
server_endpoint_delegate_.session() != nullptr &&
server_endpoint_delegate_.session()->IsEncryptionEstablished();
}));
EXPECT_EQ(client_endpoint_delegate_.session()->connection()->version(),
server_versions[0]);
EXPECT_EQ(server_endpoint_delegate_.session()->connection()->version(),
server_versions[0]);
EXPECT_EQ(2, client_endpoint_delegate_.num_sessions_created());
}
} // namespace
} // namespace quic