blob: 7b096174c05370d0585a0848be3cb010bb6269f9 [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>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010
QUICHE teama6ef0a62019-03-07 20:34:33 -050011#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
12#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
13#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
14#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
15#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
16#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
17#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
18#include "net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h"
19#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
20#include "net/third_party/quiche/src/quic/core/quic_types.h"
21#include "net/third_party/quiche/src/quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050022#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
28#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
29#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
30#include "net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
35#include "net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h"
36#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
37
38using testing::_;
39using testing::InSequence;
40using testing::Invoke;
41using testing::NiceMock;
42using testing::Return;
43using testing::WithArg;
44using testing::WithoutArgs;
45
46static const size_t kDefaultMaxConnectionsInStore = 100;
47static const size_t kMaxConnectionsWithoutCHLO =
48 kDefaultMaxConnectionsInStore / 2;
49static const int16_t kMaxNumSessionsToCreate = 16;
50
51namespace quic {
52namespace test {
53namespace {
54
55class TestQuicSpdyServerSession : public QuicServerSessionBase {
56 public:
57 TestQuicSpdyServerSession(const QuicConfig& config,
58 QuicConnection* connection,
59 const QuicCryptoServerConfig* crypto_config,
60 QuicCompressedCertsCache* compressed_certs_cache)
61 : QuicServerSessionBase(config,
62 CurrentSupportedVersions(),
63 connection,
64 nullptr,
65 nullptr,
66 crypto_config,
67 compressed_certs_cache),
68 crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {}
69 TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
70 TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
71 delete;
72
73 ~TestQuicSpdyServerSession() override { delete connection(); }
74
fkastenholz5d880a92019-06-21 09:01:56 -070075 MOCK_METHOD2(OnConnectionClosed,
76 void(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 ConnectionCloseSource source));
78 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
renjietangbaea59c2019-05-29 15:08:14 -070079 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(PendingStream* pending));
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*());
81 MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
82
83 QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
84 const QuicCryptoServerConfig* crypto_config,
85 QuicCompressedCertsCache* compressed_certs_cache) override {
wubd893df12019-05-15 18:48:20 -070086 return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
87 this, stream_helper());
QUICHE teama6ef0a62019-03-07 20:34:33 -050088 }
89
90 void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
91 crypto_stream_ = crypto_stream;
92 }
93
94 QuicCryptoServerStreamBase* GetMutableCryptoStream() override {
95 return crypto_stream_;
96 }
97
98 const QuicCryptoServerStreamBase* GetCryptoStream() const override {
99 return crypto_stream_;
100 }
101
102 QuicCryptoServerStream::Helper* stream_helper() {
103 return QuicServerSessionBase::stream_helper();
104 }
105
106 private:
107 QuicCryptoServerStreamBase* crypto_stream_;
108};
109
110class TestDispatcher : public QuicDispatcher {
111 public:
112 TestDispatcher(const QuicConfig* config,
113 const QuicCryptoServerConfig* crypto_config,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700114 QuicVersionManager* version_manager,
115 QuicRandom* random)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500116 : QuicDispatcher(config,
117 crypto_config,
118 version_manager,
119 QuicMakeUnique<MockQuicConnectionHelper>(),
120 std::unique_ptr<QuicCryptoServerStream::Helper>(
QUICHE teamc65d1d12019-03-19 20:58:04 -0700121 new QuicSimpleCryptoServerStreamHelper(random)),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122 QuicMakeUnique<MockAlarmFactory>(),
123 kQuicDefaultConnectionIdLength) {}
124
125 MOCK_METHOD4(CreateQuicSession,
126 QuicServerSessionBase*(QuicConnectionId connection_id,
127 const QuicSocketAddress& peer_address,
128 QuicStringPiece alpn,
129 const quic::ParsedQuicVersion& version));
130
fayang1ed1f762019-06-24 11:40:04 -0700131 MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
132 bool(const ReceivedPacketInfo& packet_info));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500133
134 struct TestQuicPerPacketContext : public QuicPerPacketContext {
vasilvvc48c8712019-03-11 13:38:16 -0700135 std::string custom_packet_context;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500136 };
137
138 std::unique_ptr<QuicPerPacketContext> GetPerPacketContext() const override {
139 auto test_context = QuicMakeUnique<TestQuicPerPacketContext>();
140 test_context->custom_packet_context = custom_packet_context_;
141 return std::move(test_context);
142 }
143
144 void RestorePerPacketContext(
145 std::unique_ptr<QuicPerPacketContext> context) override {
146 TestQuicPerPacketContext* test_context =
147 static_cast<TestQuicPerPacketContext*>(context.get());
148 custom_packet_context_ = test_context->custom_packet_context;
149 }
150
vasilvvc48c8712019-03-11 13:38:16 -0700151 std::string custom_packet_context_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500152
dschinazi7b9278c2019-05-20 07:36:21 -0700153 using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154 using QuicDispatcher::writer;
155};
156
157// A Connection class which unregisters the session from the dispatcher when
158// sending connection close.
159// It'd be slightly more realistic to do this from the Session but it would
160// involve a lot more mocking.
161class MockServerConnection : public MockQuicConnection {
162 public:
163 MockServerConnection(QuicConnectionId connection_id,
164 MockQuicConnectionHelper* helper,
165 MockAlarmFactory* alarm_factory,
166 QuicDispatcher* dispatcher)
167 : MockQuicConnection(connection_id,
168 helper,
169 alarm_factory,
170 Perspective::IS_SERVER),
171 dispatcher_(dispatcher) {}
172
173 void UnregisterOnConnectionClosed() {
174 QUIC_LOG(ERROR) << "Unregistering " << connection_id();
175 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
176 "Unregistering.",
177 ConnectionCloseSource::FROM_SELF);
178 }
179
180 private:
181 QuicDispatcher* dispatcher_;
182};
183
184class QuicDispatcherTest : public QuicTest {
185 public:
186 QuicDispatcherTest()
187 : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
188
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189 explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
190 :
191
nharperf5e68452019-05-29 17:24:18 -0700192 version_manager_(AllSupportedVersions()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 crypto_config_(QuicCryptoServerConfig::TESTING,
194 QuicRandom::GetInstance(),
195 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -0700196 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500197 server_address_(QuicIpAddress::Any4(), 5),
QUICHE teamc65d1d12019-03-19 20:58:04 -0700198 dispatcher_(
199 new NiceMock<TestDispatcher>(&config_,
200 &crypto_config_,
201 &version_manager_,
202 mock_helper_.GetRandomGenerator())),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500203 time_wait_list_manager_(nullptr),
204 session1_(nullptr),
205 session2_(nullptr),
fayangb880b4c2019-06-14 12:26:35 -0700206 store_(nullptr),
207 connection_id_(1) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208
209 void SetUp() override {
210 dispatcher_->InitializeWithWriter(new MockPacketWriter());
211 // Set the counter to some value to start with.
212 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
213 dispatcher_.get(), kMaxNumSessionsToCreate);
fayang1ed1f762019-06-24 11:40:04 -0700214 ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500215 .WillByDefault(Return(true));
216 }
217
218 MockQuicConnection* connection1() {
219 if (session1_ == nullptr) {
220 return nullptr;
221 }
222 return reinterpret_cast<MockQuicConnection*>(session1_->connection());
223 }
224
225 MockQuicConnection* connection2() {
226 if (session2_ == nullptr) {
227 return nullptr;
228 }
229 return reinterpret_cast<MockQuicConnection*>(session2_->connection());
230 }
231
232 // Process a packet with an 8 byte connection id,
233 // 6 byte packet number, default path id, and packet number 1,
234 // using the first supported version.
235 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700236 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700238 const std::string& data) {
dschinazi346b7ce2019-06-05 01:38:18 -0700239 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER);
241 }
242
243 // Process a packet with a default path id, and packet number 1,
244 // using the first supported version.
245 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700246 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700248 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700249 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 QuicPacketNumberLength packet_number_length) {
dschinazi346b7ce2019-06-05 01:38:18 -0700251 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
252 server_connection_id_included, packet_number_length, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253 }
254
255 // Process a packet using the first supported version.
256 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700257 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700259 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700260 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261 QuicPacketNumberLength packet_number_length,
262 uint64_t packet_number) {
dschinazi346b7ce2019-06-05 01:38:18 -0700263 ProcessPacket(peer_address, server_connection_id, has_version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500264 CurrentSupportedVersions().front(), data,
dschinazi346b7ce2019-06-05 01:38:18 -0700265 server_connection_id_included, packet_number_length,
266 packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 }
268
269 // Processes a packet.
270 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700271 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500272 bool has_version_flag,
273 ParsedQuicVersion version,
vasilvvc48c8712019-03-11 13:38:16 -0700274 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700275 QuicConnectionIdIncluded server_connection_id_included,
276 QuicPacketNumberLength packet_number_length,
277 uint64_t packet_number) {
278 ProcessPacket(peer_address, server_connection_id, EmptyQuicConnectionId(),
279 has_version_flag, version, data,
280 server_connection_id_included, CONNECTION_ID_ABSENT,
281 packet_number_length, packet_number);
282 }
283
284 // Processes a packet.
285 void ProcessPacket(QuicSocketAddress peer_address,
286 QuicConnectionId server_connection_id,
287 QuicConnectionId client_connection_id,
288 bool has_version_flag,
289 ParsedQuicVersion version,
290 const std::string& data,
291 QuicConnectionIdIncluded server_connection_id_included,
292 QuicConnectionIdIncluded client_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500293 QuicPacketNumberLength packet_number_length,
294 uint64_t packet_number) {
295 ParsedQuicVersionVector versions(SupportedVersions(version));
296 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700297 server_connection_id, client_connection_id, has_version_flag, false,
298 packet_number, data, server_connection_id_included,
299 client_connection_id_included, packet_number_length, &versions));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500300 std::unique_ptr<QuicReceivedPacket> received_packet(
301 ConstructReceivedPacket(*packet, mock_helper_.GetClock()->Now()));
302
303 if (ChloExtractor::Extract(*packet, versions, {}, nullptr,
dschinazi346b7ce2019-06-05 01:38:18 -0700304 server_connection_id.length())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305 // Add CHLO packet to the beginning to be verified first, because it is
306 // also processed first by new session.
dschinazi346b7ce2019-06-05 01:38:18 -0700307 data_connection_map_[server_connection_id].push_front(
vasilvvc48c8712019-03-11 13:38:16 -0700308 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 } else {
310 // For non-CHLO, always append to last.
dschinazi346b7ce2019-06-05 01:38:18 -0700311 data_connection_map_[server_connection_id].push_back(
vasilvvc48c8712019-03-11 13:38:16 -0700312 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 }
314 dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet);
315 }
316
317 void ValidatePacket(QuicConnectionId conn_id,
318 const QuicEncryptedPacket& packet) {
319 EXPECT_EQ(data_connection_map_[conn_id].front().length(),
320 packet.AsStringPiece().length());
321 EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
322 data_connection_map_[conn_id].pop_front();
323 }
324
325 QuicServerSessionBase* CreateSession(
326 TestDispatcher* dispatcher,
327 const QuicConfig& config,
328 QuicConnectionId connection_id,
dschinazi17d42422019-06-18 16:35:07 -0700329 const QuicSocketAddress& /*peer_address*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500330 MockQuicConnectionHelper* helper,
331 MockAlarmFactory* alarm_factory,
332 const QuicCryptoServerConfig* crypto_config,
333 QuicCompressedCertsCache* compressed_certs_cache,
334 TestQuicSpdyServerSession** session) {
335 MockServerConnection* connection = new MockServerConnection(
336 connection_id, helper, alarm_factory, dispatcher);
337 connection->SetQuicPacketWriter(dispatcher->writer(),
338 /*owns_writer=*/false);
339 *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
340 compressed_certs_cache);
341 connection->set_visitor(*session);
342 ON_CALL(*connection, CloseConnection(_, _, _))
343 .WillByDefault(WithoutArgs(Invoke(
344 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
345 return *session;
346 }
347
348 void CreateTimeWaitListManager() {
349 time_wait_list_manager_ = new MockTimeWaitListManager(
350 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
351 mock_helper_.GetClock(), &mock_alarm_factory_);
352 // dispatcher_ takes the ownership of time_wait_list_manager_.
353 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
354 time_wait_list_manager_);
355 }
356
vasilvvc48c8712019-03-11 13:38:16 -0700357 std::string SerializeCHLO() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500358 CryptoHandshakeMessage client_hello;
359 client_hello.set_tag(kCHLO);
360 client_hello.SetStringPiece(kALPN, "hq");
vasilvvc48c8712019-03-11 13:38:16 -0700361 return std::string(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500362 }
363
QUICHE teama6ef0a62019-03-07 20:34:33 -0500364 void MarkSession1Deleted() { session1_ = nullptr; }
365
fayangb880b4c2019-06-14 12:26:35 -0700366 void VerifyVersionSupported(ParsedQuicVersion version) {
367 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
368 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
369 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
370 QuicStringPiece("hq"), _))
371 .WillOnce(testing::Return(CreateSession(
372 dispatcher_.get(), config_, connection_id, client_address,
373 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
374 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
375 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
376 ProcessUdpPacket(_, _, _))
377 .WillOnce(WithArg<2>(
378 Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
379 ValidatePacket(connection_id, packet);
380 })));
381 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700382 ShouldCreateOrBufferPacketForConnection(
383 ReceivedPacketInfoConnectionIdEquals(connection_id)));
fayangb880b4c2019-06-14 12:26:35 -0700384 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
385 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
386 }
387
388 void VerifyVersionNotSupported(ParsedQuicVersion version) {
389 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
390 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
391 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
392 QuicStringPiece("hq"), _))
393 .Times(0);
394 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
395 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
396 }
397
QUICHE teama6ef0a62019-03-07 20:34:33 -0500398 MockQuicConnectionHelper mock_helper_;
399 MockAlarmFactory mock_alarm_factory_;
400 QuicConfig config_;
401 QuicVersionManager version_manager_;
402 QuicCryptoServerConfig crypto_config_;
403 QuicSocketAddress server_address_;
404 std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
405 MockTimeWaitListManager* time_wait_list_manager_;
406 TestQuicSpdyServerSession* session1_;
407 TestQuicSpdyServerSession* session2_;
vasilvvc48c8712019-03-11 13:38:16 -0700408 std::map<QuicConnectionId, std::list<std::string>> data_connection_map_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409 QuicBufferedPacketStore* store_;
fayangb880b4c2019-06-14 12:26:35 -0700410 uint64_t connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500411};
412
413TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
QUICHE teamea740082019-03-11 17:58:43 -0700414 if (!QuicVersionUsesCryptoFrames(
415 CurrentSupportedVersions().front().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500416 // TLS is only supported in versions 47 and greater.
417 return;
418 }
wub49855982019-05-01 14:16:26 -0700419 SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500420 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
421
422 EXPECT_CALL(*dispatcher_,
423 CreateQuicSession(TestConnectionId(1), client_address,
424 QuicStringPiece(""), _))
425 .WillOnce(testing::Return(CreateSession(
426 dispatcher_.get(), config_, TestConnectionId(1), client_address,
427 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
428 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
429 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
430 ProcessUdpPacket(_, _, _))
431 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
432 ValidatePacket(TestConnectionId(1), packet);
433 })));
434 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700435 ShouldCreateOrBufferPacketForConnection(
436 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500437 ProcessPacket(
438 client_address, TestConnectionId(1), true,
439 ParsedQuicVersion(PROTOCOL_TLS1_3,
440 CurrentSupportedVersions().front().transport_version),
441 SerializeCHLO(), CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500442}
443
444TEST_F(QuicDispatcherTest, ProcessPackets) {
445 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
446
447 EXPECT_CALL(*dispatcher_,
448 CreateQuicSession(TestConnectionId(1), client_address,
449 QuicStringPiece("hq"), _))
450 .WillOnce(testing::Return(CreateSession(
451 dispatcher_.get(), config_, TestConnectionId(1), client_address,
452 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
453 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
454 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
455 ProcessUdpPacket(_, _, _))
456 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
457 ValidatePacket(TestConnectionId(1), packet);
458 })));
459 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700460 ShouldCreateOrBufferPacketForConnection(
461 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500463
464 EXPECT_CALL(*dispatcher_,
465 CreateQuicSession(TestConnectionId(2), client_address,
466 QuicStringPiece("hq"), _))
467 .WillOnce(testing::Return(CreateSession(
468 dispatcher_.get(), config_, TestConnectionId(2), client_address,
469 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
470 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
471 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
472 ProcessUdpPacket(_, _, _))
473 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
474 ValidatePacket(TestConnectionId(2), packet);
475 })));
476 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700477 ShouldCreateOrBufferPacketForConnection(
478 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500479 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
480
481 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
482 ProcessUdpPacket(_, _, _))
483 .Times(1)
484 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
485 ValidatePacket(TestConnectionId(1), packet);
486 })));
487 ProcessPacket(client_address, TestConnectionId(1), false, "data");
488}
489
490// Regression test of b/93325907.
491TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
492 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
493
494 EXPECT_CALL(*dispatcher_,
495 CreateQuicSession(TestConnectionId(1), client_address,
496 QuicStringPiece("hq"), _))
497 .WillOnce(testing::Return(CreateSession(
498 dispatcher_.get(), config_, TestConnectionId(1), client_address,
499 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
500 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
501 // Verify both packets 1 and 2 are processed by connection 1.
502 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
503 ProcessUdpPacket(_, _, _))
504 .Times(2)
505 .WillRepeatedly(
506 WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
507 ValidatePacket(TestConnectionId(1), packet);
508 })));
509 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700510 ShouldCreateOrBufferPacketForConnection(
511 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500512 ProcessPacket(
513 client_address, TestConnectionId(1), true,
514 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
515 CurrentSupportedVersions().front().transport_version),
516 SerializeCHLO(), CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
517 // Packet number 256 with packet number length 1 would be considered as 0 in
518 // dispatcher.
519 ProcessPacket(
520 client_address, TestConnectionId(1), false,
521 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
522 CurrentSupportedVersions().front().transport_version),
523 "", CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500524}
525
526TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
dschinazi48ac9192019-07-31 00:07:26 -0700527 SetQuicReloadableFlag(quic_use_parse_public_header, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500528 CreateTimeWaitListManager();
529 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
530
531 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
dschinazi346b7ce2019-06-05 01:38:18 -0700532 EXPECT_CALL(
533 *time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700534 SendVersionNegotiationPacket(TestConnectionId(1), _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500535 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500536 // Pad the CHLO message with enough data to make the packet large enough
537 // to trigger version negotiation.
vasilvvc48c8712019-03-11 13:38:16 -0700538 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500539 DCHECK_LE(1200u, chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700540 ProcessPacket(client_address, TestConnectionId(1), true,
541 QuicVersionReservedForNegotiation(), chlo,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
543}
544
dschinazi346b7ce2019-06-05 01:38:18 -0700545TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
dschinazi48ac9192019-07-31 00:07:26 -0700546 SetQuicReloadableFlag(quic_use_parse_public_header, true);
dschinazi346b7ce2019-06-05 01:38:18 -0700547 CreateTimeWaitListManager();
548 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
549
550 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
551 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700552 SendVersionNegotiationPacket(
553 TestConnectionId(1), TestConnectionId(2), _, _, _, _, _, _))
dschinazi346b7ce2019-06-05 01:38:18 -0700554 .Times(1);
555 // Pad the CHLO message with enough data to make the packet large enough
556 // to trigger version negotiation.
557 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
558 DCHECK_LE(1200u, chlo.length());
559 ProcessPacket(client_address, TestConnectionId(1), TestConnectionId(2), true,
560 QuicVersionReservedForNegotiation(), chlo,
561 CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
562 PACKET_4BYTE_PACKET_NUMBER, 1);
563}
564
QUICHE teama6ef0a62019-03-07 20:34:33 -0500565TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
566 CreateTimeWaitListManager();
567 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
568
569 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
570 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700571 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500572 .Times(0);
vasilvvc48c8712019-03-11 13:38:16 -0700573 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500574 // Truncate to 1100 bytes of payload which results in a packet just
575 // under 1200 bytes after framing, packet, and encryption overhead.
576 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700577 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500578 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700579 ProcessPacket(client_address, TestConnectionId(1), true,
580 QuicVersionReservedForNegotiation(), truncated_chlo,
581 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500582}
583
584// Disabling CHLO size validation allows the dispatcher to send version
585// negotiation packets in response to a CHLO that is otherwise too small.
586TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
dschinazi48ac9192019-07-31 00:07:26 -0700587 SetQuicReloadableFlag(quic_use_parse_public_header, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500588 crypto_config_.set_validate_chlo_size(false);
589
590 CreateTimeWaitListManager();
591 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
592
593 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
594 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700595 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500596 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -0700597 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500598 // Truncate to 1100 bytes of payload which results in a packet just
599 // under 1200 bytes after framing, packet, and encryption overhead.
600 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700601 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500602 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700603 ProcessPacket(client_address, TestConnectionId(1), true,
604 QuicVersionReservedForNegotiation(), truncated_chlo,
605 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500606}
607
608TEST_F(QuicDispatcherTest, Shutdown) {
609 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
610
611 EXPECT_CALL(*dispatcher_,
612 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
613 .WillOnce(testing::Return(CreateSession(
614 dispatcher_.get(), config_, TestConnectionId(1), client_address,
615 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
616 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
617 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
618 ProcessUdpPacket(_, _, _))
619 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
620 ValidatePacket(TestConnectionId(1), packet);
621 })));
622
623 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700624 ShouldCreateOrBufferPacketForConnection(
625 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500626 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
627
628 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
629 CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
630
631 dispatcher_->Shutdown();
632}
633
634TEST_F(QuicDispatcherTest, TimeWaitListManager) {
635 CreateTimeWaitListManager();
636
637 // Create a new session.
638 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
639 QuicConnectionId connection_id = TestConnectionId(1);
640 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
641 QuicStringPiece("hq"), _))
642 .WillOnce(testing::Return(CreateSession(
643 dispatcher_.get(), config_, connection_id, client_address,
644 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
645 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
646 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
647 ProcessUdpPacket(_, _, _))
648 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
649 ValidatePacket(TestConnectionId(1), packet);
650 })));
651
652 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700653 ShouldCreateOrBufferPacketForConnection(
654 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500655 ProcessPacket(client_address, connection_id, true, SerializeCHLO());
656
657 // Now close the connection, which should add it to the time wait list.
658 session1_->connection()->CloseConnection(
659 QUIC_INVALID_VERSION,
660 "Server: Packet 2 without version flag before version negotiated.",
661 ConnectionCloseBehavior::SILENT_CLOSE);
662 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
663
664 // Dispatcher forwards subsequent packets for this connection_id to the time
665 // wait list manager.
666 EXPECT_CALL(*time_wait_list_manager_,
667 ProcessPacket(_, _, connection_id, _, _))
668 .Times(1);
669 EXPECT_CALL(*time_wait_list_manager_,
670 AddConnectionIdToTimeWait(_, _, _, _, _))
671 .Times(0);
672 ProcessPacket(client_address, connection_id, true, "data");
673}
674
675TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
676 CreateTimeWaitListManager();
677
678 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
679 QuicConnectionId connection_id = TestConnectionId(1);
680 // Dispatcher forwards all packets for this connection_id to the time wait
681 // list manager.
682 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
683 .Times(0);
fayangd057e662019-07-10 13:29:41 -0700684 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
685 EXPECT_CALL(*time_wait_list_manager_,
686 ProcessPacket(_, _, connection_id, _, _))
687 .Times(0);
688 EXPECT_CALL(*time_wait_list_manager_,
689 AddConnectionIdToTimeWait(_, _, _, _, _))
690 .Times(0);
691 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
692 .Times(1);
693 } else {
694 EXPECT_CALL(*time_wait_list_manager_,
695 ProcessPacket(_, _, connection_id, _, _))
696 .Times(1);
697 EXPECT_CALL(*time_wait_list_manager_,
698 AddConnectionIdToTimeWait(_, _, _, _, _))
699 .Times(1);
700 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500701 ProcessPacket(client_address, connection_id, false, SerializeCHLO());
702}
703
fayangd057e662019-07-10 13:29:41 -0700704TEST_F(QuicDispatcherTest,
705 DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
706 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
707 CreateTimeWaitListManager();
708
709 char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
710 QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
711 char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
712 QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
713 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
714 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
715 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
716 .Times(0);
717 EXPECT_CALL(*time_wait_list_manager_,
718 AddConnectionIdToTimeWait(_, _, _, _, _))
719 .Times(0);
720 } else {
721 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
722 .Times(2);
723 EXPECT_CALL(*time_wait_list_manager_,
724 AddConnectionIdToTimeWait(_, _, _, _, _))
725 .Times(2);
726 }
727 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
728 // Verify small packet is silently dropped.
729 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
730 .Times(0);
731 }
732 dispatcher_->ProcessPacket(server_address_, client_address, packet);
733 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
734 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
735 .Times(1);
736 }
737 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
738}
739
QUICHE teamc65d1d12019-03-19 20:58:04 -0700740// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
QUICHE team963d57e2019-03-21 10:58:47 -0700741TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
QUICHE team8e2e4532019-03-14 14:37:56 -0700742 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
743 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700744 // When variable length connection IDs are not supported, the connection
745 // fails. See StrayPacketTruncatedConnectionId.
QUICHE team8e2e4532019-03-14 14:37:56 -0700746 return;
747 }
QUICHE team8e2e4532019-03-14 14:37:56 -0700748 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
749
QUICHE teamc65d1d12019-03-19 20:58:04 -0700750 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
751 QuicConnectionId fixed_connection_id =
752 QuicUtils::CreateRandomConnectionId(mock_helper_.GetRandomGenerator());
753
754 EXPECT_CALL(*dispatcher_,
755 CreateQuicSession(fixed_connection_id, client_address,
756 QuicStringPiece("hq"), _))
757 .WillOnce(testing::Return(CreateSession(
758 dispatcher_.get(), config_, fixed_connection_id, client_address,
759 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
760 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
761 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
762 ProcessUdpPacket(_, _, _))
763 .WillOnce(WithArg<2>(
764 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
765 ValidatePacket(bad_connection_id, packet);
766 })));
767 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700768 ShouldCreateOrBufferPacketForConnection(
769 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700770 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700771}
772
QUICHE team963d57e2019-03-21 10:58:47 -0700773// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
774TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
775 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
776 CurrentSupportedVersions()[0].transport_version)) {
777 // When variable length connection IDs are not supported, the connection
778 // fails. See StrayPacketTruncatedConnectionId.
779 return;
780 }
781 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
782
783 QuicConnectionId bad_connection_id = EmptyQuicConnectionId();
784 QuicConnectionId fixed_connection_id =
785 QuicUtils::CreateRandomConnectionId(mock_helper_.GetRandomGenerator());
786
787 // Disable validation of invalid short connection IDs.
dschinazi7b9278c2019-05-20 07:36:21 -0700788 dispatcher_->SetAllowShortInitialServerConnectionIds(true);
QUICHE team963d57e2019-03-21 10:58:47 -0700789 // Note that StrayPacketTruncatedConnectionId covers the case where the
790 // validation is still enabled.
791
792 EXPECT_CALL(*dispatcher_,
793 CreateQuicSession(fixed_connection_id, client_address,
794 QuicStringPiece("hq"), _))
795 .WillOnce(testing::Return(CreateSession(
796 dispatcher_.get(), config_, fixed_connection_id, client_address,
797 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
798 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
799 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
800 ProcessUdpPacket(_, _, _))
801 .WillOnce(WithArg<2>(
802 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
803 ValidatePacket(bad_connection_id, packet);
804 })));
805 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700806 ShouldCreateOrBufferPacketForConnection(
807 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE team963d57e2019-03-21 10:58:47 -0700808 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team963d57e2019-03-21 10:58:47 -0700809}
810
QUICHE teamc65d1d12019-03-19 20:58:04 -0700811// Makes sure TestConnectionId(1) creates a new connection and
812// TestConnectionIdNineBytesLong(2) gets replaced.
QUICHE team8e2e4532019-03-14 14:37:56 -0700813TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
814 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
815 CurrentSupportedVersions()[0].transport_version)) {
816 return;
817 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700818
QUICHE team8e2e4532019-03-14 14:37:56 -0700819 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700820 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
821 QuicConnectionId fixed_connection_id =
822 QuicUtils::CreateRandomConnectionId(mock_helper_.GetRandomGenerator());
QUICHE team8e2e4532019-03-14 14:37:56 -0700823
824 EXPECT_CALL(*dispatcher_,
825 CreateQuicSession(TestConnectionId(1), client_address,
826 QuicStringPiece("hq"), _))
827 .WillOnce(testing::Return(CreateSession(
828 dispatcher_.get(), config_, TestConnectionId(1), client_address,
829 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
830 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
831 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
832 ProcessUdpPacket(_, _, _))
833 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
834 ValidatePacket(TestConnectionId(1), packet);
835 })));
836 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700837 ShouldCreateOrBufferPacketForConnection(
838 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700839 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700840
QUICHE teamc65d1d12019-03-19 20:58:04 -0700841 EXPECT_CALL(*dispatcher_,
842 CreateQuicSession(fixed_connection_id, client_address,
843 QuicStringPiece("hq"), _))
844 .WillOnce(testing::Return(CreateSession(
845 dispatcher_.get(), config_, fixed_connection_id, client_address,
846 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
847 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
848 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
849 ProcessUdpPacket(_, _, _))
850 .WillOnce(WithArg<2>(
851 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
852 ValidatePacket(bad_connection_id, packet);
853 })));
854 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700855 ShouldCreateOrBufferPacketForConnection(
856 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700857 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700858
859 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
860 ProcessUdpPacket(_, _, _))
861 .Times(1)
862 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
863 ValidatePacket(TestConnectionId(1), packet);
864 })));
865 ProcessPacket(client_address, TestConnectionId(1), false, "data");
866}
867
QUICHE teama6ef0a62019-03-07 20:34:33 -0500868TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
869 CreateTimeWaitListManager();
870
871 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
872
873 // dispatcher_ should drop this packet.
874 EXPECT_CALL(*dispatcher_,
875 CreateQuicSession(TestConnectionId(1), client_address,
876 QuicStringPiece("hq"), _))
877 .Times(0);
878 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
879 EXPECT_CALL(*time_wait_list_manager_,
880 AddConnectionIdToTimeWait(_, _, _, _, _))
881 .Times(0);
882 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
883}
884
dschinaziee07e472019-06-19 09:56:56 -0700885TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
886 SetQuicReloadableFlag(quic_drop_invalid_small_initial_connection_id, true);
887 // Enable v47 otherwise we cannot create a packet with a short connection ID.
888 SetQuicReloadableFlag(quic_enable_version_47, true);
889 CreateTimeWaitListManager();
890
891 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
892
893 // dispatcher_ should drop this packet.
894 EXPECT_CALL(*dispatcher_,
895 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
896 .Times(0);
897 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
898 EXPECT_CALL(*time_wait_list_manager_,
899 AddConnectionIdToTimeWait(_, _, _, _, _))
900 .Times(0);
901 ProcessPacket(client_address, EmptyQuicConnectionId(), true, SerializeCHLO());
902}
903
QUICHE teama6ef0a62019-03-07 20:34:33 -0500904TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
905 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
906 QuicConnectionId connection_id = TestConnectionId(1);
907
908 EXPECT_CALL(*dispatcher_,
909 CreateQuicSession(TestConnectionId(1), client_address,
910 QuicStringPiece("hq"), _))
911 .WillOnce(testing::Return(CreateSession(
912 dispatcher_.get(), config_, TestConnectionId(1), client_address,
913 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
914 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
915 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
916 ProcessUdpPacket(_, _, _))
917 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
918 ValidatePacket(TestConnectionId(1), packet);
919 })));
920
921 // A packet whose packet number is the largest that is allowed to start a
922 // connection.
923 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700924 ShouldCreateOrBufferPacketForConnection(
925 ReceivedPacketInfoConnectionIdEquals(connection_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500926 ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
927 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
928 QuicDispatcher::kMaxReasonableInitialPacketNumber);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500929}
930
QUICHE teama6ef0a62019-03-07 20:34:33 -0500931TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
dschinazi48ac9192019-07-31 00:07:26 -0700932 SetQuicRestartFlag(quic_dispatcher_hands_chlo_extractor_one_version, true);
933 SetQuicReloadableFlag(quic_use_parse_public_header, true);
nharper107ba5f2019-07-02 21:33:39 -0700934 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500935 "Supported versions out of sync");
936 SetQuicReloadableFlag(quic_disable_version_39, false);
fayangb880b4c2019-06-14 12:26:35 -0700937 SetQuicReloadableFlag(quic_disable_version_44, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500938 SetQuicReloadableFlag(quic_enable_version_47, true);
nharper107ba5f2019-07-02 21:33:39 -0700939 SetQuicReloadableFlag(quic_enable_version_48, 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
nharper107ba5f2019-07-02 21:33:39 -0700948 // Turn off version 48.
949 SetQuicReloadableFlag(quic_enable_version_48, false);
950 VerifyVersionNotSupported(
951 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
952
953 // Turn on version 48.
954 SetQuicReloadableFlag(quic_enable_version_48, true);
955 VerifyVersionSupported(
956 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
957
QUICHE teama6ef0a62019-03-07 20:34:33 -0500958 // Turn off version 47.
959 SetQuicReloadableFlag(quic_enable_version_47, false);
fayangb880b4c2019-06-14 12:26:35 -0700960 VerifyVersionNotSupported(
961 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500962
963 // Turn on version 47.
964 SetQuicReloadableFlag(quic_enable_version_47, true);
fayangb880b4c2019-06-14 12:26:35 -0700965 VerifyVersionSupported(
966 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
967
968 // Turn off version 44.
969 SetQuicReloadableFlag(quic_disable_version_44, true);
970 VerifyVersionNotSupported(
971 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44));
972
973 // Turn on version 44.
974 SetQuicReloadableFlag(quic_disable_version_44, false);
975 VerifyVersionSupported(
976 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500977
QUICHE teama6ef0a62019-03-07 20:34:33 -0500978 // Turn off version 39.
979 SetQuicReloadableFlag(quic_disable_version_39, true);
fayangb880b4c2019-06-14 12:26:35 -0700980 VerifyVersionNotSupported(
981 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500982
983 // Turn on version 39.
984 SetQuicReloadableFlag(quic_disable_version_39, false);
fayangb880b4c2019-06-14 12:26:35 -0700985 VerifyVersionSupported(
986 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500987}
988
fayangb54ac5b2019-07-01 10:30:37 -0700989TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
nharper107ba5f2019-07-02 21:33:39 -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);
1004}
1005
dschinazi30ab6db2019-08-13 14:43:32 -07001006TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
1007 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
1008 SetQuicReloadableFlag(quic_use_length_prefix_from_packet_info, true);
1009 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1010 CreateTimeWaitListManager();
1011 char packet[1200];
1012 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1013 0x6c, 0x7a, 0x20, 0x21};
1014 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1015 packet, sizeof(packet), destination_connection_id_bytes,
1016 sizeof(destination_connection_id_bytes)));
1017 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1018 std::unique_ptr<QuicReceivedPacket> received_packet(
1019 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1020 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1021 QuicConnectionId server_connection_id(
1022 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1023 bool ietf_quic = true;
1024 bool use_length_prefix =
1025 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1026 EXPECT_CALL(
1027 *time_wait_list_manager_,
1028 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1029 ietf_quic, use_length_prefix, _, _, _, _))
1030 .Times(1);
1031 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1032
1033 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1034}
1035
1036TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
1037 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
1038 SetQuicReloadableFlag(quic_use_parse_public_header, true);
1039 SetQuicReloadableFlag(quic_use_length_prefix_from_packet_info, true);
1040 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1041 CreateTimeWaitListManager();
1042 char packet[1200];
1043 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1044 0x6c, 0x7a, 0x20, 0x21};
1045 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1046 packet, sizeof(packet), destination_connection_id_bytes,
1047 sizeof(destination_connection_id_bytes)));
1048 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1049 std::unique_ptr<QuicReceivedPacket> received_packet(
1050 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1051 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1052 QuicConnectionId server_connection_id(
1053 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1054 bool ietf_quic = true;
1055 bool use_length_prefix =
1056 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1057 EXPECT_CALL(
1058 *time_wait_list_manager_,
1059 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1060 ietf_quic, use_length_prefix, _, _, _, _))
1061 .Times(1);
1062 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1063
1064 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1065}
1066
QUICHE teama6ef0a62019-03-07 20:34:33 -05001067// Verify the stopgap test: Packets with truncated connection IDs should be
1068// dropped.
1069class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
1070
1071// Packets with truncated connection IDs should be dropped.
1072TEST_F(QuicDispatcherTestStrayPacketConnectionId,
1073 StrayPacketTruncatedConnectionId) {
dschinaziee07e472019-06-19 09:56:56 -07001074 SetQuicReloadableFlag(quic_drop_invalid_small_initial_connection_id, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001075 CreateTimeWaitListManager();
1076
1077 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1078 QuicConnectionId connection_id = TestConnectionId(1);
1079 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
1080 .Times(0);
fayangd4291e42019-05-30 10:31:21 -07001081 if (VersionHasIetfInvariantHeader(
QUICHE team963d57e2019-03-21 10:58:47 -07001082 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001083 // This IETF packet has invalid connection ID length.
1084 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1085 .Times(0);
1086 EXPECT_CALL(*time_wait_list_manager_,
1087 AddConnectionIdToTimeWait(_, _, _, _, _))
1088 .Times(0);
1089 } else {
dschinaziee07e472019-06-19 09:56:56 -07001090 // This is a GQUIC packet considered as IETF QUIC packet with short header
1091 // with unacceptable packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001092 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1093 .Times(1);
1094 EXPECT_CALL(*time_wait_list_manager_,
1095 AddConnectionIdToTimeWait(_, _, _, _, _))
1096 .Times(1);
1097 }
1098 ProcessPacket(client_address, connection_id, true, "data",
1099 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
1100}
1101
1102class BlockingWriter : public QuicPacketWriterWrapper {
1103 public:
1104 BlockingWriter() : write_blocked_(false) {}
1105
1106 bool IsWriteBlocked() const override { return write_blocked_; }
1107 void SetWritable() override { write_blocked_ = false; }
1108
dschinazi17d42422019-06-18 16:35:07 -07001109 WriteResult WritePacket(const char* /*buffer*/,
1110 size_t /*buf_len*/,
1111 const QuicIpAddress& /*self_client_address*/,
1112 const QuicSocketAddress& /*peer_client_address*/,
1113 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001114 // It would be quite possible to actually implement this method here with
1115 // the fake blocked status, but it would be significantly more work in
1116 // Chromium, and since it's not called anyway, don't bother.
1117 QUIC_LOG(DFATAL) << "Not supported";
1118 return WriteResult();
1119 }
1120
1121 bool write_blocked_;
1122};
1123
1124class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
1125 public:
1126 void SetUp() override {
1127 QuicDispatcherTest::SetUp();
1128 writer_ = new BlockingWriter;
1129 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
1130
1131 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1132
1133 EXPECT_CALL(*dispatcher_,
1134 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1135 .WillOnce(testing::Return(CreateSession(
1136 dispatcher_.get(), config_, TestConnectionId(1), client_address,
1137 &helper_, &alarm_factory_, &crypto_config_,
1138 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1139 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1140 ProcessUdpPacket(_, _, _))
1141 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1142 ValidatePacket(TestConnectionId(1), packet);
1143 })));
fayang1ed1f762019-06-24 11:40:04 -07001144 EXPECT_CALL(*dispatcher_,
1145 ShouldCreateOrBufferPacketForConnection(
1146 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001147 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
1148
1149 EXPECT_CALL(*dispatcher_,
1150 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1151 .WillOnce(testing::Return(CreateSession(
1152 dispatcher_.get(), config_, TestConnectionId(2), client_address,
1153 &helper_, &alarm_factory_, &crypto_config_,
1154 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
1155 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
1156 ProcessUdpPacket(_, _, _))
1157 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1158 ValidatePacket(TestConnectionId(2), packet);
1159 })));
fayang1ed1f762019-06-24 11:40:04 -07001160 EXPECT_CALL(*dispatcher_,
1161 ShouldCreateOrBufferPacketForConnection(
1162 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001163 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
1164
1165 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
1166 }
1167
1168 void TearDown() override {
1169 if (connection1() != nullptr) {
1170 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1171 }
1172
1173 if (connection2() != nullptr) {
1174 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1175 }
1176 dispatcher_->Shutdown();
1177 }
1178
1179 // Set the dispatcher's writer to be blocked. By default, all connections use
1180 // the same writer as the dispatcher in this test.
1181 void SetBlocked() {
1182 QUIC_LOG(INFO) << "set writer " << writer_ << " to blocked";
1183 writer_->write_blocked_ = true;
1184 }
1185
1186 // Simulate what happens when connection1 gets blocked when writing.
1187 void BlockConnection1() {
1188 Connection1Writer()->write_blocked_ = true;
1189 dispatcher_->OnWriteBlocked(connection1());
1190 }
1191
1192 BlockingWriter* Connection1Writer() {
1193 return static_cast<BlockingWriter*>(connection1()->writer());
1194 }
1195
1196 // Simulate what happens when connection2 gets blocked when writing.
1197 void BlockConnection2() {
1198 Connection2Writer()->write_blocked_ = true;
1199 dispatcher_->OnWriteBlocked(connection2());
1200 }
1201
1202 BlockingWriter* Connection2Writer() {
1203 return static_cast<BlockingWriter*>(connection2()->writer());
1204 }
1205
1206 protected:
1207 MockQuicConnectionHelper helper_;
1208 MockAlarmFactory alarm_factory_;
1209 BlockingWriter* writer_;
1210 QuicDispatcher::WriteBlockedList* blocked_list_;
1211};
1212
1213TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
1214 // No OnCanWrite calls because no connections are blocked.
1215 dispatcher_->OnCanWrite();
1216
1217 // Register connection 1 for events, and make sure it's notified.
1218 SetBlocked();
1219 dispatcher_->OnWriteBlocked(connection1());
1220 EXPECT_CALL(*connection1(), OnCanWrite());
1221 dispatcher_->OnCanWrite();
1222
1223 // It should get only one notification.
1224 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1225 dispatcher_->OnCanWrite();
1226 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1227}
1228
1229TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
1230 // Make sure we handle events in order.
1231 InSequence s;
1232 SetBlocked();
1233 dispatcher_->OnWriteBlocked(connection1());
1234 dispatcher_->OnWriteBlocked(connection2());
1235 EXPECT_CALL(*connection1(), OnCanWrite());
1236 EXPECT_CALL(*connection2(), OnCanWrite());
1237 dispatcher_->OnCanWrite();
1238
1239 // Check the other ordering.
1240 SetBlocked();
1241 dispatcher_->OnWriteBlocked(connection2());
1242 dispatcher_->OnWriteBlocked(connection1());
1243 EXPECT_CALL(*connection2(), OnCanWrite());
1244 EXPECT_CALL(*connection1(), OnCanWrite());
1245 dispatcher_->OnCanWrite();
1246}
1247
1248TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
1249 // Add and remove one connction.
1250 SetBlocked();
1251 dispatcher_->OnWriteBlocked(connection1());
1252 blocked_list_->erase(connection1());
1253 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1254 dispatcher_->OnCanWrite();
1255
1256 // Add and remove one connction and make sure it doesn't affect others.
1257 SetBlocked();
1258 dispatcher_->OnWriteBlocked(connection1());
1259 dispatcher_->OnWriteBlocked(connection2());
1260 blocked_list_->erase(connection1());
1261 EXPECT_CALL(*connection2(), OnCanWrite());
1262 dispatcher_->OnCanWrite();
1263
1264 // Add it, remove it, and add it back and make sure things are OK.
1265 SetBlocked();
1266 dispatcher_->OnWriteBlocked(connection1());
1267 blocked_list_->erase(connection1());
1268 dispatcher_->OnWriteBlocked(connection1());
1269 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1270 dispatcher_->OnCanWrite();
1271}
1272
1273TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
1274 // Make sure a double add does not necessitate a double remove.
1275 SetBlocked();
1276 dispatcher_->OnWriteBlocked(connection1());
1277 dispatcher_->OnWriteBlocked(connection1());
1278 blocked_list_->erase(connection1());
1279 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1280 dispatcher_->OnCanWrite();
1281
1282 // Make sure a double add does not result in two OnCanWrite calls.
1283 SetBlocked();
1284 dispatcher_->OnWriteBlocked(connection1());
1285 dispatcher_->OnWriteBlocked(connection1());
1286 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1287 dispatcher_->OnCanWrite();
1288}
1289
1290TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
1291 // If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
1292 // into the write blocked list.
1293 InSequence s;
1294 SetBlocked();
1295 dispatcher_->OnWriteBlocked(connection1());
1296 dispatcher_->OnWriteBlocked(connection2());
1297 EXPECT_CALL(*connection1(), OnCanWrite())
1298 .WillOnce(
1299 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1300 EXPECT_CALL(*connection2(), OnCanWrite());
1301 dispatcher_->OnCanWrite();
1302
1303 // connection1 should be still in the write blocked list.
1304 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1305
1306 // Now call OnCanWrite again, connection1 should get its second chance.
1307 EXPECT_CALL(*connection1(), OnCanWrite());
1308 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
1309 dispatcher_->OnCanWrite();
1310 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1311}
1312
1313TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
1314 // If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
1315 // into the write blocked list.
1316 InSequence s;
1317 SetBlocked();
1318 dispatcher_->OnWriteBlocked(connection1());
1319 dispatcher_->OnWriteBlocked(connection2());
1320 EXPECT_CALL(*connection1(), OnCanWrite());
1321 EXPECT_CALL(*connection2(), OnCanWrite())
1322 .WillOnce(
1323 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1324 dispatcher_->OnCanWrite();
1325
1326 // connection2 should be still in the write blocked list.
1327 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1328
1329 // Now call OnCanWrite again, connection2 should get its second chance.
1330 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1331 EXPECT_CALL(*connection2(), OnCanWrite());
1332 dispatcher_->OnCanWrite();
1333 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1334}
1335
1336TEST_F(QuicDispatcherWriteBlockedListTest,
1337 OnCanWriteHandleBlockBothConnections) {
1338 // Both connections get blocked in OnCanWrite, and added back into the write
1339 // blocked list.
1340 InSequence s;
1341 SetBlocked();
1342 dispatcher_->OnWriteBlocked(connection1());
1343 dispatcher_->OnWriteBlocked(connection2());
1344 EXPECT_CALL(*connection1(), OnCanWrite())
1345 .WillOnce(
1346 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1347 EXPECT_CALL(*connection2(), OnCanWrite())
1348 .WillOnce(
1349 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1350 dispatcher_->OnCanWrite();
1351
1352 // Both connections should be still in the write blocked list.
1353 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1354
1355 // Now call OnCanWrite again, both connections should get its second chance.
1356 EXPECT_CALL(*connection1(), OnCanWrite());
1357 EXPECT_CALL(*connection2(), OnCanWrite());
1358 dispatcher_->OnCanWrite();
1359 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1360}
1361
1362TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
1363 // By default, all connections share the same packet writer with the
1364 // dispatcher.
1365 EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
1366 EXPECT_EQ(dispatcher_->writer(), connection2()->writer());
1367
1368 // Test the case where connection1 shares the same packet writer as the
1369 // dispatcher, whereas connection2 owns it's packet writer.
1370 // Change connection2's writer.
1371 connection2()->SetQuicPacketWriter(new BlockingWriter, /*owns_writer=*/true);
1372 EXPECT_NE(dispatcher_->writer(), connection2()->writer());
1373
1374 BlockConnection2();
1375 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1376
1377 EXPECT_CALL(*connection2(), OnCanWrite());
1378 dispatcher_->OnCanWrite();
1379 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1380}
1381
1382TEST_F(QuicDispatcherWriteBlockedListTest,
1383 RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001384 dispatcher_->OnConnectionClosed(connection1()->connection_id(),
1385 QUIC_PACKET_WRITE_ERROR, "Closed by test.",
1386 ConnectionCloseSource::FROM_SELF);
1387
1388 SetBlocked();
1389
1390 ASSERT_FALSE(dispatcher_->HasPendingWrites());
1391 SetBlocked();
1392 dispatcher_->OnWriteBlocked(connection1());
1393 ASSERT_TRUE(dispatcher_->HasPendingWrites());
1394
1395 EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(),
1396 "QuicConnection was in WriteBlockedList before destruction");
1397 MarkSession1Deleted();
1398}
1399
wub0a4b9c52019-05-28 13:18:58 -07001400class BufferedPacketStoreTest : public QuicDispatcherTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001401 public:
1402 BufferedPacketStoreTest()
1403 : QuicDispatcherTest(),
1404 server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
1405 client_addr_(QuicIpAddress::Loopback4(), 1234),
wub0a4b9c52019-05-28 13:18:58 -07001406 signed_config_(new QuicSignedServerConfig) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001407
1408 void SetUp() override {
1409 QuicDispatcherTest::SetUp();
1410 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
1411
1412 QuicTransportVersion version = AllSupportedTransportVersions().front();
1413 CryptoHandshakeMessage chlo =
1414 crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
1415 &crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001416 // Pass an inchoate CHLO.
1417 crypto_test_utils::GenerateFullCHLO(
1418 chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
1419 signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1420 &full_chlo_);
1421 }
1422
vasilvvc48c8712019-03-11 13:38:16 -07001423 std::string SerializeFullCHLO() {
1424 return std::string(full_chlo_.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001425 }
1426
1427 protected:
1428 QuicSocketAddress server_addr_;
1429 QuicSocketAddress client_addr_;
1430 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1431 const QuicClock* clock_;
1432 CryptoHandshakeMessage full_chlo_;
1433};
1434
wub0a4b9c52019-05-28 13:18:58 -07001435TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001436 InSequence s;
1437 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1438 QuicConnectionId conn_id = TestConnectionId(1);
1439 // A bunch of non-CHLO should be buffered upon arrival, and the first one
1440 // should trigger ShouldCreateOrBufferPacketForConnection().
fayang1ed1f762019-06-24 11:40:04 -07001441 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1442 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001443 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
1444 ProcessPacket(client_address, conn_id, true,
1445 QuicStrCat("data packet ", i + 1), CONNECTION_ID_PRESENT,
1446 PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1);
1447 }
1448 EXPECT_EQ(0u, dispatcher_->session_map().size())
1449 << "No session should be created before CHLO arrives.";
1450
1451 // Pop out the last packet as it is also be dropped by the store.
1452 data_connection_map_[conn_id].pop_back();
1453 // When CHLO arrives, a new session should be created, and all packets
1454 // buffered should be delivered to the session.
1455 EXPECT_CALL(*dispatcher_,
1456 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1457 .WillOnce(testing::Return(CreateSession(
1458 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1459 &mock_alarm_factory_, &crypto_config_,
1460 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1461
1462 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
1463 // should be delivered in arrival order.
1464 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1465 ProcessUdpPacket(_, _, _))
1466 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
1467 .WillRepeatedly(
1468 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1469 ValidatePacket(conn_id, packet);
1470 })));
1471 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1472}
1473
wub0a4b9c52019-05-28 13:18:58 -07001474TEST_F(BufferedPacketStoreTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001475 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
1476 InSequence s;
1477 // A bunch of non-CHLO should be buffered upon arrival.
1478 size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
1479 for (size_t i = 1; i <= kNumConnections; ++i) {
1480 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1481 QuicConnectionId conn_id = TestConnectionId(i);
1482 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001483 ShouldCreateOrBufferPacketForConnection(
1484 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001485 ProcessPacket(client_address, conn_id, true,
1486 QuicStrCat("data packet on connection ", i),
1487 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1488 /*packet_number=*/2);
1489 }
1490
1491 // Pop out the packet on last connection as it shouldn't be enqueued in store
1492 // as well.
1493 data_connection_map_[TestConnectionId(kNumConnections)].pop_front();
1494
1495 // Reset session creation counter to ensure processing CHLO can always
1496 // create session.
1497 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
1498 kNumConnections);
1499 // Process CHLOs to create session for these connections.
1500 for (size_t i = 1; i <= kNumConnections; ++i) {
1501 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1502 QuicConnectionId conn_id = TestConnectionId(i);
1503 if (i == kNumConnections) {
1504 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001505 ShouldCreateOrBufferPacketForConnection(
1506 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001507 }
1508 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1509 QuicStringPiece(), _))
1510 .WillOnce(testing::Return(CreateSession(
1511 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1512 &mock_alarm_factory_, &crypto_config_,
1513 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1514 // First |kNumConnections| - 1 connections should have buffered
1515 // a packet in store. The rest should have been dropped.
1516 size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
1517 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1518 ProcessUdpPacket(_, client_address, _))
1519 .Times(num_packet_to_process)
1520 .WillRepeatedly(WithArg<2>(
1521 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1522 ValidatePacket(conn_id, packet);
1523 })));
1524
1525 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1526 }
1527}
1528
1529// Tests that store delivers empty packet list if CHLO arrives firstly.
wub0a4b9c52019-05-28 13:18:58 -07001530TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001531 QuicConnectionId conn_id = TestConnectionId(1);
1532 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
fayang1ed1f762019-06-24 11:40:04 -07001533 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1534 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001535 EXPECT_CALL(*dispatcher_,
1536 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1537 .WillOnce(testing::Return(CreateSession(
1538 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1539 &mock_alarm_factory_, &crypto_config_,
1540 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1541 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1542 ProcessUdpPacket(_, client_address, _));
1543 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1544}
1545
1546// Tests that a retransmitted CHLO arrives after a connection for the
1547// CHLO has been created.
wub0a4b9c52019-05-28 13:18:58 -07001548TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001549 InSequence s;
1550 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1551 QuicConnectionId conn_id = TestConnectionId(1);
1552 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1553 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1554 /*packet_number=*/2);
1555
1556 // When CHLO arrives, a new session should be created, and all packets
1557 // buffered should be delivered to the session.
1558 EXPECT_CALL(*dispatcher_,
1559 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1560 .Times(1) // Only triggered by 1st CHLO.
1561 .WillOnce(testing::Return(CreateSession(
1562 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1563 &mock_alarm_factory_, &crypto_config_,
1564 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1565 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1566 ProcessUdpPacket(_, _, _))
1567 .Times(3) // Triggered by 1 data packet and 2 CHLOs.
1568 .WillRepeatedly(
1569 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1570 ValidatePacket(conn_id, packet);
1571 })));
1572 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1573
1574 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1575}
1576
1577// Tests that expiration of a connection add connection id to time wait list.
wub0a4b9c52019-05-28 13:18:58 -07001578TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001579 InSequence s;
1580 CreateTimeWaitListManager();
1581 QuicBufferedPacketStore* store =
1582 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1583 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
1584
1585 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1586 QuicConnectionId conn_id = TestConnectionId(1);
1587 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1588 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1589 /*packet_number=*/2);
1590
1591 mock_helper_.AdvanceTime(
1592 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
1593 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
1594 // Cancel alarm as if it had been fired.
1595 alarm->Cancel();
1596 store->OnExpirationTimeout();
1597 // New arrived CHLO will be dropped because this connection is in time wait
1598 // list.
1599 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
1600 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
1601 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1602}
1603
wub0a4b9c52019-05-28 13:18:58 -07001604TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001605 // Process more than (|kMaxNumSessionsToCreate| +
1606 // |kDefaultMaxConnectionsInStore|) CHLOs,
1607 // the first |kMaxNumSessionsToCreate| should create connections immediately,
1608 // the next |kDefaultMaxConnectionsInStore| should be buffered,
1609 // the rest should be dropped.
1610 QuicBufferedPacketStore* store =
1611 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1612 const size_t kNumCHLOs =
1613 kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
1614 for (uint64_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
fayang1ed1f762019-06-24 11:40:04 -07001615 EXPECT_CALL(
1616 *dispatcher_,
1617 ShouldCreateOrBufferPacketForConnection(
1618 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(conn_id))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001619 if (conn_id <= kMaxNumSessionsToCreate) {
1620 EXPECT_CALL(*dispatcher_,
1621 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1622 QuicStringPiece(), _))
1623 .WillOnce(testing::Return(CreateSession(
1624 dispatcher_.get(), config_, TestConnectionId(conn_id),
1625 client_addr_, &mock_helper_, &mock_alarm_factory_,
1626 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1627 &session1_)));
1628 EXPECT_CALL(
1629 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1630 ProcessUdpPacket(_, _, _))
1631 .WillOnce(WithArg<2>(
1632 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1633 ValidatePacket(TestConnectionId(conn_id), packet);
1634 })));
1635 }
1636 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1637 SerializeFullCHLO());
1638 if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
1639 conn_id > kMaxNumSessionsToCreate) {
1640 EXPECT_TRUE(store->HasChloForConnection(TestConnectionId(conn_id)));
1641 } else {
1642 // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
1643 // connections immediately, and the last CHLO should be dropped as the
1644 // store is full.
1645 EXPECT_FALSE(store->HasChloForConnection(TestConnectionId(conn_id)));
1646 }
1647 }
1648
1649 // Graduately consume buffered CHLOs. The buffered connections should be
1650 // created but the dropped one shouldn't.
1651 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1652 conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
1653 ++conn_id) {
1654 EXPECT_CALL(*dispatcher_,
1655 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1656 QuicStringPiece(), _))
1657 .WillOnce(testing::Return(CreateSession(
1658 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1659 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1660 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1661 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1662 ProcessUdpPacket(_, _, _))
1663 .WillOnce(WithArg<2>(
1664 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1665 ValidatePacket(TestConnectionId(conn_id), packet);
1666 })));
1667 }
1668 EXPECT_CALL(*dispatcher_,
1669 CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
1670 QuicStringPiece(), _))
1671 .Times(0);
1672
1673 while (store->HasChlosBuffered()) {
1674 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1675 }
1676
1677 EXPECT_EQ(TestConnectionId(static_cast<size_t>(kMaxNumSessionsToCreate) +
1678 kDefaultMaxConnectionsInStore),
1679 session1_->connection_id());
1680}
1681
1682// Duplicated CHLO shouldn't be buffered.
wub0a4b9c52019-05-28 13:18:58 -07001683TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001684 for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
1685 ++conn_id) {
1686 // Last CHLO will be buffered. Others will create connection right away.
1687 if (conn_id <= kMaxNumSessionsToCreate) {
1688 EXPECT_CALL(*dispatcher_,
1689 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1690 QuicStringPiece(), _))
1691 .WillOnce(testing::Return(CreateSession(
1692 dispatcher_.get(), config_, TestConnectionId(conn_id),
1693 client_addr_, &mock_helper_, &mock_alarm_factory_,
1694 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1695 &session1_)));
1696 EXPECT_CALL(
1697 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1698 ProcessUdpPacket(_, _, _))
1699 .WillOnce(WithArg<2>(
1700 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1701 ValidatePacket(TestConnectionId(conn_id), packet);
1702 })));
1703 }
1704 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1705 SerializeFullCHLO());
1706 }
1707 // Retransmit CHLO on last connection should be dropped.
1708 QuicConnectionId last_connection =
1709 TestConnectionId(kMaxNumSessionsToCreate + 1);
1710 ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
1711
1712 size_t packets_buffered = 2;
1713
1714 // Reset counter and process buffered CHLO.
1715 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
1716 QuicStringPiece(), _))
1717 .WillOnce(testing::Return(CreateSession(
1718 dispatcher_.get(), config_, last_connection, client_addr_,
1719 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1720 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1721 // Only one packet(CHLO) should be process.
1722 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1723 ProcessUdpPacket(_, _, _))
1724 .Times(packets_buffered)
1725 .WillRepeatedly(WithArg<2>(
1726 Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
1727 ValidatePacket(last_connection, packet);
1728 })));
1729 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1730}
1731
wub0a4b9c52019-05-28 13:18:58 -07001732TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001733 uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
1734 QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
1735 for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
1736 // Last CHLO will be buffered. Others will create connection right away.
1737 if (conn_id <= kMaxNumSessionsToCreate) {
1738 EXPECT_CALL(*dispatcher_,
1739 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1740 QuicStringPiece(), _))
1741 .WillOnce(testing::Return(CreateSession(
1742 dispatcher_.get(), config_, TestConnectionId(conn_id),
1743 client_addr_, &mock_helper_, &mock_alarm_factory_,
1744 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1745 &session1_)));
1746 EXPECT_CALL(
1747 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1748 ProcessUdpPacket(_, _, _))
1749 .WillRepeatedly(WithArg<2>(
1750 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1751 ValidatePacket(TestConnectionId(conn_id), packet);
1752 })));
1753 }
1754 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1755 SerializeFullCHLO());
1756 }
1757
1758 // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
1759 // last one should be dropped.
1760 for (uint64_t packet_number = 2;
1761 packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
1762 ProcessPacket(client_addr_, last_connection_id, true, "data packet");
1763 }
1764
1765 // Reset counter and process buffered CHLO.
1766 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
1767 QuicStringPiece(), _))
1768 .WillOnce(testing::Return(CreateSession(
1769 dispatcher_.get(), config_, last_connection_id, client_addr_,
1770 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1771 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1772 // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
1773 // should be process.
1774 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1775 ProcessUdpPacket(_, _, _))
1776 .Times(kDefaultMaxUndecryptablePackets + 1)
1777 .WillRepeatedly(WithArg<2>(
1778 Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
1779 ValidatePacket(last_connection_id, packet);
1780 })));
1781 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1782}
1783
1784// Tests that when dispatcher's packet buffer is full, a CHLO on connection
1785// which doesn't have buffered CHLO should be buffered.
wub0a4b9c52019-05-28 13:18:58 -07001786TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001787 QuicBufferedPacketStore* store =
1788 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1789
1790 uint64_t conn_id = 1;
1791 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, "data packet",
1792 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1793 /*packet_number=*/1);
1794 // Fill packet buffer to full with CHLOs on other connections. Need to feed
1795 // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
1796 // session directly.
1797 for (conn_id = 2;
1798 conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
1799 ++conn_id) {
1800 if (conn_id <= kMaxNumSessionsToCreate + 1) {
1801 EXPECT_CALL(*dispatcher_,
1802 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1803 QuicStringPiece(), _))
1804 .WillOnce(testing::Return(CreateSession(
1805 dispatcher_.get(), config_, TestConnectionId(conn_id),
1806 client_addr_, &mock_helper_, &mock_alarm_factory_,
1807 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1808 &session1_)));
1809 EXPECT_CALL(
1810 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1811 ProcessUdpPacket(_, _, _))
1812 .WillOnce(WithArg<2>(
1813 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1814 ValidatePacket(TestConnectionId(conn_id), packet);
1815 })));
1816 }
1817 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1818 SerializeFullCHLO());
1819 }
1820 EXPECT_FALSE(store->HasChloForConnection(
1821 /*connection_id=*/TestConnectionId(1)));
1822
1823 // CHLO on connection 1 should still be buffered.
1824 ProcessPacket(client_addr_, /*connection_id=*/TestConnectionId(1), true,
1825 SerializeFullCHLO());
1826 EXPECT_TRUE(store->HasChloForConnection(
1827 /*connection_id=*/TestConnectionId(1)));
1828}
1829
1830// Regression test for b/117874922.
wub0a4b9c52019-05-28 13:18:58 -07001831TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001832 // Turn off version 99, such that the preferred version is not supported by
1833 // the server.
1834 SetQuicReloadableFlag(quic_enable_version_99, false);
1835 uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
1836 ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
1837 for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
1838 // Last 5 CHLOs will be buffered. Others will create connection right away.
1839 ParsedQuicVersion version =
1840 supported_versions[(conn_id - 1) % supported_versions.size()];
1841 if (conn_id <= kMaxNumSessionsToCreate) {
1842 EXPECT_CALL(*dispatcher_,
1843 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1844 QuicStringPiece(), version))
1845 .WillOnce(testing::Return(CreateSession(
1846 dispatcher_.get(), config_, TestConnectionId(conn_id),
1847 client_addr_, &mock_helper_, &mock_alarm_factory_,
1848 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1849 &session1_)));
1850 EXPECT_CALL(
1851 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1852 ProcessUdpPacket(_, _, _))
1853 .WillRepeatedly(WithArg<2>(
1854 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1855 ValidatePacket(TestConnectionId(conn_id), packet);
1856 })));
1857 }
1858 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version,
1859 SerializeFullCHLO(), CONNECTION_ID_PRESENT,
1860 PACKET_4BYTE_PACKET_NUMBER, 1);
1861 }
1862
1863 // Process buffered CHLOs. Verify the version is correct.
1864 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1865 conn_id <= last_connection_id; ++conn_id) {
1866 ParsedQuicVersion version =
1867 supported_versions[(conn_id - 1) % supported_versions.size()];
1868 EXPECT_CALL(*dispatcher_,
1869 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1870 QuicStringPiece(), version))
1871 .WillOnce(testing::Return(CreateSession(
1872 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1873 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1874 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1875 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1876 ProcessUdpPacket(_, _, _))
1877 .WillRepeatedly(WithArg<2>(
1878 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1879 ValidatePacket(TestConnectionId(conn_id), packet);
1880 })));
1881 }
1882 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1883}
1884
QUICHE teama6ef0a62019-03-07 20:34:33 -05001885} // namespace
1886} // namespace test
1887} // namespace quic