blob: 8e7e27875463ac2193246b9855c96a37ef158463 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
6
7#include <memory>
8#include <ostream>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
bnc463f2352019-10-10 04:49:34 -070010#include <utility>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
13#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
14#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
15#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
16#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
17#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
18#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
19#include "net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h"
20#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
21#include "net/third_party/quiche/src/quic/core/quic_types.h"
22#include "net/third_party/quiche/src/quic/core/quic_utils.h"
dschinazi41616842020-01-21 15:46:11 -080023#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050024#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
28#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
29#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
30#include "net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
35#include "net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h"
36#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
bnc4e9283d2019-12-17 07:08:57 -080037#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080038#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
dmcardle8f7df532020-01-07 13:28:57 -080039#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050040
41using testing::_;
wub89490e02019-12-12 12:45:58 -080042using testing::ByMove;
QUICHE teama6ef0a62019-03-07 20:34:33 -050043using testing::InSequence;
44using testing::Invoke;
45using testing::NiceMock;
46using testing::Return;
47using testing::WithArg;
48using testing::WithoutArgs;
49
50static const size_t kDefaultMaxConnectionsInStore = 100;
51static const size_t kMaxConnectionsWithoutCHLO =
52 kDefaultMaxConnectionsInStore / 2;
53static const int16_t kMaxNumSessionsToCreate = 16;
54
55namespace quic {
56namespace test {
57namespace {
58
59class TestQuicSpdyServerSession : public QuicServerSessionBase {
60 public:
61 TestQuicSpdyServerSession(const QuicConfig& config,
62 QuicConnection* connection,
63 const QuicCryptoServerConfig* crypto_config,
64 QuicCompressedCertsCache* compressed_certs_cache)
65 : QuicServerSessionBase(config,
66 CurrentSupportedVersions(),
67 connection,
68 nullptr,
69 nullptr,
70 crypto_config,
fayang63a19842020-01-23 02:51:28 -080071 compressed_certs_cache) {
72 Initialize();
73 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050074 TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
75 TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
76 delete;
77
ianswett6aefa0b2019-12-10 07:26:15 -080078 ~TestQuicSpdyServerSession() override { DeleteConnection(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -050079
fkastenholz5d880a92019-06-21 09:01:56 -070080 MOCK_METHOD2(OnConnectionClosed,
81 void(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -050082 ConnectionCloseSource source));
83 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
renjietangbaea59c2019-05-29 15:08:14 -070084 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(PendingStream* pending));
QUICHE teama6ef0a62019-03-07 20:34:33 -050085 MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*());
86 MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
87
nharpere5e28f92020-01-03 14:10:07 -080088 std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -050089 const QuicCryptoServerConfig* crypto_config,
90 QuicCompressedCertsCache* compressed_certs_cache) override {
nharpere5e28f92020-01-03 14:10:07 -080091 return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
92 stream_helper());
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 }
94
QUICHE teama6ef0a62019-03-07 20:34:33 -050095 QuicCryptoServerStream::Helper* stream_helper() {
96 return QuicServerSessionBase::stream_helper();
97 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050098};
99
100class TestDispatcher : public QuicDispatcher {
101 public:
102 TestDispatcher(const QuicConfig* config,
103 const QuicCryptoServerConfig* crypto_config,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700104 QuicVersionManager* version_manager,
105 QuicRandom* random)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106 : QuicDispatcher(config,
107 crypto_config,
108 version_manager,
vasilvv0fc587f2019-09-06 13:33:08 -0700109 std::make_unique<MockQuicConnectionHelper>(),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110 std::unique_ptr<QuicCryptoServerStream::Helper>(
wub662a3d62019-08-16 14:10:50 -0700111 new QuicSimpleCryptoServerStreamHelper()),
vasilvv0fc587f2019-09-06 13:33:08 -0700112 std::make_unique<MockAlarmFactory>(),
wub662a3d62019-08-16 14:10:50 -0700113 kQuicDefaultConnectionIdLength),
114 random_(random) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115
wub89490e02019-12-12 12:45:58 -0800116 MOCK_METHOD4(
117 CreateQuicSession,
118 std::unique_ptr<QuicSession>(QuicConnectionId connection_id,
119 const QuicSocketAddress& peer_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800120 quiche::QuicheStringPiece alpn,
wub89490e02019-12-12 12:45:58 -0800121 const quic::ParsedQuicVersion& version));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122
fayang1ed1f762019-06-24 11:40:04 -0700123 MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
124 bool(const ReceivedPacketInfo& packet_info));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125
126 struct TestQuicPerPacketContext : public QuicPerPacketContext {
vasilvvc48c8712019-03-11 13:38:16 -0700127 std::string custom_packet_context;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 };
129
130 std::unique_ptr<QuicPerPacketContext> GetPerPacketContext() const override {
vasilvv0fc587f2019-09-06 13:33:08 -0700131 auto test_context = std::make_unique<TestQuicPerPacketContext>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132 test_context->custom_packet_context = custom_packet_context_;
133 return std::move(test_context);
134 }
135
136 void RestorePerPacketContext(
137 std::unique_ptr<QuicPerPacketContext> context) override {
138 TestQuicPerPacketContext* test_context =
139 static_cast<TestQuicPerPacketContext*>(context.get());
140 custom_packet_context_ = test_context->custom_packet_context;
141 }
142
vasilvvc48c8712019-03-11 13:38:16 -0700143 std::string custom_packet_context_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144
dschinazi7b9278c2019-05-20 07:36:21 -0700145 using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146 using QuicDispatcher::writer;
wub662a3d62019-08-16 14:10:50 -0700147
148 QuicRandom* random_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149};
150
151// A Connection class which unregisters the session from the dispatcher when
152// sending connection close.
153// It'd be slightly more realistic to do this from the Session but it would
154// involve a lot more mocking.
155class MockServerConnection : public MockQuicConnection {
156 public:
157 MockServerConnection(QuicConnectionId connection_id,
158 MockQuicConnectionHelper* helper,
159 MockAlarmFactory* alarm_factory,
160 QuicDispatcher* dispatcher)
161 : MockQuicConnection(connection_id,
162 helper,
163 alarm_factory,
164 Perspective::IS_SERVER),
165 dispatcher_(dispatcher) {}
166
167 void UnregisterOnConnectionClosed() {
168 QUIC_LOG(ERROR) << "Unregistering " << connection_id();
169 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
170 "Unregistering.",
171 ConnectionCloseSource::FROM_SELF);
172 }
173
174 private:
175 QuicDispatcher* dispatcher_;
176};
177
178class QuicDispatcherTest : public QuicTest {
179 public:
180 QuicDispatcherTest()
181 : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
182
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183 explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
wub662a3d62019-08-16 14:10:50 -0700184 : version_manager_(AllSupportedVersions()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 crypto_config_(QuicCryptoServerConfig::TESTING,
186 QuicRandom::GetInstance(),
187 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -0700188 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189 server_address_(QuicIpAddress::Any4(), 5),
QUICHE teamc65d1d12019-03-19 20:58:04 -0700190 dispatcher_(
191 new NiceMock<TestDispatcher>(&config_,
192 &crypto_config_,
193 &version_manager_,
194 mock_helper_.GetRandomGenerator())),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 time_wait_list_manager_(nullptr),
196 session1_(nullptr),
197 session2_(nullptr),
fayangb880b4c2019-06-14 12:26:35 -0700198 store_(nullptr),
199 connection_id_(1) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500200
201 void SetUp() override {
202 dispatcher_->InitializeWithWriter(new MockPacketWriter());
203 // Set the counter to some value to start with.
204 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
205 dispatcher_.get(), kMaxNumSessionsToCreate);
fayang1ed1f762019-06-24 11:40:04 -0700206 ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500207 .WillByDefault(Return(true));
208 }
209
210 MockQuicConnection* connection1() {
211 if (session1_ == nullptr) {
212 return nullptr;
213 }
214 return reinterpret_cast<MockQuicConnection*>(session1_->connection());
215 }
216
217 MockQuicConnection* connection2() {
218 if (session2_ == nullptr) {
219 return nullptr;
220 }
221 return reinterpret_cast<MockQuicConnection*>(session2_->connection());
222 }
223
224 // Process a packet with an 8 byte connection id,
225 // 6 byte packet number, default path id, and packet number 1,
226 // using the first supported version.
227 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700228 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700230 const std::string& data) {
dschinazi346b7ce2019-06-05 01:38:18 -0700231 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500232 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER);
233 }
234
235 // Process a packet with a default path id, and packet number 1,
236 // using the first supported version.
237 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700238 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500239 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700240 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700241 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500242 QuicPacketNumberLength packet_number_length) {
dschinazi346b7ce2019-06-05 01:38:18 -0700243 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
244 server_connection_id_included, packet_number_length, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245 }
246
247 // Process a packet using the first supported version.
248 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700249 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700251 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700252 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253 QuicPacketNumberLength packet_number_length,
254 uint64_t packet_number) {
dschinazi346b7ce2019-06-05 01:38:18 -0700255 ProcessPacket(peer_address, server_connection_id, has_version_flag,
fayange3f2f7b2019-09-19 17:01:57 -0700256 CurrentSupportedVersions().front(), data, true,
dschinazi346b7ce2019-06-05 01:38:18 -0700257 server_connection_id_included, packet_number_length,
258 packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500259 }
260
261 // Processes a packet.
262 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700263 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500264 bool has_version_flag,
265 ParsedQuicVersion version,
vasilvvc48c8712019-03-11 13:38:16 -0700266 const std::string& data,
fayange3f2f7b2019-09-19 17:01:57 -0700267 bool full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700268 QuicConnectionIdIncluded server_connection_id_included,
269 QuicPacketNumberLength packet_number_length,
270 uint64_t packet_number) {
271 ProcessPacket(peer_address, server_connection_id, EmptyQuicConnectionId(),
fayange3f2f7b2019-09-19 17:01:57 -0700272 has_version_flag, version, data, full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700273 server_connection_id_included, CONNECTION_ID_ABSENT,
274 packet_number_length, packet_number);
275 }
276
277 // Processes a packet.
278 void ProcessPacket(QuicSocketAddress peer_address,
279 QuicConnectionId server_connection_id,
280 QuicConnectionId client_connection_id,
281 bool has_version_flag,
282 ParsedQuicVersion version,
283 const std::string& data,
fayange3f2f7b2019-09-19 17:01:57 -0700284 bool full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700285 QuicConnectionIdIncluded server_connection_id_included,
286 QuicConnectionIdIncluded client_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500287 QuicPacketNumberLength packet_number_length,
288 uint64_t packet_number) {
289 ParsedQuicVersionVector versions(SupportedVersions(version));
290 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700291 server_connection_id, client_connection_id, has_version_flag, false,
fayange3f2f7b2019-09-19 17:01:57 -0700292 packet_number, data, full_padding, server_connection_id_included,
dschinazi346b7ce2019-06-05 01:38:18 -0700293 client_connection_id_included, packet_number_length, &versions));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 std::unique_ptr<QuicReceivedPacket> received_packet(
295 ConstructReceivedPacket(*packet, mock_helper_.GetClock()->Now()));
296
dschinazi4fd8cb12019-09-09 16:31:06 -0700297 if (ChloExtractor::Extract(*packet, version, {}, nullptr,
dschinazi346b7ce2019-06-05 01:38:18 -0700298 server_connection_id.length())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500299 // Add CHLO packet to the beginning to be verified first, because it is
300 // also processed first by new session.
dschinazi346b7ce2019-06-05 01:38:18 -0700301 data_connection_map_[server_connection_id].push_front(
vasilvvc48c8712019-03-11 13:38:16 -0700302 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500303 } else {
304 // For non-CHLO, always append to last.
dschinazi346b7ce2019-06-05 01:38:18 -0700305 data_connection_map_[server_connection_id].push_back(
vasilvvc48c8712019-03-11 13:38:16 -0700306 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500307 }
308 dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet);
309 }
310
311 void ValidatePacket(QuicConnectionId conn_id,
312 const QuicEncryptedPacket& packet) {
313 EXPECT_EQ(data_connection_map_[conn_id].front().length(),
314 packet.AsStringPiece().length());
315 EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
316 data_connection_map_[conn_id].pop_front();
317 }
318
wub89490e02019-12-12 12:45:58 -0800319 std::unique_ptr<QuicSession> CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500320 TestDispatcher* dispatcher,
321 const QuicConfig& config,
322 QuicConnectionId connection_id,
dschinazi17d42422019-06-18 16:35:07 -0700323 const QuicSocketAddress& /*peer_address*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500324 MockQuicConnectionHelper* helper,
325 MockAlarmFactory* alarm_factory,
326 const QuicCryptoServerConfig* crypto_config,
327 QuicCompressedCertsCache* compressed_certs_cache,
wub89490e02019-12-12 12:45:58 -0800328 TestQuicSpdyServerSession** session_ptr) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500329 MockServerConnection* connection = new MockServerConnection(
330 connection_id, helper, alarm_factory, dispatcher);
331 connection->SetQuicPacketWriter(dispatcher->writer(),
332 /*owns_writer=*/false);
wub89490e02019-12-12 12:45:58 -0800333 auto session = std::make_unique<TestQuicSpdyServerSession>(
334 config, connection, crypto_config, compressed_certs_cache);
335 *session_ptr = session.get();
336 connection->set_visitor(session.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500337 ON_CALL(*connection, CloseConnection(_, _, _))
338 .WillByDefault(WithoutArgs(Invoke(
339 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
wub89490e02019-12-12 12:45:58 -0800340 return session;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500341 }
342
343 void CreateTimeWaitListManager() {
344 time_wait_list_manager_ = new MockTimeWaitListManager(
345 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
346 mock_helper_.GetClock(), &mock_alarm_factory_);
347 // dispatcher_ takes the ownership of time_wait_list_manager_.
348 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
349 time_wait_list_manager_);
350 }
351
vasilvvc48c8712019-03-11 13:38:16 -0700352 std::string SerializeCHLO() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500353 CryptoHandshakeMessage client_hello;
354 client_hello.set_tag(kCHLO);
355 client_hello.SetStringPiece(kALPN, "hq");
vasilvvc48c8712019-03-11 13:38:16 -0700356 return std::string(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500357 }
358
QUICHE teama6ef0a62019-03-07 20:34:33 -0500359 void MarkSession1Deleted() { session1_ = nullptr; }
360
fayangb880b4c2019-06-14 12:26:35 -0700361 void VerifyVersionSupported(ParsedQuicVersion version) {
362 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
363 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800364 EXPECT_CALL(*dispatcher_,
365 CreateQuicSession(connection_id, client_address,
366 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800367 .WillOnce(Return(ByMove(CreateSession(
fayangb880b4c2019-06-14 12:26:35 -0700368 dispatcher_.get(), config_, connection_id, client_address,
369 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800370 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
fayangb880b4c2019-06-14 12:26:35 -0700371 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
372 ProcessUdpPacket(_, _, _))
373 .WillOnce(WithArg<2>(
374 Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
375 ValidatePacket(connection_id, packet);
376 })));
377 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700378 ShouldCreateOrBufferPacketForConnection(
379 ReceivedPacketInfoConnectionIdEquals(connection_id)));
fayangb880b4c2019-06-14 12:26:35 -0700380 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
fayange3f2f7b2019-09-19 17:01:57 -0700381 true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
fayangb880b4c2019-06-14 12:26:35 -0700382 }
383
384 void VerifyVersionNotSupported(ParsedQuicVersion version) {
385 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
386 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800387 EXPECT_CALL(*dispatcher_,
388 CreateQuicSession(connection_id, client_address,
389 quiche::QuicheStringPiece("hq"), _))
fayangb880b4c2019-06-14 12:26:35 -0700390 .Times(0);
391 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
fayange3f2f7b2019-09-19 17:01:57 -0700392 true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
fayangb880b4c2019-06-14 12:26:35 -0700393 }
394
QUICHE teama6ef0a62019-03-07 20:34:33 -0500395 MockQuicConnectionHelper mock_helper_;
396 MockAlarmFactory mock_alarm_factory_;
397 QuicConfig config_;
398 QuicVersionManager version_manager_;
399 QuicCryptoServerConfig crypto_config_;
400 QuicSocketAddress server_address_;
401 std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
402 MockTimeWaitListManager* time_wait_list_manager_;
403 TestQuicSpdyServerSession* session1_;
404 TestQuicSpdyServerSession* session2_;
vasilvvc48c8712019-03-11 13:38:16 -0700405 std::map<QuicConnectionId, std::list<std::string>> data_connection_map_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500406 QuicBufferedPacketStore* store_;
fayangb880b4c2019-06-14 12:26:35 -0700407 uint64_t connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500408};
409
410TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
dschinazi76881f02019-12-09 14:56:14 -0800411 if (CurrentSupportedVersions().front().handshake_protocol !=
412 PROTOCOL_TLS1_3) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413 return;
414 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500415 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
416
417 EXPECT_CALL(*dispatcher_,
418 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800419 quiche::QuicheStringPiece(""), _))
wub89490e02019-12-12 12:45:58 -0800420 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500421 dispatcher_.get(), config_, TestConnectionId(1), client_address,
422 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800423 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500424 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
425 ProcessUdpPacket(_, _, _))
426 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
427 ValidatePacket(TestConnectionId(1), packet);
428 })));
429 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700430 ShouldCreateOrBufferPacketForConnection(
431 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
dschinazi76881f02019-12-09 14:56:14 -0800432 ProcessPacket(client_address, TestConnectionId(1), true,
433 CurrentSupportedVersions().front(), SerializeCHLO(), true,
434 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500435}
436
437TEST_F(QuicDispatcherTest, ProcessPackets) {
438 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
439
440 EXPECT_CALL(*dispatcher_,
441 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800442 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800443 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500444 dispatcher_.get(), config_, TestConnectionId(1), client_address,
445 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800446 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500447 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
448 ProcessUdpPacket(_, _, _))
449 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
450 ValidatePacket(TestConnectionId(1), packet);
451 })));
452 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700453 ShouldCreateOrBufferPacketForConnection(
454 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500455 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500456
457 EXPECT_CALL(*dispatcher_,
458 CreateQuicSession(TestConnectionId(2), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800459 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800460 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500461 dispatcher_.get(), config_, TestConnectionId(2), client_address,
462 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800463 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500464 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
465 ProcessUdpPacket(_, _, _))
466 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
467 ValidatePacket(TestConnectionId(2), packet);
468 })));
469 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700470 ShouldCreateOrBufferPacketForConnection(
471 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500472 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
473
474 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
475 ProcessUdpPacket(_, _, _))
476 .Times(1)
477 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
478 ValidatePacket(TestConnectionId(1), packet);
479 })));
480 ProcessPacket(client_address, TestConnectionId(1), false, "data");
481}
482
483// Regression test of b/93325907.
484TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
485 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
486
487 EXPECT_CALL(*dispatcher_,
488 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800489 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800490 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500491 dispatcher_.get(), config_, TestConnectionId(1), client_address,
492 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800493 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500494 // Verify both packets 1 and 2 are processed by connection 1.
495 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
496 ProcessUdpPacket(_, _, _))
497 .Times(2)
498 .WillRepeatedly(
499 WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
500 ValidatePacket(TestConnectionId(1), packet);
501 })));
502 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700503 ShouldCreateOrBufferPacketForConnection(
504 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500505 ProcessPacket(
506 client_address, TestConnectionId(1), true,
507 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
508 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700509 SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
510 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500511 // Packet number 256 with packet number length 1 would be considered as 0 in
512 // dispatcher.
513 ProcessPacket(
514 client_address, TestConnectionId(1), false,
515 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
516 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700517 "", true, CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518}
519
520TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
521 CreateTimeWaitListManager();
522 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
523
524 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
dschinazi346b7ce2019-06-05 01:38:18 -0700525 EXPECT_CALL(
526 *time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700527 SendVersionNegotiationPacket(TestConnectionId(1), _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500528 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500529 // Pad the CHLO message with enough data to make the packet large enough
530 // to trigger version negotiation.
vasilvvc48c8712019-03-11 13:38:16 -0700531 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500532 DCHECK_LE(1200u, chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700533 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700534 QuicVersionReservedForNegotiation(), chlo, true,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500535 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
536}
537
dschinaziffa83552019-12-17 11:00:23 -0800538TEST_F(QuicDispatcherTest,
539 StatelessVersionNegotiationWithVeryLongConnectionId) {
dschinaziffa83552019-12-17 11:00:23 -0800540 QuicConnectionId connection_id = QuicUtils::CreateRandomConnectionId(33);
541 CreateTimeWaitListManager();
542 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
543
544 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
545 EXPECT_CALL(*time_wait_list_manager_,
546 SendVersionNegotiationPacket(connection_id, _, _, _, _, _, _, _))
547 .Times(1);
548 // Pad the CHLO message with enough data to make the packet large enough
549 // to trigger version negotiation.
550 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
551 DCHECK_LE(1200u, chlo.length());
552 ProcessPacket(client_address, connection_id, true,
553 QuicVersionReservedForNegotiation(), chlo, true,
554 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
555}
556
dschinazi346b7ce2019-06-05 01:38:18 -0700557TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
dschinazi346b7ce2019-06-05 01:38:18 -0700558 CreateTimeWaitListManager();
559 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
560
561 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
562 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700563 SendVersionNegotiationPacket(
564 TestConnectionId(1), TestConnectionId(2), _, _, _, _, _, _))
dschinazi346b7ce2019-06-05 01:38:18 -0700565 .Times(1);
566 // Pad the CHLO message with enough data to make the packet large enough
567 // to trigger version negotiation.
568 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
569 DCHECK_LE(1200u, chlo.length());
570 ProcessPacket(client_address, TestConnectionId(1), TestConnectionId(2), true,
fayange3f2f7b2019-09-19 17:01:57 -0700571 QuicVersionReservedForNegotiation(), chlo, true,
dschinazi346b7ce2019-06-05 01:38:18 -0700572 CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
573 PACKET_4BYTE_PACKET_NUMBER, 1);
574}
575
QUICHE teama6ef0a62019-03-07 20:34:33 -0500576TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
577 CreateTimeWaitListManager();
578 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
579
580 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
581 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700582 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583 .Times(0);
vasilvvc48c8712019-03-11 13:38:16 -0700584 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500585 // Truncate to 1100 bytes of payload which results in a packet just
586 // under 1200 bytes after framing, packet, and encryption overhead.
587 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700588 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500589 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700590 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700591 QuicVersionReservedForNegotiation(), truncated_chlo, false,
nharper4fd11052019-06-04 14:23:22 -0700592 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500593}
594
595// Disabling CHLO size validation allows the dispatcher to send version
596// negotiation packets in response to a CHLO that is otherwise too small.
597TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
598 crypto_config_.set_validate_chlo_size(false);
599
600 CreateTimeWaitListManager();
601 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
602
603 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
604 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700605 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500606 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -0700607 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500608 // Truncate to 1100 bytes of payload which results in a packet just
609 // under 1200 bytes after framing, packet, and encryption overhead.
610 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700611 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500612 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700613 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700614 QuicVersionReservedForNegotiation(), truncated_chlo, true,
nharper4fd11052019-06-04 14:23:22 -0700615 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500616}
617
618TEST_F(QuicDispatcherTest, Shutdown) {
619 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
620
dmcardlecf0bfcf2019-12-13 08:08:21 -0800621 EXPECT_CALL(
622 *dispatcher_,
623 CreateQuicSession(_, client_address, quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800624 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500625 dispatcher_.get(), config_, TestConnectionId(1), client_address,
626 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800627 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500628 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
629 ProcessUdpPacket(_, _, _))
630 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
631 ValidatePacket(TestConnectionId(1), packet);
632 })));
633
634 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700635 ShouldCreateOrBufferPacketForConnection(
636 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500637 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
638
639 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
640 CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
641
642 dispatcher_->Shutdown();
643}
644
645TEST_F(QuicDispatcherTest, TimeWaitListManager) {
646 CreateTimeWaitListManager();
647
648 // Create a new session.
649 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
650 QuicConnectionId connection_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800651 EXPECT_CALL(*dispatcher_,
652 CreateQuicSession(connection_id, client_address,
653 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800654 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500655 dispatcher_.get(), config_, connection_id, client_address,
656 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800657 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500658 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
659 ProcessUdpPacket(_, _, _))
660 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
661 ValidatePacket(TestConnectionId(1), packet);
662 })));
663
664 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700665 ShouldCreateOrBufferPacketForConnection(
666 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500667 ProcessPacket(client_address, connection_id, true, SerializeCHLO());
668
669 // Now close the connection, which should add it to the time wait list.
670 session1_->connection()->CloseConnection(
671 QUIC_INVALID_VERSION,
672 "Server: Packet 2 without version flag before version negotiated.",
673 ConnectionCloseBehavior::SILENT_CLOSE);
674 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
675
676 // Dispatcher forwards subsequent packets for this connection_id to the time
677 // wait list manager.
678 EXPECT_CALL(*time_wait_list_manager_,
679 ProcessPacket(_, _, connection_id, _, _))
680 .Times(1);
681 EXPECT_CALL(*time_wait_list_manager_,
682 AddConnectionIdToTimeWait(_, _, _, _, _))
683 .Times(0);
684 ProcessPacket(client_address, connection_id, true, "data");
685}
686
687TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
688 CreateTimeWaitListManager();
689
690 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
691 QuicConnectionId connection_id = TestConnectionId(1);
692 // Dispatcher forwards all packets for this connection_id to the time wait
693 // list manager.
dmcardlecf0bfcf2019-12-13 08:08:21 -0800694 EXPECT_CALL(*dispatcher_,
695 CreateQuicSession(_, _, quiche::QuicheStringPiece("hq"), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500696 .Times(0);
fayang9d6231c2019-12-04 07:10:13 -0800697 EXPECT_CALL(*time_wait_list_manager_,
698 ProcessPacket(_, _, connection_id, _, _))
699 .Times(0);
700 EXPECT_CALL(*time_wait_list_manager_,
701 AddConnectionIdToTimeWait(_, _, _, _, _))
702 .Times(0);
703 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
704 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500705 ProcessPacket(client_address, connection_id, false, SerializeCHLO());
706}
707
fayangd057e662019-07-10 13:29:41 -0700708TEST_F(QuicDispatcherTest,
709 DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
710 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
711 CreateTimeWaitListManager();
712
713 char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
714 QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
715 char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
716 QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
717 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
fayang9d6231c2019-12-04 07:10:13 -0800718 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
719 EXPECT_CALL(*time_wait_list_manager_,
720 AddConnectionIdToTimeWait(_, _, _, _, _))
721 .Times(0);
722 // Verify small packet is silently dropped.
723 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
724 .Times(0);
fayangd057e662019-07-10 13:29:41 -0700725 dispatcher_->ProcessPacket(server_address_, client_address, packet);
fayang9d6231c2019-12-04 07:10:13 -0800726 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
727 .Times(1);
fayangd057e662019-07-10 13:29:41 -0700728 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
729}
730
QUICHE teamc65d1d12019-03-19 20:58:04 -0700731// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
QUICHE team963d57e2019-03-21 10:58:47 -0700732TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
dschinazi97da52b2020-01-13 15:44:43 -0800733 if (!CurrentSupportedVersions()[0].AllowsVariableLengthConnectionIds()) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700734 // When variable length connection IDs are not supported, the connection
735 // fails. See StrayPacketTruncatedConnectionId.
QUICHE team8e2e4532019-03-14 14:37:56 -0700736 return;
737 }
QUICHE team8e2e4532019-03-14 14:37:56 -0700738 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
739
QUICHE teamc65d1d12019-03-19 20:58:04 -0700740 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700741 QuicConnectionId fixed_connection_id =
742 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700743
744 EXPECT_CALL(*dispatcher_,
745 CreateQuicSession(fixed_connection_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800746 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800747 .WillOnce(Return(ByMove(CreateSession(
QUICHE teamc65d1d12019-03-19 20:58:04 -0700748 dispatcher_.get(), config_, fixed_connection_id, client_address,
749 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800750 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700751 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
752 ProcessUdpPacket(_, _, _))
753 .WillOnce(WithArg<2>(
754 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
755 ValidatePacket(bad_connection_id, packet);
756 })));
757 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700758 ShouldCreateOrBufferPacketForConnection(
759 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700760 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700761}
762
QUICHE team963d57e2019-03-21 10:58:47 -0700763// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
764TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
dschinazi97da52b2020-01-13 15:44:43 -0800765 if (!CurrentSupportedVersions()[0].AllowsVariableLengthConnectionIds()) {
QUICHE team963d57e2019-03-21 10:58:47 -0700766 // When variable length connection IDs are not supported, the connection
767 // fails. See StrayPacketTruncatedConnectionId.
768 return;
769 }
770 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
771
772 QuicConnectionId bad_connection_id = EmptyQuicConnectionId();
dschinazi28c1bf32019-08-19 11:54:46 -0700773 QuicConnectionId fixed_connection_id =
774 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team963d57e2019-03-21 10:58:47 -0700775
776 // Disable validation of invalid short connection IDs.
dschinazi7b9278c2019-05-20 07:36:21 -0700777 dispatcher_->SetAllowShortInitialServerConnectionIds(true);
QUICHE team963d57e2019-03-21 10:58:47 -0700778 // Note that StrayPacketTruncatedConnectionId covers the case where the
779 // validation is still enabled.
780
781 EXPECT_CALL(*dispatcher_,
782 CreateQuicSession(fixed_connection_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800783 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800784 .WillOnce(Return(ByMove(CreateSession(
QUICHE team963d57e2019-03-21 10:58:47 -0700785 dispatcher_.get(), config_, fixed_connection_id, client_address,
786 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800787 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE team963d57e2019-03-21 10:58:47 -0700788 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
789 ProcessUdpPacket(_, _, _))
790 .WillOnce(WithArg<2>(
791 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
792 ValidatePacket(bad_connection_id, packet);
793 })));
794 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700795 ShouldCreateOrBufferPacketForConnection(
796 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE team963d57e2019-03-21 10:58:47 -0700797 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team963d57e2019-03-21 10:58:47 -0700798}
799
QUICHE teamc65d1d12019-03-19 20:58:04 -0700800// Makes sure TestConnectionId(1) creates a new connection and
801// TestConnectionIdNineBytesLong(2) gets replaced.
QUICHE team8e2e4532019-03-14 14:37:56 -0700802TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
dschinazi97da52b2020-01-13 15:44:43 -0800803 if (!CurrentSupportedVersions()[0].AllowsVariableLengthConnectionIds()) {
QUICHE team8e2e4532019-03-14 14:37:56 -0700804 return;
805 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700806
QUICHE team8e2e4532019-03-14 14:37:56 -0700807 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700808 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700809 QuicConnectionId fixed_connection_id =
810 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team8e2e4532019-03-14 14:37:56 -0700811
812 EXPECT_CALL(*dispatcher_,
813 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800814 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800815 .WillOnce(Return(ByMove(CreateSession(
QUICHE team8e2e4532019-03-14 14:37:56 -0700816 dispatcher_.get(), config_, TestConnectionId(1), client_address,
817 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800818 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700819 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
820 ProcessUdpPacket(_, _, _))
821 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
822 ValidatePacket(TestConnectionId(1), packet);
823 })));
824 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700825 ShouldCreateOrBufferPacketForConnection(
826 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700827 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700828
QUICHE teamc65d1d12019-03-19 20:58:04 -0700829 EXPECT_CALL(*dispatcher_,
830 CreateQuicSession(fixed_connection_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800831 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800832 .WillOnce(Return(ByMove(CreateSession(
QUICHE teamc65d1d12019-03-19 20:58:04 -0700833 dispatcher_.get(), config_, fixed_connection_id, client_address,
834 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800835 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700836 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
837 ProcessUdpPacket(_, _, _))
838 .WillOnce(WithArg<2>(
839 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
840 ValidatePacket(bad_connection_id, packet);
841 })));
842 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700843 ShouldCreateOrBufferPacketForConnection(
844 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700845 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700846
847 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
848 ProcessUdpPacket(_, _, _))
849 .Times(1)
850 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
851 ValidatePacket(TestConnectionId(1), packet);
852 })));
853 ProcessPacket(client_address, TestConnectionId(1), false, "data");
854}
855
QUICHE teama6ef0a62019-03-07 20:34:33 -0500856TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
857 CreateTimeWaitListManager();
858
859 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
860
861 // dispatcher_ should drop this packet.
862 EXPECT_CALL(*dispatcher_,
863 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800864 quiche::QuicheStringPiece("hq"), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500865 .Times(0);
866 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
867 EXPECT_CALL(*time_wait_list_manager_,
868 AddConnectionIdToTimeWait(_, _, _, _, _))
869 .Times(0);
870 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
871}
872
dschinaziee07e472019-06-19 09:56:56 -0700873TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
dschinazi8b1c45a2019-10-17 08:48:13 -0700874 // Enable a version that supports connection IDs of length different than 8.
dschinaziee07e472019-06-19 09:56:56 -0700875 CreateTimeWaitListManager();
876
877 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
878
879 // dispatcher_ should drop this packet.
dmcardlecf0bfcf2019-12-13 08:08:21 -0800880 EXPECT_CALL(
881 *dispatcher_,
882 CreateQuicSession(_, client_address, quiche::QuicheStringPiece("hq"), _))
dschinaziee07e472019-06-19 09:56:56 -0700883 .Times(0);
884 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
885 EXPECT_CALL(*time_wait_list_manager_,
886 AddConnectionIdToTimeWait(_, _, _, _, _))
887 .Times(0);
888 ProcessPacket(client_address, EmptyQuicConnectionId(), true, SerializeCHLO());
889}
890
QUICHE teama6ef0a62019-03-07 20:34:33 -0500891TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
892 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
893 QuicConnectionId connection_id = TestConnectionId(1);
894
895 EXPECT_CALL(*dispatcher_,
896 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800897 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800898 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500899 dispatcher_.get(), config_, TestConnectionId(1), client_address,
900 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800901 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500902 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
903 ProcessUdpPacket(_, _, _))
904 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
905 ValidatePacket(TestConnectionId(1), packet);
906 })));
907
908 // A packet whose packet number is the largest that is allowed to start a
909 // connection.
910 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700911 ShouldCreateOrBufferPacketForConnection(
912 ReceivedPacketInfoConnectionIdEquals(connection_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500913 ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
914 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
915 QuicDispatcher::kMaxReasonableInitialPacketNumber);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500916}
917
dschinazi76881f02019-12-09 14:56:14 -0800918TEST_F(QuicDispatcherTest, VersionsChangeInFlight) {
919 for (ParsedQuicVersion version : AllSupportedVersions()) {
920 QuicEnableVersion(version);
921 }
922 ASSERT_EQ(AllSupportedVersions(), CurrentSupportedVersions());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500923
fayangb880b4c2019-06-14 12:26:35 -0700924 VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
925
926 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
927 QuicVersionMin().transport_version));
dschinazi76881f02019-12-09 14:56:14 -0800928 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
929 QuicVersionMax().transport_version));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500930
dschinazi41616842020-01-21 15:46:11 -0800931 // Turn off version Q050.
932 SetQuicReloadableFlag(quic_disable_version_q050, true);
nharperc32d8ab2019-10-09 11:09:06 -0700933 VerifyVersionNotSupported(
dschinazi41616842020-01-21 15:46:11 -0800934 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
nharperc32d8ab2019-10-09 11:09:06 -0700935
dschinazi41616842020-01-21 15:46:11 -0800936 // Turn on version Q050.
937 SetQuicReloadableFlag(quic_disable_version_q050, false);
nharperc32d8ab2019-10-09 11:09:06 -0700938 VerifyVersionSupported(
dschinazi41616842020-01-21 15:46:11 -0800939 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500940}
941
fayangb54ac5b2019-07-01 10:30:37 -0700942TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
vasilvv228602e2020-02-06 01:11:49 -0800943 static_assert(SupportedTransportVersions().size() == 6u,
fayangb54ac5b2019-07-01 10:30:37 -0700944 "Please add deprecated versions to this test");
945 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
946 CreateTimeWaitListManager();
947
dschinazi8b1c45a2019-10-17 08:48:13 -0700948 {
949 char packet47[kMinPacketSizeForVersionNegotiation] = {
950 0xC0, 'Q', '0', '4', '7', /*connection ID length byte*/ 0x50};
951 QuicReceivedPacket received_packet47(
952 packet47, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
953 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
954 EXPECT_CALL(*time_wait_list_manager_,
955 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
956 .Times(1);
957 dispatcher_->ProcessPacket(server_address_, client_address,
958 received_packet47);
959 }
fayang36825da2019-08-21 14:01:27 -0700960
dschinazi8b1c45a2019-10-17 08:48:13 -0700961 {
962 char packet45[kMinPacketSizeForVersionNegotiation] = {
963 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
964 QuicReceivedPacket received_packet45(
965 packet45, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
966 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
967 EXPECT_CALL(*time_wait_list_manager_,
968 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
969 .Times(1);
970 dispatcher_->ProcessPacket(server_address_, client_address,
971 received_packet45);
972 }
973
974 {
975 char packet44[kMinPacketSizeForVersionNegotiation] = {
976 0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
977 QuicReceivedPacket received_packet44(
978 packet44, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
979 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
980 EXPECT_CALL(*time_wait_list_manager_,
981 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
982 .Times(1);
983 dispatcher_->ProcessPacket(server_address_, client_address,
984 received_packet44);
985 }
fayangb54ac5b2019-07-01 10:30:37 -0700986}
987
dschinazi30ab6db2019-08-13 14:43:32 -0700988TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
989 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi30ab6db2019-08-13 14:43:32 -0700990 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
991 CreateTimeWaitListManager();
992 char packet[1200];
993 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
994 0x6c, 0x7a, 0x20, 0x21};
995 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
996 packet, sizeof(packet), destination_connection_id_bytes,
997 sizeof(destination_connection_id_bytes)));
998 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
999 std::unique_ptr<QuicReceivedPacket> received_packet(
1000 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1001 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1002 QuicConnectionId server_connection_id(
1003 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1004 bool ietf_quic = true;
1005 bool use_length_prefix =
1006 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1007 EXPECT_CALL(
1008 *time_wait_list_manager_,
1009 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1010 ietf_quic, use_length_prefix, _, _, _, _))
1011 .Times(1);
1012 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1013
1014 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1015}
1016
1017TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
1018 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi30ab6db2019-08-13 14:43:32 -07001019 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1020 CreateTimeWaitListManager();
1021 char packet[1200];
1022 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1023 0x6c, 0x7a, 0x20, 0x21};
1024 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1025 packet, sizeof(packet), destination_connection_id_bytes,
1026 sizeof(destination_connection_id_bytes)));
1027 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1028 std::unique_ptr<QuicReceivedPacket> received_packet(
1029 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1030 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1031 QuicConnectionId server_connection_id(
1032 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1033 bool ietf_quic = true;
1034 bool use_length_prefix =
1035 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1036 EXPECT_CALL(
1037 *time_wait_list_manager_,
1038 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1039 ietf_quic, use_length_prefix, _, _, _, _))
1040 .Times(1);
1041 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1042
1043 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1044}
1045
dschinazi0185ebb2019-08-14 11:09:35 -07001046// Testing packet writer that saves all packets instead of sending them.
1047// Useful for tests that need access to sent packets.
1048class SavingWriter : public QuicPacketWriterWrapper {
1049 public:
1050 bool IsWriteBlocked() const override { return false; }
1051
1052 WriteResult WritePacket(const char* buffer,
1053 size_t buf_len,
1054 const QuicIpAddress& /*self_client_address*/,
1055 const QuicSocketAddress& /*peer_client_address*/,
1056 PerPacketOptions* /*options*/) override {
1057 packets_.push_back(
1058 QuicEncryptedPacket(buffer, buf_len, /*owns_buffer=*/false).Clone());
1059 return WriteResult(WRITE_STATUS_OK, buf_len);
1060 }
1061
1062 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
1063 return &packets_;
1064 }
1065
1066 private:
1067 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
1068};
1069
1070TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
1071 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi0185ebb2019-08-14 11:09:35 -07001072
1073 SavingWriter* saving_writer = new SavingWriter();
1074 // dispatcher_ takes ownership of saving_writer.
1075 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1076
1077 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1078 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1079 &mock_alarm_factory_);
1080 // dispatcher_ takes ownership of time_wait_list_manager.
1081 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1082 time_wait_list_manager);
1083 char packet[1200] = {};
1084 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1085 0x6c, 0x7a, 0x20, 0x21};
1086 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1087 packet, sizeof(packet), destination_connection_id_bytes,
1088 sizeof(destination_connection_id_bytes)));
1089 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1090 std::unique_ptr<QuicReceivedPacket> received_packet(
1091 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1092 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1093
1094 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1095 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1096 ASSERT_EQ(1u, saving_writer->packets()->size());
1097
1098 char source_connection_id_bytes[255] = {};
1099 uint8_t source_connection_id_length = 0;
1100 std::string detailed_error = "foobar";
1101 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1102 (*(saving_writer->packets()))[0]->data(),
1103 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1104 &source_connection_id_length, &detailed_error));
1105 EXPECT_EQ("", detailed_error);
1106
1107 // The source connection ID of the probe response should match the
1108 // destination connection ID of the probe request.
dmcardle8f7df532020-01-07 13:28:57 -08001109 quiche::test::CompareCharArraysWithHexError(
dschinazi0185ebb2019-08-14 11:09:35 -07001110 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1111 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1112}
1113
1114TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
1115 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi0185ebb2019-08-14 11:09:35 -07001116
1117 SavingWriter* saving_writer = new SavingWriter();
1118 // dispatcher_ takes ownership of saving_writer.
1119 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1120
1121 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1122 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1123 &mock_alarm_factory_);
1124 // dispatcher_ takes ownership of time_wait_list_manager.
1125 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1126 time_wait_list_manager);
1127 char packet[1200] = {};
1128 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1129 0x6c, 0x7a, 0x20, 0x21};
1130 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1131 packet, sizeof(packet), destination_connection_id_bytes,
1132 sizeof(destination_connection_id_bytes)));
1133 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1134 std::unique_ptr<QuicReceivedPacket> received_packet(
1135 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1136 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1137
1138 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1139 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1140 ASSERT_EQ(1u, saving_writer->packets()->size());
1141
1142 char source_connection_id_bytes[255] = {};
1143 uint8_t source_connection_id_length = 0;
1144 std::string detailed_error = "foobar";
1145 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1146 (*(saving_writer->packets()))[0]->data(),
1147 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1148 &source_connection_id_length, &detailed_error));
1149 EXPECT_EQ("", detailed_error);
1150
1151 // The source connection ID of the probe response should match the
1152 // destination connection ID of the probe request.
dmcardle8f7df532020-01-07 13:28:57 -08001153 quiche::test::CompareCharArraysWithHexError(
dschinazi0185ebb2019-08-14 11:09:35 -07001154 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1155 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1156}
1157
dschinazi5b236be2019-08-19 14:55:22 -07001158TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
1159 // TODO(b/139691956) Remove this test once the workaround is removed.
dschinazi5b236be2019-08-19 14:55:22 -07001160 SavingWriter* saving_writer = new SavingWriter();
1161 // dispatcher_ takes ownership of saving_writer.
1162 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1163
1164 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1165 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1166 &mock_alarm_factory_);
1167 // dispatcher_ takes ownership of time_wait_list_manager.
1168 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1169 time_wait_list_manager);
1170 // clang-format off
1171 static const unsigned char packet[] = {
1172 // Android UDP network conformance test packet as it was before this change:
1173 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1174 0x0c, // public flags: 8-byte connection ID, 1-byte packet number
1175 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1176 0x01, // 1-byte packet number
1177 0x00, // private flags
1178 0x07, // PING frame
1179 };
1180 // clang-format on
1181
1182 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1183 sizeof(packet), false);
1184 std::unique_ptr<QuicReceivedPacket> received_packet(
1185 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1186 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1187
1188 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1189 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1190 ASSERT_EQ(1u, saving_writer->packets()->size());
1191
1192 // The Android UDP network conformance test directly checks that bytes 1-9
1193 // of the response match the connection ID that was sent.
1194 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1195 0x75, 0x76, 0x77, 0x78};
1196 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1197 1u + sizeof(connection_id_bytes));
dmcardle8f7df532020-01-07 13:28:57 -08001198 quiche::test::CompareCharArraysWithHexError(
dschinazi5b236be2019-08-19 14:55:22 -07001199 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1200 sizeof(connection_id_bytes), connection_id_bytes,
1201 sizeof(connection_id_bytes));
1202}
1203
dschinazi5b236be2019-08-19 14:55:22 -07001204TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
1205 // WARNING: do not remove or modify this test without making sure that we
1206 // still have adequate coverage for the Android conformance test.
dschinazi5b236be2019-08-19 14:55:22 -07001207 SavingWriter* saving_writer = new SavingWriter();
1208 // dispatcher_ takes ownership of saving_writer.
1209 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1210
1211 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1212 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1213 &mock_alarm_factory_);
1214 // dispatcher_ takes ownership of time_wait_list_manager.
1215 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1216 time_wait_list_manager);
1217 // clang-format off
1218 static const unsigned char packet[1200] = {
1219 // Android UDP network conformance test packet as it was after this change:
1220 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1221 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1222 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1223 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1224 0x01, // 1-byte packet number
1225 0x00, // private flags
1226 0x07, // PING frame
1227 };
1228 // clang-format on
1229
1230 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1231 sizeof(packet), false);
1232 std::unique_ptr<QuicReceivedPacket> received_packet(
1233 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1234 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1235
1236 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1237 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1238 ASSERT_EQ(1u, saving_writer->packets()->size());
1239
1240 // The Android UDP network conformance test directly checks that bytes 1-9
1241 // of the response match the connection ID that was sent.
1242 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1243 0x75, 0x76, 0x77, 0x78};
1244 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1245 1u + sizeof(connection_id_bytes));
dmcardle8f7df532020-01-07 13:28:57 -08001246 quiche::test::CompareCharArraysWithHexError(
dschinazi5b236be2019-08-19 14:55:22 -07001247 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1248 sizeof(connection_id_bytes), connection_id_bytes,
1249 sizeof(connection_id_bytes));
1250}
1251
fayange3f2f7b2019-09-19 17:01:57 -07001252TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) {
fayange3f2f7b2019-09-19 17:01:57 -07001253 CreateTimeWaitListManager();
1254 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1255
1256 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
rch9d76c2d2019-12-20 12:19:48 -08001257 if (GetQuicReloadableFlag(quic_drop_small_initial_packets)) {
1258 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
1259 } else {
1260 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(1);
1261 }
1262 EXPECT_CALL(*time_wait_list_manager_,
1263 AddConnectionIdToTimeWait(_, _, _, _, _))
1264 .Times(0);
fayange3f2f7b2019-09-19 17:01:57 -07001265 ProcessPacket(client_address, TestConnectionId(1), true,
1266 CurrentSupportedVersions()[0], SerializeCHLO(), false,
1267 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
1268}
1269
1270TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) {
dschinazi41616842020-01-21 15:46:11 -08001271 SetQuicReloadableFlag(quic_enable_version_t099, true);
fayange3f2f7b2019-09-19 17:01:57 -07001272 CreateTimeWaitListManager();
1273 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1274
1275 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
1276
1277 // clang-format off
1278 char coalesced_packet[1200] = {
1279 // first coalesced packet
1280 // public flags (long header with packet type INITIAL and
1281 // 4-byte packet number)
1282 0xC3,
1283 // version
1284 'Q', '0', '9', '9',
1285 // destination connection ID length
1286 0x08,
1287 // destination connection ID
1288 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1289 // source connection ID length
1290 0x00,
1291 // long header packet length
1292 0x05,
1293 // packet number
1294 0x12, 0x34, 0x56, 0x78,
1295 // Padding
1296 0x00,
1297 // second coalesced packet
1298 // public flags (long header with packet type ZERO_RTT_PROTECTED and
1299 // 4-byte packet number)
1300 0xC3,
1301 // version
1302 'Q', '0', '9', '9',
1303 // destination connection ID length
1304 0x08,
1305 // destination connection ID
1306 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1307 // source connection ID length
1308 0x00,
1309 // long header packet length
1310 0x1E,
1311 // packet number
1312 0x12, 0x34, 0x56, 0x79,
1313 };
1314 // clang-format on
1315 QuicReceivedPacket packet(coalesced_packet, 1200, QuicTime::Zero());
1316 dispatcher_->ProcessPacket(server_address_, client_address, packet);
1317}
1318
QUICHE teama6ef0a62019-03-07 20:34:33 -05001319// Verify the stopgap test: Packets with truncated connection IDs should be
1320// dropped.
1321class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
1322
1323// Packets with truncated connection IDs should be dropped.
1324TEST_F(QuicDispatcherTestStrayPacketConnectionId,
1325 StrayPacketTruncatedConnectionId) {
1326 CreateTimeWaitListManager();
1327
1328 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1329 QuicConnectionId connection_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001330 EXPECT_CALL(*dispatcher_,
1331 CreateQuicSession(_, _, quiche::QuicheStringPiece("hq"), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001332 .Times(0);
fayangd4291e42019-05-30 10:31:21 -07001333 if (VersionHasIetfInvariantHeader(
QUICHE team963d57e2019-03-21 10:58:47 -07001334 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001335 // This IETF packet has invalid connection ID length.
1336 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1337 .Times(0);
1338 EXPECT_CALL(*time_wait_list_manager_,
1339 AddConnectionIdToTimeWait(_, _, _, _, _))
1340 .Times(0);
1341 } else {
dschinaziee07e472019-06-19 09:56:56 -07001342 // This is a GQUIC packet considered as IETF QUIC packet with short header
1343 // with unacceptable packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001344 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1345 .Times(1);
1346 EXPECT_CALL(*time_wait_list_manager_,
1347 AddConnectionIdToTimeWait(_, _, _, _, _))
1348 .Times(1);
1349 }
1350 ProcessPacket(client_address, connection_id, true, "data",
1351 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
1352}
1353
1354class BlockingWriter : public QuicPacketWriterWrapper {
1355 public:
1356 BlockingWriter() : write_blocked_(false) {}
1357
1358 bool IsWriteBlocked() const override { return write_blocked_; }
1359 void SetWritable() override { write_blocked_ = false; }
1360
dschinazi17d42422019-06-18 16:35:07 -07001361 WriteResult WritePacket(const char* /*buffer*/,
1362 size_t /*buf_len*/,
1363 const QuicIpAddress& /*self_client_address*/,
1364 const QuicSocketAddress& /*peer_client_address*/,
1365 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001366 // It would be quite possible to actually implement this method here with
1367 // the fake blocked status, but it would be significantly more work in
1368 // Chromium, and since it's not called anyway, don't bother.
1369 QUIC_LOG(DFATAL) << "Not supported";
1370 return WriteResult();
1371 }
1372
1373 bool write_blocked_;
1374};
1375
1376class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
1377 public:
1378 void SetUp() override {
1379 QuicDispatcherTest::SetUp();
1380 writer_ = new BlockingWriter;
1381 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
1382
1383 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1384
1385 EXPECT_CALL(*dispatcher_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001386 CreateQuicSession(_, client_address,
1387 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -08001388 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001389 dispatcher_.get(), config_, TestConnectionId(1), client_address,
1390 &helper_, &alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001391 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001392 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1393 ProcessUdpPacket(_, _, _))
1394 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1395 ValidatePacket(TestConnectionId(1), packet);
1396 })));
fayang1ed1f762019-06-24 11:40:04 -07001397 EXPECT_CALL(*dispatcher_,
1398 ShouldCreateOrBufferPacketForConnection(
1399 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001400 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
1401
1402 EXPECT_CALL(*dispatcher_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001403 CreateQuicSession(_, client_address,
1404 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -08001405 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001406 dispatcher_.get(), config_, TestConnectionId(2), client_address,
1407 &helper_, &alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001408 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001409 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
1410 ProcessUdpPacket(_, _, _))
1411 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1412 ValidatePacket(TestConnectionId(2), packet);
1413 })));
fayang1ed1f762019-06-24 11:40:04 -07001414 EXPECT_CALL(*dispatcher_,
1415 ShouldCreateOrBufferPacketForConnection(
1416 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001417 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
1418
1419 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
1420 }
1421
1422 void TearDown() override {
1423 if (connection1() != nullptr) {
1424 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1425 }
1426
1427 if (connection2() != nullptr) {
1428 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1429 }
1430 dispatcher_->Shutdown();
1431 }
1432
1433 // Set the dispatcher's writer to be blocked. By default, all connections use
1434 // the same writer as the dispatcher in this test.
1435 void SetBlocked() {
1436 QUIC_LOG(INFO) << "set writer " << writer_ << " to blocked";
1437 writer_->write_blocked_ = true;
1438 }
1439
1440 // Simulate what happens when connection1 gets blocked when writing.
1441 void BlockConnection1() {
1442 Connection1Writer()->write_blocked_ = true;
1443 dispatcher_->OnWriteBlocked(connection1());
1444 }
1445
1446 BlockingWriter* Connection1Writer() {
1447 return static_cast<BlockingWriter*>(connection1()->writer());
1448 }
1449
1450 // Simulate what happens when connection2 gets blocked when writing.
1451 void BlockConnection2() {
1452 Connection2Writer()->write_blocked_ = true;
1453 dispatcher_->OnWriteBlocked(connection2());
1454 }
1455
1456 BlockingWriter* Connection2Writer() {
1457 return static_cast<BlockingWriter*>(connection2()->writer());
1458 }
1459
1460 protected:
1461 MockQuicConnectionHelper helper_;
1462 MockAlarmFactory alarm_factory_;
1463 BlockingWriter* writer_;
1464 QuicDispatcher::WriteBlockedList* blocked_list_;
1465};
1466
1467TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
1468 // No OnCanWrite calls because no connections are blocked.
1469 dispatcher_->OnCanWrite();
1470
1471 // Register connection 1 for events, and make sure it's notified.
1472 SetBlocked();
1473 dispatcher_->OnWriteBlocked(connection1());
1474 EXPECT_CALL(*connection1(), OnCanWrite());
1475 dispatcher_->OnCanWrite();
1476
1477 // It should get only one notification.
1478 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1479 dispatcher_->OnCanWrite();
1480 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1481}
1482
1483TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
1484 // Make sure we handle events in order.
1485 InSequence s;
1486 SetBlocked();
1487 dispatcher_->OnWriteBlocked(connection1());
1488 dispatcher_->OnWriteBlocked(connection2());
1489 EXPECT_CALL(*connection1(), OnCanWrite());
1490 EXPECT_CALL(*connection2(), OnCanWrite());
1491 dispatcher_->OnCanWrite();
1492
1493 // Check the other ordering.
1494 SetBlocked();
1495 dispatcher_->OnWriteBlocked(connection2());
1496 dispatcher_->OnWriteBlocked(connection1());
1497 EXPECT_CALL(*connection2(), OnCanWrite());
1498 EXPECT_CALL(*connection1(), OnCanWrite());
1499 dispatcher_->OnCanWrite();
1500}
1501
1502TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
1503 // Add and remove one connction.
1504 SetBlocked();
1505 dispatcher_->OnWriteBlocked(connection1());
1506 blocked_list_->erase(connection1());
1507 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1508 dispatcher_->OnCanWrite();
1509
1510 // Add and remove one connction and make sure it doesn't affect others.
1511 SetBlocked();
1512 dispatcher_->OnWriteBlocked(connection1());
1513 dispatcher_->OnWriteBlocked(connection2());
1514 blocked_list_->erase(connection1());
1515 EXPECT_CALL(*connection2(), OnCanWrite());
1516 dispatcher_->OnCanWrite();
1517
1518 // Add it, remove it, and add it back and make sure things are OK.
1519 SetBlocked();
1520 dispatcher_->OnWriteBlocked(connection1());
1521 blocked_list_->erase(connection1());
1522 dispatcher_->OnWriteBlocked(connection1());
1523 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1524 dispatcher_->OnCanWrite();
1525}
1526
1527TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
1528 // Make sure a double add does not necessitate a double remove.
1529 SetBlocked();
1530 dispatcher_->OnWriteBlocked(connection1());
1531 dispatcher_->OnWriteBlocked(connection1());
1532 blocked_list_->erase(connection1());
1533 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1534 dispatcher_->OnCanWrite();
1535
1536 // Make sure a double add does not result in two OnCanWrite calls.
1537 SetBlocked();
1538 dispatcher_->OnWriteBlocked(connection1());
1539 dispatcher_->OnWriteBlocked(connection1());
1540 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1541 dispatcher_->OnCanWrite();
1542}
1543
1544TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
1545 // If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
1546 // into the write blocked list.
1547 InSequence s;
1548 SetBlocked();
1549 dispatcher_->OnWriteBlocked(connection1());
1550 dispatcher_->OnWriteBlocked(connection2());
1551 EXPECT_CALL(*connection1(), OnCanWrite())
1552 .WillOnce(
1553 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1554 EXPECT_CALL(*connection2(), OnCanWrite());
1555 dispatcher_->OnCanWrite();
1556
1557 // connection1 should be still in the write blocked list.
1558 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1559
1560 // Now call OnCanWrite again, connection1 should get its second chance.
1561 EXPECT_CALL(*connection1(), OnCanWrite());
1562 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
1563 dispatcher_->OnCanWrite();
1564 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1565}
1566
1567TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
1568 // If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
1569 // into the write blocked list.
1570 InSequence s;
1571 SetBlocked();
1572 dispatcher_->OnWriteBlocked(connection1());
1573 dispatcher_->OnWriteBlocked(connection2());
1574 EXPECT_CALL(*connection1(), OnCanWrite());
1575 EXPECT_CALL(*connection2(), OnCanWrite())
1576 .WillOnce(
1577 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1578 dispatcher_->OnCanWrite();
1579
1580 // connection2 should be still in the write blocked list.
1581 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1582
1583 // Now call OnCanWrite again, connection2 should get its second chance.
1584 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1585 EXPECT_CALL(*connection2(), OnCanWrite());
1586 dispatcher_->OnCanWrite();
1587 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1588}
1589
1590TEST_F(QuicDispatcherWriteBlockedListTest,
1591 OnCanWriteHandleBlockBothConnections) {
1592 // Both connections get blocked in OnCanWrite, and added back into the write
1593 // blocked list.
1594 InSequence s;
1595 SetBlocked();
1596 dispatcher_->OnWriteBlocked(connection1());
1597 dispatcher_->OnWriteBlocked(connection2());
1598 EXPECT_CALL(*connection1(), OnCanWrite())
1599 .WillOnce(
1600 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1601 EXPECT_CALL(*connection2(), OnCanWrite())
1602 .WillOnce(
1603 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1604 dispatcher_->OnCanWrite();
1605
1606 // Both connections should be still in the write blocked list.
1607 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1608
1609 // Now call OnCanWrite again, both connections should get its second chance.
1610 EXPECT_CALL(*connection1(), OnCanWrite());
1611 EXPECT_CALL(*connection2(), OnCanWrite());
1612 dispatcher_->OnCanWrite();
1613 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1614}
1615
1616TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
1617 // By default, all connections share the same packet writer with the
1618 // dispatcher.
1619 EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
1620 EXPECT_EQ(dispatcher_->writer(), connection2()->writer());
1621
1622 // Test the case where connection1 shares the same packet writer as the
1623 // dispatcher, whereas connection2 owns it's packet writer.
1624 // Change connection2's writer.
1625 connection2()->SetQuicPacketWriter(new BlockingWriter, /*owns_writer=*/true);
1626 EXPECT_NE(dispatcher_->writer(), connection2()->writer());
1627
1628 BlockConnection2();
1629 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1630
1631 EXPECT_CALL(*connection2(), OnCanWrite());
1632 dispatcher_->OnCanWrite();
1633 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1634}
1635
1636TEST_F(QuicDispatcherWriteBlockedListTest,
1637 RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001638 dispatcher_->OnConnectionClosed(connection1()->connection_id(),
1639 QUIC_PACKET_WRITE_ERROR, "Closed by test.",
1640 ConnectionCloseSource::FROM_SELF);
1641
1642 SetBlocked();
1643
1644 ASSERT_FALSE(dispatcher_->HasPendingWrites());
1645 SetBlocked();
1646 dispatcher_->OnWriteBlocked(connection1());
1647 ASSERT_TRUE(dispatcher_->HasPendingWrites());
1648
1649 EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(),
1650 "QuicConnection was in WriteBlockedList before destruction");
1651 MarkSession1Deleted();
1652}
1653
wub0a4b9c52019-05-28 13:18:58 -07001654class BufferedPacketStoreTest : public QuicDispatcherTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001655 public:
1656 BufferedPacketStoreTest()
1657 : QuicDispatcherTest(),
1658 server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
1659 client_addr_(QuicIpAddress::Loopback4(), 1234),
wub0a4b9c52019-05-28 13:18:58 -07001660 signed_config_(new QuicSignedServerConfig) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001661
1662 void SetUp() override {
1663 QuicDispatcherTest::SetUp();
1664 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
1665
dschinazi41616842020-01-21 15:46:11 -08001666 // The methods below use a PROTOCOL_QUIC_CRYPTO version so we pick the
1667 // first one from the list of supported versions.
1668 QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
1669 for (const ParsedQuicVersion& version : AllSupportedVersions()) {
1670 if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
1671 transport_version = version.transport_version;
1672 break;
1673 }
1674 }
1675 ASSERT_NE(QUIC_VERSION_UNSUPPORTED, transport_version);
1676
QUICHE teama6ef0a62019-03-07 20:34:33 -05001677 CryptoHandshakeMessage chlo =
dschinazi41616842020-01-21 15:46:11 -08001678 crypto_test_utils::GenerateDefaultInchoateCHLO(
1679 clock_, transport_version, &crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001680 // Pass an inchoate CHLO.
1681 crypto_test_utils::GenerateFullCHLO(
dschinazi41616842020-01-21 15:46:11 -08001682 chlo, &crypto_config_, server_addr_, client_addr_, transport_version,
1683 clock_, signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001684 &full_chlo_);
1685 }
1686
vasilvvc48c8712019-03-11 13:38:16 -07001687 std::string SerializeFullCHLO() {
1688 return std::string(full_chlo_.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001689 }
1690
1691 protected:
1692 QuicSocketAddress server_addr_;
1693 QuicSocketAddress client_addr_;
1694 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1695 const QuicClock* clock_;
1696 CryptoHandshakeMessage full_chlo_;
1697};
1698
wub0a4b9c52019-05-28 13:18:58 -07001699TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001700 InSequence s;
1701 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1702 QuicConnectionId conn_id = TestConnectionId(1);
1703 // A bunch of non-CHLO should be buffered upon arrival, and the first one
1704 // should trigger ShouldCreateOrBufferPacketForConnection().
fayang1ed1f762019-06-24 11:40:04 -07001705 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1706 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001707 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
1708 ProcessPacket(client_address, conn_id, true,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001709 quiche::QuicheStrCat("data packet ", i + 1),
1710 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1711 /*packet_number=*/i + 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001712 }
1713 EXPECT_EQ(0u, dispatcher_->session_map().size())
1714 << "No session should be created before CHLO arrives.";
1715
1716 // Pop out the last packet as it is also be dropped by the store.
1717 data_connection_map_[conn_id].pop_back();
1718 // When CHLO arrives, a new session should be created, and all packets
1719 // buffered should be delivered to the session.
dmcardlecf0bfcf2019-12-13 08:08:21 -08001720 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1721 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001722 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001723 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1724 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001725 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001726
1727 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
1728 // should be delivered in arrival order.
1729 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1730 ProcessUdpPacket(_, _, _))
1731 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
1732 .WillRepeatedly(
1733 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1734 ValidatePacket(conn_id, packet);
1735 })));
1736 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1737}
1738
wub0a4b9c52019-05-28 13:18:58 -07001739TEST_F(BufferedPacketStoreTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001740 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
1741 InSequence s;
1742 // A bunch of non-CHLO should be buffered upon arrival.
1743 size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
1744 for (size_t i = 1; i <= kNumConnections; ++i) {
1745 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1746 QuicConnectionId conn_id = TestConnectionId(i);
1747 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001748 ShouldCreateOrBufferPacketForConnection(
1749 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001750 ProcessPacket(client_address, conn_id, true,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001751 quiche::QuicheStrCat("data packet on connection ", i),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001752 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1753 /*packet_number=*/2);
1754 }
1755
1756 // Pop out the packet on last connection as it shouldn't be enqueued in store
1757 // as well.
1758 data_connection_map_[TestConnectionId(kNumConnections)].pop_front();
1759
1760 // Reset session creation counter to ensure processing CHLO can always
1761 // create session.
1762 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
1763 kNumConnections);
1764 // Process CHLOs to create session for these connections.
1765 for (size_t i = 1; i <= kNumConnections; ++i) {
1766 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1767 QuicConnectionId conn_id = TestConnectionId(i);
1768 if (i == kNumConnections) {
1769 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001770 ShouldCreateOrBufferPacketForConnection(
1771 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001772 }
1773 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001774 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001775 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001776 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1777 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001778 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001779 // First |kNumConnections| - 1 connections should have buffered
1780 // a packet in store. The rest should have been dropped.
1781 size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
1782 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1783 ProcessUdpPacket(_, client_address, _))
1784 .Times(num_packet_to_process)
1785 .WillRepeatedly(WithArg<2>(
1786 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1787 ValidatePacket(conn_id, packet);
1788 })));
1789
1790 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1791 }
1792}
1793
1794// Tests that store delivers empty packet list if CHLO arrives firstly.
wub0a4b9c52019-05-28 13:18:58 -07001795TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001796 QuicConnectionId conn_id = TestConnectionId(1);
1797 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
fayang1ed1f762019-06-24 11:40:04 -07001798 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1799 ReceivedPacketInfoConnectionIdEquals(conn_id)));
dmcardlecf0bfcf2019-12-13 08:08:21 -08001800 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1801 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001802 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001803 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1804 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001805 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001806 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1807 ProcessUdpPacket(_, client_address, _));
1808 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1809}
1810
1811// Tests that a retransmitted CHLO arrives after a connection for the
1812// CHLO has been created.
wub0a4b9c52019-05-28 13:18:58 -07001813TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001814 InSequence s;
1815 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1816 QuicConnectionId conn_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001817 ProcessPacket(client_address, conn_id, true,
1818 quiche::QuicheStrCat("data packet ", 2), CONNECTION_ID_PRESENT,
1819 PACKET_4BYTE_PACKET_NUMBER,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001820 /*packet_number=*/2);
1821
1822 // When CHLO arrives, a new session should be created, and all packets
1823 // buffered should be delivered to the session.
dmcardlecf0bfcf2019-12-13 08:08:21 -08001824 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1825 quiche::QuicheStringPiece(), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001826 .Times(1) // Only triggered by 1st CHLO.
wub89490e02019-12-12 12:45:58 -08001827 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001828 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1829 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001830 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001831 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1832 ProcessUdpPacket(_, _, _))
1833 .Times(3) // Triggered by 1 data packet and 2 CHLOs.
1834 .WillRepeatedly(
1835 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1836 ValidatePacket(conn_id, packet);
1837 })));
1838 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1839
1840 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1841}
1842
1843// Tests that expiration of a connection add connection id to time wait list.
wub0a4b9c52019-05-28 13:18:58 -07001844TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001845 InSequence s;
1846 CreateTimeWaitListManager();
1847 QuicBufferedPacketStore* store =
1848 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1849 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
1850
1851 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1852 QuicConnectionId conn_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001853 ProcessPacket(client_address, conn_id, true,
1854 quiche::QuicheStrCat("data packet ", 2), CONNECTION_ID_PRESENT,
1855 PACKET_4BYTE_PACKET_NUMBER,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001856 /*packet_number=*/2);
1857
1858 mock_helper_.AdvanceTime(
1859 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
1860 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
1861 // Cancel alarm as if it had been fired.
1862 alarm->Cancel();
1863 store->OnExpirationTimeout();
1864 // New arrived CHLO will be dropped because this connection is in time wait
1865 // list.
1866 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
1867 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
1868 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1869}
1870
wub0a4b9c52019-05-28 13:18:58 -07001871TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001872 // Process more than (|kMaxNumSessionsToCreate| +
1873 // |kDefaultMaxConnectionsInStore|) CHLOs,
1874 // the first |kMaxNumSessionsToCreate| should create connections immediately,
1875 // the next |kDefaultMaxConnectionsInStore| should be buffered,
1876 // the rest should be dropped.
1877 QuicBufferedPacketStore* store =
1878 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1879 const size_t kNumCHLOs =
1880 kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
1881 for (uint64_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
fayang1ed1f762019-06-24 11:40:04 -07001882 EXPECT_CALL(
1883 *dispatcher_,
1884 ShouldCreateOrBufferPacketForConnection(
1885 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(conn_id))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001886 if (conn_id <= kMaxNumSessionsToCreate) {
1887 EXPECT_CALL(*dispatcher_,
1888 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001889 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001890 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001891 dispatcher_.get(), config_, TestConnectionId(conn_id),
1892 client_addr_, &mock_helper_, &mock_alarm_factory_,
1893 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08001894 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001895 EXPECT_CALL(
1896 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1897 ProcessUdpPacket(_, _, _))
1898 .WillOnce(WithArg<2>(
1899 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1900 ValidatePacket(TestConnectionId(conn_id), packet);
1901 })));
1902 }
1903 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1904 SerializeFullCHLO());
1905 if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
1906 conn_id > kMaxNumSessionsToCreate) {
1907 EXPECT_TRUE(store->HasChloForConnection(TestConnectionId(conn_id)));
1908 } else {
1909 // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
1910 // connections immediately, and the last CHLO should be dropped as the
1911 // store is full.
1912 EXPECT_FALSE(store->HasChloForConnection(TestConnectionId(conn_id)));
1913 }
1914 }
1915
1916 // Graduately consume buffered CHLOs. The buffered connections should be
1917 // created but the dropped one shouldn't.
1918 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1919 conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
1920 ++conn_id) {
1921 EXPECT_CALL(*dispatcher_,
1922 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001923 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001924 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001925 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1926 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001927 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001928 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1929 ProcessUdpPacket(_, _, _))
1930 .WillOnce(WithArg<2>(
1931 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1932 ValidatePacket(TestConnectionId(conn_id), packet);
1933 })));
1934 }
1935 EXPECT_CALL(*dispatcher_,
1936 CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001937 quiche::QuicheStringPiece(), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001938 .Times(0);
1939
1940 while (store->HasChlosBuffered()) {
1941 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1942 }
1943
1944 EXPECT_EQ(TestConnectionId(static_cast<size_t>(kMaxNumSessionsToCreate) +
1945 kDefaultMaxConnectionsInStore),
1946 session1_->connection_id());
1947}
1948
1949// Duplicated CHLO shouldn't be buffered.
wub0a4b9c52019-05-28 13:18:58 -07001950TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001951 for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
1952 ++conn_id) {
1953 // Last CHLO will be buffered. Others will create connection right away.
1954 if (conn_id <= kMaxNumSessionsToCreate) {
1955 EXPECT_CALL(*dispatcher_,
1956 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001957 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001958 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001959 dispatcher_.get(), config_, TestConnectionId(conn_id),
1960 client_addr_, &mock_helper_, &mock_alarm_factory_,
1961 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08001962 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001963 EXPECT_CALL(
1964 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1965 ProcessUdpPacket(_, _, _))
1966 .WillOnce(WithArg<2>(
1967 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1968 ValidatePacket(TestConnectionId(conn_id), packet);
1969 })));
1970 }
1971 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1972 SerializeFullCHLO());
1973 }
1974 // Retransmit CHLO on last connection should be dropped.
1975 QuicConnectionId last_connection =
1976 TestConnectionId(kMaxNumSessionsToCreate + 1);
1977 ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
1978
1979 size_t packets_buffered = 2;
1980
1981 // Reset counter and process buffered CHLO.
1982 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001983 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001984 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001985 dispatcher_.get(), config_, last_connection, client_addr_,
1986 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001987 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001988 // Only one packet(CHLO) should be process.
1989 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1990 ProcessUdpPacket(_, _, _))
1991 .Times(packets_buffered)
1992 .WillRepeatedly(WithArg<2>(
1993 Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
1994 ValidatePacket(last_connection, packet);
1995 })));
1996 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1997}
1998
wub0a4b9c52019-05-28 13:18:58 -07001999TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002000 uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
2001 QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
2002 for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
2003 // Last CHLO will be buffered. Others will create connection right away.
2004 if (conn_id <= kMaxNumSessionsToCreate) {
2005 EXPECT_CALL(*dispatcher_,
2006 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002007 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08002008 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002009 dispatcher_.get(), config_, TestConnectionId(conn_id),
2010 client_addr_, &mock_helper_, &mock_alarm_factory_,
2011 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08002012 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002013 EXPECT_CALL(
2014 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2015 ProcessUdpPacket(_, _, _))
2016 .WillRepeatedly(WithArg<2>(
2017 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2018 ValidatePacket(TestConnectionId(conn_id), packet);
2019 })));
2020 }
2021 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2022 SerializeFullCHLO());
2023 }
2024
2025 // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
2026 // last one should be dropped.
2027 for (uint64_t packet_number = 2;
2028 packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
2029 ProcessPacket(client_addr_, last_connection_id, true, "data packet");
2030 }
2031
2032 // Reset counter and process buffered CHLO.
2033 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002034 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08002035 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002036 dispatcher_.get(), config_, last_connection_id, client_addr_,
2037 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08002038 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002039 // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
2040 // should be process.
2041 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2042 ProcessUdpPacket(_, _, _))
2043 .Times(kDefaultMaxUndecryptablePackets + 1)
2044 .WillRepeatedly(WithArg<2>(
2045 Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
2046 ValidatePacket(last_connection_id, packet);
2047 })));
2048 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2049}
2050
2051// Tests that when dispatcher's packet buffer is full, a CHLO on connection
2052// which doesn't have buffered CHLO should be buffered.
wub0a4b9c52019-05-28 13:18:58 -07002053TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002054 QuicBufferedPacketStore* store =
2055 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
2056
2057 uint64_t conn_id = 1;
2058 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, "data packet",
2059 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
2060 /*packet_number=*/1);
2061 // Fill packet buffer to full with CHLOs on other connections. Need to feed
2062 // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
2063 // session directly.
2064 for (conn_id = 2;
2065 conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
2066 ++conn_id) {
2067 if (conn_id <= kMaxNumSessionsToCreate + 1) {
2068 EXPECT_CALL(*dispatcher_,
2069 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002070 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08002071 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002072 dispatcher_.get(), config_, TestConnectionId(conn_id),
2073 client_addr_, &mock_helper_, &mock_alarm_factory_,
2074 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08002075 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002076 EXPECT_CALL(
2077 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2078 ProcessUdpPacket(_, _, _))
2079 .WillOnce(WithArg<2>(
2080 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2081 ValidatePacket(TestConnectionId(conn_id), packet);
2082 })));
2083 }
2084 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2085 SerializeFullCHLO());
2086 }
2087 EXPECT_FALSE(store->HasChloForConnection(
2088 /*connection_id=*/TestConnectionId(1)));
2089
2090 // CHLO on connection 1 should still be buffered.
wub0b2ae542019-10-24 08:32:06 -07002091 ProcessPacket(client_addr_, /*server_connection_id=*/TestConnectionId(1),
2092 true, SerializeFullCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002093 EXPECT_TRUE(store->HasChloForConnection(
2094 /*connection_id=*/TestConnectionId(1)));
2095}
2096
2097// Regression test for b/117874922.
wub0a4b9c52019-05-28 13:18:58 -07002098TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
dschinazi41616842020-01-21 15:46:11 -08002099 // Turn off version T099, so the preferred version is not supported by the
2100 // server.
dschinazi76881f02019-12-09 14:56:14 -08002101 SetQuicReloadableFlag(quic_enable_version_t099, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002102 uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
2103 ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
2104 for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
2105 // Last 5 CHLOs will be buffered. Others will create connection right away.
2106 ParsedQuicVersion version =
2107 supported_versions[(conn_id - 1) % supported_versions.size()];
2108 if (conn_id <= kMaxNumSessionsToCreate) {
2109 EXPECT_CALL(*dispatcher_,
2110 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002111 quiche::QuicheStringPiece(), version))
wub89490e02019-12-12 12:45:58 -08002112 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002113 dispatcher_.get(), config_, TestConnectionId(conn_id),
2114 client_addr_, &mock_helper_, &mock_alarm_factory_,
2115 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08002116 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002117 EXPECT_CALL(
2118 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2119 ProcessUdpPacket(_, _, _))
2120 .WillRepeatedly(WithArg<2>(
2121 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2122 ValidatePacket(TestConnectionId(conn_id), packet);
2123 })));
2124 }
2125 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version,
fayange3f2f7b2019-09-19 17:01:57 -07002126 SerializeFullCHLO(), true, CONNECTION_ID_PRESENT,
QUICHE teama6ef0a62019-03-07 20:34:33 -05002127 PACKET_4BYTE_PACKET_NUMBER, 1);
2128 }
2129
2130 // Process buffered CHLOs. Verify the version is correct.
2131 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
2132 conn_id <= last_connection_id; ++conn_id) {
2133 ParsedQuicVersion version =
2134 supported_versions[(conn_id - 1) % supported_versions.size()];
2135 EXPECT_CALL(*dispatcher_,
2136 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002137 quiche::QuicheStringPiece(), version))
wub89490e02019-12-12 12:45:58 -08002138 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002139 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
2140 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08002141 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002142 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2143 ProcessUdpPacket(_, _, _))
2144 .WillRepeatedly(WithArg<2>(
2145 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2146 ValidatePacket(TestConnectionId(conn_id), packet);
2147 })));
2148 }
2149 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2150}
2151
QUICHE teama6ef0a62019-03-07 20:34:33 -05002152} // namespace
2153} // namespace test
2154} // namespace quic