blob: 896438a2b7385b839c1eac0c351e9784ec6660ee [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"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
24#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"
27#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050028#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
29#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
30#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
31#include "net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h"
35#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
36#include "net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h"
37#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
38
39using testing::_;
40using testing::InSequence;
41using testing::Invoke;
42using testing::NiceMock;
43using testing::Return;
44using testing::WithArg;
45using testing::WithoutArgs;
46
47static const size_t kDefaultMaxConnectionsInStore = 100;
48static const size_t kMaxConnectionsWithoutCHLO =
49 kDefaultMaxConnectionsInStore / 2;
50static const int16_t kMaxNumSessionsToCreate = 16;
51
52namespace quic {
53namespace test {
54namespace {
55
56class TestQuicSpdyServerSession : public QuicServerSessionBase {
57 public:
58 TestQuicSpdyServerSession(const QuicConfig& config,
59 QuicConnection* connection,
60 const QuicCryptoServerConfig* crypto_config,
61 QuicCompressedCertsCache* compressed_certs_cache)
62 : QuicServerSessionBase(config,
63 CurrentSupportedVersions(),
64 connection,
65 nullptr,
66 nullptr,
67 crypto_config,
68 compressed_certs_cache),
69 crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {}
70 TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
71 TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
72 delete;
73
74 ~TestQuicSpdyServerSession() override { delete connection(); }
75
fkastenholz5d880a92019-06-21 09:01:56 -070076 MOCK_METHOD2(OnConnectionClosed,
77 void(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -050078 ConnectionCloseSource source));
79 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
renjietangbaea59c2019-05-29 15:08:14 -070080 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(PendingStream* pending));
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*());
82 MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
83
84 QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
85 const QuicCryptoServerConfig* crypto_config,
86 QuicCompressedCertsCache* compressed_certs_cache) override {
wubd893df12019-05-15 18:48:20 -070087 return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
88 this, stream_helper());
QUICHE teama6ef0a62019-03-07 20:34:33 -050089 }
90
91 void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
92 crypto_stream_ = crypto_stream;
93 }
94
95 QuicCryptoServerStreamBase* GetMutableCryptoStream() override {
96 return crypto_stream_;
97 }
98
99 const QuicCryptoServerStreamBase* GetCryptoStream() const override {
100 return crypto_stream_;
101 }
102
103 QuicCryptoServerStream::Helper* stream_helper() {
104 return QuicServerSessionBase::stream_helper();
105 }
106
107 private:
108 QuicCryptoServerStreamBase* crypto_stream_;
109};
110
111class TestDispatcher : public QuicDispatcher {
112 public:
113 TestDispatcher(const QuicConfig* config,
114 const QuicCryptoServerConfig* crypto_config,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700115 QuicVersionManager* version_manager,
116 QuicRandom* random)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117 : QuicDispatcher(config,
118 crypto_config,
119 version_manager,
vasilvv0fc587f2019-09-06 13:33:08 -0700120 std::make_unique<MockQuicConnectionHelper>(),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 std::unique_ptr<QuicCryptoServerStream::Helper>(
wub662a3d62019-08-16 14:10:50 -0700122 new QuicSimpleCryptoServerStreamHelper()),
vasilvv0fc587f2019-09-06 13:33:08 -0700123 std::make_unique<MockAlarmFactory>(),
wub662a3d62019-08-16 14:10:50 -0700124 kQuicDefaultConnectionIdLength),
125 random_(random) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500126
127 MOCK_METHOD4(CreateQuicSession,
128 QuicServerSessionBase*(QuicConnectionId connection_id,
129 const QuicSocketAddress& peer_address,
130 QuicStringPiece alpn,
131 const quic::ParsedQuicVersion& version));
132
fayang1ed1f762019-06-24 11:40:04 -0700133 MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
134 bool(const ReceivedPacketInfo& packet_info));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135
136 struct TestQuicPerPacketContext : public QuicPerPacketContext {
vasilvvc48c8712019-03-11 13:38:16 -0700137 std::string custom_packet_context;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138 };
139
140 std::unique_ptr<QuicPerPacketContext> GetPerPacketContext() const override {
vasilvv0fc587f2019-09-06 13:33:08 -0700141 auto test_context = std::make_unique<TestQuicPerPacketContext>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500142 test_context->custom_packet_context = custom_packet_context_;
143 return std::move(test_context);
144 }
145
146 void RestorePerPacketContext(
147 std::unique_ptr<QuicPerPacketContext> context) override {
148 TestQuicPerPacketContext* test_context =
149 static_cast<TestQuicPerPacketContext*>(context.get());
150 custom_packet_context_ = test_context->custom_packet_context;
151 }
152
vasilvvc48c8712019-03-11 13:38:16 -0700153 std::string custom_packet_context_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154
dschinazi7b9278c2019-05-20 07:36:21 -0700155 using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500156 using QuicDispatcher::writer;
wub662a3d62019-08-16 14:10:50 -0700157
158 QuicRandom* random_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500159};
160
161// A Connection class which unregisters the session from the dispatcher when
162// sending connection close.
163// It'd be slightly more realistic to do this from the Session but it would
164// involve a lot more mocking.
165class MockServerConnection : public MockQuicConnection {
166 public:
167 MockServerConnection(QuicConnectionId connection_id,
168 MockQuicConnectionHelper* helper,
169 MockAlarmFactory* alarm_factory,
170 QuicDispatcher* dispatcher)
171 : MockQuicConnection(connection_id,
172 helper,
173 alarm_factory,
174 Perspective::IS_SERVER),
175 dispatcher_(dispatcher) {}
176
177 void UnregisterOnConnectionClosed() {
178 QUIC_LOG(ERROR) << "Unregistering " << connection_id();
179 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
180 "Unregistering.",
181 ConnectionCloseSource::FROM_SELF);
182 }
183
184 private:
185 QuicDispatcher* dispatcher_;
186};
187
188class QuicDispatcherTest : public QuicTest {
189 public:
190 QuicDispatcherTest()
191 : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
192
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
wub662a3d62019-08-16 14:10:50 -0700194 : version_manager_(AllSupportedVersions()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 crypto_config_(QuicCryptoServerConfig::TESTING,
196 QuicRandom::GetInstance(),
197 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -0700198 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 server_address_(QuicIpAddress::Any4(), 5),
QUICHE teamc65d1d12019-03-19 20:58:04 -0700200 dispatcher_(
201 new NiceMock<TestDispatcher>(&config_,
202 &crypto_config_,
203 &version_manager_,
204 mock_helper_.GetRandomGenerator())),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500205 time_wait_list_manager_(nullptr),
206 session1_(nullptr),
207 session2_(nullptr),
fayangb880b4c2019-06-14 12:26:35 -0700208 store_(nullptr),
209 connection_id_(1) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500210
211 void SetUp() override {
212 dispatcher_->InitializeWithWriter(new MockPacketWriter());
213 // Set the counter to some value to start with.
214 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
215 dispatcher_.get(), kMaxNumSessionsToCreate);
fayang1ed1f762019-06-24 11:40:04 -0700216 ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500217 .WillByDefault(Return(true));
218 }
219
220 MockQuicConnection* connection1() {
221 if (session1_ == nullptr) {
222 return nullptr;
223 }
224 return reinterpret_cast<MockQuicConnection*>(session1_->connection());
225 }
226
227 MockQuicConnection* connection2() {
228 if (session2_ == nullptr) {
229 return nullptr;
230 }
231 return reinterpret_cast<MockQuicConnection*>(session2_->connection());
232 }
233
234 // Process a packet with an 8 byte connection id,
235 // 6 byte packet number, 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 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500242 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER);
243 }
244
245 // Process a packet with a default path id, and packet number 1,
246 // using the first supported version.
247 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700248 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500249 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700250 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700251 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 QuicPacketNumberLength packet_number_length) {
dschinazi346b7ce2019-06-05 01:38:18 -0700253 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
254 server_connection_id_included, packet_number_length, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500255 }
256
257 // Process a packet using the first supported version.
258 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700259 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700261 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700262 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500263 QuicPacketNumberLength packet_number_length,
264 uint64_t packet_number) {
dschinazi346b7ce2019-06-05 01:38:18 -0700265 ProcessPacket(peer_address, server_connection_id, has_version_flag,
fayange3f2f7b2019-09-19 17:01:57 -0700266 CurrentSupportedVersions().front(), data, true,
dschinazi346b7ce2019-06-05 01:38:18 -0700267 server_connection_id_included, packet_number_length,
268 packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500269 }
270
271 // Processes a packet.
272 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700273 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274 bool has_version_flag,
275 ParsedQuicVersion version,
vasilvvc48c8712019-03-11 13:38:16 -0700276 const std::string& data,
fayange3f2f7b2019-09-19 17:01:57 -0700277 bool full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700278 QuicConnectionIdIncluded server_connection_id_included,
279 QuicPacketNumberLength packet_number_length,
280 uint64_t packet_number) {
281 ProcessPacket(peer_address, server_connection_id, EmptyQuicConnectionId(),
fayange3f2f7b2019-09-19 17:01:57 -0700282 has_version_flag, version, data, full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700283 server_connection_id_included, CONNECTION_ID_ABSENT,
284 packet_number_length, packet_number);
285 }
286
287 // Processes a packet.
288 void ProcessPacket(QuicSocketAddress peer_address,
289 QuicConnectionId server_connection_id,
290 QuicConnectionId client_connection_id,
291 bool has_version_flag,
292 ParsedQuicVersion version,
293 const std::string& data,
fayange3f2f7b2019-09-19 17:01:57 -0700294 bool full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700295 QuicConnectionIdIncluded server_connection_id_included,
296 QuicConnectionIdIncluded client_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500297 QuicPacketNumberLength packet_number_length,
298 uint64_t packet_number) {
299 ParsedQuicVersionVector versions(SupportedVersions(version));
300 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700301 server_connection_id, client_connection_id, has_version_flag, false,
fayange3f2f7b2019-09-19 17:01:57 -0700302 packet_number, data, full_padding, server_connection_id_included,
dschinazi346b7ce2019-06-05 01:38:18 -0700303 client_connection_id_included, packet_number_length, &versions));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 std::unique_ptr<QuicReceivedPacket> received_packet(
305 ConstructReceivedPacket(*packet, mock_helper_.GetClock()->Now()));
306
dschinazi4fd8cb12019-09-09 16:31:06 -0700307 if (ChloExtractor::Extract(*packet, version, {}, nullptr,
dschinazi346b7ce2019-06-05 01:38:18 -0700308 server_connection_id.length())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 // Add CHLO packet to the beginning to be verified first, because it is
310 // also processed first by new session.
dschinazi346b7ce2019-06-05 01:38:18 -0700311 data_connection_map_[server_connection_id].push_front(
vasilvvc48c8712019-03-11 13:38:16 -0700312 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 } else {
314 // For non-CHLO, always append to last.
dschinazi346b7ce2019-06-05 01:38:18 -0700315 data_connection_map_[server_connection_id].push_back(
vasilvvc48c8712019-03-11 13:38:16 -0700316 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500317 }
318 dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet);
319 }
320
321 void ValidatePacket(QuicConnectionId conn_id,
322 const QuicEncryptedPacket& packet) {
323 EXPECT_EQ(data_connection_map_[conn_id].front().length(),
324 packet.AsStringPiece().length());
325 EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
326 data_connection_map_[conn_id].pop_front();
327 }
328
329 QuicServerSessionBase* CreateSession(
330 TestDispatcher* dispatcher,
331 const QuicConfig& config,
332 QuicConnectionId connection_id,
dschinazi17d42422019-06-18 16:35:07 -0700333 const QuicSocketAddress& /*peer_address*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500334 MockQuicConnectionHelper* helper,
335 MockAlarmFactory* alarm_factory,
336 const QuicCryptoServerConfig* crypto_config,
337 QuicCompressedCertsCache* compressed_certs_cache,
338 TestQuicSpdyServerSession** session) {
339 MockServerConnection* connection = new MockServerConnection(
340 connection_id, helper, alarm_factory, dispatcher);
341 connection->SetQuicPacketWriter(dispatcher->writer(),
342 /*owns_writer=*/false);
343 *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
344 compressed_certs_cache);
345 connection->set_visitor(*session);
346 ON_CALL(*connection, CloseConnection(_, _, _))
347 .WillByDefault(WithoutArgs(Invoke(
348 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
349 return *session;
350 }
351
352 void CreateTimeWaitListManager() {
353 time_wait_list_manager_ = new MockTimeWaitListManager(
354 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
355 mock_helper_.GetClock(), &mock_alarm_factory_);
356 // dispatcher_ takes the ownership of time_wait_list_manager_.
357 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
358 time_wait_list_manager_);
359 }
360
vasilvvc48c8712019-03-11 13:38:16 -0700361 std::string SerializeCHLO() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500362 CryptoHandshakeMessage client_hello;
363 client_hello.set_tag(kCHLO);
364 client_hello.SetStringPiece(kALPN, "hq");
vasilvvc48c8712019-03-11 13:38:16 -0700365 return std::string(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500366 }
367
QUICHE teama6ef0a62019-03-07 20:34:33 -0500368 void MarkSession1Deleted() { session1_ = nullptr; }
369
fayangb880b4c2019-06-14 12:26:35 -0700370 void VerifyVersionSupported(ParsedQuicVersion version) {
371 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
372 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
373 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
374 QuicStringPiece("hq"), _))
375 .WillOnce(testing::Return(CreateSession(
376 dispatcher_.get(), config_, connection_id, client_address,
377 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
378 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
379 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
380 ProcessUdpPacket(_, _, _))
381 .WillOnce(WithArg<2>(
382 Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
383 ValidatePacket(connection_id, packet);
384 })));
385 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700386 ShouldCreateOrBufferPacketForConnection(
387 ReceivedPacketInfoConnectionIdEquals(connection_id)));
fayangb880b4c2019-06-14 12:26:35 -0700388 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
fayange3f2f7b2019-09-19 17:01:57 -0700389 true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
fayangb880b4c2019-06-14 12:26:35 -0700390 }
391
392 void VerifyVersionNotSupported(ParsedQuicVersion version) {
393 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
394 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
395 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
396 QuicStringPiece("hq"), _))
397 .Times(0);
398 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
fayange3f2f7b2019-09-19 17:01:57 -0700399 true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
fayangb880b4c2019-06-14 12:26:35 -0700400 }
401
QUICHE teama6ef0a62019-03-07 20:34:33 -0500402 MockQuicConnectionHelper mock_helper_;
403 MockAlarmFactory mock_alarm_factory_;
404 QuicConfig config_;
405 QuicVersionManager version_manager_;
406 QuicCryptoServerConfig crypto_config_;
407 QuicSocketAddress server_address_;
408 std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
409 MockTimeWaitListManager* time_wait_list_manager_;
410 TestQuicSpdyServerSession* session1_;
411 TestQuicSpdyServerSession* session2_;
vasilvvc48c8712019-03-11 13:38:16 -0700412 std::map<QuicConnectionId, std::list<std::string>> data_connection_map_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500413 QuicBufferedPacketStore* store_;
fayangb880b4c2019-06-14 12:26:35 -0700414 uint64_t connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500415};
416
417TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
QUICHE teamea740082019-03-11 17:58:43 -0700418 if (!QuicVersionUsesCryptoFrames(
419 CurrentSupportedVersions().front().transport_version)) {
dschinazi8b1c45a2019-10-17 08:48:13 -0700420 // TLS is only supported in versions with crypto frames.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500421 return;
422 }
rch16df2a52019-09-10 10:50:09 -0700423 SetQuicReloadableFlag(quic_supports_tls_handshake, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500424 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
425
426 EXPECT_CALL(*dispatcher_,
427 CreateQuicSession(TestConnectionId(1), client_address,
428 QuicStringPiece(""), _))
429 .WillOnce(testing::Return(CreateSession(
430 dispatcher_.get(), config_, TestConnectionId(1), client_address,
431 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
432 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
433 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
434 ProcessUdpPacket(_, _, _))
435 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
436 ValidatePacket(TestConnectionId(1), packet);
437 })));
438 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700439 ShouldCreateOrBufferPacketForConnection(
440 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500441 ProcessPacket(
442 client_address, TestConnectionId(1), true,
443 ParsedQuicVersion(PROTOCOL_TLS1_3,
444 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700445 SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
446 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500447}
448
449TEST_F(QuicDispatcherTest, ProcessPackets) {
450 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
451
452 EXPECT_CALL(*dispatcher_,
453 CreateQuicSession(TestConnectionId(1), client_address,
454 QuicStringPiece("hq"), _))
455 .WillOnce(testing::Return(CreateSession(
456 dispatcher_.get(), config_, TestConnectionId(1), client_address,
457 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
458 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
459 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
460 ProcessUdpPacket(_, _, _))
461 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
462 ValidatePacket(TestConnectionId(1), packet);
463 })));
464 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700465 ShouldCreateOrBufferPacketForConnection(
466 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500467 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500468
469 EXPECT_CALL(*dispatcher_,
470 CreateQuicSession(TestConnectionId(2), client_address,
471 QuicStringPiece("hq"), _))
472 .WillOnce(testing::Return(CreateSession(
473 dispatcher_.get(), config_, TestConnectionId(2), client_address,
474 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
475 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
476 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
477 ProcessUdpPacket(_, _, _))
478 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
479 ValidatePacket(TestConnectionId(2), packet);
480 })));
481 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700482 ShouldCreateOrBufferPacketForConnection(
483 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500484 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
485
486 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
487 ProcessUdpPacket(_, _, _))
488 .Times(1)
489 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
490 ValidatePacket(TestConnectionId(1), packet);
491 })));
492 ProcessPacket(client_address, TestConnectionId(1), false, "data");
493}
494
495// Regression test of b/93325907.
496TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
497 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
498
499 EXPECT_CALL(*dispatcher_,
500 CreateQuicSession(TestConnectionId(1), client_address,
501 QuicStringPiece("hq"), _))
502 .WillOnce(testing::Return(CreateSession(
503 dispatcher_.get(), config_, TestConnectionId(1), client_address,
504 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
505 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
506 // Verify both packets 1 and 2 are processed by connection 1.
507 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
508 ProcessUdpPacket(_, _, _))
509 .Times(2)
510 .WillRepeatedly(
511 WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
512 ValidatePacket(TestConnectionId(1), packet);
513 })));
514 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700515 ShouldCreateOrBufferPacketForConnection(
516 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500517 ProcessPacket(
518 client_address, TestConnectionId(1), true,
519 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
520 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700521 SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
522 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500523 // Packet number 256 with packet number length 1 would be considered as 0 in
524 // dispatcher.
525 ProcessPacket(
526 client_address, TestConnectionId(1), false,
527 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
528 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700529 "", true, CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500530}
531
532TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
533 CreateTimeWaitListManager();
534 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
535
536 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
dschinazi346b7ce2019-06-05 01:38:18 -0700537 EXPECT_CALL(
538 *time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700539 SendVersionNegotiationPacket(TestConnectionId(1), _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500540 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500541 // Pad the CHLO message with enough data to make the packet large enough
542 // to trigger version negotiation.
vasilvvc48c8712019-03-11 13:38:16 -0700543 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500544 DCHECK_LE(1200u, chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700545 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700546 QuicVersionReservedForNegotiation(), chlo, true,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500547 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
548}
549
dschinazi346b7ce2019-06-05 01:38:18 -0700550TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
dschinazi346b7ce2019-06-05 01:38:18 -0700551 CreateTimeWaitListManager();
552 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
553
554 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
555 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700556 SendVersionNegotiationPacket(
557 TestConnectionId(1), TestConnectionId(2), _, _, _, _, _, _))
dschinazi346b7ce2019-06-05 01:38:18 -0700558 .Times(1);
559 // Pad the CHLO message with enough data to make the packet large enough
560 // to trigger version negotiation.
561 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
562 DCHECK_LE(1200u, chlo.length());
563 ProcessPacket(client_address, TestConnectionId(1), TestConnectionId(2), true,
fayange3f2f7b2019-09-19 17:01:57 -0700564 QuicVersionReservedForNegotiation(), chlo, true,
dschinazi346b7ce2019-06-05 01:38:18 -0700565 CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
566 PACKET_4BYTE_PACKET_NUMBER, 1);
567}
568
QUICHE teama6ef0a62019-03-07 20:34:33 -0500569TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
570 CreateTimeWaitListManager();
571 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
572
573 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
574 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700575 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500576 .Times(0);
vasilvvc48c8712019-03-11 13:38:16 -0700577 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500578 // Truncate to 1100 bytes of payload which results in a packet just
579 // under 1200 bytes after framing, packet, and encryption overhead.
580 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700581 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500582 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700583 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700584 QuicVersionReservedForNegotiation(), truncated_chlo, false,
nharper4fd11052019-06-04 14:23:22 -0700585 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500586}
587
588// Disabling CHLO size validation allows the dispatcher to send version
589// negotiation packets in response to a CHLO that is otherwise too small.
590TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
591 crypto_config_.set_validate_chlo_size(false);
592
593 CreateTimeWaitListManager();
594 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
595
596 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
597 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700598 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500599 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -0700600 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500601 // Truncate to 1100 bytes of payload which results in a packet just
602 // under 1200 bytes after framing, packet, and encryption overhead.
603 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700604 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500605 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700606 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700607 QuicVersionReservedForNegotiation(), truncated_chlo, true,
nharper4fd11052019-06-04 14:23:22 -0700608 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500609}
610
611TEST_F(QuicDispatcherTest, Shutdown) {
612 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
613
614 EXPECT_CALL(*dispatcher_,
615 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
616 .WillOnce(testing::Return(CreateSession(
617 dispatcher_.get(), config_, TestConnectionId(1), client_address,
618 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
619 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
620 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
621 ProcessUdpPacket(_, _, _))
622 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
623 ValidatePacket(TestConnectionId(1), packet);
624 })));
625
626 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700627 ShouldCreateOrBufferPacketForConnection(
628 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500629 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
630
631 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
632 CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
633
634 dispatcher_->Shutdown();
635}
636
637TEST_F(QuicDispatcherTest, TimeWaitListManager) {
638 CreateTimeWaitListManager();
639
640 // Create a new session.
641 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
642 QuicConnectionId connection_id = TestConnectionId(1);
643 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
644 QuicStringPiece("hq"), _))
645 .WillOnce(testing::Return(CreateSession(
646 dispatcher_.get(), config_, connection_id, client_address,
647 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
648 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
649 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
650 ProcessUdpPacket(_, _, _))
651 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
652 ValidatePacket(TestConnectionId(1), packet);
653 })));
654
655 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700656 ShouldCreateOrBufferPacketForConnection(
657 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500658 ProcessPacket(client_address, connection_id, true, SerializeCHLO());
659
660 // Now close the connection, which should add it to the time wait list.
661 session1_->connection()->CloseConnection(
662 QUIC_INVALID_VERSION,
663 "Server: Packet 2 without version flag before version negotiated.",
664 ConnectionCloseBehavior::SILENT_CLOSE);
665 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
666
667 // Dispatcher forwards subsequent packets for this connection_id to the time
668 // wait list manager.
669 EXPECT_CALL(*time_wait_list_manager_,
670 ProcessPacket(_, _, connection_id, _, _))
671 .Times(1);
672 EXPECT_CALL(*time_wait_list_manager_,
673 AddConnectionIdToTimeWait(_, _, _, _, _))
674 .Times(0);
675 ProcessPacket(client_address, connection_id, true, "data");
676}
677
678TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
679 CreateTimeWaitListManager();
680
681 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
682 QuicConnectionId connection_id = TestConnectionId(1);
683 // Dispatcher forwards all packets for this connection_id to the time wait
684 // list manager.
685 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
686 .Times(0);
fayang9d6231c2019-12-04 07:10:13 -0800687 EXPECT_CALL(*time_wait_list_manager_,
688 ProcessPacket(_, _, connection_id, _, _))
689 .Times(0);
690 EXPECT_CALL(*time_wait_list_manager_,
691 AddConnectionIdToTimeWait(_, _, _, _, _))
692 .Times(0);
693 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
694 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500695 ProcessPacket(client_address, connection_id, false, SerializeCHLO());
696}
697
fayangd057e662019-07-10 13:29:41 -0700698TEST_F(QuicDispatcherTest,
699 DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
700 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
701 CreateTimeWaitListManager();
702
703 char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
704 QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
705 char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
706 QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
707 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
fayang9d6231c2019-12-04 07:10:13 -0800708 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
709 EXPECT_CALL(*time_wait_list_manager_,
710 AddConnectionIdToTimeWait(_, _, _, _, _))
711 .Times(0);
712 // Verify small packet is silently dropped.
713 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
714 .Times(0);
fayangd057e662019-07-10 13:29:41 -0700715 dispatcher_->ProcessPacket(server_address_, client_address, packet);
fayang9d6231c2019-12-04 07:10:13 -0800716 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
717 .Times(1);
fayangd057e662019-07-10 13:29:41 -0700718 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
719}
720
QUICHE teamc65d1d12019-03-19 20:58:04 -0700721// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
QUICHE team963d57e2019-03-21 10:58:47 -0700722TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
QUICHE team8e2e4532019-03-14 14:37:56 -0700723 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
724 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700725 // When variable length connection IDs are not supported, the connection
726 // fails. See StrayPacketTruncatedConnectionId.
QUICHE team8e2e4532019-03-14 14:37:56 -0700727 return;
728 }
QUICHE team8e2e4532019-03-14 14:37:56 -0700729 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
730
QUICHE teamc65d1d12019-03-19 20:58:04 -0700731 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700732 QuicConnectionId fixed_connection_id =
733 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700734
735 EXPECT_CALL(*dispatcher_,
736 CreateQuicSession(fixed_connection_id, client_address,
737 QuicStringPiece("hq"), _))
738 .WillOnce(testing::Return(CreateSession(
739 dispatcher_.get(), config_, fixed_connection_id, client_address,
740 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
741 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
742 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
743 ProcessUdpPacket(_, _, _))
744 .WillOnce(WithArg<2>(
745 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
746 ValidatePacket(bad_connection_id, packet);
747 })));
748 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700749 ShouldCreateOrBufferPacketForConnection(
750 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700751 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700752}
753
QUICHE team963d57e2019-03-21 10:58:47 -0700754// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
755TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
756 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
757 CurrentSupportedVersions()[0].transport_version)) {
758 // When variable length connection IDs are not supported, the connection
759 // fails. See StrayPacketTruncatedConnectionId.
760 return;
761 }
762 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
763
764 QuicConnectionId bad_connection_id = EmptyQuicConnectionId();
dschinazi28c1bf32019-08-19 11:54:46 -0700765 QuicConnectionId fixed_connection_id =
766 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team963d57e2019-03-21 10:58:47 -0700767
768 // Disable validation of invalid short connection IDs.
dschinazi7b9278c2019-05-20 07:36:21 -0700769 dispatcher_->SetAllowShortInitialServerConnectionIds(true);
QUICHE team963d57e2019-03-21 10:58:47 -0700770 // Note that StrayPacketTruncatedConnectionId covers the case where the
771 // validation is still enabled.
772
773 EXPECT_CALL(*dispatcher_,
774 CreateQuicSession(fixed_connection_id, client_address,
775 QuicStringPiece("hq"), _))
776 .WillOnce(testing::Return(CreateSession(
777 dispatcher_.get(), config_, fixed_connection_id, client_address,
778 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
779 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
780 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
781 ProcessUdpPacket(_, _, _))
782 .WillOnce(WithArg<2>(
783 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
784 ValidatePacket(bad_connection_id, packet);
785 })));
786 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700787 ShouldCreateOrBufferPacketForConnection(
788 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE team963d57e2019-03-21 10:58:47 -0700789 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team963d57e2019-03-21 10:58:47 -0700790}
791
QUICHE teamc65d1d12019-03-19 20:58:04 -0700792// Makes sure TestConnectionId(1) creates a new connection and
793// TestConnectionIdNineBytesLong(2) gets replaced.
QUICHE team8e2e4532019-03-14 14:37:56 -0700794TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
795 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
796 CurrentSupportedVersions()[0].transport_version)) {
797 return;
798 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700799
QUICHE team8e2e4532019-03-14 14:37:56 -0700800 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700801 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700802 QuicConnectionId fixed_connection_id =
803 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team8e2e4532019-03-14 14:37:56 -0700804
805 EXPECT_CALL(*dispatcher_,
806 CreateQuicSession(TestConnectionId(1), client_address,
807 QuicStringPiece("hq"), _))
808 .WillOnce(testing::Return(CreateSession(
809 dispatcher_.get(), config_, TestConnectionId(1), client_address,
810 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
811 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
812 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
813 ProcessUdpPacket(_, _, _))
814 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
815 ValidatePacket(TestConnectionId(1), packet);
816 })));
817 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700818 ShouldCreateOrBufferPacketForConnection(
819 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700820 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700821
QUICHE teamc65d1d12019-03-19 20:58:04 -0700822 EXPECT_CALL(*dispatcher_,
823 CreateQuicSession(fixed_connection_id, client_address,
824 QuicStringPiece("hq"), _))
825 .WillOnce(testing::Return(CreateSession(
826 dispatcher_.get(), config_, fixed_connection_id, client_address,
827 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
828 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
829 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
830 ProcessUdpPacket(_, _, _))
831 .WillOnce(WithArg<2>(
832 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
833 ValidatePacket(bad_connection_id, packet);
834 })));
835 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700836 ShouldCreateOrBufferPacketForConnection(
837 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700838 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700839
840 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
841 ProcessUdpPacket(_, _, _))
842 .Times(1)
843 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
844 ValidatePacket(TestConnectionId(1), packet);
845 })));
846 ProcessPacket(client_address, TestConnectionId(1), false, "data");
847}
848
QUICHE teama6ef0a62019-03-07 20:34:33 -0500849TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
850 CreateTimeWaitListManager();
851
852 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
853
854 // dispatcher_ should drop this packet.
855 EXPECT_CALL(*dispatcher_,
856 CreateQuicSession(TestConnectionId(1), client_address,
857 QuicStringPiece("hq"), _))
858 .Times(0);
859 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
860 EXPECT_CALL(*time_wait_list_manager_,
861 AddConnectionIdToTimeWait(_, _, _, _, _))
862 .Times(0);
863 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
864}
865
dschinaziee07e472019-06-19 09:56:56 -0700866TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
dschinazi8b1c45a2019-10-17 08:48:13 -0700867 // Enable a version that supports connection IDs of length different than 8.
868 SetQuicReloadableFlag(quic_enable_version_50, true);
dschinaziee07e472019-06-19 09:56:56 -0700869 CreateTimeWaitListManager();
870
871 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
872
873 // dispatcher_ should drop this packet.
874 EXPECT_CALL(*dispatcher_,
875 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
876 .Times(0);
877 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
878 EXPECT_CALL(*time_wait_list_manager_,
879 AddConnectionIdToTimeWait(_, _, _, _, _))
880 .Times(0);
881 ProcessPacket(client_address, EmptyQuicConnectionId(), true, SerializeCHLO());
882}
883
QUICHE teama6ef0a62019-03-07 20:34:33 -0500884TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
885 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
886 QuicConnectionId connection_id = TestConnectionId(1);
887
888 EXPECT_CALL(*dispatcher_,
889 CreateQuicSession(TestConnectionId(1), client_address,
890 QuicStringPiece("hq"), _))
891 .WillOnce(testing::Return(CreateSession(
892 dispatcher_.get(), config_, TestConnectionId(1), client_address,
893 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
894 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
895 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
896 ProcessUdpPacket(_, _, _))
897 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
898 ValidatePacket(TestConnectionId(1), packet);
899 })));
900
901 // A packet whose packet number is the largest that is allowed to start a
902 // connection.
903 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700904 ShouldCreateOrBufferPacketForConnection(
905 ReceivedPacketInfoConnectionIdEquals(connection_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500906 ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
907 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
908 QuicDispatcher::kMaxReasonableInitialPacketNumber);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500909}
910
QUICHE teama6ef0a62019-03-07 20:34:33 -0500911TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
dschinazi8b1c45a2019-10-17 08:48:13 -0700912 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500913 "Supported versions out of sync");
nharperc32d8ab2019-10-09 11:09:06 -0700914 SetQuicReloadableFlag(quic_enable_version_50, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500915 SetQuicReloadableFlag(quic_enable_version_99, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500916
fayangb880b4c2019-06-14 12:26:35 -0700917 VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
918
919 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
920 QuicVersionMin().transport_version));
921 VerifyVersionSupported(QuicVersionMax());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500922
nharperc32d8ab2019-10-09 11:09:06 -0700923 // Turn off version 50.
924 SetQuicReloadableFlag(quic_enable_version_50, false);
925 VerifyVersionNotSupported(
926 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
927
928 // Turn on version 50.
929 SetQuicReloadableFlag(quic_enable_version_50, true);
930 VerifyVersionSupported(
931 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500932}
933
fayangb54ac5b2019-07-01 10:30:37 -0700934TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
dschinazi8b1c45a2019-10-17 08:48:13 -0700935 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
fayangb54ac5b2019-07-01 10:30:37 -0700936 "Please add deprecated versions to this test");
937 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
938 CreateTimeWaitListManager();
939
dschinazi8b1c45a2019-10-17 08:48:13 -0700940 {
941 char packet47[kMinPacketSizeForVersionNegotiation] = {
942 0xC0, 'Q', '0', '4', '7', /*connection ID length byte*/ 0x50};
943 QuicReceivedPacket received_packet47(
944 packet47, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
945 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
946 EXPECT_CALL(*time_wait_list_manager_,
947 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
948 .Times(1);
949 dispatcher_->ProcessPacket(server_address_, client_address,
950 received_packet47);
951 }
fayang36825da2019-08-21 14:01:27 -0700952
dschinazi8b1c45a2019-10-17 08:48:13 -0700953 {
954 char packet45[kMinPacketSizeForVersionNegotiation] = {
955 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
956 QuicReceivedPacket received_packet45(
957 packet45, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
958 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
959 EXPECT_CALL(*time_wait_list_manager_,
960 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
961 .Times(1);
962 dispatcher_->ProcessPacket(server_address_, client_address,
963 received_packet45);
964 }
965
966 {
967 char packet44[kMinPacketSizeForVersionNegotiation] = {
968 0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
969 QuicReceivedPacket received_packet44(
970 packet44, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
971 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
972 EXPECT_CALL(*time_wait_list_manager_,
973 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
974 .Times(1);
975 dispatcher_->ProcessPacket(server_address_, client_address,
976 received_packet44);
977 }
fayangb54ac5b2019-07-01 10:30:37 -0700978}
979
dschinazi30ab6db2019-08-13 14:43:32 -0700980TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
981 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi30ab6db2019-08-13 14:43:32 -0700982 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
983 CreateTimeWaitListManager();
984 char packet[1200];
985 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
986 0x6c, 0x7a, 0x20, 0x21};
987 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
988 packet, sizeof(packet), destination_connection_id_bytes,
989 sizeof(destination_connection_id_bytes)));
990 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
991 std::unique_ptr<QuicReceivedPacket> received_packet(
992 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
993 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
994 QuicConnectionId server_connection_id(
995 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
996 bool ietf_quic = true;
997 bool use_length_prefix =
998 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
999 EXPECT_CALL(
1000 *time_wait_list_manager_,
1001 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1002 ietf_quic, use_length_prefix, _, _, _, _))
1003 .Times(1);
1004 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1005
1006 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1007}
1008
1009TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
1010 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi30ab6db2019-08-13 14:43:32 -07001011 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1012 CreateTimeWaitListManager();
1013 char packet[1200];
1014 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1015 0x6c, 0x7a, 0x20, 0x21};
1016 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1017 packet, sizeof(packet), destination_connection_id_bytes,
1018 sizeof(destination_connection_id_bytes)));
1019 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1020 std::unique_ptr<QuicReceivedPacket> received_packet(
1021 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1022 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1023 QuicConnectionId server_connection_id(
1024 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1025 bool ietf_quic = true;
1026 bool use_length_prefix =
1027 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1028 EXPECT_CALL(
1029 *time_wait_list_manager_,
1030 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1031 ietf_quic, use_length_prefix, _, _, _, _))
1032 .Times(1);
1033 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1034
1035 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1036}
1037
dschinazi0185ebb2019-08-14 11:09:35 -07001038// Testing packet writer that saves all packets instead of sending them.
1039// Useful for tests that need access to sent packets.
1040class SavingWriter : public QuicPacketWriterWrapper {
1041 public:
1042 bool IsWriteBlocked() const override { return false; }
1043
1044 WriteResult WritePacket(const char* buffer,
1045 size_t buf_len,
1046 const QuicIpAddress& /*self_client_address*/,
1047 const QuicSocketAddress& /*peer_client_address*/,
1048 PerPacketOptions* /*options*/) override {
1049 packets_.push_back(
1050 QuicEncryptedPacket(buffer, buf_len, /*owns_buffer=*/false).Clone());
1051 return WriteResult(WRITE_STATUS_OK, buf_len);
1052 }
1053
1054 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
1055 return &packets_;
1056 }
1057
1058 private:
1059 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
1060};
1061
1062TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
1063 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi0185ebb2019-08-14 11:09:35 -07001064
1065 SavingWriter* saving_writer = new SavingWriter();
1066 // dispatcher_ takes ownership of saving_writer.
1067 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1068
1069 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1070 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1071 &mock_alarm_factory_);
1072 // dispatcher_ takes ownership of time_wait_list_manager.
1073 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1074 time_wait_list_manager);
1075 char packet[1200] = {};
1076 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1077 0x6c, 0x7a, 0x20, 0x21};
1078 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1079 packet, sizeof(packet), destination_connection_id_bytes,
1080 sizeof(destination_connection_id_bytes)));
1081 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1082 std::unique_ptr<QuicReceivedPacket> received_packet(
1083 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1084 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1085
1086 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1087 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1088 ASSERT_EQ(1u, saving_writer->packets()->size());
1089
1090 char source_connection_id_bytes[255] = {};
1091 uint8_t source_connection_id_length = 0;
1092 std::string detailed_error = "foobar";
1093 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1094 (*(saving_writer->packets()))[0]->data(),
1095 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1096 &source_connection_id_length, &detailed_error));
1097 EXPECT_EQ("", detailed_error);
1098
1099 // The source connection ID of the probe response should match the
1100 // destination connection ID of the probe request.
1101 test::CompareCharArraysWithHexError(
1102 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1103 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1104}
1105
1106TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
1107 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi0185ebb2019-08-14 11:09:35 -07001108
1109 SavingWriter* saving_writer = new SavingWriter();
1110 // dispatcher_ takes ownership of saving_writer.
1111 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1112
1113 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1114 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1115 &mock_alarm_factory_);
1116 // dispatcher_ takes ownership of time_wait_list_manager.
1117 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1118 time_wait_list_manager);
1119 char packet[1200] = {};
1120 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1121 0x6c, 0x7a, 0x20, 0x21};
1122 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1123 packet, sizeof(packet), destination_connection_id_bytes,
1124 sizeof(destination_connection_id_bytes)));
1125 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1126 std::unique_ptr<QuicReceivedPacket> received_packet(
1127 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1128 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1129
1130 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1131 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1132 ASSERT_EQ(1u, saving_writer->packets()->size());
1133
1134 char source_connection_id_bytes[255] = {};
1135 uint8_t source_connection_id_length = 0;
1136 std::string detailed_error = "foobar";
1137 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1138 (*(saving_writer->packets()))[0]->data(),
1139 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1140 &source_connection_id_length, &detailed_error));
1141 EXPECT_EQ("", detailed_error);
1142
1143 // The source connection ID of the probe response should match the
1144 // destination connection ID of the probe request.
1145 test::CompareCharArraysWithHexError(
1146 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1147 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1148}
1149
dschinazi5b236be2019-08-19 14:55:22 -07001150TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
1151 // TODO(b/139691956) Remove this test once the workaround is removed.
dschinazi5b236be2019-08-19 14:55:22 -07001152 SavingWriter* saving_writer = new SavingWriter();
1153 // dispatcher_ takes ownership of saving_writer.
1154 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1155
1156 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1157 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1158 &mock_alarm_factory_);
1159 // dispatcher_ takes ownership of time_wait_list_manager.
1160 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1161 time_wait_list_manager);
1162 // clang-format off
1163 static const unsigned char packet[] = {
1164 // Android UDP network conformance test packet as it was before this change:
1165 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1166 0x0c, // public flags: 8-byte connection ID, 1-byte packet number
1167 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1168 0x01, // 1-byte packet number
1169 0x00, // private flags
1170 0x07, // PING frame
1171 };
1172 // clang-format on
1173
1174 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1175 sizeof(packet), false);
1176 std::unique_ptr<QuicReceivedPacket> received_packet(
1177 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1178 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1179
1180 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1181 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1182 ASSERT_EQ(1u, saving_writer->packets()->size());
1183
1184 // The Android UDP network conformance test directly checks that bytes 1-9
1185 // of the response match the connection ID that was sent.
1186 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1187 0x75, 0x76, 0x77, 0x78};
1188 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1189 1u + sizeof(connection_id_bytes));
1190 test::CompareCharArraysWithHexError(
1191 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1192 sizeof(connection_id_bytes), connection_id_bytes,
1193 sizeof(connection_id_bytes));
1194}
1195
dschinazi5b236be2019-08-19 14:55:22 -07001196TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
1197 // WARNING: do not remove or modify this test without making sure that we
1198 // still have adequate coverage for the Android conformance test.
dschinazi5b236be2019-08-19 14:55:22 -07001199 SavingWriter* saving_writer = new SavingWriter();
1200 // dispatcher_ takes ownership of saving_writer.
1201 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1202
1203 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1204 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1205 &mock_alarm_factory_);
1206 // dispatcher_ takes ownership of time_wait_list_manager.
1207 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1208 time_wait_list_manager);
1209 // clang-format off
1210 static const unsigned char packet[1200] = {
1211 // Android UDP network conformance test packet as it was after this change:
1212 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1213 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1214 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1215 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1216 0x01, // 1-byte packet number
1217 0x00, // private flags
1218 0x07, // PING frame
1219 };
1220 // clang-format on
1221
1222 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1223 sizeof(packet), false);
1224 std::unique_ptr<QuicReceivedPacket> received_packet(
1225 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1226 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1227
1228 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1229 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1230 ASSERT_EQ(1u, saving_writer->packets()->size());
1231
1232 // The Android UDP network conformance test directly checks that bytes 1-9
1233 // of the response match the connection ID that was sent.
1234 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1235 0x75, 0x76, 0x77, 0x78};
1236 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1237 1u + sizeof(connection_id_bytes));
1238 test::CompareCharArraysWithHexError(
1239 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1240 sizeof(connection_id_bytes), connection_id_bytes,
1241 sizeof(connection_id_bytes));
1242}
1243
fayange3f2f7b2019-09-19 17:01:57 -07001244TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) {
fayange3f2f7b2019-09-19 17:01:57 -07001245 CreateTimeWaitListManager();
1246 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1247
1248 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1249 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(1);
1250 ProcessPacket(client_address, TestConnectionId(1), true,
1251 CurrentSupportedVersions()[0], SerializeCHLO(), false,
1252 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
1253}
1254
1255TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) {
1256 SetQuicReloadableFlag(quic_enable_version_99, true);
1257 CreateTimeWaitListManager();
1258 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1259
1260 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
1261
1262 // clang-format off
1263 char coalesced_packet[1200] = {
1264 // first coalesced packet
1265 // public flags (long header with packet type INITIAL and
1266 // 4-byte packet number)
1267 0xC3,
1268 // version
1269 'Q', '0', '9', '9',
1270 // destination connection ID length
1271 0x08,
1272 // destination connection ID
1273 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1274 // source connection ID length
1275 0x00,
1276 // long header packet length
1277 0x05,
1278 // packet number
1279 0x12, 0x34, 0x56, 0x78,
1280 // Padding
1281 0x00,
1282 // second coalesced packet
1283 // public flags (long header with packet type ZERO_RTT_PROTECTED and
1284 // 4-byte packet number)
1285 0xC3,
1286 // version
1287 'Q', '0', '9', '9',
1288 // destination connection ID length
1289 0x08,
1290 // destination connection ID
1291 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1292 // source connection ID length
1293 0x00,
1294 // long header packet length
1295 0x1E,
1296 // packet number
1297 0x12, 0x34, 0x56, 0x79,
1298 };
1299 // clang-format on
1300 QuicReceivedPacket packet(coalesced_packet, 1200, QuicTime::Zero());
1301 dispatcher_->ProcessPacket(server_address_, client_address, packet);
1302}
1303
QUICHE teama6ef0a62019-03-07 20:34:33 -05001304// Verify the stopgap test: Packets with truncated connection IDs should be
1305// dropped.
1306class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
1307
1308// Packets with truncated connection IDs should be dropped.
1309TEST_F(QuicDispatcherTestStrayPacketConnectionId,
1310 StrayPacketTruncatedConnectionId) {
1311 CreateTimeWaitListManager();
1312
1313 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1314 QuicConnectionId connection_id = TestConnectionId(1);
1315 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
1316 .Times(0);
fayangd4291e42019-05-30 10:31:21 -07001317 if (VersionHasIetfInvariantHeader(
QUICHE team963d57e2019-03-21 10:58:47 -07001318 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001319 // This IETF packet has invalid connection ID length.
1320 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1321 .Times(0);
1322 EXPECT_CALL(*time_wait_list_manager_,
1323 AddConnectionIdToTimeWait(_, _, _, _, _))
1324 .Times(0);
1325 } else {
dschinaziee07e472019-06-19 09:56:56 -07001326 // This is a GQUIC packet considered as IETF QUIC packet with short header
1327 // with unacceptable packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001328 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1329 .Times(1);
1330 EXPECT_CALL(*time_wait_list_manager_,
1331 AddConnectionIdToTimeWait(_, _, _, _, _))
1332 .Times(1);
1333 }
1334 ProcessPacket(client_address, connection_id, true, "data",
1335 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
1336}
1337
1338class BlockingWriter : public QuicPacketWriterWrapper {
1339 public:
1340 BlockingWriter() : write_blocked_(false) {}
1341
1342 bool IsWriteBlocked() const override { return write_blocked_; }
1343 void SetWritable() override { write_blocked_ = false; }
1344
dschinazi17d42422019-06-18 16:35:07 -07001345 WriteResult WritePacket(const char* /*buffer*/,
1346 size_t /*buf_len*/,
1347 const QuicIpAddress& /*self_client_address*/,
1348 const QuicSocketAddress& /*peer_client_address*/,
1349 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001350 // It would be quite possible to actually implement this method here with
1351 // the fake blocked status, but it would be significantly more work in
1352 // Chromium, and since it's not called anyway, don't bother.
1353 QUIC_LOG(DFATAL) << "Not supported";
1354 return WriteResult();
1355 }
1356
1357 bool write_blocked_;
1358};
1359
1360class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
1361 public:
1362 void SetUp() override {
1363 QuicDispatcherTest::SetUp();
1364 writer_ = new BlockingWriter;
1365 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
1366
1367 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1368
1369 EXPECT_CALL(*dispatcher_,
1370 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1371 .WillOnce(testing::Return(CreateSession(
1372 dispatcher_.get(), config_, TestConnectionId(1), client_address,
1373 &helper_, &alarm_factory_, &crypto_config_,
1374 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1375 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1376 ProcessUdpPacket(_, _, _))
1377 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1378 ValidatePacket(TestConnectionId(1), packet);
1379 })));
fayang1ed1f762019-06-24 11:40:04 -07001380 EXPECT_CALL(*dispatcher_,
1381 ShouldCreateOrBufferPacketForConnection(
1382 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001383 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
1384
1385 EXPECT_CALL(*dispatcher_,
1386 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1387 .WillOnce(testing::Return(CreateSession(
1388 dispatcher_.get(), config_, TestConnectionId(2), client_address,
1389 &helper_, &alarm_factory_, &crypto_config_,
1390 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
1391 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
1392 ProcessUdpPacket(_, _, _))
1393 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1394 ValidatePacket(TestConnectionId(2), packet);
1395 })));
fayang1ed1f762019-06-24 11:40:04 -07001396 EXPECT_CALL(*dispatcher_,
1397 ShouldCreateOrBufferPacketForConnection(
1398 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001399 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
1400
1401 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
1402 }
1403
1404 void TearDown() override {
1405 if (connection1() != nullptr) {
1406 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1407 }
1408
1409 if (connection2() != nullptr) {
1410 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1411 }
1412 dispatcher_->Shutdown();
1413 }
1414
1415 // Set the dispatcher's writer to be blocked. By default, all connections use
1416 // the same writer as the dispatcher in this test.
1417 void SetBlocked() {
1418 QUIC_LOG(INFO) << "set writer " << writer_ << " to blocked";
1419 writer_->write_blocked_ = true;
1420 }
1421
1422 // Simulate what happens when connection1 gets blocked when writing.
1423 void BlockConnection1() {
1424 Connection1Writer()->write_blocked_ = true;
1425 dispatcher_->OnWriteBlocked(connection1());
1426 }
1427
1428 BlockingWriter* Connection1Writer() {
1429 return static_cast<BlockingWriter*>(connection1()->writer());
1430 }
1431
1432 // Simulate what happens when connection2 gets blocked when writing.
1433 void BlockConnection2() {
1434 Connection2Writer()->write_blocked_ = true;
1435 dispatcher_->OnWriteBlocked(connection2());
1436 }
1437
1438 BlockingWriter* Connection2Writer() {
1439 return static_cast<BlockingWriter*>(connection2()->writer());
1440 }
1441
1442 protected:
1443 MockQuicConnectionHelper helper_;
1444 MockAlarmFactory alarm_factory_;
1445 BlockingWriter* writer_;
1446 QuicDispatcher::WriteBlockedList* blocked_list_;
1447};
1448
1449TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
1450 // No OnCanWrite calls because no connections are blocked.
1451 dispatcher_->OnCanWrite();
1452
1453 // Register connection 1 for events, and make sure it's notified.
1454 SetBlocked();
1455 dispatcher_->OnWriteBlocked(connection1());
1456 EXPECT_CALL(*connection1(), OnCanWrite());
1457 dispatcher_->OnCanWrite();
1458
1459 // It should get only one notification.
1460 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1461 dispatcher_->OnCanWrite();
1462 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1463}
1464
1465TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
1466 // Make sure we handle events in order.
1467 InSequence s;
1468 SetBlocked();
1469 dispatcher_->OnWriteBlocked(connection1());
1470 dispatcher_->OnWriteBlocked(connection2());
1471 EXPECT_CALL(*connection1(), OnCanWrite());
1472 EXPECT_CALL(*connection2(), OnCanWrite());
1473 dispatcher_->OnCanWrite();
1474
1475 // Check the other ordering.
1476 SetBlocked();
1477 dispatcher_->OnWriteBlocked(connection2());
1478 dispatcher_->OnWriteBlocked(connection1());
1479 EXPECT_CALL(*connection2(), OnCanWrite());
1480 EXPECT_CALL(*connection1(), OnCanWrite());
1481 dispatcher_->OnCanWrite();
1482}
1483
1484TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
1485 // Add and remove one connction.
1486 SetBlocked();
1487 dispatcher_->OnWriteBlocked(connection1());
1488 blocked_list_->erase(connection1());
1489 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1490 dispatcher_->OnCanWrite();
1491
1492 // Add and remove one connction and make sure it doesn't affect others.
1493 SetBlocked();
1494 dispatcher_->OnWriteBlocked(connection1());
1495 dispatcher_->OnWriteBlocked(connection2());
1496 blocked_list_->erase(connection1());
1497 EXPECT_CALL(*connection2(), OnCanWrite());
1498 dispatcher_->OnCanWrite();
1499
1500 // Add it, remove it, and add it back and make sure things are OK.
1501 SetBlocked();
1502 dispatcher_->OnWriteBlocked(connection1());
1503 blocked_list_->erase(connection1());
1504 dispatcher_->OnWriteBlocked(connection1());
1505 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1506 dispatcher_->OnCanWrite();
1507}
1508
1509TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
1510 // Make sure a double add does not necessitate a double remove.
1511 SetBlocked();
1512 dispatcher_->OnWriteBlocked(connection1());
1513 dispatcher_->OnWriteBlocked(connection1());
1514 blocked_list_->erase(connection1());
1515 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1516 dispatcher_->OnCanWrite();
1517
1518 // Make sure a double add does not result in two OnCanWrite calls.
1519 SetBlocked();
1520 dispatcher_->OnWriteBlocked(connection1());
1521 dispatcher_->OnWriteBlocked(connection1());
1522 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1523 dispatcher_->OnCanWrite();
1524}
1525
1526TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
1527 // If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
1528 // into the write blocked list.
1529 InSequence s;
1530 SetBlocked();
1531 dispatcher_->OnWriteBlocked(connection1());
1532 dispatcher_->OnWriteBlocked(connection2());
1533 EXPECT_CALL(*connection1(), OnCanWrite())
1534 .WillOnce(
1535 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1536 EXPECT_CALL(*connection2(), OnCanWrite());
1537 dispatcher_->OnCanWrite();
1538
1539 // connection1 should be still in the write blocked list.
1540 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1541
1542 // Now call OnCanWrite again, connection1 should get its second chance.
1543 EXPECT_CALL(*connection1(), OnCanWrite());
1544 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
1545 dispatcher_->OnCanWrite();
1546 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1547}
1548
1549TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
1550 // If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
1551 // into the write blocked list.
1552 InSequence s;
1553 SetBlocked();
1554 dispatcher_->OnWriteBlocked(connection1());
1555 dispatcher_->OnWriteBlocked(connection2());
1556 EXPECT_CALL(*connection1(), OnCanWrite());
1557 EXPECT_CALL(*connection2(), OnCanWrite())
1558 .WillOnce(
1559 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1560 dispatcher_->OnCanWrite();
1561
1562 // connection2 should be still in the write blocked list.
1563 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1564
1565 // Now call OnCanWrite again, connection2 should get its second chance.
1566 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1567 EXPECT_CALL(*connection2(), OnCanWrite());
1568 dispatcher_->OnCanWrite();
1569 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1570}
1571
1572TEST_F(QuicDispatcherWriteBlockedListTest,
1573 OnCanWriteHandleBlockBothConnections) {
1574 // Both connections get blocked in OnCanWrite, and added back into the write
1575 // blocked list.
1576 InSequence s;
1577 SetBlocked();
1578 dispatcher_->OnWriteBlocked(connection1());
1579 dispatcher_->OnWriteBlocked(connection2());
1580 EXPECT_CALL(*connection1(), OnCanWrite())
1581 .WillOnce(
1582 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1583 EXPECT_CALL(*connection2(), OnCanWrite())
1584 .WillOnce(
1585 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1586 dispatcher_->OnCanWrite();
1587
1588 // Both connections should be still in the write blocked list.
1589 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1590
1591 // Now call OnCanWrite again, both connections should get its second chance.
1592 EXPECT_CALL(*connection1(), OnCanWrite());
1593 EXPECT_CALL(*connection2(), OnCanWrite());
1594 dispatcher_->OnCanWrite();
1595 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1596}
1597
1598TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
1599 // By default, all connections share the same packet writer with the
1600 // dispatcher.
1601 EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
1602 EXPECT_EQ(dispatcher_->writer(), connection2()->writer());
1603
1604 // Test the case where connection1 shares the same packet writer as the
1605 // dispatcher, whereas connection2 owns it's packet writer.
1606 // Change connection2's writer.
1607 connection2()->SetQuicPacketWriter(new BlockingWriter, /*owns_writer=*/true);
1608 EXPECT_NE(dispatcher_->writer(), connection2()->writer());
1609
1610 BlockConnection2();
1611 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1612
1613 EXPECT_CALL(*connection2(), OnCanWrite());
1614 dispatcher_->OnCanWrite();
1615 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1616}
1617
1618TEST_F(QuicDispatcherWriteBlockedListTest,
1619 RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001620 dispatcher_->OnConnectionClosed(connection1()->connection_id(),
1621 QUIC_PACKET_WRITE_ERROR, "Closed by test.",
1622 ConnectionCloseSource::FROM_SELF);
1623
1624 SetBlocked();
1625
1626 ASSERT_FALSE(dispatcher_->HasPendingWrites());
1627 SetBlocked();
1628 dispatcher_->OnWriteBlocked(connection1());
1629 ASSERT_TRUE(dispatcher_->HasPendingWrites());
1630
1631 EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(),
1632 "QuicConnection was in WriteBlockedList before destruction");
1633 MarkSession1Deleted();
1634}
1635
wub0a4b9c52019-05-28 13:18:58 -07001636class BufferedPacketStoreTest : public QuicDispatcherTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001637 public:
1638 BufferedPacketStoreTest()
1639 : QuicDispatcherTest(),
1640 server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
1641 client_addr_(QuicIpAddress::Loopback4(), 1234),
wub0a4b9c52019-05-28 13:18:58 -07001642 signed_config_(new QuicSignedServerConfig) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001643
1644 void SetUp() override {
1645 QuicDispatcherTest::SetUp();
1646 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
1647
1648 QuicTransportVersion version = AllSupportedTransportVersions().front();
1649 CryptoHandshakeMessage chlo =
1650 crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
1651 &crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001652 // Pass an inchoate CHLO.
1653 crypto_test_utils::GenerateFullCHLO(
1654 chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
1655 signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1656 &full_chlo_);
1657 }
1658
vasilvvc48c8712019-03-11 13:38:16 -07001659 std::string SerializeFullCHLO() {
1660 return std::string(full_chlo_.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001661 }
1662
1663 protected:
1664 QuicSocketAddress server_addr_;
1665 QuicSocketAddress client_addr_;
1666 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1667 const QuicClock* clock_;
1668 CryptoHandshakeMessage full_chlo_;
1669};
1670
wub0a4b9c52019-05-28 13:18:58 -07001671TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001672 InSequence s;
1673 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1674 QuicConnectionId conn_id = TestConnectionId(1);
1675 // A bunch of non-CHLO should be buffered upon arrival, and the first one
1676 // should trigger ShouldCreateOrBufferPacketForConnection().
fayang1ed1f762019-06-24 11:40:04 -07001677 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1678 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001679 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
1680 ProcessPacket(client_address, conn_id, true,
1681 QuicStrCat("data packet ", i + 1), CONNECTION_ID_PRESENT,
1682 PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1);
1683 }
1684 EXPECT_EQ(0u, dispatcher_->session_map().size())
1685 << "No session should be created before CHLO arrives.";
1686
1687 // Pop out the last packet as it is also be dropped by the store.
1688 data_connection_map_[conn_id].pop_back();
1689 // When CHLO arrives, a new session should be created, and all packets
1690 // buffered should be delivered to the session.
1691 EXPECT_CALL(*dispatcher_,
1692 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1693 .WillOnce(testing::Return(CreateSession(
1694 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1695 &mock_alarm_factory_, &crypto_config_,
1696 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1697
1698 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
1699 // should be delivered in arrival order.
1700 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1701 ProcessUdpPacket(_, _, _))
1702 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
1703 .WillRepeatedly(
1704 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1705 ValidatePacket(conn_id, packet);
1706 })));
1707 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1708}
1709
wub0a4b9c52019-05-28 13:18:58 -07001710TEST_F(BufferedPacketStoreTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001711 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
1712 InSequence s;
1713 // A bunch of non-CHLO should be buffered upon arrival.
1714 size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
1715 for (size_t i = 1; i <= kNumConnections; ++i) {
1716 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1717 QuicConnectionId conn_id = TestConnectionId(i);
1718 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001719 ShouldCreateOrBufferPacketForConnection(
1720 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001721 ProcessPacket(client_address, conn_id, true,
1722 QuicStrCat("data packet on connection ", i),
1723 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1724 /*packet_number=*/2);
1725 }
1726
1727 // Pop out the packet on last connection as it shouldn't be enqueued in store
1728 // as well.
1729 data_connection_map_[TestConnectionId(kNumConnections)].pop_front();
1730
1731 // Reset session creation counter to ensure processing CHLO can always
1732 // create session.
1733 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
1734 kNumConnections);
1735 // Process CHLOs to create session for these connections.
1736 for (size_t i = 1; i <= kNumConnections; ++i) {
1737 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1738 QuicConnectionId conn_id = TestConnectionId(i);
1739 if (i == kNumConnections) {
1740 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001741 ShouldCreateOrBufferPacketForConnection(
1742 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001743 }
1744 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1745 QuicStringPiece(), _))
1746 .WillOnce(testing::Return(CreateSession(
1747 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1748 &mock_alarm_factory_, &crypto_config_,
1749 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1750 // First |kNumConnections| - 1 connections should have buffered
1751 // a packet in store. The rest should have been dropped.
1752 size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
1753 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1754 ProcessUdpPacket(_, client_address, _))
1755 .Times(num_packet_to_process)
1756 .WillRepeatedly(WithArg<2>(
1757 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1758 ValidatePacket(conn_id, packet);
1759 })));
1760
1761 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1762 }
1763}
1764
1765// Tests that store delivers empty packet list if CHLO arrives firstly.
wub0a4b9c52019-05-28 13:18:58 -07001766TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001767 QuicConnectionId conn_id = TestConnectionId(1);
1768 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
fayang1ed1f762019-06-24 11:40:04 -07001769 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1770 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001771 EXPECT_CALL(*dispatcher_,
1772 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1773 .WillOnce(testing::Return(CreateSession(
1774 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1775 &mock_alarm_factory_, &crypto_config_,
1776 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1777 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1778 ProcessUdpPacket(_, client_address, _));
1779 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1780}
1781
1782// Tests that a retransmitted CHLO arrives after a connection for the
1783// CHLO has been created.
wub0a4b9c52019-05-28 13:18:58 -07001784TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001785 InSequence s;
1786 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1787 QuicConnectionId conn_id = TestConnectionId(1);
1788 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1789 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1790 /*packet_number=*/2);
1791
1792 // When CHLO arrives, a new session should be created, and all packets
1793 // buffered should be delivered to the session.
1794 EXPECT_CALL(*dispatcher_,
1795 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1796 .Times(1) // Only triggered by 1st CHLO.
1797 .WillOnce(testing::Return(CreateSession(
1798 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1799 &mock_alarm_factory_, &crypto_config_,
1800 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1801 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1802 ProcessUdpPacket(_, _, _))
1803 .Times(3) // Triggered by 1 data packet and 2 CHLOs.
1804 .WillRepeatedly(
1805 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1806 ValidatePacket(conn_id, packet);
1807 })));
1808 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1809
1810 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1811}
1812
1813// Tests that expiration of a connection add connection id to time wait list.
wub0a4b9c52019-05-28 13:18:58 -07001814TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001815 InSequence s;
1816 CreateTimeWaitListManager();
1817 QuicBufferedPacketStore* store =
1818 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1819 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
1820
1821 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1822 QuicConnectionId conn_id = TestConnectionId(1);
1823 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1824 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1825 /*packet_number=*/2);
1826
1827 mock_helper_.AdvanceTime(
1828 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
1829 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
1830 // Cancel alarm as if it had been fired.
1831 alarm->Cancel();
1832 store->OnExpirationTimeout();
1833 // New arrived CHLO will be dropped because this connection is in time wait
1834 // list.
1835 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
1836 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
1837 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1838}
1839
wub0a4b9c52019-05-28 13:18:58 -07001840TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001841 // Process more than (|kMaxNumSessionsToCreate| +
1842 // |kDefaultMaxConnectionsInStore|) CHLOs,
1843 // the first |kMaxNumSessionsToCreate| should create connections immediately,
1844 // the next |kDefaultMaxConnectionsInStore| should be buffered,
1845 // the rest should be dropped.
1846 QuicBufferedPacketStore* store =
1847 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1848 const size_t kNumCHLOs =
1849 kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
1850 for (uint64_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
fayang1ed1f762019-06-24 11:40:04 -07001851 EXPECT_CALL(
1852 *dispatcher_,
1853 ShouldCreateOrBufferPacketForConnection(
1854 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(conn_id))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001855 if (conn_id <= kMaxNumSessionsToCreate) {
1856 EXPECT_CALL(*dispatcher_,
1857 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1858 QuicStringPiece(), _))
1859 .WillOnce(testing::Return(CreateSession(
1860 dispatcher_.get(), config_, TestConnectionId(conn_id),
1861 client_addr_, &mock_helper_, &mock_alarm_factory_,
1862 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1863 &session1_)));
1864 EXPECT_CALL(
1865 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1866 ProcessUdpPacket(_, _, _))
1867 .WillOnce(WithArg<2>(
1868 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1869 ValidatePacket(TestConnectionId(conn_id), packet);
1870 })));
1871 }
1872 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1873 SerializeFullCHLO());
1874 if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
1875 conn_id > kMaxNumSessionsToCreate) {
1876 EXPECT_TRUE(store->HasChloForConnection(TestConnectionId(conn_id)));
1877 } else {
1878 // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
1879 // connections immediately, and the last CHLO should be dropped as the
1880 // store is full.
1881 EXPECT_FALSE(store->HasChloForConnection(TestConnectionId(conn_id)));
1882 }
1883 }
1884
1885 // Graduately consume buffered CHLOs. The buffered connections should be
1886 // created but the dropped one shouldn't.
1887 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1888 conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
1889 ++conn_id) {
1890 EXPECT_CALL(*dispatcher_,
1891 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1892 QuicStringPiece(), _))
1893 .WillOnce(testing::Return(CreateSession(
1894 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1895 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1896 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1897 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1898 ProcessUdpPacket(_, _, _))
1899 .WillOnce(WithArg<2>(
1900 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1901 ValidatePacket(TestConnectionId(conn_id), packet);
1902 })));
1903 }
1904 EXPECT_CALL(*dispatcher_,
1905 CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
1906 QuicStringPiece(), _))
1907 .Times(0);
1908
1909 while (store->HasChlosBuffered()) {
1910 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1911 }
1912
1913 EXPECT_EQ(TestConnectionId(static_cast<size_t>(kMaxNumSessionsToCreate) +
1914 kDefaultMaxConnectionsInStore),
1915 session1_->connection_id());
1916}
1917
1918// Duplicated CHLO shouldn't be buffered.
wub0a4b9c52019-05-28 13:18:58 -07001919TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001920 for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
1921 ++conn_id) {
1922 // Last CHLO will be buffered. Others will create connection right away.
1923 if (conn_id <= kMaxNumSessionsToCreate) {
1924 EXPECT_CALL(*dispatcher_,
1925 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1926 QuicStringPiece(), _))
1927 .WillOnce(testing::Return(CreateSession(
1928 dispatcher_.get(), config_, TestConnectionId(conn_id),
1929 client_addr_, &mock_helper_, &mock_alarm_factory_,
1930 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1931 &session1_)));
1932 EXPECT_CALL(
1933 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1934 ProcessUdpPacket(_, _, _))
1935 .WillOnce(WithArg<2>(
1936 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1937 ValidatePacket(TestConnectionId(conn_id), packet);
1938 })));
1939 }
1940 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1941 SerializeFullCHLO());
1942 }
1943 // Retransmit CHLO on last connection should be dropped.
1944 QuicConnectionId last_connection =
1945 TestConnectionId(kMaxNumSessionsToCreate + 1);
1946 ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
1947
1948 size_t packets_buffered = 2;
1949
1950 // Reset counter and process buffered CHLO.
1951 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
1952 QuicStringPiece(), _))
1953 .WillOnce(testing::Return(CreateSession(
1954 dispatcher_.get(), config_, last_connection, client_addr_,
1955 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1956 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1957 // Only one packet(CHLO) should be process.
1958 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1959 ProcessUdpPacket(_, _, _))
1960 .Times(packets_buffered)
1961 .WillRepeatedly(WithArg<2>(
1962 Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
1963 ValidatePacket(last_connection, packet);
1964 })));
1965 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1966}
1967
wub0a4b9c52019-05-28 13:18:58 -07001968TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001969 uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
1970 QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
1971 for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
1972 // Last CHLO will be buffered. Others will create connection right away.
1973 if (conn_id <= kMaxNumSessionsToCreate) {
1974 EXPECT_CALL(*dispatcher_,
1975 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1976 QuicStringPiece(), _))
1977 .WillOnce(testing::Return(CreateSession(
1978 dispatcher_.get(), config_, TestConnectionId(conn_id),
1979 client_addr_, &mock_helper_, &mock_alarm_factory_,
1980 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1981 &session1_)));
1982 EXPECT_CALL(
1983 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1984 ProcessUdpPacket(_, _, _))
1985 .WillRepeatedly(WithArg<2>(
1986 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1987 ValidatePacket(TestConnectionId(conn_id), packet);
1988 })));
1989 }
1990 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1991 SerializeFullCHLO());
1992 }
1993
1994 // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
1995 // last one should be dropped.
1996 for (uint64_t packet_number = 2;
1997 packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
1998 ProcessPacket(client_addr_, last_connection_id, true, "data packet");
1999 }
2000
2001 // Reset counter and process buffered CHLO.
2002 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
2003 QuicStringPiece(), _))
2004 .WillOnce(testing::Return(CreateSession(
2005 dispatcher_.get(), config_, last_connection_id, client_addr_,
2006 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2007 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2008 // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
2009 // should be process.
2010 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2011 ProcessUdpPacket(_, _, _))
2012 .Times(kDefaultMaxUndecryptablePackets + 1)
2013 .WillRepeatedly(WithArg<2>(
2014 Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
2015 ValidatePacket(last_connection_id, packet);
2016 })));
2017 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2018}
2019
2020// Tests that when dispatcher's packet buffer is full, a CHLO on connection
2021// which doesn't have buffered CHLO should be buffered.
wub0a4b9c52019-05-28 13:18:58 -07002022TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002023 QuicBufferedPacketStore* store =
2024 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
2025
2026 uint64_t conn_id = 1;
2027 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, "data packet",
2028 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
2029 /*packet_number=*/1);
2030 // Fill packet buffer to full with CHLOs on other connections. Need to feed
2031 // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
2032 // session directly.
2033 for (conn_id = 2;
2034 conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
2035 ++conn_id) {
2036 if (conn_id <= kMaxNumSessionsToCreate + 1) {
2037 EXPECT_CALL(*dispatcher_,
2038 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2039 QuicStringPiece(), _))
2040 .WillOnce(testing::Return(CreateSession(
2041 dispatcher_.get(), config_, TestConnectionId(conn_id),
2042 client_addr_, &mock_helper_, &mock_alarm_factory_,
2043 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2044 &session1_)));
2045 EXPECT_CALL(
2046 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2047 ProcessUdpPacket(_, _, _))
2048 .WillOnce(WithArg<2>(
2049 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2050 ValidatePacket(TestConnectionId(conn_id), packet);
2051 })));
2052 }
2053 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2054 SerializeFullCHLO());
2055 }
2056 EXPECT_FALSE(store->HasChloForConnection(
2057 /*connection_id=*/TestConnectionId(1)));
2058
2059 // CHLO on connection 1 should still be buffered.
wub0b2ae542019-10-24 08:32:06 -07002060 ProcessPacket(client_addr_, /*server_connection_id=*/TestConnectionId(1),
2061 true, SerializeFullCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002062 EXPECT_TRUE(store->HasChloForConnection(
2063 /*connection_id=*/TestConnectionId(1)));
2064}
2065
2066// Regression test for b/117874922.
wub0a4b9c52019-05-28 13:18:58 -07002067TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002068 // Turn off version 99, such that the preferred version is not supported by
2069 // the server.
2070 SetQuicReloadableFlag(quic_enable_version_99, false);
2071 uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
2072 ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
2073 for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
2074 // Last 5 CHLOs will be buffered. Others will create connection right away.
2075 ParsedQuicVersion version =
2076 supported_versions[(conn_id - 1) % supported_versions.size()];
2077 if (conn_id <= kMaxNumSessionsToCreate) {
2078 EXPECT_CALL(*dispatcher_,
2079 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2080 QuicStringPiece(), version))
2081 .WillOnce(testing::Return(CreateSession(
2082 dispatcher_.get(), config_, TestConnectionId(conn_id),
2083 client_addr_, &mock_helper_, &mock_alarm_factory_,
2084 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2085 &session1_)));
2086 EXPECT_CALL(
2087 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2088 ProcessUdpPacket(_, _, _))
2089 .WillRepeatedly(WithArg<2>(
2090 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2091 ValidatePacket(TestConnectionId(conn_id), packet);
2092 })));
2093 }
2094 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version,
fayange3f2f7b2019-09-19 17:01:57 -07002095 SerializeFullCHLO(), true, CONNECTION_ID_PRESENT,
QUICHE teama6ef0a62019-03-07 20:34:33 -05002096 PACKET_4BYTE_PACKET_NUMBER, 1);
2097 }
2098
2099 // Process buffered CHLOs. Verify the version is correct.
2100 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
2101 conn_id <= last_connection_id; ++conn_id) {
2102 ParsedQuicVersion version =
2103 supported_versions[(conn_id - 1) % supported_versions.size()];
2104 EXPECT_CALL(*dispatcher_,
2105 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2106 QuicStringPiece(), version))
2107 .WillOnce(testing::Return(CreateSession(
2108 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
2109 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2110 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2111 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2112 ProcessUdpPacket(_, _, _))
2113 .WillRepeatedly(WithArg<2>(
2114 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2115 ValidatePacket(TestConnectionId(conn_id), packet);
2116 })));
2117 }
2118 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2119}
2120
QUICHE teama6ef0a62019-03-07 20:34:33 -05002121} // namespace
2122} // namespace test
2123} // namespace quic