blob: 985a1c35d2bec929c8963d0b513a96e003da3d0b [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)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500420 // TLS is only supported in versions 47 and greater.
421 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);
fayangd057e662019-07-10 13:29:41 -0700687 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
688 EXPECT_CALL(*time_wait_list_manager_,
689 ProcessPacket(_, _, connection_id, _, _))
690 .Times(0);
691 EXPECT_CALL(*time_wait_list_manager_,
692 AddConnectionIdToTimeWait(_, _, _, _, _))
693 .Times(0);
694 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
695 .Times(1);
696 } else {
697 EXPECT_CALL(*time_wait_list_manager_,
698 ProcessPacket(_, _, connection_id, _, _))
699 .Times(1);
700 EXPECT_CALL(*time_wait_list_manager_,
701 AddConnectionIdToTimeWait(_, _, _, _, _))
702 .Times(1);
703 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500704 ProcessPacket(client_address, connection_id, false, SerializeCHLO());
705}
706
fayangd057e662019-07-10 13:29:41 -0700707TEST_F(QuicDispatcherTest,
708 DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
709 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
710 CreateTimeWaitListManager();
711
712 char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
713 QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
714 char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
715 QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
716 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
717 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
718 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
719 .Times(0);
720 EXPECT_CALL(*time_wait_list_manager_,
721 AddConnectionIdToTimeWait(_, _, _, _, _))
722 .Times(0);
723 } else {
724 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
725 .Times(2);
726 EXPECT_CALL(*time_wait_list_manager_,
727 AddConnectionIdToTimeWait(_, _, _, _, _))
728 .Times(2);
729 }
730 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
731 // Verify small packet is silently dropped.
732 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
733 .Times(0);
734 }
735 dispatcher_->ProcessPacket(server_address_, client_address, packet);
736 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
737 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
738 .Times(1);
739 }
740 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
741}
742
QUICHE teamc65d1d12019-03-19 20:58:04 -0700743// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
QUICHE team963d57e2019-03-21 10:58:47 -0700744TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
QUICHE team8e2e4532019-03-14 14:37:56 -0700745 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
746 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700747 // When variable length connection IDs are not supported, the connection
748 // fails. See StrayPacketTruncatedConnectionId.
QUICHE team8e2e4532019-03-14 14:37:56 -0700749 return;
750 }
QUICHE team8e2e4532019-03-14 14:37:56 -0700751 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
752
QUICHE teamc65d1d12019-03-19 20:58:04 -0700753 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700754 QuicConnectionId fixed_connection_id =
755 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700756
757 EXPECT_CALL(*dispatcher_,
758 CreateQuicSession(fixed_connection_id, client_address,
759 QuicStringPiece("hq"), _))
760 .WillOnce(testing::Return(CreateSession(
761 dispatcher_.get(), config_, fixed_connection_id, client_address,
762 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
763 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
764 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
765 ProcessUdpPacket(_, _, _))
766 .WillOnce(WithArg<2>(
767 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
768 ValidatePacket(bad_connection_id, packet);
769 })));
770 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700771 ShouldCreateOrBufferPacketForConnection(
772 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700773 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700774}
775
QUICHE team963d57e2019-03-21 10:58:47 -0700776// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
777TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
778 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
779 CurrentSupportedVersions()[0].transport_version)) {
780 // When variable length connection IDs are not supported, the connection
781 // fails. See StrayPacketTruncatedConnectionId.
782 return;
783 }
784 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
785
786 QuicConnectionId bad_connection_id = EmptyQuicConnectionId();
dschinazi28c1bf32019-08-19 11:54:46 -0700787 QuicConnectionId fixed_connection_id =
788 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team963d57e2019-03-21 10:58:47 -0700789
790 // Disable validation of invalid short connection IDs.
dschinazi7b9278c2019-05-20 07:36:21 -0700791 dispatcher_->SetAllowShortInitialServerConnectionIds(true);
QUICHE team963d57e2019-03-21 10:58:47 -0700792 // Note that StrayPacketTruncatedConnectionId covers the case where the
793 // validation is still enabled.
794
795 EXPECT_CALL(*dispatcher_,
796 CreateQuicSession(fixed_connection_id, client_address,
797 QuicStringPiece("hq"), _))
798 .WillOnce(testing::Return(CreateSession(
799 dispatcher_.get(), config_, fixed_connection_id, client_address,
800 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
801 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
802 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
803 ProcessUdpPacket(_, _, _))
804 .WillOnce(WithArg<2>(
805 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
806 ValidatePacket(bad_connection_id, packet);
807 })));
808 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700809 ShouldCreateOrBufferPacketForConnection(
810 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE team963d57e2019-03-21 10:58:47 -0700811 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team963d57e2019-03-21 10:58:47 -0700812}
813
QUICHE teamc65d1d12019-03-19 20:58:04 -0700814// Makes sure TestConnectionId(1) creates a new connection and
815// TestConnectionIdNineBytesLong(2) gets replaced.
QUICHE team8e2e4532019-03-14 14:37:56 -0700816TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
817 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
818 CurrentSupportedVersions()[0].transport_version)) {
819 return;
820 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700821
QUICHE team8e2e4532019-03-14 14:37:56 -0700822 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700823 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700824 QuicConnectionId fixed_connection_id =
825 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team8e2e4532019-03-14 14:37:56 -0700826
827 EXPECT_CALL(*dispatcher_,
828 CreateQuicSession(TestConnectionId(1), client_address,
829 QuicStringPiece("hq"), _))
830 .WillOnce(testing::Return(CreateSession(
831 dispatcher_.get(), config_, TestConnectionId(1), client_address,
832 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
833 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
834 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
835 ProcessUdpPacket(_, _, _))
836 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
837 ValidatePacket(TestConnectionId(1), packet);
838 })));
839 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700840 ShouldCreateOrBufferPacketForConnection(
841 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700842 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700843
QUICHE teamc65d1d12019-03-19 20:58:04 -0700844 EXPECT_CALL(*dispatcher_,
845 CreateQuicSession(fixed_connection_id, client_address,
846 QuicStringPiece("hq"), _))
847 .WillOnce(testing::Return(CreateSession(
848 dispatcher_.get(), config_, fixed_connection_id, client_address,
849 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
850 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
851 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
852 ProcessUdpPacket(_, _, _))
853 .WillOnce(WithArg<2>(
854 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
855 ValidatePacket(bad_connection_id, packet);
856 })));
857 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700858 ShouldCreateOrBufferPacketForConnection(
859 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700860 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700861
862 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
863 ProcessUdpPacket(_, _, _))
864 .Times(1)
865 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
866 ValidatePacket(TestConnectionId(1), packet);
867 })));
868 ProcessPacket(client_address, TestConnectionId(1), false, "data");
869}
870
QUICHE teama6ef0a62019-03-07 20:34:33 -0500871TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
872 CreateTimeWaitListManager();
873
874 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
875
876 // dispatcher_ should drop this packet.
877 EXPECT_CALL(*dispatcher_,
878 CreateQuicSession(TestConnectionId(1), client_address,
879 QuicStringPiece("hq"), _))
880 .Times(0);
881 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
882 EXPECT_CALL(*time_wait_list_manager_,
883 AddConnectionIdToTimeWait(_, _, _, _, _))
884 .Times(0);
885 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
886}
887
dschinaziee07e472019-06-19 09:56:56 -0700888TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
dschinaziee07e472019-06-19 09:56:56 -0700889 // Enable v47 otherwise we cannot create a packet with a short connection ID.
890 SetQuicReloadableFlag(quic_enable_version_47, true);
891 CreateTimeWaitListManager();
892
893 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
894
895 // dispatcher_ should drop this packet.
896 EXPECT_CALL(*dispatcher_,
897 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
898 .Times(0);
899 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
900 EXPECT_CALL(*time_wait_list_manager_,
901 AddConnectionIdToTimeWait(_, _, _, _, _))
902 .Times(0);
903 ProcessPacket(client_address, EmptyQuicConnectionId(), true, SerializeCHLO());
904}
905
QUICHE teama6ef0a62019-03-07 20:34:33 -0500906TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
907 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
908 QuicConnectionId connection_id = TestConnectionId(1);
909
910 EXPECT_CALL(*dispatcher_,
911 CreateQuicSession(TestConnectionId(1), client_address,
912 QuicStringPiece("hq"), _))
913 .WillOnce(testing::Return(CreateSession(
914 dispatcher_.get(), config_, TestConnectionId(1), client_address,
915 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
916 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
917 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
918 ProcessUdpPacket(_, _, _))
919 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
920 ValidatePacket(TestConnectionId(1), packet);
921 })));
922
923 // A packet whose packet number is the largest that is allowed to start a
924 // connection.
925 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700926 ShouldCreateOrBufferPacketForConnection(
927 ReceivedPacketInfoConnectionIdEquals(connection_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500928 ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
929 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
930 QuicDispatcher::kMaxReasonableInitialPacketNumber);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500931}
932
QUICHE teama6ef0a62019-03-07 20:34:33 -0500933TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
fayang8265a2a2019-10-16 11:23:51 -0700934 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500935 "Supported versions out of sync");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500936 SetQuicReloadableFlag(quic_enable_version_47, true);
nharperd0f4a162019-08-21 11:03:21 -0700937 SetQuicReloadableFlag(quic_enable_version_48_2, true);
dschinazic73506e2019-09-20 13:26:46 -0700938 SetQuicReloadableFlag(quic_enable_version_49, true);
nharperc32d8ab2019-10-09 11:09:06 -0700939 SetQuicReloadableFlag(quic_enable_version_50, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500940 SetQuicReloadableFlag(quic_enable_version_99, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500941
fayangb880b4c2019-06-14 12:26:35 -0700942 VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
943
944 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
945 QuicVersionMin().transport_version));
946 VerifyVersionSupported(QuicVersionMax());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500947
nharperc32d8ab2019-10-09 11:09:06 -0700948 // Turn off version 50.
949 SetQuicReloadableFlag(quic_enable_version_50, false);
950 VerifyVersionNotSupported(
951 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
952
953 // Turn on version 50.
954 SetQuicReloadableFlag(quic_enable_version_50, true);
955 VerifyVersionSupported(
956 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
957
dschinazic73506e2019-09-20 13:26:46 -0700958 // Turn off version 49.
959 SetQuicReloadableFlag(quic_enable_version_49, false);
960 VerifyVersionNotSupported(
961 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
962
963 // Turn on version 49.
964 SetQuicReloadableFlag(quic_enable_version_49, true);
965 VerifyVersionSupported(
966 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
967
nharper107ba5f2019-07-02 21:33:39 -0700968 // Turn off version 48.
nharperd0f4a162019-08-21 11:03:21 -0700969 SetQuicReloadableFlag(quic_enable_version_48_2, false);
nharper107ba5f2019-07-02 21:33:39 -0700970 VerifyVersionNotSupported(
971 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
972
973 // Turn on version 48.
nharperd0f4a162019-08-21 11:03:21 -0700974 SetQuicReloadableFlag(quic_enable_version_48_2, true);
nharper107ba5f2019-07-02 21:33:39 -0700975 VerifyVersionSupported(
976 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
977
QUICHE teama6ef0a62019-03-07 20:34:33 -0500978 // Turn off version 47.
979 SetQuicReloadableFlag(quic_enable_version_47, false);
fayangb880b4c2019-06-14 12:26:35 -0700980 VerifyVersionNotSupported(
981 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500982
983 // Turn on version 47.
984 SetQuicReloadableFlag(quic_enable_version_47, true);
fayangb880b4c2019-06-14 12:26:35 -0700985 VerifyVersionSupported(
986 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500987}
988
fayangb54ac5b2019-07-01 10:30:37 -0700989TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
fayang8265a2a2019-10-16 11:23:51 -0700990 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
fayangb54ac5b2019-07-01 10:30:37 -0700991 "Please add deprecated versions to this test");
992 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
993 CreateTimeWaitListManager();
994
995 char packet45[kMinPacketSizeForVersionNegotiation] = {
996 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
997 QuicReceivedPacket packet(packet45, kMinPacketSizeForVersionNegotiation,
998 QuicTime::Zero());
999 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1000 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -07001001 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
fayangb54ac5b2019-07-01 10:30:37 -07001002 .Times(1);
1003 dispatcher_->ProcessPacket(server_address_, client_address, packet);
fayang36825da2019-08-21 14:01:27 -07001004
1005 char packet44[kMinPacketSizeForVersionNegotiation] = {
1006 0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
1007 QuicReceivedPacket packet2(packet44, kMinPacketSizeForVersionNegotiation,
1008 QuicTime::Zero());
1009 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1010 EXPECT_CALL(*time_wait_list_manager_,
1011 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
1012 .Times(1);
1013 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
fayangb54ac5b2019-07-01 10:30:37 -07001014}
1015
dschinazi30ab6db2019-08-13 14:43:32 -07001016TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
1017 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi30ab6db2019-08-13 14:43:32 -07001018 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1019 CreateTimeWaitListManager();
1020 char packet[1200];
1021 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1022 0x6c, 0x7a, 0x20, 0x21};
1023 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1024 packet, sizeof(packet), destination_connection_id_bytes,
1025 sizeof(destination_connection_id_bytes)));
1026 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1027 std::unique_ptr<QuicReceivedPacket> received_packet(
1028 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1029 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1030 QuicConnectionId server_connection_id(
1031 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1032 bool ietf_quic = true;
1033 bool use_length_prefix =
1034 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1035 EXPECT_CALL(
1036 *time_wait_list_manager_,
1037 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1038 ietf_quic, use_length_prefix, _, _, _, _))
1039 .Times(1);
1040 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1041
1042 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1043}
1044
1045TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
1046 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi30ab6db2019-08-13 14:43:32 -07001047 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1048 CreateTimeWaitListManager();
1049 char packet[1200];
1050 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1051 0x6c, 0x7a, 0x20, 0x21};
1052 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1053 packet, sizeof(packet), destination_connection_id_bytes,
1054 sizeof(destination_connection_id_bytes)));
1055 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1056 std::unique_ptr<QuicReceivedPacket> received_packet(
1057 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1058 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1059 QuicConnectionId server_connection_id(
1060 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1061 bool ietf_quic = true;
1062 bool use_length_prefix =
1063 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1064 EXPECT_CALL(
1065 *time_wait_list_manager_,
1066 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1067 ietf_quic, use_length_prefix, _, _, _, _))
1068 .Times(1);
1069 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1070
1071 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1072}
1073
dschinazi0185ebb2019-08-14 11:09:35 -07001074// Testing packet writer that saves all packets instead of sending them.
1075// Useful for tests that need access to sent packets.
1076class SavingWriter : public QuicPacketWriterWrapper {
1077 public:
1078 bool IsWriteBlocked() const override { return false; }
1079
1080 WriteResult WritePacket(const char* buffer,
1081 size_t buf_len,
1082 const QuicIpAddress& /*self_client_address*/,
1083 const QuicSocketAddress& /*peer_client_address*/,
1084 PerPacketOptions* /*options*/) override {
1085 packets_.push_back(
1086 QuicEncryptedPacket(buffer, buf_len, /*owns_buffer=*/false).Clone());
1087 return WriteResult(WRITE_STATUS_OK, buf_len);
1088 }
1089
1090 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
1091 return &packets_;
1092 }
1093
1094 private:
1095 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
1096};
1097
1098TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
1099 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi0185ebb2019-08-14 11:09:35 -07001100
1101 SavingWriter* saving_writer = new SavingWriter();
1102 // dispatcher_ takes ownership of saving_writer.
1103 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1104
1105 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1106 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1107 &mock_alarm_factory_);
1108 // dispatcher_ takes ownership of time_wait_list_manager.
1109 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1110 time_wait_list_manager);
1111 char packet[1200] = {};
1112 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1113 0x6c, 0x7a, 0x20, 0x21};
1114 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1115 packet, sizeof(packet), destination_connection_id_bytes,
1116 sizeof(destination_connection_id_bytes)));
1117 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1118 std::unique_ptr<QuicReceivedPacket> received_packet(
1119 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1120 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1121
1122 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1123 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1124 ASSERT_EQ(1u, saving_writer->packets()->size());
1125
1126 char source_connection_id_bytes[255] = {};
1127 uint8_t source_connection_id_length = 0;
1128 std::string detailed_error = "foobar";
1129 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1130 (*(saving_writer->packets()))[0]->data(),
1131 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1132 &source_connection_id_length, &detailed_error));
1133 EXPECT_EQ("", detailed_error);
1134
1135 // The source connection ID of the probe response should match the
1136 // destination connection ID of the probe request.
1137 test::CompareCharArraysWithHexError(
1138 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1139 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1140}
1141
1142TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
1143 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi0185ebb2019-08-14 11:09:35 -07001144
1145 SavingWriter* saving_writer = new SavingWriter();
1146 // dispatcher_ takes ownership of saving_writer.
1147 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1148
1149 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1150 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1151 &mock_alarm_factory_);
1152 // dispatcher_ takes ownership of time_wait_list_manager.
1153 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1154 time_wait_list_manager);
1155 char packet[1200] = {};
1156 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1157 0x6c, 0x7a, 0x20, 0x21};
1158 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1159 packet, sizeof(packet), destination_connection_id_bytes,
1160 sizeof(destination_connection_id_bytes)));
1161 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1162 std::unique_ptr<QuicReceivedPacket> received_packet(
1163 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1164 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1165
1166 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1167 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1168 ASSERT_EQ(1u, saving_writer->packets()->size());
1169
1170 char source_connection_id_bytes[255] = {};
1171 uint8_t source_connection_id_length = 0;
1172 std::string detailed_error = "foobar";
1173 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1174 (*(saving_writer->packets()))[0]->data(),
1175 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1176 &source_connection_id_length, &detailed_error));
1177 EXPECT_EQ("", detailed_error);
1178
1179 // The source connection ID of the probe response should match the
1180 // destination connection ID of the probe request.
1181 test::CompareCharArraysWithHexError(
1182 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1183 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1184}
1185
dschinazi5b236be2019-08-19 14:55:22 -07001186TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
1187 // TODO(b/139691956) Remove this test once the workaround is removed.
1188 // This test requires the workaround behind this flag to pass.
1189 SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, true);
1190 SavingWriter* saving_writer = new SavingWriter();
1191 // dispatcher_ takes ownership of saving_writer.
1192 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1193
1194 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1195 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1196 &mock_alarm_factory_);
1197 // dispatcher_ takes ownership of time_wait_list_manager.
1198 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1199 time_wait_list_manager);
1200 // clang-format off
1201 static const unsigned char packet[] = {
1202 // Android UDP network conformance test packet as it was before this change:
1203 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1204 0x0c, // public flags: 8-byte connection ID, 1-byte packet number
1205 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1206 0x01, // 1-byte packet number
1207 0x00, // private flags
1208 0x07, // PING frame
1209 };
1210 // clang-format on
1211
1212 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1213 sizeof(packet), false);
1214 std::unique_ptr<QuicReceivedPacket> received_packet(
1215 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1216 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1217
1218 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1219 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1220 ASSERT_EQ(1u, saving_writer->packets()->size());
1221
1222 // The Android UDP network conformance test directly checks that bytes 1-9
1223 // of the response match the connection ID that was sent.
1224 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1225 0x75, 0x76, 0x77, 0x78};
1226 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1227 1u + sizeof(connection_id_bytes));
1228 test::CompareCharArraysWithHexError(
1229 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1230 sizeof(connection_id_bytes), connection_id_bytes,
1231 sizeof(connection_id_bytes));
1232}
1233
1234TEST_F(QuicDispatcherTest, AndroidConformanceTestNewWithWorkaround) {
1235 // TODO(b/139691956) Remove this test once the workaround is removed.
1236 // This test doesn't need the workaround but we make sure that it passes even
1237 // when the flag is true, also see AndroidConformanceTest below.
1238 SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, true);
1239 SavingWriter* saving_writer = new SavingWriter();
1240 // dispatcher_ takes ownership of saving_writer.
1241 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1242
1243 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1244 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1245 &mock_alarm_factory_);
1246 // dispatcher_ takes ownership of time_wait_list_manager.
1247 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1248 time_wait_list_manager);
1249 // clang-format off
1250 static const unsigned char packet[1200] = {
1251 // Android UDP network conformance test packet as it was after this change:
1252 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1253 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1254 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1255 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1256 0x01, // 1-byte packet number
1257 0x00, // private flags
1258 0x07, // PING frame
1259 };
1260 // clang-format on
1261
1262 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1263 sizeof(packet), false);
1264 std::unique_ptr<QuicReceivedPacket> received_packet(
1265 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1266 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1267
1268 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1269 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1270 ASSERT_EQ(1u, saving_writer->packets()->size());
1271
1272 // The Android UDP network conformance test directly checks that bytes 1-9
1273 // of the response match the connection ID that was sent.
1274 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1275 0x75, 0x76, 0x77, 0x78};
1276 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1277 1u + sizeof(connection_id_bytes));
1278 test::CompareCharArraysWithHexError(
1279 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1280 sizeof(connection_id_bytes), connection_id_bytes,
1281 sizeof(connection_id_bytes));
1282}
1283
1284TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
1285 // WARNING: do not remove or modify this test without making sure that we
1286 // still have adequate coverage for the Android conformance test.
1287
1288 // Set the flag to false to make sure this test passes even when the
1289 // workaround is disabled.
1290 SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, false);
1291 SavingWriter* saving_writer = new SavingWriter();
1292 // dispatcher_ takes ownership of saving_writer.
1293 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1294
1295 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1296 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1297 &mock_alarm_factory_);
1298 // dispatcher_ takes ownership of time_wait_list_manager.
1299 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1300 time_wait_list_manager);
1301 // clang-format off
1302 static const unsigned char packet[1200] = {
1303 // Android UDP network conformance test packet as it was after this change:
1304 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1305 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1306 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1307 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1308 0x01, // 1-byte packet number
1309 0x00, // private flags
1310 0x07, // PING frame
1311 };
1312 // clang-format on
1313
1314 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1315 sizeof(packet), false);
1316 std::unique_ptr<QuicReceivedPacket> received_packet(
1317 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1318 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1319
1320 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1321 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1322 ASSERT_EQ(1u, saving_writer->packets()->size());
1323
1324 // The Android UDP network conformance test directly checks that bytes 1-9
1325 // of the response match the connection ID that was sent.
1326 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1327 0x75, 0x76, 0x77, 0x78};
1328 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1329 1u + sizeof(connection_id_bytes));
1330 test::CompareCharArraysWithHexError(
1331 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1332 sizeof(connection_id_bytes), connection_id_bytes,
1333 sizeof(connection_id_bytes));
1334}
1335
fayange3f2f7b2019-09-19 17:01:57 -07001336TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) {
1337 SetQuicReloadableFlag(quic_donot_process_small_initial_packets, true);
fayange3f2f7b2019-09-19 17:01:57 -07001338 CreateTimeWaitListManager();
1339 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1340
1341 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1342 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(1);
1343 ProcessPacket(client_address, TestConnectionId(1), true,
1344 CurrentSupportedVersions()[0], SerializeCHLO(), false,
1345 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
1346}
1347
1348TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) {
1349 SetQuicReloadableFlag(quic_enable_version_99, true);
1350 CreateTimeWaitListManager();
1351 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1352
1353 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
1354
1355 // clang-format off
1356 char coalesced_packet[1200] = {
1357 // first coalesced packet
1358 // public flags (long header with packet type INITIAL and
1359 // 4-byte packet number)
1360 0xC3,
1361 // version
1362 'Q', '0', '9', '9',
1363 // destination connection ID length
1364 0x08,
1365 // destination connection ID
1366 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1367 // source connection ID length
1368 0x00,
1369 // long header packet length
1370 0x05,
1371 // packet number
1372 0x12, 0x34, 0x56, 0x78,
1373 // Padding
1374 0x00,
1375 // second coalesced packet
1376 // public flags (long header with packet type ZERO_RTT_PROTECTED and
1377 // 4-byte packet number)
1378 0xC3,
1379 // version
1380 'Q', '0', '9', '9',
1381 // destination connection ID length
1382 0x08,
1383 // destination connection ID
1384 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1385 // source connection ID length
1386 0x00,
1387 // long header packet length
1388 0x1E,
1389 // packet number
1390 0x12, 0x34, 0x56, 0x79,
1391 };
1392 // clang-format on
1393 QuicReceivedPacket packet(coalesced_packet, 1200, QuicTime::Zero());
1394 dispatcher_->ProcessPacket(server_address_, client_address, packet);
1395}
1396
QUICHE teama6ef0a62019-03-07 20:34:33 -05001397// Verify the stopgap test: Packets with truncated connection IDs should be
1398// dropped.
1399class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
1400
1401// Packets with truncated connection IDs should be dropped.
1402TEST_F(QuicDispatcherTestStrayPacketConnectionId,
1403 StrayPacketTruncatedConnectionId) {
1404 CreateTimeWaitListManager();
1405
1406 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1407 QuicConnectionId connection_id = TestConnectionId(1);
1408 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
1409 .Times(0);
fayangd4291e42019-05-30 10:31:21 -07001410 if (VersionHasIetfInvariantHeader(
QUICHE team963d57e2019-03-21 10:58:47 -07001411 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001412 // This IETF packet has invalid connection ID length.
1413 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1414 .Times(0);
1415 EXPECT_CALL(*time_wait_list_manager_,
1416 AddConnectionIdToTimeWait(_, _, _, _, _))
1417 .Times(0);
1418 } else {
dschinaziee07e472019-06-19 09:56:56 -07001419 // This is a GQUIC packet considered as IETF QUIC packet with short header
1420 // with unacceptable packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001421 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1422 .Times(1);
1423 EXPECT_CALL(*time_wait_list_manager_,
1424 AddConnectionIdToTimeWait(_, _, _, _, _))
1425 .Times(1);
1426 }
1427 ProcessPacket(client_address, connection_id, true, "data",
1428 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
1429}
1430
1431class BlockingWriter : public QuicPacketWriterWrapper {
1432 public:
1433 BlockingWriter() : write_blocked_(false) {}
1434
1435 bool IsWriteBlocked() const override { return write_blocked_; }
1436 void SetWritable() override { write_blocked_ = false; }
1437
dschinazi17d42422019-06-18 16:35:07 -07001438 WriteResult WritePacket(const char* /*buffer*/,
1439 size_t /*buf_len*/,
1440 const QuicIpAddress& /*self_client_address*/,
1441 const QuicSocketAddress& /*peer_client_address*/,
1442 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001443 // It would be quite possible to actually implement this method here with
1444 // the fake blocked status, but it would be significantly more work in
1445 // Chromium, and since it's not called anyway, don't bother.
1446 QUIC_LOG(DFATAL) << "Not supported";
1447 return WriteResult();
1448 }
1449
1450 bool write_blocked_;
1451};
1452
1453class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
1454 public:
1455 void SetUp() override {
1456 QuicDispatcherTest::SetUp();
1457 writer_ = new BlockingWriter;
1458 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
1459
1460 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1461
1462 EXPECT_CALL(*dispatcher_,
1463 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1464 .WillOnce(testing::Return(CreateSession(
1465 dispatcher_.get(), config_, TestConnectionId(1), client_address,
1466 &helper_, &alarm_factory_, &crypto_config_,
1467 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1468 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1469 ProcessUdpPacket(_, _, _))
1470 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1471 ValidatePacket(TestConnectionId(1), packet);
1472 })));
fayang1ed1f762019-06-24 11:40:04 -07001473 EXPECT_CALL(*dispatcher_,
1474 ShouldCreateOrBufferPacketForConnection(
1475 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001476 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
1477
1478 EXPECT_CALL(*dispatcher_,
1479 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1480 .WillOnce(testing::Return(CreateSession(
1481 dispatcher_.get(), config_, TestConnectionId(2), client_address,
1482 &helper_, &alarm_factory_, &crypto_config_,
1483 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
1484 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
1485 ProcessUdpPacket(_, _, _))
1486 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1487 ValidatePacket(TestConnectionId(2), packet);
1488 })));
fayang1ed1f762019-06-24 11:40:04 -07001489 EXPECT_CALL(*dispatcher_,
1490 ShouldCreateOrBufferPacketForConnection(
1491 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001492 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
1493
1494 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
1495 }
1496
1497 void TearDown() override {
1498 if (connection1() != nullptr) {
1499 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1500 }
1501
1502 if (connection2() != nullptr) {
1503 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1504 }
1505 dispatcher_->Shutdown();
1506 }
1507
1508 // Set the dispatcher's writer to be blocked. By default, all connections use
1509 // the same writer as the dispatcher in this test.
1510 void SetBlocked() {
1511 QUIC_LOG(INFO) << "set writer " << writer_ << " to blocked";
1512 writer_->write_blocked_ = true;
1513 }
1514
1515 // Simulate what happens when connection1 gets blocked when writing.
1516 void BlockConnection1() {
1517 Connection1Writer()->write_blocked_ = true;
1518 dispatcher_->OnWriteBlocked(connection1());
1519 }
1520
1521 BlockingWriter* Connection1Writer() {
1522 return static_cast<BlockingWriter*>(connection1()->writer());
1523 }
1524
1525 // Simulate what happens when connection2 gets blocked when writing.
1526 void BlockConnection2() {
1527 Connection2Writer()->write_blocked_ = true;
1528 dispatcher_->OnWriteBlocked(connection2());
1529 }
1530
1531 BlockingWriter* Connection2Writer() {
1532 return static_cast<BlockingWriter*>(connection2()->writer());
1533 }
1534
1535 protected:
1536 MockQuicConnectionHelper helper_;
1537 MockAlarmFactory alarm_factory_;
1538 BlockingWriter* writer_;
1539 QuicDispatcher::WriteBlockedList* blocked_list_;
1540};
1541
1542TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
1543 // No OnCanWrite calls because no connections are blocked.
1544 dispatcher_->OnCanWrite();
1545
1546 // Register connection 1 for events, and make sure it's notified.
1547 SetBlocked();
1548 dispatcher_->OnWriteBlocked(connection1());
1549 EXPECT_CALL(*connection1(), OnCanWrite());
1550 dispatcher_->OnCanWrite();
1551
1552 // It should get only one notification.
1553 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1554 dispatcher_->OnCanWrite();
1555 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1556}
1557
1558TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
1559 // Make sure we handle events in order.
1560 InSequence s;
1561 SetBlocked();
1562 dispatcher_->OnWriteBlocked(connection1());
1563 dispatcher_->OnWriteBlocked(connection2());
1564 EXPECT_CALL(*connection1(), OnCanWrite());
1565 EXPECT_CALL(*connection2(), OnCanWrite());
1566 dispatcher_->OnCanWrite();
1567
1568 // Check the other ordering.
1569 SetBlocked();
1570 dispatcher_->OnWriteBlocked(connection2());
1571 dispatcher_->OnWriteBlocked(connection1());
1572 EXPECT_CALL(*connection2(), OnCanWrite());
1573 EXPECT_CALL(*connection1(), OnCanWrite());
1574 dispatcher_->OnCanWrite();
1575}
1576
1577TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
1578 // Add and remove one connction.
1579 SetBlocked();
1580 dispatcher_->OnWriteBlocked(connection1());
1581 blocked_list_->erase(connection1());
1582 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1583 dispatcher_->OnCanWrite();
1584
1585 // Add and remove one connction and make sure it doesn't affect others.
1586 SetBlocked();
1587 dispatcher_->OnWriteBlocked(connection1());
1588 dispatcher_->OnWriteBlocked(connection2());
1589 blocked_list_->erase(connection1());
1590 EXPECT_CALL(*connection2(), OnCanWrite());
1591 dispatcher_->OnCanWrite();
1592
1593 // Add it, remove it, and add it back and make sure things are OK.
1594 SetBlocked();
1595 dispatcher_->OnWriteBlocked(connection1());
1596 blocked_list_->erase(connection1());
1597 dispatcher_->OnWriteBlocked(connection1());
1598 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1599 dispatcher_->OnCanWrite();
1600}
1601
1602TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
1603 // Make sure a double add does not necessitate a double remove.
1604 SetBlocked();
1605 dispatcher_->OnWriteBlocked(connection1());
1606 dispatcher_->OnWriteBlocked(connection1());
1607 blocked_list_->erase(connection1());
1608 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1609 dispatcher_->OnCanWrite();
1610
1611 // Make sure a double add does not result in two OnCanWrite calls.
1612 SetBlocked();
1613 dispatcher_->OnWriteBlocked(connection1());
1614 dispatcher_->OnWriteBlocked(connection1());
1615 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1616 dispatcher_->OnCanWrite();
1617}
1618
1619TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
1620 // If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
1621 // into the write blocked list.
1622 InSequence s;
1623 SetBlocked();
1624 dispatcher_->OnWriteBlocked(connection1());
1625 dispatcher_->OnWriteBlocked(connection2());
1626 EXPECT_CALL(*connection1(), OnCanWrite())
1627 .WillOnce(
1628 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1629 EXPECT_CALL(*connection2(), OnCanWrite());
1630 dispatcher_->OnCanWrite();
1631
1632 // connection1 should be still in the write blocked list.
1633 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1634
1635 // Now call OnCanWrite again, connection1 should get its second chance.
1636 EXPECT_CALL(*connection1(), OnCanWrite());
1637 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
1638 dispatcher_->OnCanWrite();
1639 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1640}
1641
1642TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
1643 // If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
1644 // into the write blocked list.
1645 InSequence s;
1646 SetBlocked();
1647 dispatcher_->OnWriteBlocked(connection1());
1648 dispatcher_->OnWriteBlocked(connection2());
1649 EXPECT_CALL(*connection1(), OnCanWrite());
1650 EXPECT_CALL(*connection2(), OnCanWrite())
1651 .WillOnce(
1652 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1653 dispatcher_->OnCanWrite();
1654
1655 // connection2 should be still in the write blocked list.
1656 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1657
1658 // Now call OnCanWrite again, connection2 should get its second chance.
1659 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1660 EXPECT_CALL(*connection2(), OnCanWrite());
1661 dispatcher_->OnCanWrite();
1662 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1663}
1664
1665TEST_F(QuicDispatcherWriteBlockedListTest,
1666 OnCanWriteHandleBlockBothConnections) {
1667 // Both connections get blocked in OnCanWrite, and added back into the write
1668 // blocked list.
1669 InSequence s;
1670 SetBlocked();
1671 dispatcher_->OnWriteBlocked(connection1());
1672 dispatcher_->OnWriteBlocked(connection2());
1673 EXPECT_CALL(*connection1(), OnCanWrite())
1674 .WillOnce(
1675 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1676 EXPECT_CALL(*connection2(), OnCanWrite())
1677 .WillOnce(
1678 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1679 dispatcher_->OnCanWrite();
1680
1681 // Both connections should be still in the write blocked list.
1682 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1683
1684 // Now call OnCanWrite again, both connections should get its second chance.
1685 EXPECT_CALL(*connection1(), OnCanWrite());
1686 EXPECT_CALL(*connection2(), OnCanWrite());
1687 dispatcher_->OnCanWrite();
1688 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1689}
1690
1691TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
1692 // By default, all connections share the same packet writer with the
1693 // dispatcher.
1694 EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
1695 EXPECT_EQ(dispatcher_->writer(), connection2()->writer());
1696
1697 // Test the case where connection1 shares the same packet writer as the
1698 // dispatcher, whereas connection2 owns it's packet writer.
1699 // Change connection2's writer.
1700 connection2()->SetQuicPacketWriter(new BlockingWriter, /*owns_writer=*/true);
1701 EXPECT_NE(dispatcher_->writer(), connection2()->writer());
1702
1703 BlockConnection2();
1704 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1705
1706 EXPECT_CALL(*connection2(), OnCanWrite());
1707 dispatcher_->OnCanWrite();
1708 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1709}
1710
1711TEST_F(QuicDispatcherWriteBlockedListTest,
1712 RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001713 dispatcher_->OnConnectionClosed(connection1()->connection_id(),
1714 QUIC_PACKET_WRITE_ERROR, "Closed by test.",
1715 ConnectionCloseSource::FROM_SELF);
1716
1717 SetBlocked();
1718
1719 ASSERT_FALSE(dispatcher_->HasPendingWrites());
1720 SetBlocked();
1721 dispatcher_->OnWriteBlocked(connection1());
1722 ASSERT_TRUE(dispatcher_->HasPendingWrites());
1723
1724 EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(),
1725 "QuicConnection was in WriteBlockedList before destruction");
1726 MarkSession1Deleted();
1727}
1728
wub0a4b9c52019-05-28 13:18:58 -07001729class BufferedPacketStoreTest : public QuicDispatcherTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001730 public:
1731 BufferedPacketStoreTest()
1732 : QuicDispatcherTest(),
1733 server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
1734 client_addr_(QuicIpAddress::Loopback4(), 1234),
wub0a4b9c52019-05-28 13:18:58 -07001735 signed_config_(new QuicSignedServerConfig) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001736
1737 void SetUp() override {
1738 QuicDispatcherTest::SetUp();
1739 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
1740
1741 QuicTransportVersion version = AllSupportedTransportVersions().front();
1742 CryptoHandshakeMessage chlo =
1743 crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
1744 &crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001745 // Pass an inchoate CHLO.
1746 crypto_test_utils::GenerateFullCHLO(
1747 chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
1748 signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1749 &full_chlo_);
1750 }
1751
vasilvvc48c8712019-03-11 13:38:16 -07001752 std::string SerializeFullCHLO() {
1753 return std::string(full_chlo_.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001754 }
1755
1756 protected:
1757 QuicSocketAddress server_addr_;
1758 QuicSocketAddress client_addr_;
1759 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1760 const QuicClock* clock_;
1761 CryptoHandshakeMessage full_chlo_;
1762};
1763
wub0a4b9c52019-05-28 13:18:58 -07001764TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001765 InSequence s;
1766 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1767 QuicConnectionId conn_id = TestConnectionId(1);
1768 // A bunch of non-CHLO should be buffered upon arrival, and the first one
1769 // should trigger ShouldCreateOrBufferPacketForConnection().
fayang1ed1f762019-06-24 11:40:04 -07001770 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1771 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001772 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
1773 ProcessPacket(client_address, conn_id, true,
1774 QuicStrCat("data packet ", i + 1), CONNECTION_ID_PRESENT,
1775 PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1);
1776 }
1777 EXPECT_EQ(0u, dispatcher_->session_map().size())
1778 << "No session should be created before CHLO arrives.";
1779
1780 // Pop out the last packet as it is also be dropped by the store.
1781 data_connection_map_[conn_id].pop_back();
1782 // When CHLO arrives, a new session should be created, and all packets
1783 // buffered should be delivered to the session.
1784 EXPECT_CALL(*dispatcher_,
1785 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1786 .WillOnce(testing::Return(CreateSession(
1787 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1788 &mock_alarm_factory_, &crypto_config_,
1789 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1790
1791 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
1792 // should be delivered in arrival order.
1793 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1794 ProcessUdpPacket(_, _, _))
1795 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
1796 .WillRepeatedly(
1797 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1798 ValidatePacket(conn_id, packet);
1799 })));
1800 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1801}
1802
wub0a4b9c52019-05-28 13:18:58 -07001803TEST_F(BufferedPacketStoreTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001804 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
1805 InSequence s;
1806 // A bunch of non-CHLO should be buffered upon arrival.
1807 size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
1808 for (size_t i = 1; i <= kNumConnections; ++i) {
1809 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1810 QuicConnectionId conn_id = TestConnectionId(i);
1811 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001812 ShouldCreateOrBufferPacketForConnection(
1813 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001814 ProcessPacket(client_address, conn_id, true,
1815 QuicStrCat("data packet on connection ", i),
1816 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1817 /*packet_number=*/2);
1818 }
1819
1820 // Pop out the packet on last connection as it shouldn't be enqueued in store
1821 // as well.
1822 data_connection_map_[TestConnectionId(kNumConnections)].pop_front();
1823
1824 // Reset session creation counter to ensure processing CHLO can always
1825 // create session.
1826 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
1827 kNumConnections);
1828 // Process CHLOs to create session for these connections.
1829 for (size_t i = 1; i <= kNumConnections; ++i) {
1830 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1831 QuicConnectionId conn_id = TestConnectionId(i);
1832 if (i == kNumConnections) {
1833 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001834 ShouldCreateOrBufferPacketForConnection(
1835 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001836 }
1837 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1838 QuicStringPiece(), _))
1839 .WillOnce(testing::Return(CreateSession(
1840 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1841 &mock_alarm_factory_, &crypto_config_,
1842 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1843 // First |kNumConnections| - 1 connections should have buffered
1844 // a packet in store. The rest should have been dropped.
1845 size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
1846 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1847 ProcessUdpPacket(_, client_address, _))
1848 .Times(num_packet_to_process)
1849 .WillRepeatedly(WithArg<2>(
1850 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1851 ValidatePacket(conn_id, packet);
1852 })));
1853
1854 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1855 }
1856}
1857
1858// Tests that store delivers empty packet list if CHLO arrives firstly.
wub0a4b9c52019-05-28 13:18:58 -07001859TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001860 QuicConnectionId conn_id = TestConnectionId(1);
1861 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
fayang1ed1f762019-06-24 11:40:04 -07001862 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1863 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001864 EXPECT_CALL(*dispatcher_,
1865 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1866 .WillOnce(testing::Return(CreateSession(
1867 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1868 &mock_alarm_factory_, &crypto_config_,
1869 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1870 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1871 ProcessUdpPacket(_, client_address, _));
1872 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1873}
1874
1875// Tests that a retransmitted CHLO arrives after a connection for the
1876// CHLO has been created.
wub0a4b9c52019-05-28 13:18:58 -07001877TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001878 InSequence s;
1879 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1880 QuicConnectionId conn_id = TestConnectionId(1);
1881 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1882 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1883 /*packet_number=*/2);
1884
1885 // When CHLO arrives, a new session should be created, and all packets
1886 // buffered should be delivered to the session.
1887 EXPECT_CALL(*dispatcher_,
1888 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1889 .Times(1) // Only triggered by 1st CHLO.
1890 .WillOnce(testing::Return(CreateSession(
1891 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1892 &mock_alarm_factory_, &crypto_config_,
1893 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1894 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1895 ProcessUdpPacket(_, _, _))
1896 .Times(3) // Triggered by 1 data packet and 2 CHLOs.
1897 .WillRepeatedly(
1898 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1899 ValidatePacket(conn_id, packet);
1900 })));
1901 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1902
1903 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1904}
1905
1906// Tests that expiration of a connection add connection id to time wait list.
wub0a4b9c52019-05-28 13:18:58 -07001907TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001908 InSequence s;
1909 CreateTimeWaitListManager();
1910 QuicBufferedPacketStore* store =
1911 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1912 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
1913
1914 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1915 QuicConnectionId conn_id = TestConnectionId(1);
1916 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1917 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1918 /*packet_number=*/2);
1919
1920 mock_helper_.AdvanceTime(
1921 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
1922 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
1923 // Cancel alarm as if it had been fired.
1924 alarm->Cancel();
1925 store->OnExpirationTimeout();
1926 // New arrived CHLO will be dropped because this connection is in time wait
1927 // list.
1928 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
1929 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
1930 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1931}
1932
wub0a4b9c52019-05-28 13:18:58 -07001933TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001934 // Process more than (|kMaxNumSessionsToCreate| +
1935 // |kDefaultMaxConnectionsInStore|) CHLOs,
1936 // the first |kMaxNumSessionsToCreate| should create connections immediately,
1937 // the next |kDefaultMaxConnectionsInStore| should be buffered,
1938 // the rest should be dropped.
1939 QuicBufferedPacketStore* store =
1940 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1941 const size_t kNumCHLOs =
1942 kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
1943 for (uint64_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
fayang1ed1f762019-06-24 11:40:04 -07001944 EXPECT_CALL(
1945 *dispatcher_,
1946 ShouldCreateOrBufferPacketForConnection(
1947 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(conn_id))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001948 if (conn_id <= kMaxNumSessionsToCreate) {
1949 EXPECT_CALL(*dispatcher_,
1950 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1951 QuicStringPiece(), _))
1952 .WillOnce(testing::Return(CreateSession(
1953 dispatcher_.get(), config_, TestConnectionId(conn_id),
1954 client_addr_, &mock_helper_, &mock_alarm_factory_,
1955 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1956 &session1_)));
1957 EXPECT_CALL(
1958 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1959 ProcessUdpPacket(_, _, _))
1960 .WillOnce(WithArg<2>(
1961 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1962 ValidatePacket(TestConnectionId(conn_id), packet);
1963 })));
1964 }
1965 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1966 SerializeFullCHLO());
1967 if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
1968 conn_id > kMaxNumSessionsToCreate) {
1969 EXPECT_TRUE(store->HasChloForConnection(TestConnectionId(conn_id)));
1970 } else {
1971 // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
1972 // connections immediately, and the last CHLO should be dropped as the
1973 // store is full.
1974 EXPECT_FALSE(store->HasChloForConnection(TestConnectionId(conn_id)));
1975 }
1976 }
1977
1978 // Graduately consume buffered CHLOs. The buffered connections should be
1979 // created but the dropped one shouldn't.
1980 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1981 conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
1982 ++conn_id) {
1983 EXPECT_CALL(*dispatcher_,
1984 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1985 QuicStringPiece(), _))
1986 .WillOnce(testing::Return(CreateSession(
1987 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1988 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1989 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1990 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1991 ProcessUdpPacket(_, _, _))
1992 .WillOnce(WithArg<2>(
1993 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1994 ValidatePacket(TestConnectionId(conn_id), packet);
1995 })));
1996 }
1997 EXPECT_CALL(*dispatcher_,
1998 CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
1999 QuicStringPiece(), _))
2000 .Times(0);
2001
2002 while (store->HasChlosBuffered()) {
2003 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2004 }
2005
2006 EXPECT_EQ(TestConnectionId(static_cast<size_t>(kMaxNumSessionsToCreate) +
2007 kDefaultMaxConnectionsInStore),
2008 session1_->connection_id());
2009}
2010
2011// Duplicated CHLO shouldn't be buffered.
wub0a4b9c52019-05-28 13:18:58 -07002012TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002013 for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
2014 ++conn_id) {
2015 // Last CHLO will be buffered. Others will create connection right away.
2016 if (conn_id <= kMaxNumSessionsToCreate) {
2017 EXPECT_CALL(*dispatcher_,
2018 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2019 QuicStringPiece(), _))
2020 .WillOnce(testing::Return(CreateSession(
2021 dispatcher_.get(), config_, TestConnectionId(conn_id),
2022 client_addr_, &mock_helper_, &mock_alarm_factory_,
2023 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2024 &session1_)));
2025 EXPECT_CALL(
2026 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2027 ProcessUdpPacket(_, _, _))
2028 .WillOnce(WithArg<2>(
2029 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2030 ValidatePacket(TestConnectionId(conn_id), packet);
2031 })));
2032 }
2033 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2034 SerializeFullCHLO());
2035 }
2036 // Retransmit CHLO on last connection should be dropped.
2037 QuicConnectionId last_connection =
2038 TestConnectionId(kMaxNumSessionsToCreate + 1);
2039 ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
2040
2041 size_t packets_buffered = 2;
2042
2043 // Reset counter and process buffered CHLO.
2044 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
2045 QuicStringPiece(), _))
2046 .WillOnce(testing::Return(CreateSession(
2047 dispatcher_.get(), config_, last_connection, client_addr_,
2048 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2049 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2050 // Only one packet(CHLO) should be process.
2051 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2052 ProcessUdpPacket(_, _, _))
2053 .Times(packets_buffered)
2054 .WillRepeatedly(WithArg<2>(
2055 Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
2056 ValidatePacket(last_connection, packet);
2057 })));
2058 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2059}
2060
wub0a4b9c52019-05-28 13:18:58 -07002061TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002062 uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
2063 QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
2064 for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
2065 // Last CHLO will be buffered. Others will create connection right away.
2066 if (conn_id <= kMaxNumSessionsToCreate) {
2067 EXPECT_CALL(*dispatcher_,
2068 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2069 QuicStringPiece(), _))
2070 .WillOnce(testing::Return(CreateSession(
2071 dispatcher_.get(), config_, TestConnectionId(conn_id),
2072 client_addr_, &mock_helper_, &mock_alarm_factory_,
2073 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2074 &session1_)));
2075 EXPECT_CALL(
2076 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2077 ProcessUdpPacket(_, _, _))
2078 .WillRepeatedly(WithArg<2>(
2079 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2080 ValidatePacket(TestConnectionId(conn_id), packet);
2081 })));
2082 }
2083 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2084 SerializeFullCHLO());
2085 }
2086
2087 // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
2088 // last one should be dropped.
2089 for (uint64_t packet_number = 2;
2090 packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
2091 ProcessPacket(client_addr_, last_connection_id, true, "data packet");
2092 }
2093
2094 // Reset counter and process buffered CHLO.
2095 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
2096 QuicStringPiece(), _))
2097 .WillOnce(testing::Return(CreateSession(
2098 dispatcher_.get(), config_, last_connection_id, client_addr_,
2099 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2100 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2101 // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
2102 // should be process.
2103 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2104 ProcessUdpPacket(_, _, _))
2105 .Times(kDefaultMaxUndecryptablePackets + 1)
2106 .WillRepeatedly(WithArg<2>(
2107 Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
2108 ValidatePacket(last_connection_id, packet);
2109 })));
2110 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2111}
2112
2113// Tests that when dispatcher's packet buffer is full, a CHLO on connection
2114// which doesn't have buffered CHLO should be buffered.
wub0a4b9c52019-05-28 13:18:58 -07002115TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002116 QuicBufferedPacketStore* store =
2117 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
2118
2119 uint64_t conn_id = 1;
2120 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, "data packet",
2121 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
2122 /*packet_number=*/1);
2123 // Fill packet buffer to full with CHLOs on other connections. Need to feed
2124 // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
2125 // session directly.
2126 for (conn_id = 2;
2127 conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
2128 ++conn_id) {
2129 if (conn_id <= kMaxNumSessionsToCreate + 1) {
2130 EXPECT_CALL(*dispatcher_,
2131 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2132 QuicStringPiece(), _))
2133 .WillOnce(testing::Return(CreateSession(
2134 dispatcher_.get(), config_, TestConnectionId(conn_id),
2135 client_addr_, &mock_helper_, &mock_alarm_factory_,
2136 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2137 &session1_)));
2138 EXPECT_CALL(
2139 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2140 ProcessUdpPacket(_, _, _))
2141 .WillOnce(WithArg<2>(
2142 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2143 ValidatePacket(TestConnectionId(conn_id), packet);
2144 })));
2145 }
2146 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2147 SerializeFullCHLO());
2148 }
2149 EXPECT_FALSE(store->HasChloForConnection(
2150 /*connection_id=*/TestConnectionId(1)));
2151
2152 // CHLO on connection 1 should still be buffered.
2153 ProcessPacket(client_addr_, /*connection_id=*/TestConnectionId(1), true,
2154 SerializeFullCHLO());
2155 EXPECT_TRUE(store->HasChloForConnection(
2156 /*connection_id=*/TestConnectionId(1)));
2157}
2158
2159// Regression test for b/117874922.
wub0a4b9c52019-05-28 13:18:58 -07002160TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002161 // Turn off version 99, such that the preferred version is not supported by
2162 // the server.
2163 SetQuicReloadableFlag(quic_enable_version_99, false);
2164 uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
2165 ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
2166 for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
2167 // Last 5 CHLOs will be buffered. Others will create connection right away.
2168 ParsedQuicVersion version =
2169 supported_versions[(conn_id - 1) % supported_versions.size()];
2170 if (conn_id <= kMaxNumSessionsToCreate) {
2171 EXPECT_CALL(*dispatcher_,
2172 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2173 QuicStringPiece(), version))
2174 .WillOnce(testing::Return(CreateSession(
2175 dispatcher_.get(), config_, TestConnectionId(conn_id),
2176 client_addr_, &mock_helper_, &mock_alarm_factory_,
2177 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2178 &session1_)));
2179 EXPECT_CALL(
2180 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2181 ProcessUdpPacket(_, _, _))
2182 .WillRepeatedly(WithArg<2>(
2183 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2184 ValidatePacket(TestConnectionId(conn_id), packet);
2185 })));
2186 }
2187 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version,
fayange3f2f7b2019-09-19 17:01:57 -07002188 SerializeFullCHLO(), true, CONNECTION_ID_PRESENT,
QUICHE teama6ef0a62019-03-07 20:34:33 -05002189 PACKET_4BYTE_PACKET_NUMBER, 1);
2190 }
2191
2192 // Process buffered CHLOs. Verify the version is correct.
2193 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
2194 conn_id <= last_connection_id; ++conn_id) {
2195 ParsedQuicVersion version =
2196 supported_versions[(conn_id - 1) % supported_versions.size()];
2197 EXPECT_CALL(*dispatcher_,
2198 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2199 QuicStringPiece(), version))
2200 .WillOnce(testing::Return(CreateSession(
2201 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
2202 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2203 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2204 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2205 ProcessUdpPacket(_, _, _))
2206 .WillRepeatedly(WithArg<2>(
2207 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2208 ValidatePacket(TestConnectionId(conn_id), packet);
2209 })));
2210 }
2211 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2212}
2213
QUICHE teama6ef0a62019-03-07 20:34:33 -05002214} // namespace
2215} // namespace test
2216} // namespace quic