|  | // 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_session_delegate_(&server_stream_delegate_, | 
|  | simulator_.GetClock()), | 
|  | server_endpoint_delegate_(&server_session_delegate_), | 
|  | server_endpoint_( | 
|  | QuicMakeUnique<QuartcServerEndpoint>(simulator_.GetAlarmFactory(), | 
|  | simulator_.GetClock(), | 
|  | &server_endpoint_delegate_, | 
|  | QuartcSessionConfig())), | 
|  | client_session_delegate_(&client_stream_delegate_, | 
|  | simulator_.GetClock()), | 
|  | client_endpoint_delegate_(&client_session_delegate_), | 
|  | client_endpoint_(QuicMakeUnique<QuartcClientEndpoint>( | 
|  | simulator_.GetAlarmFactory(), | 
|  | simulator_.GetClock(), | 
|  | &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_; | 
|  | FakeQuartcSessionDelegate server_session_delegate_; | 
|  | FakeQuartcEndpointDelegate server_endpoint_delegate_; | 
|  |  | 
|  | std::unique_ptr<QuartcServerEndpoint> server_endpoint_; | 
|  |  | 
|  | FakeQuartcStreamDelegate client_stream_delegate_; | 
|  | FakeQuartcSessionDelegate client_session_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); | 
|  | SetQuicReloadableFlag(quic_enable_version_43, 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(), | 
|  | &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(), | 
|  | &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); | 
|  | SetQuicReloadableFlag(quic_enable_version_43, 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(), | 
|  | &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(), | 
|  | &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); | 
|  | SetQuicReloadableFlag(quic_enable_version_43, 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(), | 
|  | &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(), | 
|  | &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); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace quic |