summaryrefslogtreecommitdiff
path: root/chromium/net/tools/quic/quic_dispatcher_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/tools/quic/quic_dispatcher_test.cc')
-rw-r--r--chromium/net/tools/quic/quic_dispatcher_test.cc2421
1 files changed, 0 insertions, 2421 deletions
diff --git a/chromium/net/tools/quic/quic_dispatcher_test.cc b/chromium/net/tools/quic/quic_dispatcher_test.cc
deleted file mode 100644
index 1f118e14f62..00000000000
--- a/chromium/net/tools/quic/quic_dispatcher_test.cc
+++ /dev/null
@@ -1,2421 +0,0 @@
-// Copyright (c) 2012 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/tools/quic/quic_dispatcher.h"
-
-#include <memory>
-#include <ostream>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "net/quic/core/crypto/crypto_handshake.h"
-#include "net/quic/core/crypto/crypto_protocol.h"
-#include "net/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/quic/core/crypto/quic_random.h"
-#include "net/quic/core/quic_crypto_stream.h"
-#include "net/quic/core/quic_utils.h"
-#include "net/quic/core/tls_server_handshaker.h"
-#include "net/quic/platform/api/quic_arraysize.h"
-#include "net/quic/platform/api/quic_flags.h"
-#include "net/quic/platform/api/quic_logging.h"
-#include "net/quic/platform/api/quic_str_cat.h"
-#include "net/quic/platform/api/quic_string.h"
-#include "net/quic/platform/api/quic_test.h"
-#include "net/quic/test_tools/crypto_test_utils.h"
-#include "net/quic/test_tools/fake_proof_source.h"
-#include "net/quic/test_tools/quic_buffered_packet_store_peer.h"
-#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/quic/test_tools/quic_time_wait_list_manager_peer.h"
-#include "net/test/gtest_util.h"
-#include "net/tools/epoll_server/epoll_server.h"
-#include "net/tools/quic/chlo_extractor.h"
-#include "net/tools/quic/quic_epoll_alarm_factory.h"
-#include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_packet_writer_wrapper.h"
-#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h"
-#include "net/tools/quic/quic_time_wait_list_manager.h"
-#include "net/tools/quic/stateless_rejector.h"
-#include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h"
-#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gmock_mutant.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using std::string;
-using testing::_;
-using testing::InSequence;
-using testing::Invoke;
-using testing::Return;
-using testing::WithArg;
-using testing::WithoutArgs;
-
-static const size_t kDefaultMaxConnectionsInStore = 100;
-static const size_t kMaxConnectionsWithoutCHLO =
- kDefaultMaxConnectionsInStore / 2;
-static const int16_t kMaxNumSessionsToCreate = 16;
-
-namespace net {
-namespace test {
-namespace {
-
-class TestQuicSpdyServerSession : public QuicServerSessionBase {
- public:
- TestQuicSpdyServerSession(const QuicConfig& config,
- QuicConnection* connection,
- const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache)
- : QuicServerSessionBase(config,
- connection,
- nullptr,
- nullptr,
- crypto_config,
- compressed_certs_cache),
- crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {}
-
- ~TestQuicSpdyServerSession() override { delete connection(); };
-
- MOCK_METHOD3(OnConnectionClosed,
- void(QuicErrorCode error,
- const QuicString& error_details,
- ConnectionCloseSource source));
- MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
- MOCK_METHOD0(CreateOutgoingDynamicStream, QuicSpdyStream*());
-
- QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache) override {
- return new QuicCryptoServerStream(
- crypto_config, compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support), this,
- stream_helper());
- }
-
- void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
- crypto_stream_ = crypto_stream;
- }
-
- QuicCryptoServerStreamBase* GetMutableCryptoStream() override {
- return crypto_stream_;
- }
-
- const QuicCryptoServerStreamBase* GetCryptoStream() const override {
- return crypto_stream_;
- }
-
- QuicCryptoServerStream::Helper* stream_helper() {
- return QuicServerSessionBase::stream_helper();
- }
-
- private:
- QuicCryptoServerStreamBase* crypto_stream_;
-
- DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyServerSession);
-};
-
-class TestDispatcher : public QuicDispatcher {
- public:
- TestDispatcher(const QuicConfig& config,
- const QuicCryptoServerConfig* crypto_config,
- QuicVersionManager* version_manager,
- EpollServer* eps)
- : QuicDispatcher(
- config,
- crypto_config,
- version_manager,
- std::unique_ptr<QuicEpollConnectionHelper>(
- new QuicEpollConnectionHelper(eps, QuicAllocator::BUFFER_POOL)),
- std::unique_ptr<QuicCryptoServerStream::Helper>(
- new QuicSimpleCryptoServerStreamHelper(
- QuicRandom::GetInstance())),
- std::unique_ptr<QuicEpollAlarmFactory>(
- new QuicEpollAlarmFactory(eps))) {}
-
- MOCK_METHOD3(CreateQuicSession,
- QuicServerSessionBase*(QuicConnectionId connection_id,
- const QuicSocketAddress& peer_address,
- QuicStringPiece alpn));
-
- MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
- bool(QuicConnectionId connection_id));
-
- using QuicDispatcher::current_client_address;
- using QuicDispatcher::current_peer_address;
- using QuicDispatcher::current_self_address;
-};
-
-// A Connection class which unregisters the session from the dispatcher when
-// sending connection close.
-// It'd be slightly more realistic to do this from the Session but it would
-// involve a lot more mocking.
-class MockServerConnection : public MockQuicConnection {
- public:
- MockServerConnection(QuicConnectionId connection_id,
- MockQuicConnectionHelper* helper,
- MockAlarmFactory* alarm_factory,
- QuicDispatcher* dispatcher)
- : MockQuicConnection(connection_id,
- helper,
- alarm_factory,
- Perspective::IS_SERVER),
- dispatcher_(dispatcher) {}
-
- void UnregisterOnConnectionClosed() {
- QUIC_LOG(ERROR) << "Unregistering " << connection_id();
- dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
- "Unregistering.");
- }
-
- private:
- QuicDispatcher* dispatcher_;
-};
-
-class QuicDispatcherTest : public QuicTest {
- public:
- QuicDispatcherTest()
- : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
-
- ParsedQuicVersionVector AllSupportedVersionsIncludingTls() {
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
- return AllSupportedVersions();
- }
-
- explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
- : helper_(&eps_, QuicAllocator::BUFFER_POOL),
- alarm_factory_(&eps_),
- version_manager_(AllSupportedVersionsIncludingTls()),
- crypto_config_(QuicCryptoServerConfig::TESTING,
- QuicRandom::GetInstance(),
- std::move(proof_source),
- TlsServerHandshaker::CreateSslCtx()),
- dispatcher_(new TestDispatcher(config_,
- &crypto_config_,
- &version_manager_,
- &eps_)),
- time_wait_list_manager_(nullptr),
- session1_(nullptr),
- session2_(nullptr),
- store_(nullptr) {}
-
- void SetUp() override {
- dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1));
- // Set the counter to some value to start with.
- QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
- dispatcher_.get(), kMaxNumSessionsToCreate);
- ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_))
- .WillByDefault(Return(true));
- }
-
- ~QuicDispatcherTest() override = default;
-
- MockQuicConnection* connection1() {
- return reinterpret_cast<MockQuicConnection*>(session1_->connection());
- }
-
- MockQuicConnection* connection2() {
- return reinterpret_cast<MockQuicConnection*>(session2_->connection());
- }
-
- // Process a packet with an 8 byte connection id,
- // 6 byte packet number, default path id, and packet number 1,
- // using the first supported version.
- void ProcessPacket(QuicSocketAddress peer_address,
- QuicConnectionId connection_id,
- bool has_version_flag,
- const QuicString& data) {
- ProcessPacket(peer_address, connection_id, has_version_flag, data,
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER);
- }
-
- // Process a packet with a default path id, and packet number 1,
- // using the first supported version.
- void ProcessPacket(QuicSocketAddress peer_address,
- QuicConnectionId connection_id,
- bool has_version_flag,
- const QuicString& data,
- QuicConnectionIdLength connection_id_length,
- QuicPacketNumberLength packet_number_length) {
- ProcessPacket(peer_address, connection_id, has_version_flag, data,
- connection_id_length, packet_number_length, 1);
- }
-
- // Process a packet using the first supported version.
- void ProcessPacket(QuicSocketAddress peer_address,
- QuicConnectionId connection_id,
- bool has_version_flag,
- const QuicString& data,
- QuicConnectionIdLength connection_id_length,
- QuicPacketNumberLength packet_number_length,
- QuicPacketNumber packet_number) {
- ProcessPacket(peer_address, connection_id, has_version_flag,
- CurrentSupportedVersions().front(), data,
- connection_id_length, packet_number_length, packet_number);
- }
-
- // Processes a packet.
- void ProcessPacket(QuicSocketAddress peer_address,
- QuicConnectionId connection_id,
- bool has_version_flag,
- ParsedQuicVersion version,
- const QuicString& data,
- QuicConnectionIdLength connection_id_length,
- QuicPacketNumberLength packet_number_length,
- QuicPacketNumber packet_number) {
- ParsedQuicVersionVector versions(SupportedVersions(version));
- std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
- connection_id, has_version_flag, false, packet_number, data,
- connection_id_length, packet_number_length, &versions));
- std::unique_ptr<QuicReceivedPacket> received_packet(
- ConstructReceivedPacket(*packet, helper_.GetClock()->Now()));
-
- if (ChloExtractor::Extract(*packet, versions, {}, nullptr)) {
- // Add CHLO packet to the beginning to be verified first, because it is
- // also processed first by new session.
- data_connection_map_[connection_id].push_front(
- QuicString(packet->data(), packet->length()));
- } else {
- // For non-CHLO, always append to last.
- data_connection_map_[connection_id].push_back(
- QuicString(packet->data(), packet->length()));
- }
- dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet);
- }
-
- void ValidatePacket(QuicConnectionId conn_id,
- const QuicEncryptedPacket& packet) {
- EXPECT_EQ(data_connection_map_[conn_id].front().length(),
- packet.AsStringPiece().length());
- EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
- data_connection_map_[conn_id].pop_front();
- }
-
- QuicServerSessionBase* CreateSession(
- QuicDispatcher* dispatcher,
- const QuicConfig& config,
- QuicConnectionId connection_id,
- const QuicSocketAddress& peer_address,
- MockQuicConnectionHelper* helper,
- MockAlarmFactory* alarm_factory,
- const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- TestQuicSpdyServerSession** session) {
- MockServerConnection* connection = new MockServerConnection(
- connection_id, helper, alarm_factory, dispatcher);
- *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
- compressed_certs_cache);
- connection->set_visitor(*session);
- ON_CALL(*connection, CloseConnection(_, _, _))
- .WillByDefault(WithoutArgs(Invoke(
- connection, &MockServerConnection::UnregisterOnConnectionClosed)));
- return *session;
- }
-
- void CreateTimeWaitListManager() {
- time_wait_list_manager_ = new MockTimeWaitListManager(
- QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
- &helper_, &alarm_factory_);
- // dispatcher_ takes the ownership of time_wait_list_manager_.
- QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
- time_wait_list_manager_);
- }
-
- QuicString SerializeCHLO() {
- CryptoHandshakeMessage client_hello;
- client_hello.set_tag(kCHLO);
- client_hello.SetStringPiece(kALPN, "hq");
- return string(
- client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece());
- }
-
- QuicString SerializeTlsClientHello() { return ""; }
-
- EpollServer eps_;
- QuicEpollConnectionHelper helper_;
- MockQuicConnectionHelper mock_helper_;
- QuicEpollAlarmFactory alarm_factory_;
- MockAlarmFactory mock_alarm_factory_;
- QuicConfig config_;
- QuicVersionManager version_manager_;
- QuicCryptoServerConfig crypto_config_;
- QuicSocketAddress server_address_;
- std::unique_ptr<TestDispatcher> dispatcher_;
- MockTimeWaitListManager* time_wait_list_manager_;
- TestQuicSpdyServerSession* session1_;
- TestQuicSpdyServerSession* session2_;
- std::map<QuicConnectionId, std::list<QuicString>> data_connection_map_;
- QuicBufferedPacketStore* store_;
-};
-
-TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
- FLAGS_quic_supports_tls_handshake = true;
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(1, client_address, QuicStringPiece("")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 1, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1));
- ProcessPacket(
- client_address, 1, true,
- ParsedQuicVersion(PROTOCOL_TLS1_3,
- CurrentSupportedVersions().front().transport_version),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- 1);
- EXPECT_EQ(client_address, dispatcher_->current_peer_address());
- EXPECT_EQ(server_address_, dispatcher_->current_self_address());
-}
-
-TEST_F(QuicDispatcherTest, ProcessPackets) {
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(1, client_address, QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 1, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1));
- ProcessPacket(client_address, 1, true, SerializeCHLO());
- EXPECT_EQ(client_address, dispatcher_->current_peer_address());
- EXPECT_EQ(server_address_, dispatcher_->current_self_address());
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(2, client_address, QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 2, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(2, packet);
- })));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(2));
- ProcessPacket(client_address, 2, true, SerializeCHLO());
-
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(1)
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
- ProcessPacket(client_address, 1, false, "data");
-}
-
-TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(1, client_address, QuicStringPiece("hq")))
- .Times(0);
- QuicTransportVersion version =
- static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
- ParsedQuicVersion parsed_version(PROTOCOL_QUIC_CRYPTO, version);
- ProcessPacket(client_address, 1, true, parsed_version, SerializeCHLO(),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1);
-}
-
-TEST_F(QuicDispatcherTest, Shutdown) {
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 1, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
-
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1));
- ProcessPacket(client_address, 1, true, SerializeCHLO());
-
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
-
- dispatcher_->Shutdown();
-}
-
-TEST_F(QuicDispatcherTest, TimeWaitListManager) {
- CreateTimeWaitListManager();
-
- // Create a new session.
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
-
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1));
- ProcessPacket(client_address, connection_id, true, SerializeCHLO());
-
- // Close the connection by sending public reset packet.
- QuicPublicResetPacket packet;
- packet.connection_id = connection_id;
- packet.nonce_proof = 132232;
- std::unique_ptr<QuicEncryptedPacket> encrypted(
- QuicFramer::BuildPublicResetPacket(packet));
- std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket(
- *encrypted, session1_->connection()->clock()->Now()));
- EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, _,
- ConnectionCloseSource::FROM_PEER))
- .Times(1)
- .WillOnce(WithoutArgs(Invoke(
- reinterpret_cast<MockServerConnection*>(session1_->connection()),
- &MockServerConnection::UnregisterOnConnectionClosed)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(
- Invoke(reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- &MockQuicConnection::ReallyProcessUdpPacket));
- dispatcher_->ProcessPacket(QuicSocketAddress(), client_address, *received);
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
-
- // Dispatcher forwards subsequent packets for this connection_id to the time
- // wait list manager.
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
- .Times(1);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(0);
- ProcessPacket(client_address, connection_id, true, "data");
-}
-
-TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
- // Dispatcher forwards all packets for this connection_id to the time wait
- // list manager.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq")))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
- .Times(1);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(1);
- ProcessPacket(client_address, connection_id, false, SerializeCHLO());
-}
-
-TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
-
- // dispatcher_ should drop this packet.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(1, client_address, QuicStringPiece("hq")))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(0);
- ProcessPacket(client_address, 1, true, SerializeCHLO());
-}
-
-TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(1, client_address, QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 1, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
-
- // A packet whose packet number is the largest that is allowed to start a
- // connection.
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- QuicDispatcher::kMaxReasonableInitialPacketNumber);
- EXPECT_EQ(client_address, dispatcher_->current_peer_address());
- EXPECT_EQ(server_address_, dispatcher_->current_self_address());
-}
-
-TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
- CreateTimeWaitListManager();
- SetQuicRestartFlag(quic_enable_accept_random_ipn, false);
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
-
- // Dispatcher forwards this packet for this connection_id to the time wait
- // list manager.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq")))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 1)).Times(1);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 2)).Times(1);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(2);
- // A packet whose packet number is one to large to be allowed to start a
- // connection.
- ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
- connection_id = 2;
- SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
- ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- kMaxRandomInitialPacketNumber +
- QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
-}
-
-TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
- "Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_37, false);
- SetQuicReloadableFlag(quic_disable_version_38, false);
- SetQuicReloadableFlag(quic_disable_version_41, false);
- SetQuicReloadableFlag(quic_enable_version_42_2, true);
- SetQuicReloadableFlag(quic_enable_version_43, true);
- SetQuicFlag(&FLAGS_quic_enable_version_99, true);
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
- QuicConnectionId connection_id = 1;
-
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .Times(0);
- ParsedQuicVersion version(
- PROTOCOL_QUIC_CRYPTO,
- static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1));
- ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
- QuicVersionMin().transport_version),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true, QuicVersionMax(),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn off version 43.
- SetQuicReloadableFlag(quic_enable_version_43, false);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 43.
- SetQuicReloadableFlag(quic_enable_version_43, true);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn off version 42.
- SetQuicReloadableFlag(quic_enable_version_42_2, false);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_42),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 42.
- SetQuicReloadableFlag(quic_enable_version_42_2, true);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_42),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn off version 41.
- SetQuicReloadableFlag(quic_disable_version_41, true);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 41.
- SetQuicReloadableFlag(quic_disable_version_41, false);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn off version 38.
- SetQuicReloadableFlag(quic_disable_version_38, true);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 38.
- SetQuicReloadableFlag(quic_disable_version_38, false);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn off version 37.
- SetQuicReloadableFlag(quic_disable_version_37, true);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 37.
- SetQuicReloadableFlag(quic_disable_version_37, false);
- ++connection_id;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-}
-
-// Enables mocking of the handshake-confirmation for stateless rejects.
-class MockQuicCryptoServerStream : public QuicCryptoServerStream {
- public:
- MockQuicCryptoServerStream(const QuicCryptoServerConfig& crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- QuicServerSessionBase* session,
- QuicCryptoServerStream::Helper* helper)
- : QuicCryptoServerStream(
- &crypto_config,
- compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support),
- session,
- helper),
- handshake_confirmed_(false) {}
-
- void set_handshake_confirmed_for_testing(bool handshake_confirmed) {
- handshake_confirmed_ = handshake_confirmed;
- }
-
- bool handshake_confirmed() const override { return handshake_confirmed_; }
-
- private:
- bool handshake_confirmed_;
- DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
-};
-
-struct StatelessRejectTestParams {
- StatelessRejectTestParams(bool enable_stateless_rejects_via_flag,
- bool client_supports_statelesss_rejects,
- bool crypto_handshake_successful)
- : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
- client_supports_statelesss_rejects(client_supports_statelesss_rejects),
- crypto_handshake_successful(crypto_handshake_successful) {}
-
- friend std::ostream& operator<<(std::ostream& os,
- const StatelessRejectTestParams& p) {
- os << "{ enable_stateless_rejects_via_flag: "
- << p.enable_stateless_rejects_via_flag << std::endl;
- os << " client_supports_statelesss_rejects: "
- << p.client_supports_statelesss_rejects << std::endl;
- os << " crypto_handshake_successful: " << p.crypto_handshake_successful
- << " }";
- return os;
- }
-
- // This only enables the stateless reject feature via the feature-flag.
- // This should be a no-op if the peer does not support them.
- bool enable_stateless_rejects_via_flag;
- // Whether or not the client supports stateless rejects.
- bool client_supports_statelesss_rejects;
- // Should the initial crypto handshake succeed or not.
- bool crypto_handshake_successful;
-};
-
-// Constructs various test permutations for stateless rejects.
-std::vector<StatelessRejectTestParams> GetStatelessRejectTestParams() {
- std::vector<StatelessRejectTestParams> params;
- for (bool enable_stateless_rejects_via_flag : {true, false}) {
- for (bool client_supports_statelesss_rejects : {true, false}) {
- for (bool crypto_handshake_successful : {true, false}) {
- params.push_back(StatelessRejectTestParams(
- enable_stateless_rejects_via_flag,
- client_supports_statelesss_rejects, crypto_handshake_successful));
- }
- }
- }
- return params;
-}
-
-class QuicDispatcherStatelessRejectTest
- : public QuicDispatcherTest,
- public testing::WithParamInterface<StatelessRejectTestParams> {
- public:
- QuicDispatcherStatelessRejectTest()
- : QuicDispatcherTest(), crypto_stream1_(nullptr) {}
-
- ~QuicDispatcherStatelessRejectTest() override {
- if (crypto_stream1_) {
- delete crypto_stream1_;
- }
- }
-
- // This test setup assumes that all testing will be done using
- // crypto_stream1_.
- void SetUp() override {
- QuicDispatcherTest::SetUp();
- SetQuicReloadableFlag(enable_quic_stateless_reject_support,
- GetParam().enable_stateless_rejects_via_flag);
- }
-
- // Returns true or false, depending on whether the server will emit
- // a stateless reject, depending upon the parameters of the test.
- bool ExpectStatelessReject() {
- return GetParam().enable_stateless_rejects_via_flag &&
- !GetParam().crypto_handshake_successful &&
- GetParam().client_supports_statelesss_rejects;
- }
-
- // Sets up dispatcher_, session1_, and crypto_stream1_ based on
- // the test parameters.
- QuicServerSessionBase* CreateSessionBasedOnTestParams(
- QuicConnectionId connection_id,
- const QuicSocketAddress& client_address) {
- CreateSession(dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_);
-
- crypto_stream1_ = new MockQuicCryptoServerStream(
- crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- session1_, session1_->stream_helper());
- session1_->SetCryptoStream(crypto_stream1_);
- crypto_stream1_->set_handshake_confirmed_for_testing(
- GetParam().crypto_handshake_successful);
- crypto_stream1_->SetPeerSupportsStatelessRejects(
- GetParam().client_supports_statelesss_rejects);
- return session1_;
- }
-
- MockQuicCryptoServerStream* crypto_stream1_;
-};
-
-// Parameterized test for stateless rejects. Should test all
-// combinations of enabling/disabling, reject/no-reject for stateless
-// rejects.
-INSTANTIATE_TEST_CASE_P(QuicDispatcherStatelessRejectTests,
- QuicDispatcherStatelessRejectTest,
- ::testing::ValuesIn(GetStatelessRejectTestParams()));
-
-TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq")))
- .WillOnce(testing::Return(
- CreateSessionBasedOnTestParams(connection_id, client_address)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id))
- .Times(1);
-
- // Process the first packet for the connection.
- ProcessPacket(client_address, connection_id, true, SerializeCHLO());
- if (ExpectStatelessReject()) {
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- // If this is a stateless reject, the crypto stream will close the
- // connection.
- session1_->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
- ConnectionCloseBehavior::SILENT_CLOSE);
- }
-
- // Send a second packet and check the results. If this is a stateless reject,
- // the existing connection_id will go on the time-wait list.
- EXPECT_EQ(ExpectStatelessReject(),
- time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
- if (ExpectStatelessReject()) {
- // The second packet will be processed on the time-wait list.
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
- .Times(1);
- } else {
- // The second packet will trigger a packet-validation
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(1)
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- }
- ProcessPacket(client_address, connection_id, true, "data");
-}
-
-TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
- if (GetParam().enable_stateless_rejects_via_flag) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(connection_id, client_address, _))
- .Times(0);
- } else {
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("h2")))
- .WillOnce(testing::Return(
- CreateSessionBasedOnTestParams(connection_id, client_address)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
- }
-
- QUIC_LOG(INFO) << "ExpectStatelessReject: " << ExpectStatelessReject();
- QUIC_LOG(INFO) << "Params: " << GetParam();
- // Process the first packet for the connection.
- CryptoHandshakeMessage client_hello =
- crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"COPT", "SREJ"},
- {"NONC", "1234567890123456789012"},
- {"ALPN", "h2"},
- {"VER\0", "Q025"}},
- kClientHelloMinimumSize);
-
- if (GetParam().enable_stateless_rejects_via_flag) {
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
- .Times(1);
- } else {
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id))
- .Times(1);
- }
- ProcessPacket(
- client_address, connection_id, true,
- string(
- client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()));
-
- if (GetParam().enable_stateless_rejects_via_flag) {
- EXPECT_EQ(true,
- time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
- }
-}
-
-TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
- CreateTimeWaitListManager();
-
- const QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- const QuicConnectionId connection_id = 1;
-
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id))
- .Times(1);
- ProcessPacket(client_address, connection_id, true, "NOT DATA FOR A CHLO");
-
- // Process the first packet for the connection.
- CryptoHandshakeMessage client_hello =
- crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"NONC", "1234567890123456789012"},
- {"ALPN", "h3"},
- {"VER\0", "Q025"}},
- kClientHelloMinimumSize);
-
- // If stateless rejects are enabled then a connection will be created now
- // and the buffered packet will be processed
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("h3")))
- .WillOnce(testing::Return(
- CreateSessionBasedOnTestParams(connection_id, client_address)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, client_address, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- // Expect both packets to be passed to ProcessUdpPacket(). And one of them
- // is already expected in CreateSessionBasedOnTestParams().
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, client_address, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })))
- .RetiresOnSaturation();
- ProcessPacket(
- client_address, connection_id, true,
- string(
- client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()));
- EXPECT_FALSE(
- time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
-}
-
-// Verify the stopgap test: Packets with truncated connection IDs should be
-// dropped.
-class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
-
-// Packets with truncated connection IDs should be dropped.
-TEST_F(QuicDispatcherTestStrayPacketConnectionId,
- StrayPacketTruncatedConnectionId) {
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = 1;
- // Dispatcher drops this packet.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq")))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(0);
- ProcessPacket(client_address, connection_id, true, "data",
- PACKET_0BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER);
-}
-
-class BlockingWriter : public QuicPacketWriterWrapper {
- public:
- BlockingWriter() : write_blocked_(false) {}
-
- bool IsWriteBlocked() const override { return write_blocked_; }
- void SetWritable() override { write_blocked_ = false; }
-
- WriteResult WritePacket(const char* buffer,
- size_t buf_len,
- const QuicIpAddress& self_client_address,
- const QuicSocketAddress& peer_client_address,
- PerPacketOptions* options) override {
- // It would be quite possible to actually implement this method here with
- // the fake blocked status, but it would be significantly more work in
- // Chromium, and since it's not called anyway, don't bother.
- QUIC_LOG(DFATAL) << "Not supported";
- return WriteResult();
- }
-
- bool write_blocked_;
-};
-
-class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
- public:
- void SetUp() override {
- QuicDispatcherTest::SetUp();
- writer_ = new BlockingWriter;
- QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 1, client_address, &helper_,
- &alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(1, packet);
- })));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1));
- ProcessPacket(client_address, 1, true, SerializeCHLO());
-
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, client_address, QuicStringPiece("hq")))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, 2, client_address, &helper_,
- &alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
- ValidatePacket(2, packet);
- })));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(2));
- ProcessPacket(client_address, 2, true, SerializeCHLO());
-
- blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
- }
-
- void TearDown() override {
- EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
- EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
- dispatcher_->Shutdown();
- }
-
- void SetBlocked() { writer_->write_blocked_ = true; }
-
- void BlockConnection2() {
- writer_->write_blocked_ = true;
- dispatcher_->OnWriteBlocked(connection2());
- }
-
- protected:
- MockQuicConnectionHelper helper_;
- MockAlarmFactory alarm_factory_;
- BlockingWriter* writer_;
- QuicDispatcher::WriteBlockedList* blocked_list_;
-};
-
-TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
- // No OnCanWrite calls because no connections are blocked.
- dispatcher_->OnCanWrite();
-
- // Register connection 1 for events, and make sure it's notified.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- EXPECT_CALL(*connection1(), OnCanWrite());
- dispatcher_->OnCanWrite();
-
- // It should get only one notification.
- EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
- dispatcher_->OnCanWrite();
- EXPECT_FALSE(dispatcher_->HasPendingWrites());
-}
-
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
- // Make sure we handle events in order.
- InSequence s;
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection2());
- EXPECT_CALL(*connection1(), OnCanWrite());
- EXPECT_CALL(*connection2(), OnCanWrite());
- dispatcher_->OnCanWrite();
-
- // Check the other ordering.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection2());
- dispatcher_->OnWriteBlocked(connection1());
- EXPECT_CALL(*connection2(), OnCanWrite());
- EXPECT_CALL(*connection1(), OnCanWrite());
- dispatcher_->OnCanWrite();
-}
-
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
- // Add and remove one connction.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- blocked_list_->erase(connection1());
- EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
- dispatcher_->OnCanWrite();
-
- // Add and remove one connction and make sure it doesn't affect others.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection2());
- blocked_list_->erase(connection1());
- EXPECT_CALL(*connection2(), OnCanWrite());
- dispatcher_->OnCanWrite();
-
- // Add it, remove it, and add it back and make sure things are OK.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- blocked_list_->erase(connection1());
- dispatcher_->OnWriteBlocked(connection1());
- EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
- dispatcher_->OnCanWrite();
-}
-
-TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
- // Make sure a double add does not necessitate a double remove.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection1());
- blocked_list_->erase(connection1());
- EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
- dispatcher_->OnCanWrite();
-
- // Make sure a double add does not result in two OnCanWrite calls.
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection1());
- EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
- dispatcher_->OnCanWrite();
-}
-
-TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
- // Finally make sure if we write block on a write call, we stop calling.
- InSequence s;
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection2());
- EXPECT_CALL(*connection1(), OnCanWrite())
- .WillOnce(Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
- EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
- dispatcher_->OnCanWrite();
-
- // And we'll resume where we left off when we get another call.
- EXPECT_CALL(*connection2(), OnCanWrite());
- dispatcher_->OnCanWrite();
-}
-
-TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
- // Make sure we call both writers. The first will register for more writing
- // but should not be immediately called due to limits.
- InSequence s;
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection2());
- EXPECT_CALL(*connection1(), OnCanWrite());
- EXPECT_CALL(*connection2(), OnCanWrite())
- .WillOnce(
- Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
- dispatcher_->OnCanWrite();
- EXPECT_TRUE(dispatcher_->HasPendingWrites());
-
- // Now call OnCanWrite again, and connection1 should get its second chance
- EXPECT_CALL(*connection2(), OnCanWrite());
- dispatcher_->OnCanWrite();
- EXPECT_FALSE(dispatcher_->HasPendingWrites());
-}
-
-TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
- // Finally make sure if we write block on a write call, we stop calling.
- InSequence s;
- SetBlocked();
- dispatcher_->OnWriteBlocked(connection1());
- dispatcher_->OnWriteBlocked(connection2());
- EXPECT_CALL(*connection1(), OnCanWrite())
- .WillOnce(Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
- EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
- dispatcher_->OnCanWrite();
- EXPECT_TRUE(dispatcher_->HasPendingWrites());
-
- // And we'll resume where we left off when we get another call.
- EXPECT_CALL(*connection2(), OnCanWrite());
- dispatcher_->OnCanWrite();
- EXPECT_FALSE(dispatcher_->HasPendingWrites());
-}
-
-// Tests that bufferring packets works in stateful reject, expensive stateless
-// reject and cheap stateless reject.
-struct BufferedPacketStoreTestParams {
- BufferedPacketStoreTestParams(bool enable_stateless_rejects_via_flag,
- bool support_cheap_stateless_reject)
- : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
- support_cheap_stateless_reject(support_cheap_stateless_reject) {}
-
- friend std::ostream& operator<<(std::ostream& os,
- const BufferedPacketStoreTestParams& p) {
- os << "{ enable_stateless_rejects_via_flag: "
- << p.enable_stateless_rejects_via_flag << std::endl;
- os << " support_cheap_stateless_reject: "
- << p.support_cheap_stateless_reject << " }";
- return os;
- }
-
- // This only enables the stateless reject feature via the feature-flag.
- // This should be a no-op if the peer does not support them.
- bool enable_stateless_rejects_via_flag;
- // Whether to do cheap stateless or not.
- bool support_cheap_stateless_reject;
-};
-
-std::vector<BufferedPacketStoreTestParams> GetBufferedPacketStoreTestParams() {
- std::vector<BufferedPacketStoreTestParams> params;
- for (bool enable_stateless_rejects_via_flag : {true, false}) {
- for (bool support_cheap_stateless_reject : {true, false}) {
- params.push_back(BufferedPacketStoreTestParams(
- enable_stateless_rejects_via_flag, support_cheap_stateless_reject));
- }
- }
- return params;
-}
-
-// A dispatcher whose stateless rejector will always ACCEPTs CHLO.
-class BufferedPacketStoreTest
- : public QuicDispatcherTest,
- public testing::WithParamInterface<BufferedPacketStoreTestParams> {
- public:
- BufferedPacketStoreTest()
- : QuicDispatcherTest(),
- client_addr_(QuicIpAddress::Loopback4(), 1234),
- signed_config_(new QuicSignedServerConfig) {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects,
- GetParam().support_cheap_stateless_reject);
- SetQuicReloadableFlag(enable_quic_stateless_reject_support,
- GetParam().enable_stateless_rejects_via_flag);
- }
-
- void SetUp() override {
- QuicDispatcherTest::SetUp();
- clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
-
- QuicTransportVersion version = AllSupportedTransportVersions().front();
- CryptoHandshakeMessage chlo =
- crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
- &crypto_config_);
- chlo.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ});
- // Pass an inchoate CHLO.
- crypto_test_utils::GenerateFullCHLO(
- chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
- signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &full_chlo_);
- }
-
- QuicString SerializeFullCHLO() {
- return string(
- full_chlo_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece());
- }
-
- protected:
- QuicSocketAddress server_addr_;
- QuicSocketAddress client_addr_;
- QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
- const QuicClock* clock_;
- CryptoHandshakeMessage full_chlo_;
-};
-
-INSTANTIATE_TEST_CASE_P(
- BufferedPacketStoreTests,
- BufferedPacketStoreTest,
- ::testing::ValuesIn(GetBufferedPacketStoreTestParams()));
-
-TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
- InSequence s;
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
- QuicConnectionId conn_id = 1;
- // A bunch of non-CHLO should be buffered upon arrival, and the first one
- // should trigger ShouldCreateOrBufferPacketForConnection().
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id))
- .Times(1);
- for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
- ProcessPacket(client_address, conn_id, true,
- QuicStrCat("data packet ", i + 1), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1);
- }
- EXPECT_EQ(0u, dispatcher_->session_map().size())
- << "No session should be created before CHLO arrives.";
-
- // Pop out the last packet as it is also be dropped by the store.
- data_connection_map_[conn_id].pop_back();
- // When CHLO arrives, a new session should be created, and all packets
- // buffered should be delivered to the session.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
-
- // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
- // should be delivered in arrival order.
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
- .WillOnce(
- WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
-}
-
-TEST_P(BufferedPacketStoreTest,
- ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
- InSequence s;
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
- // A bunch of non-CHLO should be buffered upon arrival.
- size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
- for (size_t i = 1; i <= kNumConnections; ++i) {
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
- QuicConnectionId conn_id = i;
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
- ProcessPacket(client_address, conn_id, true,
- QuicStrCat("data packet on connection ", i),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- /*packet_number=*/2);
- }
-
- // Pop out the packet on last connection as it shouldn't be enqueued in store
- // as well.
- data_connection_map_[kNumConnections].pop_front();
-
- // Reset session creation counter to ensure processing CHLO can always
- // create session.
- QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
- kNumConnections);
- // Process CHLOs to create session for these connections.
- for (size_t i = 1; i <= kNumConnections; ++i) {
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
- QuicConnectionId conn_id = i;
- if (conn_id == kNumConnections) {
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id));
- }
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- // First |kNumConnections| - 1 connections should have buffered
- // a packet in store. The rest should have been dropped.
- size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, client_address, _))
- .Times(num_packet_to_process)
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
-
- ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
- }
-}
-
-// Tests that store delivers empty packet list if CHLO arrives firstly.
-TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
- QuicConnectionId conn_id = 1;
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
-}
-
-// Tests that a retransmitted CHLO arrives after a connection for the
-// CHLO has been created.
-TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
- InSequence s;
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
- QuicConnectionId conn_id = 1;
- ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- /*packet_number=*/2);
-
- // When CHLO arrives, a new session should be created, and all packets
- // buffered should be delivered to the session.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_address, QuicStringPiece()))
- .Times(1) // Only triggered by 1st CHLO.
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(3) // Triggered by 1 data packet and 2 CHLOs.
- .WillOnce(
- WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
-
- ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
-}
-
-// Tests that expiration of a connection add connection id to time wait list.
-TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
- InSequence s;
- CreateTimeWaitListManager();
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
- QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
- QuicConnectionId conn_id = 1;
- ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- /*packet_number=*/2);
-
- mock_helper_.AdvanceTime(
- QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
- QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
- // Cancel alarm as if it had been fired.
- alarm->Cancel();
- store->OnExpirationTimeout();
- // New arrived CHLO will be dropped because this connection is in time wait
- // list.
- ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id));
- ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
-}
-
-TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
- // Process more than (|kMaxNumSessionsToCreate| +
- // |kDefaultMaxConnectionsInStore|) CHLOs,
- // the first |kMaxNumSessionsToCreate| should create connections immediately,
- // the next |kDefaultMaxConnectionsInStore| should be buffered,
- // the rest should be dropped.
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
- const size_t kNumCHLOs =
- kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
- for (size_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
- if (conn_id <= kMaxNumSessionsToCreate) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(
- *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
- conn_id > kMaxNumSessionsToCreate) {
- EXPECT_TRUE(store->HasChloForConnection(conn_id));
- } else {
- // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
- // connections immediately, and the last CHLO should be dropped as the
- // store is full.
- EXPECT_FALSE(store->HasChloForConnection(conn_id));
- }
- }
-
- // Graduately consume buffered CHLOs. The buffered connections should be
- // created but the dropped one shouldn't.
- for (size_t conn_id = kMaxNumSessionsToCreate + 1;
- conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
- ++conn_id) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(kNumCHLOs, client_addr_, QuicStringPiece()))
- .Times(0);
-
- while (store->HasChlosBuffered()) {
- dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
- }
-
- EXPECT_EQ(static_cast<size_t>(kMaxNumSessionsToCreate) +
- kDefaultMaxConnectionsInStore,
- session1_->connection_id());
-}
-
-// Duplicated CHLO shouldn't be buffered.
-TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
- for (QuicConnectionId conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
- ++conn_id) {
- // Last CHLO will be buffered. Others will create connection right away.
- if (conn_id <= kMaxNumSessionsToCreate) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(
- *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- }
- // Retransmit CHLO on last connection should be dropped.
- QuicConnectionId last_connection = kMaxNumSessionsToCreate + 1;
- ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
-
- size_t packets_buffered = 2;
-
- // Reset counter and process buffered CHLO.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
- QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, last_connection, client_addr_,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- // Only one packet(CHLO) should be process.
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(packets_buffered)
- .WillOnce(WithArg<2>(
- Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
- ValidatePacket(last_connection, packet);
- })));
- dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
-}
-
-TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
- QuicConnectionId last_connection_id = kMaxNumSessionsToCreate + 1;
- for (QuicConnectionId conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
- // Last CHLO will be buffered. Others will create connection right away.
- if (conn_id <= kMaxNumSessionsToCreate) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(
- *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- }
-
- // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
- // last one should be dropped.
- for (QuicPacketNumber packet_number = 2;
- packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
- ProcessPacket(client_addr_, last_connection_id, true, "data packet");
- }
-
- // Reset counter and process buffered CHLO.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
- QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, last_connection_id, client_addr_,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
- // should be process.
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(kDefaultMaxUndecryptablePackets + 1)
- .WillOnce(WithArg<2>(
- Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(last_connection_id, packet);
- })));
- dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
-}
-
-// Tests that when dispatcher's packet buffer is full, a CHLO on connection
-// which doesn't have buffered CHLO should be buffered.
-TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- QuicConnectionId conn_id = 1;
- ProcessPacket(client_addr_, conn_id, true, "data packet",
- PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- /*packet_number=*/1);
- // Fill packet buffer to full with CHLOs on other connections. Need to feed
- // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
- // session directly.
- for (conn_id = 2;
- conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
- ++conn_id) {
- if (conn_id <= kMaxNumSessionsToCreate + 1) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece()))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
- &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(
- *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- }
- EXPECT_FALSE(store->HasChloForConnection(/*connection_id=*/1));
-
- // CHLO on connection 1 should still be buffered.
- ProcessPacket(client_addr_, /*connection_id=*/1, true, SerializeFullCHLO());
- EXPECT_TRUE(store->HasChloForConnection(/*connection_id=*/1));
-}
-
-// Test which exercises the async GetProof codepaths, especially in the context
-// of stateless rejection.
-class AsyncGetProofTest : public QuicDispatcherTest {
- public:
- AsyncGetProofTest()
- : QuicDispatcherTest(
- std::unique_ptr<FakeProofSource>(new FakeProofSource())),
- client_addr_(QuicIpAddress::Loopback4(), 1234),
- client_addr_2_(QuicIpAddress::Loopback4(), 1357),
- crypto_config_peer_(&crypto_config_),
- signed_config_(new QuicSignedServerConfig) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
- }
-
- void SetUp() override {
- QuicDispatcherTest::SetUp();
-
- clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
- QuicTransportVersion version = AllSupportedTransportVersions().front();
- chlo_ = crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
- &crypto_config_);
- chlo_.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ});
- chlo_.SetStringPiece(kALPN, "HTTP/1");
- // Pass an inchoate CHLO.
- crypto_test_utils::GenerateFullCHLO(
- chlo_, &crypto_config_, server_addr_, client_addr_, version, clock_,
- signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &full_chlo_);
-
- crypto_test_utils::GenerateFullCHLO(
- chlo_, &crypto_config_, server_addr_, client_addr_2_, version, clock_,
- signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &full_chlo_2_);
-
- GetFakeProofSource()->Activate();
- }
-
- FakeProofSource* GetFakeProofSource() const {
- return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
- }
-
- QuicString SerializeFullCHLO() {
- return QuicString(
- full_chlo_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece());
- }
-
- QuicString SerializeFullCHLOForClient2() {
- return QuicString(
- full_chlo_2_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece());
- }
-
- QuicString SerializeCHLO() {
- return string(chlo_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece());
- }
-
- // Sets up a session, and crypto stream based on the test parameters.
- QuicServerSessionBase* GetSession(QuicConnectionId connection_id,
- QuicSocketAddress client_address) {
- auto it = sessions_.find(connection_id);
- if (it != sessions_.end()) {
- return it->second.session;
- }
-
- TestQuicSpdyServerSession* session;
- CreateSession(dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session);
-
- std::unique_ptr<MockQuicCryptoServerStream> crypto_stream(
- new MockQuicCryptoServerStream(
- crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- session, session->stream_helper()));
- session->SetCryptoStream(crypto_stream.get());
- crypto_stream->SetPeerSupportsStatelessRejects(true);
- const bool ok =
- sessions_
- .insert(std::make_pair(
- connection_id, SessionInfo{session, std::move(crypto_stream)}))
- .second;
- CHECK(ok);
- return session;
- }
-
- protected:
- const QuicSocketAddress client_addr_;
- const QuicSocketAddress client_addr_2_;
-
- private:
- QuicCryptoServerConfigPeer crypto_config_peer_;
- QuicSocketAddress server_addr_;
- QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
- const QuicClock* clock_;
- CryptoHandshakeMessage chlo_;
- CryptoHandshakeMessage full_chlo_; // CHLO for client_addr_
- CryptoHandshakeMessage full_chlo_2_; // CHLO for client_addr_2_
-
- struct SessionInfo {
- TestQuicSpdyServerSession* session;
- std::unique_ptr<MockQuicCryptoServerStream> crypto_stream;
- };
- std::map<QuicConnectionId, SessionInfo> sessions_;
-};
-
-// Test a simple situation of connections which the StatelessRejector will
-// accept.
-TEST_F(AsyncGetProofTest, BasicAccept) {
- QuicConnectionId conn_id = 1;
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
-
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_,
- QuicStringPiece("HTTP/1")))
- .WillOnce(testing::Return(GetSession(conn_id, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- check.Call(1);
- // Complete the ProofSource::GetProof call and verify that a session is
- // created.
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-
- check.Call(2);
- // Verify that a data packet gets processed immediately.
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
-}
-
-TEST_F(AsyncGetProofTest, RestorePacketContext) {
- QuicConnectionId conn_id_1 = 1;
- QuicConnectionId conn_id_2 = 2;
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1));
-
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_,
- QuicStringPiece("HTTP/1")))
- .WillOnce(testing::Return(GetSession(conn_id_1, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_1, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillRepeatedly(WithArg<2>(
- Invoke([this, conn_id_1](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_1, packet);
- })));
-
- EXPECT_CALL(check, Call(2));
-
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_2));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_2_,
- QuicStringPiece("HTTP/1")))
- .WillOnce(testing::Return(GetSession(conn_id_2, client_addr_2_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_2, client_addr_2_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_2, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Send another CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_2_, conn_id_2, true, SerializeFullCHLOForClient2());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the first ProofSource::GetProof call and verify that a session is
- // created.
- check.Call(1);
-
- EXPECT_EQ(client_addr_2_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_2_, dispatcher_->current_peer_address());
-
- // Runs the async proof callback for conn_id_1 from client_addr_.
- GetFakeProofSource()->InvokePendingCallback(0);
-
- EXPECT_EQ(client_addr_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_, dispatcher_->current_peer_address());
-
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Complete the second ProofSource::GetProof call and verify that a session is
- // created.
- check.Call(2);
-
- EXPECT_EQ(client_addr_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_, dispatcher_->current_peer_address());
-
- // Runs the async proof callback for conn_id_2 from client_addr_2_.
- GetFakeProofSource()->InvokePendingCallback(0);
-
- EXPECT_EQ(client_addr_2_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_2_, dispatcher_->current_peer_address());
-
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-}
-
-// Test a simple situation of connections which the StatelessRejector will
-// reject.
-TEST_F(AsyncGetProofTest, BasicReject) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id = 1;
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id, _, _, true, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece("hq")))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id));
- }
-
- // Send a CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Complete the ProofSource::GetProof call and verify that the connection and
- // packet are processed by the time wait list manager.
- check.Call(1);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-
- // Verify that a data packet is passed to the time wait list manager.
- check.Call(2);
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
-}
-
-// Test a situation with multiple interleaved connections which the
-// StatelessRejector will accept.
-TEST_F(AsyncGetProofTest, MultipleAccept) {
- QuicConnectionId conn_id_1 = 1;
- QuicConnectionId conn_id_2 = 2;
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_2));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_,
- QuicStringPiece("HTTP/1")))
- .WillOnce(testing::Return(GetSession(conn_id_2, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_2, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_2, packet);
- })));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_2, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_2, packet);
- })));
-
- EXPECT_CALL(check, Call(3));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1));
-
- EXPECT_CALL(check, Call(4));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_,
- QuicStringPiece("HTTP/1")))
- .WillOnce(testing::Return(GetSession(conn_id_1, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_1, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillRepeatedly(WithArg<2>(
- Invoke([this, conn_id_1](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_1, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Send another CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id_2, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the second ProofSource::GetProof call and verify that a session is
- // created.
- check.Call(1);
- GetFakeProofSource()->InvokePendingCallback(1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Verify that a data packet on that connection gets processed immediately.
- check.Call(2);
- ProcessPacket(client_addr_, conn_id_2, true, "My name is Data");
-
- // Verify that a data packet on the other connection does not get processed
- // yet.
- check.Call(3);
- ProcessPacket(client_addr_, conn_id_1, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
-
- // Complete the first ProofSource::GetProof call and verify that a session is
- // created and the buffered packet is processed.
- check.Call(4);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-}
-
-// Test a situation with multiple interleaved connections which the
-// StatelessRejector will reject.
-TEST_F(AsyncGetProofTest, MultipleReject) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id_1 = 1;
- QuicConnectionId conn_id_2 = 2;
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
-
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_, _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id_2, _, _, true, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_2));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_2));
-
- EXPECT_CALL(check, Call(3));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1));
-
- EXPECT_CALL(check, Call(4));
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id_1, _, _, true, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_1));
- }
-
- // Send a CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Send another CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id_2, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the second ProofSource::GetProof call and verify that the
- // connection and packet are processed by the time wait manager.
- check.Call(1);
- GetFakeProofSource()->InvokePendingCallback(1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Verify that a data packet on that connection gets processed immediately by
- // the time wait manager.
- check.Call(2);
- ProcessPacket(client_addr_, conn_id_2, true, "My name is Data");
-
- // Verify that a data packet on the first connection gets buffered.
- check.Call(3);
- ProcessPacket(client_addr_, conn_id_1, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
-
- // Complete the first ProofSource::GetProof call and verify that the CHLO is
- // processed by the time wait manager and the remaining packets are discarded.
- check.Call(4);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
-}
-
-// Test a situation with multiple identical CHLOs which the StatelessRejector
-// will reject.
-TEST_F(AsyncGetProofTest, MultipleIdenticalReject) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id_1 = 1;
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id_1, client_addr_, QuicStringPiece()))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id_1, _, _, true, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_1));
- }
-
- // Send a CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
-
- // Send an identical CHLO which should get buffered.
- check.Call(1);
- ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
-
- // Complete the ProofSource::GetProof call and verify that the CHLO is
- // rejected and the copy is discarded.
- check.Call(2);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
-}
-
-// Test dispatcher behavior when packets time out of the buffer while CHLO
-// validation is still pending.
-TEST_F(AsyncGetProofTest, BufferTimeout) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id = 1;
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
- QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece()))
- .Times(0);
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
-
- // Send a data packet that will get buffered
- check.Call(1);
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id));
-
- // Pretend that enough time has gone by for the packets to get expired out of
- // the buffer
- mock_helper_.AdvanceTime(
- QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
- QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel();
- store->OnExpirationTimeout();
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-
- // Now allow the CHLO validation to complete, and verify that no connection
- // gets created.
- check.Call(2);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-}
-
-// Test behavior when packets time out of the buffer *and* the connection times
-// out of the time wait manager while CHLO validation is still pending. This
-// *should* be impossible, but anything can happen with timing conditions.
-TEST_F(AsyncGetProofTest, TimeWaitTimeout) {
- QuicConnectionId conn_id = 1;
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
- QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
- CreateTimeWaitListManager();
- QuicTimeWaitListManagerPeer::set_clock(time_wait_list_manager_,
- mock_helper_.GetClock());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_,
- QuicStringPiece("HTTP/1")))
- .WillOnce(testing::Return(GetSession(conn_id, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
-
- // Send a data packet that will get buffered
- check.Call(1);
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id));
-
- // Pretend that enough time has gone by for the packets to get expired out of
- // the buffer
- mock_helper_.AdvanceTime(
- QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
- QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel();
- store->OnExpirationTimeout();
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-
- // Pretend that enough time has gone by for the connection ID to be removed
- // from the time wait manager
- mock_helper_.AdvanceTime(
- QuicTimeWaitListManagerPeer::time_wait_period(time_wait_list_manager_));
- QuicTimeWaitListManagerPeer::expiration_alarm(time_wait_list_manager_)
- ->Cancel();
- time_wait_list_manager_->CleanUpOldConnectionIds();
- EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-
- // Now allow the CHLO validation to complete. Expect that a connection is
- // indeed created, since QUIC has forgotten that this connection ever existed.
- // This is a miniscule corner case which should never happen in the wild, so
- // really we are just verifying that the dispatcher does not explode in this
- // situation.
- check.Call(2);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-}
-
-// Regression test for
-// https://bugs.chromium.org/p/chromium/issues/detail?id=748289
-TEST_F(AsyncGetProofTest, DispatcherFailedToPickUpVersionForAsyncProof) {
- // This test mimics the scenario that dispatcher's framer can have different
- // version when async proof returns.
- // When dispatcher sends SREJ, the SREJ frame can be serialized in
- // different endianness which causes the client to close the connection
- // because of QUIC_INVALID_STREAM_DATA.
-
- // Send a CHLO with v39. Dispatcher framer's version is set to v39.
- ProcessPacket(client_addr_, 1, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Send another CHLO with v35. Dispatcher framer's version is set to v35.
- ProcessPacket(client_addr_, 2, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the ProofSource::GetProof call for v39. This would cause the
- // version mismatch between the CHLO packet and the dispatcher.
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-}
-
-} // namespace
-} // namespace test
-} // namespace net