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