| // 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 |