blob: 34408e08bb4d0103d64196422e047fc6bcc7ad21 [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,
vasilvv0fc587f2019-09-06 13:33:08 -0700119 std::make_unique<MockQuicConnectionHelper>(),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500120 std::unique_ptr<QuicCryptoServerStream::Helper>(
wub662a3d62019-08-16 14:10:50 -0700121 new QuicSimpleCryptoServerStreamHelper()),
vasilvv0fc587f2019-09-06 13:33:08 -0700122 std::make_unique<MockAlarmFactory>(),
wub662a3d62019-08-16 14:10:50 -0700123 kQuicDefaultConnectionIdLength),
124 random_(random) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125
126 MOCK_METHOD4(CreateQuicSession,
127 QuicServerSessionBase*(QuicConnectionId connection_id,
128 const QuicSocketAddress& peer_address,
129 QuicStringPiece alpn,
130 const quic::ParsedQuicVersion& version));
131
fayang1ed1f762019-06-24 11:40:04 -0700132 MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
133 bool(const ReceivedPacketInfo& packet_info));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134
135 struct TestQuicPerPacketContext : public QuicPerPacketContext {
vasilvvc48c8712019-03-11 13:38:16 -0700136 std::string custom_packet_context;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 };
138
139 std::unique_ptr<QuicPerPacketContext> GetPerPacketContext() const override {
vasilvv0fc587f2019-09-06 13:33:08 -0700140 auto test_context = std::make_unique<TestQuicPerPacketContext>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 test_context->custom_packet_context = custom_packet_context_;
142 return std::move(test_context);
143 }
144
145 void RestorePerPacketContext(
146 std::unique_ptr<QuicPerPacketContext> context) override {
147 TestQuicPerPacketContext* test_context =
148 static_cast<TestQuicPerPacketContext*>(context.get());
149 custom_packet_context_ = test_context->custom_packet_context;
150 }
151
vasilvvc48c8712019-03-11 13:38:16 -0700152 std::string custom_packet_context_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500153
dschinazi7b9278c2019-05-20 07:36:21 -0700154 using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155 using QuicDispatcher::writer;
wub662a3d62019-08-16 14:10:50 -0700156
157 QuicRandom* random_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500158};
159
160// A Connection class which unregisters the session from the dispatcher when
161// sending connection close.
162// It'd be slightly more realistic to do this from the Session but it would
163// involve a lot more mocking.
164class MockServerConnection : public MockQuicConnection {
165 public:
166 MockServerConnection(QuicConnectionId connection_id,
167 MockQuicConnectionHelper* helper,
168 MockAlarmFactory* alarm_factory,
169 QuicDispatcher* dispatcher)
170 : MockQuicConnection(connection_id,
171 helper,
172 alarm_factory,
173 Perspective::IS_SERVER),
174 dispatcher_(dispatcher) {}
175
176 void UnregisterOnConnectionClosed() {
177 QUIC_LOG(ERROR) << "Unregistering " << connection_id();
178 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
179 "Unregistering.",
180 ConnectionCloseSource::FROM_SELF);
181 }
182
183 private:
184 QuicDispatcher* dispatcher_;
185};
186
187class QuicDispatcherTest : public QuicTest {
188 public:
189 QuicDispatcherTest()
190 : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
191
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
wub662a3d62019-08-16 14:10:50 -0700193 : version_manager_(AllSupportedVersions()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 crypto_config_(QuicCryptoServerConfig::TESTING,
195 QuicRandom::GetInstance(),
196 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -0700197 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500198 server_address_(QuicIpAddress::Any4(), 5),
QUICHE teamc65d1d12019-03-19 20:58:04 -0700199 dispatcher_(
200 new NiceMock<TestDispatcher>(&config_,
201 &crypto_config_,
202 &version_manager_,
203 mock_helper_.GetRandomGenerator())),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204 time_wait_list_manager_(nullptr),
205 session1_(nullptr),
206 session2_(nullptr),
fayangb880b4c2019-06-14 12:26:35 -0700207 store_(nullptr),
208 connection_id_(1) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500209
210 void SetUp() override {
211 dispatcher_->InitializeWithWriter(new MockPacketWriter());
212 // Set the counter to some value to start with.
213 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
214 dispatcher_.get(), kMaxNumSessionsToCreate);
fayang1ed1f762019-06-24 11:40:04 -0700215 ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500216 .WillByDefault(Return(true));
217 }
218
219 MockQuicConnection* connection1() {
220 if (session1_ == nullptr) {
221 return nullptr;
222 }
223 return reinterpret_cast<MockQuicConnection*>(session1_->connection());
224 }
225
226 MockQuicConnection* connection2() {
227 if (session2_ == nullptr) {
228 return nullptr;
229 }
230 return reinterpret_cast<MockQuicConnection*>(session2_->connection());
231 }
232
233 // Process a packet with an 8 byte connection id,
234 // 6 byte packet number, default path id, and packet number 1,
235 // using the first supported version.
236 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700237 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500238 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700239 const std::string& data) {
dschinazi346b7ce2019-06-05 01:38:18 -0700240 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER);
242 }
243
244 // Process a packet with a default path id, and packet number 1,
245 // using the first supported version.
246 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700247 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500248 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700249 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700250 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500251 QuicPacketNumberLength packet_number_length) {
dschinazi346b7ce2019-06-05 01:38:18 -0700252 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
253 server_connection_id_included, packet_number_length, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500254 }
255
256 // Process a packet using the first supported version.
257 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700258 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500259 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700260 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700261 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500262 QuicPacketNumberLength packet_number_length,
263 uint64_t packet_number) {
dschinazi346b7ce2019-06-05 01:38:18 -0700264 ProcessPacket(peer_address, server_connection_id, has_version_flag,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500265 CurrentSupportedVersions().front(), data,
dschinazi346b7ce2019-06-05 01:38:18 -0700266 server_connection_id_included, packet_number_length,
267 packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 }
269
270 // Processes a packet.
271 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700272 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500273 bool has_version_flag,
274 ParsedQuicVersion version,
vasilvvc48c8712019-03-11 13:38:16 -0700275 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700276 QuicConnectionIdIncluded server_connection_id_included,
277 QuicPacketNumberLength packet_number_length,
278 uint64_t packet_number) {
279 ProcessPacket(peer_address, server_connection_id, EmptyQuicConnectionId(),
280 has_version_flag, version, data,
281 server_connection_id_included, CONNECTION_ID_ABSENT,
282 packet_number_length, packet_number);
283 }
284
285 // Processes a packet.
286 void ProcessPacket(QuicSocketAddress peer_address,
287 QuicConnectionId server_connection_id,
288 QuicConnectionId client_connection_id,
289 bool has_version_flag,
290 ParsedQuicVersion version,
291 const std::string& data,
292 QuicConnectionIdIncluded server_connection_id_included,
293 QuicConnectionIdIncluded client_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 QuicPacketNumberLength packet_number_length,
295 uint64_t packet_number) {
296 ParsedQuicVersionVector versions(SupportedVersions(version));
297 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700298 server_connection_id, client_connection_id, has_version_flag, false,
299 packet_number, data, server_connection_id_included,
300 client_connection_id_included, packet_number_length, &versions));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500301 std::unique_ptr<QuicReceivedPacket> received_packet(
302 ConstructReceivedPacket(*packet, mock_helper_.GetClock()->Now()));
303
dschinazi4fd8cb12019-09-09 16:31:06 -0700304 if (ChloExtractor::Extract(*packet, version, {}, nullptr,
dschinazi346b7ce2019-06-05 01:38:18 -0700305 server_connection_id.length())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500306 // Add CHLO packet to the beginning to be verified first, because it is
307 // also processed first by new session.
dschinazi346b7ce2019-06-05 01:38:18 -0700308 data_connection_map_[server_connection_id].push_front(
vasilvvc48c8712019-03-11 13:38:16 -0700309 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500310 } else {
311 // For non-CHLO, always append to last.
dschinazi346b7ce2019-06-05 01:38:18 -0700312 data_connection_map_[server_connection_id].push_back(
vasilvvc48c8712019-03-11 13:38:16 -0700313 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500314 }
315 dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet);
316 }
317
318 void ValidatePacket(QuicConnectionId conn_id,
319 const QuicEncryptedPacket& packet) {
320 EXPECT_EQ(data_connection_map_[conn_id].front().length(),
321 packet.AsStringPiece().length());
322 EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
323 data_connection_map_[conn_id].pop_front();
324 }
325
326 QuicServerSessionBase* CreateSession(
327 TestDispatcher* dispatcher,
328 const QuicConfig& config,
329 QuicConnectionId connection_id,
dschinazi17d42422019-06-18 16:35:07 -0700330 const QuicSocketAddress& /*peer_address*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500331 MockQuicConnectionHelper* helper,
332 MockAlarmFactory* alarm_factory,
333 const QuicCryptoServerConfig* crypto_config,
334 QuicCompressedCertsCache* compressed_certs_cache,
335 TestQuicSpdyServerSession** session) {
336 MockServerConnection* connection = new MockServerConnection(
337 connection_id, helper, alarm_factory, dispatcher);
338 connection->SetQuicPacketWriter(dispatcher->writer(),
339 /*owns_writer=*/false);
340 *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
341 compressed_certs_cache);
342 connection->set_visitor(*session);
343 ON_CALL(*connection, CloseConnection(_, _, _))
344 .WillByDefault(WithoutArgs(Invoke(
345 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
346 return *session;
347 }
348
349 void CreateTimeWaitListManager() {
350 time_wait_list_manager_ = new MockTimeWaitListManager(
351 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
352 mock_helper_.GetClock(), &mock_alarm_factory_);
353 // dispatcher_ takes the ownership of time_wait_list_manager_.
354 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
355 time_wait_list_manager_);
356 }
357
vasilvvc48c8712019-03-11 13:38:16 -0700358 std::string SerializeCHLO() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500359 CryptoHandshakeMessage client_hello;
360 client_hello.set_tag(kCHLO);
361 client_hello.SetStringPiece(kALPN, "hq");
vasilvvc48c8712019-03-11 13:38:16 -0700362 return std::string(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500363 }
364
QUICHE teama6ef0a62019-03-07 20:34:33 -0500365 void MarkSession1Deleted() { session1_ = nullptr; }
366
fayangb880b4c2019-06-14 12:26:35 -0700367 void VerifyVersionSupported(ParsedQuicVersion version) {
368 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
369 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
370 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
371 QuicStringPiece("hq"), _))
372 .WillOnce(testing::Return(CreateSession(
373 dispatcher_.get(), config_, connection_id, client_address,
374 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
375 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
376 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
377 ProcessUdpPacket(_, _, _))
378 .WillOnce(WithArg<2>(
379 Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
380 ValidatePacket(connection_id, packet);
381 })));
382 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700383 ShouldCreateOrBufferPacketForConnection(
384 ReceivedPacketInfoConnectionIdEquals(connection_id)));
fayangb880b4c2019-06-14 12:26:35 -0700385 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
386 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
387 }
388
389 void VerifyVersionNotSupported(ParsedQuicVersion version) {
390 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
391 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
392 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
393 QuicStringPiece("hq"), _))
394 .Times(0);
395 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
396 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
397 }
398
QUICHE teama6ef0a62019-03-07 20:34:33 -0500399 MockQuicConnectionHelper mock_helper_;
400 MockAlarmFactory mock_alarm_factory_;
401 QuicConfig config_;
402 QuicVersionManager version_manager_;
403 QuicCryptoServerConfig crypto_config_;
404 QuicSocketAddress server_address_;
405 std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
406 MockTimeWaitListManager* time_wait_list_manager_;
407 TestQuicSpdyServerSession* session1_;
408 TestQuicSpdyServerSession* session2_;
vasilvvc48c8712019-03-11 13:38:16 -0700409 std::map<QuicConnectionId, std::list<std::string>> data_connection_map_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500410 QuicBufferedPacketStore* store_;
fayangb880b4c2019-06-14 12:26:35 -0700411 uint64_t connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500412};
413
414TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
QUICHE teamea740082019-03-11 17:58:43 -0700415 if (!QuicVersionUsesCryptoFrames(
416 CurrentSupportedVersions().front().transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500417 // TLS is only supported in versions 47 and greater.
418 return;
419 }
rch16df2a52019-09-10 10:50:09 -0700420 SetQuicReloadableFlag(quic_supports_tls_handshake, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500421 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
422
423 EXPECT_CALL(*dispatcher_,
424 CreateQuicSession(TestConnectionId(1), client_address,
425 QuicStringPiece(""), _))
426 .WillOnce(testing::Return(CreateSession(
427 dispatcher_.get(), config_, TestConnectionId(1), client_address,
428 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
429 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
430 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
431 ProcessUdpPacket(_, _, _))
432 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
433 ValidatePacket(TestConnectionId(1), packet);
434 })));
435 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700436 ShouldCreateOrBufferPacketForConnection(
437 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500438 ProcessPacket(
439 client_address, TestConnectionId(1), true,
440 ParsedQuicVersion(PROTOCOL_TLS1_3,
441 CurrentSupportedVersions().front().transport_version),
442 SerializeCHLO(), CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500443}
444
445TEST_F(QuicDispatcherTest, ProcessPackets) {
446 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
447
448 EXPECT_CALL(*dispatcher_,
449 CreateQuicSession(TestConnectionId(1), client_address,
450 QuicStringPiece("hq"), _))
451 .WillOnce(testing::Return(CreateSession(
452 dispatcher_.get(), config_, TestConnectionId(1), client_address,
453 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
454 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
455 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
456 ProcessUdpPacket(_, _, _))
457 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
458 ValidatePacket(TestConnectionId(1), packet);
459 })));
460 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700461 ShouldCreateOrBufferPacketForConnection(
462 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500463 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500464
465 EXPECT_CALL(*dispatcher_,
466 CreateQuicSession(TestConnectionId(2), client_address,
467 QuicStringPiece("hq"), _))
468 .WillOnce(testing::Return(CreateSession(
469 dispatcher_.get(), config_, TestConnectionId(2), client_address,
470 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
471 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
472 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
473 ProcessUdpPacket(_, _, _))
474 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
475 ValidatePacket(TestConnectionId(2), packet);
476 })));
477 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700478 ShouldCreateOrBufferPacketForConnection(
479 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500480 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
481
482 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
483 ProcessUdpPacket(_, _, _))
484 .Times(1)
485 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
486 ValidatePacket(TestConnectionId(1), packet);
487 })));
488 ProcessPacket(client_address, TestConnectionId(1), false, "data");
489}
490
491// Regression test of b/93325907.
492TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
493 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
494
495 EXPECT_CALL(*dispatcher_,
496 CreateQuicSession(TestConnectionId(1), client_address,
497 QuicStringPiece("hq"), _))
498 .WillOnce(testing::Return(CreateSession(
499 dispatcher_.get(), config_, TestConnectionId(1), client_address,
500 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
501 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
502 // Verify both packets 1 and 2 are processed by connection 1.
503 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
504 ProcessUdpPacket(_, _, _))
505 .Times(2)
506 .WillRepeatedly(
507 WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
508 ValidatePacket(TestConnectionId(1), packet);
509 })));
510 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700511 ShouldCreateOrBufferPacketForConnection(
512 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500513 ProcessPacket(
514 client_address, TestConnectionId(1), true,
515 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
516 CurrentSupportedVersions().front().transport_version),
517 SerializeCHLO(), CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
518 // Packet number 256 with packet number length 1 would be considered as 0 in
519 // dispatcher.
520 ProcessPacket(
521 client_address, TestConnectionId(1), false,
522 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
523 CurrentSupportedVersions().front().transport_version),
524 "", CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500525}
526
527TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
dschinazi48ac9192019-07-31 00:07:26 -0700528 SetQuicReloadableFlag(quic_use_parse_public_header, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500529 CreateTimeWaitListManager();
530 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
531
532 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
dschinazi346b7ce2019-06-05 01:38:18 -0700533 EXPECT_CALL(
534 *time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700535 SendVersionNegotiationPacket(TestConnectionId(1), _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500536 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500537 // Pad the CHLO message with enough data to make the packet large enough
538 // to trigger version negotiation.
vasilvvc48c8712019-03-11 13:38:16 -0700539 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500540 DCHECK_LE(1200u, chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700541 ProcessPacket(client_address, TestConnectionId(1), true,
542 QuicVersionReservedForNegotiation(), chlo,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500543 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
544}
545
dschinazi346b7ce2019-06-05 01:38:18 -0700546TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
dschinazi48ac9192019-07-31 00:07:26 -0700547 SetQuicReloadableFlag(quic_use_parse_public_header, true);
dschinazi346b7ce2019-06-05 01:38:18 -0700548 CreateTimeWaitListManager();
549 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
550
551 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
552 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700553 SendVersionNegotiationPacket(
554 TestConnectionId(1), TestConnectionId(2), _, _, _, _, _, _))
dschinazi346b7ce2019-06-05 01:38:18 -0700555 .Times(1);
556 // Pad the CHLO message with enough data to make the packet large enough
557 // to trigger version negotiation.
558 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
559 DCHECK_LE(1200u, chlo.length());
560 ProcessPacket(client_address, TestConnectionId(1), TestConnectionId(2), true,
561 QuicVersionReservedForNegotiation(), chlo,
562 CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
563 PACKET_4BYTE_PACKET_NUMBER, 1);
564}
565
QUICHE teama6ef0a62019-03-07 20:34:33 -0500566TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
567 CreateTimeWaitListManager();
568 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
569
570 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
571 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700572 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500573 .Times(0);
vasilvvc48c8712019-03-11 13:38:16 -0700574 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500575 // Truncate to 1100 bytes of payload which results in a packet just
576 // under 1200 bytes after framing, packet, and encryption overhead.
577 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700578 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500579 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700580 ProcessPacket(client_address, TestConnectionId(1), true,
581 QuicVersionReservedForNegotiation(), truncated_chlo,
582 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500583}
584
585// Disabling CHLO size validation allows the dispatcher to send version
586// negotiation packets in response to a CHLO that is otherwise too small.
587TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
dschinazi48ac9192019-07-31 00:07:26 -0700588 SetQuicReloadableFlag(quic_use_parse_public_header, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500589 crypto_config_.set_validate_chlo_size(false);
590
591 CreateTimeWaitListManager();
592 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
593
594 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
595 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700596 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500597 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -0700598 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500599 // Truncate to 1100 bytes of payload which results in a packet just
600 // under 1200 bytes after framing, packet, and encryption overhead.
601 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700602 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500603 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700604 ProcessPacket(client_address, TestConnectionId(1), true,
605 QuicVersionReservedForNegotiation(), truncated_chlo,
606 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500607}
608
609TEST_F(QuicDispatcherTest, Shutdown) {
610 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
611
612 EXPECT_CALL(*dispatcher_,
613 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
614 .WillOnce(testing::Return(CreateSession(
615 dispatcher_.get(), config_, TestConnectionId(1), client_address,
616 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
617 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
618 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
619 ProcessUdpPacket(_, _, _))
620 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
621 ValidatePacket(TestConnectionId(1), packet);
622 })));
623
624 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700625 ShouldCreateOrBufferPacketForConnection(
626 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500627 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
628
629 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
630 CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
631
632 dispatcher_->Shutdown();
633}
634
635TEST_F(QuicDispatcherTest, TimeWaitListManager) {
636 CreateTimeWaitListManager();
637
638 // Create a new session.
639 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
640 QuicConnectionId connection_id = TestConnectionId(1);
641 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
642 QuicStringPiece("hq"), _))
643 .WillOnce(testing::Return(CreateSession(
644 dispatcher_.get(), config_, connection_id, client_address,
645 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
646 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
647 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
648 ProcessUdpPacket(_, _, _))
649 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
650 ValidatePacket(TestConnectionId(1), packet);
651 })));
652
653 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700654 ShouldCreateOrBufferPacketForConnection(
655 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500656 ProcessPacket(client_address, connection_id, true, SerializeCHLO());
657
658 // Now close the connection, which should add it to the time wait list.
659 session1_->connection()->CloseConnection(
660 QUIC_INVALID_VERSION,
661 "Server: Packet 2 without version flag before version negotiated.",
662 ConnectionCloseBehavior::SILENT_CLOSE);
663 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
664
665 // Dispatcher forwards subsequent packets for this connection_id to the time
666 // wait list manager.
667 EXPECT_CALL(*time_wait_list_manager_,
668 ProcessPacket(_, _, connection_id, _, _))
669 .Times(1);
670 EXPECT_CALL(*time_wait_list_manager_,
671 AddConnectionIdToTimeWait(_, _, _, _, _))
672 .Times(0);
673 ProcessPacket(client_address, connection_id, true, "data");
674}
675
676TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
677 CreateTimeWaitListManager();
678
679 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
680 QuicConnectionId connection_id = TestConnectionId(1);
681 // Dispatcher forwards all packets for this connection_id to the time wait
682 // list manager.
683 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
684 .Times(0);
fayangd057e662019-07-10 13:29:41 -0700685 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
686 EXPECT_CALL(*time_wait_list_manager_,
687 ProcessPacket(_, _, connection_id, _, _))
688 .Times(0);
689 EXPECT_CALL(*time_wait_list_manager_,
690 AddConnectionIdToTimeWait(_, _, _, _, _))
691 .Times(0);
692 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
693 .Times(1);
694 } else {
695 EXPECT_CALL(*time_wait_list_manager_,
696 ProcessPacket(_, _, connection_id, _, _))
697 .Times(1);
698 EXPECT_CALL(*time_wait_list_manager_,
699 AddConnectionIdToTimeWait(_, _, _, _, _))
700 .Times(1);
701 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500702 ProcessPacket(client_address, connection_id, false, SerializeCHLO());
703}
704
fayangd057e662019-07-10 13:29:41 -0700705TEST_F(QuicDispatcherTest,
706 DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
707 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
708 CreateTimeWaitListManager();
709
710 char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
711 QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
712 char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
713 QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
714 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
715 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
716 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
717 .Times(0);
718 EXPECT_CALL(*time_wait_list_manager_,
719 AddConnectionIdToTimeWait(_, _, _, _, _))
720 .Times(0);
721 } else {
722 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
723 .Times(2);
724 EXPECT_CALL(*time_wait_list_manager_,
725 AddConnectionIdToTimeWait(_, _, _, _, _))
726 .Times(2);
727 }
728 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
729 // Verify small packet is silently dropped.
730 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
731 .Times(0);
732 }
733 dispatcher_->ProcessPacket(server_address_, client_address, packet);
734 if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
735 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
736 .Times(1);
737 }
738 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
739}
740
QUICHE teamc65d1d12019-03-19 20:58:04 -0700741// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
QUICHE team963d57e2019-03-21 10:58:47 -0700742TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
QUICHE team8e2e4532019-03-14 14:37:56 -0700743 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
744 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700745 // When variable length connection IDs are not supported, the connection
746 // fails. See StrayPacketTruncatedConnectionId.
QUICHE team8e2e4532019-03-14 14:37:56 -0700747 return;
748 }
QUICHE team8e2e4532019-03-14 14:37:56 -0700749 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
750
QUICHE teamc65d1d12019-03-19 20:58:04 -0700751 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700752 QuicConnectionId fixed_connection_id =
753 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700754
755 EXPECT_CALL(*dispatcher_,
756 CreateQuicSession(fixed_connection_id, client_address,
757 QuicStringPiece("hq"), _))
758 .WillOnce(testing::Return(CreateSession(
759 dispatcher_.get(), config_, fixed_connection_id, client_address,
760 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
761 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
762 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
763 ProcessUdpPacket(_, _, _))
764 .WillOnce(WithArg<2>(
765 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
766 ValidatePacket(bad_connection_id, packet);
767 })));
768 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700769 ShouldCreateOrBufferPacketForConnection(
770 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700771 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700772}
773
QUICHE team963d57e2019-03-21 10:58:47 -0700774// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
775TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
776 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
777 CurrentSupportedVersions()[0].transport_version)) {
778 // When variable length connection IDs are not supported, the connection
779 // fails. See StrayPacketTruncatedConnectionId.
780 return;
781 }
782 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
783
784 QuicConnectionId bad_connection_id = EmptyQuicConnectionId();
dschinazi28c1bf32019-08-19 11:54:46 -0700785 QuicConnectionId fixed_connection_id =
786 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team963d57e2019-03-21 10:58:47 -0700787
788 // Disable validation of invalid short connection IDs.
dschinazi7b9278c2019-05-20 07:36:21 -0700789 dispatcher_->SetAllowShortInitialServerConnectionIds(true);
QUICHE team963d57e2019-03-21 10:58:47 -0700790 // Note that StrayPacketTruncatedConnectionId covers the case where the
791 // validation is still enabled.
792
793 EXPECT_CALL(*dispatcher_,
794 CreateQuicSession(fixed_connection_id, client_address,
795 QuicStringPiece("hq"), _))
796 .WillOnce(testing::Return(CreateSession(
797 dispatcher_.get(), config_, fixed_connection_id, client_address,
798 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
799 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
800 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
801 ProcessUdpPacket(_, _, _))
802 .WillOnce(WithArg<2>(
803 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
804 ValidatePacket(bad_connection_id, packet);
805 })));
806 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700807 ShouldCreateOrBufferPacketForConnection(
808 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE team963d57e2019-03-21 10:58:47 -0700809 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team963d57e2019-03-21 10:58:47 -0700810}
811
QUICHE teamc65d1d12019-03-19 20:58:04 -0700812// Makes sure TestConnectionId(1) creates a new connection and
813// TestConnectionIdNineBytesLong(2) gets replaced.
QUICHE team8e2e4532019-03-14 14:37:56 -0700814TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
815 if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
816 CurrentSupportedVersions()[0].transport_version)) {
817 return;
818 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700819
QUICHE team8e2e4532019-03-14 14:37:56 -0700820 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700821 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700822 QuicConnectionId fixed_connection_id =
823 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team8e2e4532019-03-14 14:37:56 -0700824
825 EXPECT_CALL(*dispatcher_,
826 CreateQuicSession(TestConnectionId(1), client_address,
827 QuicStringPiece("hq"), _))
828 .WillOnce(testing::Return(CreateSession(
829 dispatcher_.get(), config_, TestConnectionId(1), client_address,
830 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
831 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
832 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
833 ProcessUdpPacket(_, _, _))
834 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
835 ValidatePacket(TestConnectionId(1), packet);
836 })));
837 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700838 ShouldCreateOrBufferPacketForConnection(
839 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700840 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700841
QUICHE teamc65d1d12019-03-19 20:58:04 -0700842 EXPECT_CALL(*dispatcher_,
843 CreateQuicSession(fixed_connection_id, client_address,
844 QuicStringPiece("hq"), _))
845 .WillOnce(testing::Return(CreateSession(
846 dispatcher_.get(), config_, fixed_connection_id, client_address,
847 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
848 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
849 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
850 ProcessUdpPacket(_, _, _))
851 .WillOnce(WithArg<2>(
852 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
853 ValidatePacket(bad_connection_id, packet);
854 })));
855 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700856 ShouldCreateOrBufferPacketForConnection(
857 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700858 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700859
860 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
861 ProcessUdpPacket(_, _, _))
862 .Times(1)
863 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
864 ValidatePacket(TestConnectionId(1), packet);
865 })));
866 ProcessPacket(client_address, TestConnectionId(1), false, "data");
867}
868
QUICHE teama6ef0a62019-03-07 20:34:33 -0500869TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
870 CreateTimeWaitListManager();
871
872 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
873
874 // dispatcher_ should drop this packet.
875 EXPECT_CALL(*dispatcher_,
876 CreateQuicSession(TestConnectionId(1), client_address,
877 QuicStringPiece("hq"), _))
878 .Times(0);
879 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
880 EXPECT_CALL(*time_wait_list_manager_,
881 AddConnectionIdToTimeWait(_, _, _, _, _))
882 .Times(0);
883 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
884}
885
dschinaziee07e472019-06-19 09:56:56 -0700886TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
dschinaziee07e472019-06-19 09:56:56 -0700887 // 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 SetQuicReloadableFlag(quic_use_parse_public_header, true);
fayang36825da2019-08-21 14:01:27 -0700933 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500934 "Supported versions out of sync");
935 SetQuicReloadableFlag(quic_disable_version_39, false);
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);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500938 SetQuicReloadableFlag(quic_enable_version_99, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500939
fayangb880b4c2019-06-14 12:26:35 -0700940 VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
941
942 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
943 QuicVersionMin().transport_version));
944 VerifyVersionSupported(QuicVersionMax());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500945
nharper107ba5f2019-07-02 21:33:39 -0700946 // Turn off version 48.
nharperd0f4a162019-08-21 11:03:21 -0700947 SetQuicReloadableFlag(quic_enable_version_48_2, false);
nharper107ba5f2019-07-02 21:33:39 -0700948 VerifyVersionNotSupported(
949 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
950
951 // Turn on version 48.
nharperd0f4a162019-08-21 11:03:21 -0700952 SetQuicReloadableFlag(quic_enable_version_48_2, true);
nharper107ba5f2019-07-02 21:33:39 -0700953 VerifyVersionSupported(
954 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
955
QUICHE teama6ef0a62019-03-07 20:34:33 -0500956 // Turn off version 47.
957 SetQuicReloadableFlag(quic_enable_version_47, false);
fayangb880b4c2019-06-14 12:26:35 -0700958 VerifyVersionNotSupported(
959 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500960
961 // Turn on version 47.
962 SetQuicReloadableFlag(quic_enable_version_47, true);
fayangb880b4c2019-06-14 12:26:35 -0700963 VerifyVersionSupported(
964 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
965
QUICHE teama6ef0a62019-03-07 20:34:33 -0500966 // Turn off version 39.
967 SetQuicReloadableFlag(quic_disable_version_39, true);
fayangb880b4c2019-06-14 12:26:35 -0700968 VerifyVersionNotSupported(
969 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500970
971 // Turn on version 39.
972 SetQuicReloadableFlag(quic_disable_version_39, false);
fayangb880b4c2019-06-14 12:26:35 -0700973 VerifyVersionSupported(
974 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500975}
976
fayangb54ac5b2019-07-01 10:30:37 -0700977TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
fayang36825da2019-08-21 14:01:27 -0700978 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
fayangb54ac5b2019-07-01 10:30:37 -0700979 "Please add deprecated versions to this test");
980 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
981 CreateTimeWaitListManager();
982
983 char packet45[kMinPacketSizeForVersionNegotiation] = {
984 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
985 QuicReceivedPacket packet(packet45, kMinPacketSizeForVersionNegotiation,
986 QuicTime::Zero());
987 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
988 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700989 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
fayangb54ac5b2019-07-01 10:30:37 -0700990 .Times(1);
991 dispatcher_->ProcessPacket(server_address_, client_address, packet);
fayang36825da2019-08-21 14:01:27 -0700992
993 char packet44[kMinPacketSizeForVersionNegotiation] = {
994 0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
995 QuicReceivedPacket packet2(packet44, kMinPacketSizeForVersionNegotiation,
996 QuicTime::Zero());
997 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
998 EXPECT_CALL(*time_wait_list_manager_,
999 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
1000 .Times(1);
1001 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
fayangb54ac5b2019-07-01 10:30:37 -07001002}
1003
dschinazi30ab6db2019-08-13 14:43:32 -07001004TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
1005 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
1006 SetQuicReloadableFlag(quic_use_length_prefix_from_packet_info, true);
1007 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1008 CreateTimeWaitListManager();
1009 char packet[1200];
1010 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1011 0x6c, 0x7a, 0x20, 0x21};
1012 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1013 packet, sizeof(packet), destination_connection_id_bytes,
1014 sizeof(destination_connection_id_bytes)));
1015 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1016 std::unique_ptr<QuicReceivedPacket> received_packet(
1017 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1018 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1019 QuicConnectionId server_connection_id(
1020 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1021 bool ietf_quic = true;
1022 bool use_length_prefix =
1023 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1024 EXPECT_CALL(
1025 *time_wait_list_manager_,
1026 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1027 ietf_quic, use_length_prefix, _, _, _, _))
1028 .Times(1);
1029 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1030
1031 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1032}
1033
1034TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
1035 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
1036 SetQuicReloadableFlag(quic_use_parse_public_header, true);
1037 SetQuicReloadableFlag(quic_use_length_prefix_from_packet_info, true);
1038 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1039 CreateTimeWaitListManager();
1040 char packet[1200];
1041 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1042 0x6c, 0x7a, 0x20, 0x21};
1043 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1044 packet, sizeof(packet), destination_connection_id_bytes,
1045 sizeof(destination_connection_id_bytes)));
1046 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1047 std::unique_ptr<QuicReceivedPacket> received_packet(
1048 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1049 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1050 QuicConnectionId server_connection_id(
1051 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1052 bool ietf_quic = true;
1053 bool use_length_prefix =
1054 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1055 EXPECT_CALL(
1056 *time_wait_list_manager_,
1057 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1058 ietf_quic, use_length_prefix, _, _, _, _))
1059 .Times(1);
1060 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1061
1062 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1063}
1064
dschinazi0185ebb2019-08-14 11:09:35 -07001065// Testing packet writer that saves all packets instead of sending them.
1066// Useful for tests that need access to sent packets.
1067class SavingWriter : public QuicPacketWriterWrapper {
1068 public:
1069 bool IsWriteBlocked() const override { return false; }
1070
1071 WriteResult WritePacket(const char* buffer,
1072 size_t buf_len,
1073 const QuicIpAddress& /*self_client_address*/,
1074 const QuicSocketAddress& /*peer_client_address*/,
1075 PerPacketOptions* /*options*/) override {
1076 packets_.push_back(
1077 QuicEncryptedPacket(buffer, buf_len, /*owns_buffer=*/false).Clone());
1078 return WriteResult(WRITE_STATUS_OK, buf_len);
1079 }
1080
1081 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
1082 return &packets_;
1083 }
1084
1085 private:
1086 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
1087};
1088
1089TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
1090 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
1091 SetQuicReloadableFlag(quic_use_length_prefix_from_packet_info, true);
1092
1093 SavingWriter* saving_writer = new SavingWriter();
1094 // dispatcher_ takes ownership of saving_writer.
1095 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1096
1097 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1098 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1099 &mock_alarm_factory_);
1100 // dispatcher_ takes ownership of time_wait_list_manager.
1101 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1102 time_wait_list_manager);
1103 char packet[1200] = {};
1104 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1105 0x6c, 0x7a, 0x20, 0x21};
1106 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1107 packet, sizeof(packet), destination_connection_id_bytes,
1108 sizeof(destination_connection_id_bytes)));
1109 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1110 std::unique_ptr<QuicReceivedPacket> received_packet(
1111 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1112 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1113
1114 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1115 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1116 ASSERT_EQ(1u, saving_writer->packets()->size());
1117
1118 char source_connection_id_bytes[255] = {};
1119 uint8_t source_connection_id_length = 0;
1120 std::string detailed_error = "foobar";
1121 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1122 (*(saving_writer->packets()))[0]->data(),
1123 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1124 &source_connection_id_length, &detailed_error));
1125 EXPECT_EQ("", detailed_error);
1126
1127 // The source connection ID of the probe response should match the
1128 // destination connection ID of the probe request.
1129 test::CompareCharArraysWithHexError(
1130 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1131 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1132}
1133
1134TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
1135 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
1136 SetQuicReloadableFlag(quic_use_parse_public_header, true);
1137 SetQuicReloadableFlag(quic_use_length_prefix_from_packet_info, true);
1138
1139 SavingWriter* saving_writer = new SavingWriter();
1140 // dispatcher_ takes ownership of saving_writer.
1141 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1142
1143 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1144 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1145 &mock_alarm_factory_);
1146 // dispatcher_ takes ownership of time_wait_list_manager.
1147 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1148 time_wait_list_manager);
1149 char packet[1200] = {};
1150 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1151 0x6c, 0x7a, 0x20, 0x21};
1152 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1153 packet, sizeof(packet), destination_connection_id_bytes,
1154 sizeof(destination_connection_id_bytes)));
1155 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1156 std::unique_ptr<QuicReceivedPacket> received_packet(
1157 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1158 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1159
1160 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1161 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1162 ASSERT_EQ(1u, saving_writer->packets()->size());
1163
1164 char source_connection_id_bytes[255] = {};
1165 uint8_t source_connection_id_length = 0;
1166 std::string detailed_error = "foobar";
1167 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1168 (*(saving_writer->packets()))[0]->data(),
1169 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1170 &source_connection_id_length, &detailed_error));
1171 EXPECT_EQ("", detailed_error);
1172
1173 // The source connection ID of the probe response should match the
1174 // destination connection ID of the probe request.
1175 test::CompareCharArraysWithHexError(
1176 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1177 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1178}
1179
dschinazi5b236be2019-08-19 14:55:22 -07001180TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
1181 // TODO(b/139691956) Remove this test once the workaround is removed.
1182 // This test requires the workaround behind this flag to pass.
1183 SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, true);
1184 SavingWriter* saving_writer = new SavingWriter();
1185 // dispatcher_ takes ownership of saving_writer.
1186 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1187
1188 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1189 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1190 &mock_alarm_factory_);
1191 // dispatcher_ takes ownership of time_wait_list_manager.
1192 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1193 time_wait_list_manager);
1194 // clang-format off
1195 static const unsigned char packet[] = {
1196 // Android UDP network conformance test packet as it was before this change:
1197 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1198 0x0c, // public flags: 8-byte connection ID, 1-byte packet number
1199 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1200 0x01, // 1-byte packet number
1201 0x00, // private flags
1202 0x07, // PING frame
1203 };
1204 // clang-format on
1205
1206 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1207 sizeof(packet), false);
1208 std::unique_ptr<QuicReceivedPacket> received_packet(
1209 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1210 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1211
1212 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1213 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1214 ASSERT_EQ(1u, saving_writer->packets()->size());
1215
1216 // The Android UDP network conformance test directly checks that bytes 1-9
1217 // of the response match the connection ID that was sent.
1218 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1219 0x75, 0x76, 0x77, 0x78};
1220 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1221 1u + sizeof(connection_id_bytes));
1222 test::CompareCharArraysWithHexError(
1223 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1224 sizeof(connection_id_bytes), connection_id_bytes,
1225 sizeof(connection_id_bytes));
1226}
1227
1228TEST_F(QuicDispatcherTest, AndroidConformanceTestNewWithWorkaround) {
1229 // TODO(b/139691956) Remove this test once the workaround is removed.
1230 // This test doesn't need the workaround but we make sure that it passes even
1231 // when the flag is true, also see AndroidConformanceTest below.
1232 SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, true);
1233 SavingWriter* saving_writer = new SavingWriter();
1234 // dispatcher_ takes ownership of saving_writer.
1235 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1236
1237 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1238 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1239 &mock_alarm_factory_);
1240 // dispatcher_ takes ownership of time_wait_list_manager.
1241 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1242 time_wait_list_manager);
1243 // clang-format off
1244 static const unsigned char packet[1200] = {
1245 // Android UDP network conformance test packet as it was after this change:
1246 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1247 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1248 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1249 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1250 0x01, // 1-byte packet number
1251 0x00, // private flags
1252 0x07, // PING frame
1253 };
1254 // clang-format on
1255
1256 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1257 sizeof(packet), false);
1258 std::unique_ptr<QuicReceivedPacket> received_packet(
1259 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1260 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1261
1262 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1263 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1264 ASSERT_EQ(1u, saving_writer->packets()->size());
1265
1266 // The Android UDP network conformance test directly checks that bytes 1-9
1267 // of the response match the connection ID that was sent.
1268 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1269 0x75, 0x76, 0x77, 0x78};
1270 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1271 1u + sizeof(connection_id_bytes));
1272 test::CompareCharArraysWithHexError(
1273 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1274 sizeof(connection_id_bytes), connection_id_bytes,
1275 sizeof(connection_id_bytes));
1276}
1277
1278TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
1279 // WARNING: do not remove or modify this test without making sure that we
1280 // still have adequate coverage for the Android conformance test.
1281
1282 // Set the flag to false to make sure this test passes even when the
1283 // workaround is disabled.
1284 SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, false);
1285 SavingWriter* saving_writer = new SavingWriter();
1286 // dispatcher_ takes ownership of saving_writer.
1287 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1288
1289 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1290 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1291 &mock_alarm_factory_);
1292 // dispatcher_ takes ownership of time_wait_list_manager.
1293 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1294 time_wait_list_manager);
1295 // clang-format off
1296 static const unsigned char packet[1200] = {
1297 // Android UDP network conformance test packet as it was after this change:
1298 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1299 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1300 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1301 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1302 0x01, // 1-byte packet number
1303 0x00, // private flags
1304 0x07, // PING frame
1305 };
1306 // clang-format on
1307
1308 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1309 sizeof(packet), false);
1310 std::unique_ptr<QuicReceivedPacket> received_packet(
1311 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1312 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1313
1314 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1315 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1316 ASSERT_EQ(1u, saving_writer->packets()->size());
1317
1318 // The Android UDP network conformance test directly checks that bytes 1-9
1319 // of the response match the connection ID that was sent.
1320 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1321 0x75, 0x76, 0x77, 0x78};
1322 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1323 1u + sizeof(connection_id_bytes));
1324 test::CompareCharArraysWithHexError(
1325 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1326 sizeof(connection_id_bytes), connection_id_bytes,
1327 sizeof(connection_id_bytes));
1328}
1329
QUICHE teama6ef0a62019-03-07 20:34:33 -05001330// Verify the stopgap test: Packets with truncated connection IDs should be
1331// dropped.
1332class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
1333
1334// Packets with truncated connection IDs should be dropped.
1335TEST_F(QuicDispatcherTestStrayPacketConnectionId,
1336 StrayPacketTruncatedConnectionId) {
1337 CreateTimeWaitListManager();
1338
1339 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1340 QuicConnectionId connection_id = TestConnectionId(1);
1341 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
1342 .Times(0);
fayangd4291e42019-05-30 10:31:21 -07001343 if (VersionHasIetfInvariantHeader(
QUICHE team963d57e2019-03-21 10:58:47 -07001344 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001345 // This IETF packet has invalid connection ID length.
1346 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1347 .Times(0);
1348 EXPECT_CALL(*time_wait_list_manager_,
1349 AddConnectionIdToTimeWait(_, _, _, _, _))
1350 .Times(0);
1351 } else {
dschinaziee07e472019-06-19 09:56:56 -07001352 // This is a GQUIC packet considered as IETF QUIC packet with short header
1353 // with unacceptable packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001354 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1355 .Times(1);
1356 EXPECT_CALL(*time_wait_list_manager_,
1357 AddConnectionIdToTimeWait(_, _, _, _, _))
1358 .Times(1);
1359 }
1360 ProcessPacket(client_address, connection_id, true, "data",
1361 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
1362}
1363
1364class BlockingWriter : public QuicPacketWriterWrapper {
1365 public:
1366 BlockingWriter() : write_blocked_(false) {}
1367
1368 bool IsWriteBlocked() const override { return write_blocked_; }
1369 void SetWritable() override { write_blocked_ = false; }
1370
dschinazi17d42422019-06-18 16:35:07 -07001371 WriteResult WritePacket(const char* /*buffer*/,
1372 size_t /*buf_len*/,
1373 const QuicIpAddress& /*self_client_address*/,
1374 const QuicSocketAddress& /*peer_client_address*/,
1375 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001376 // It would be quite possible to actually implement this method here with
1377 // the fake blocked status, but it would be significantly more work in
1378 // Chromium, and since it's not called anyway, don't bother.
1379 QUIC_LOG(DFATAL) << "Not supported";
1380 return WriteResult();
1381 }
1382
1383 bool write_blocked_;
1384};
1385
1386class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
1387 public:
1388 void SetUp() override {
1389 QuicDispatcherTest::SetUp();
1390 writer_ = new BlockingWriter;
1391 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
1392
1393 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1394
1395 EXPECT_CALL(*dispatcher_,
1396 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1397 .WillOnce(testing::Return(CreateSession(
1398 dispatcher_.get(), config_, TestConnectionId(1), client_address,
1399 &helper_, &alarm_factory_, &crypto_config_,
1400 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1401 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1402 ProcessUdpPacket(_, _, _))
1403 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1404 ValidatePacket(TestConnectionId(1), packet);
1405 })));
fayang1ed1f762019-06-24 11:40:04 -07001406 EXPECT_CALL(*dispatcher_,
1407 ShouldCreateOrBufferPacketForConnection(
1408 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001409 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
1410
1411 EXPECT_CALL(*dispatcher_,
1412 CreateQuicSession(_, client_address, QuicStringPiece("hq"), _))
1413 .WillOnce(testing::Return(CreateSession(
1414 dispatcher_.get(), config_, TestConnectionId(2), client_address,
1415 &helper_, &alarm_factory_, &crypto_config_,
1416 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
1417 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
1418 ProcessUdpPacket(_, _, _))
1419 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1420 ValidatePacket(TestConnectionId(2), packet);
1421 })));
fayang1ed1f762019-06-24 11:40:04 -07001422 EXPECT_CALL(*dispatcher_,
1423 ShouldCreateOrBufferPacketForConnection(
1424 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001425 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
1426
1427 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
1428 }
1429
1430 void TearDown() override {
1431 if (connection1() != nullptr) {
1432 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1433 }
1434
1435 if (connection2() != nullptr) {
1436 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1437 }
1438 dispatcher_->Shutdown();
1439 }
1440
1441 // Set the dispatcher's writer to be blocked. By default, all connections use
1442 // the same writer as the dispatcher in this test.
1443 void SetBlocked() {
1444 QUIC_LOG(INFO) << "set writer " << writer_ << " to blocked";
1445 writer_->write_blocked_ = true;
1446 }
1447
1448 // Simulate what happens when connection1 gets blocked when writing.
1449 void BlockConnection1() {
1450 Connection1Writer()->write_blocked_ = true;
1451 dispatcher_->OnWriteBlocked(connection1());
1452 }
1453
1454 BlockingWriter* Connection1Writer() {
1455 return static_cast<BlockingWriter*>(connection1()->writer());
1456 }
1457
1458 // Simulate what happens when connection2 gets blocked when writing.
1459 void BlockConnection2() {
1460 Connection2Writer()->write_blocked_ = true;
1461 dispatcher_->OnWriteBlocked(connection2());
1462 }
1463
1464 BlockingWriter* Connection2Writer() {
1465 return static_cast<BlockingWriter*>(connection2()->writer());
1466 }
1467
1468 protected:
1469 MockQuicConnectionHelper helper_;
1470 MockAlarmFactory alarm_factory_;
1471 BlockingWriter* writer_;
1472 QuicDispatcher::WriteBlockedList* blocked_list_;
1473};
1474
1475TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
1476 // No OnCanWrite calls because no connections are blocked.
1477 dispatcher_->OnCanWrite();
1478
1479 // Register connection 1 for events, and make sure it's notified.
1480 SetBlocked();
1481 dispatcher_->OnWriteBlocked(connection1());
1482 EXPECT_CALL(*connection1(), OnCanWrite());
1483 dispatcher_->OnCanWrite();
1484
1485 // It should get only one notification.
1486 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1487 dispatcher_->OnCanWrite();
1488 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1489}
1490
1491TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
1492 // Make sure we handle events in order.
1493 InSequence s;
1494 SetBlocked();
1495 dispatcher_->OnWriteBlocked(connection1());
1496 dispatcher_->OnWriteBlocked(connection2());
1497 EXPECT_CALL(*connection1(), OnCanWrite());
1498 EXPECT_CALL(*connection2(), OnCanWrite());
1499 dispatcher_->OnCanWrite();
1500
1501 // Check the other ordering.
1502 SetBlocked();
1503 dispatcher_->OnWriteBlocked(connection2());
1504 dispatcher_->OnWriteBlocked(connection1());
1505 EXPECT_CALL(*connection2(), OnCanWrite());
1506 EXPECT_CALL(*connection1(), OnCanWrite());
1507 dispatcher_->OnCanWrite();
1508}
1509
1510TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
1511 // Add and remove one connction.
1512 SetBlocked();
1513 dispatcher_->OnWriteBlocked(connection1());
1514 blocked_list_->erase(connection1());
1515 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1516 dispatcher_->OnCanWrite();
1517
1518 // Add and remove one connction and make sure it doesn't affect others.
1519 SetBlocked();
1520 dispatcher_->OnWriteBlocked(connection1());
1521 dispatcher_->OnWriteBlocked(connection2());
1522 blocked_list_->erase(connection1());
1523 EXPECT_CALL(*connection2(), OnCanWrite());
1524 dispatcher_->OnCanWrite();
1525
1526 // Add it, remove it, and add it back and make sure things are OK.
1527 SetBlocked();
1528 dispatcher_->OnWriteBlocked(connection1());
1529 blocked_list_->erase(connection1());
1530 dispatcher_->OnWriteBlocked(connection1());
1531 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1532 dispatcher_->OnCanWrite();
1533}
1534
1535TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
1536 // Make sure a double add does not necessitate a double remove.
1537 SetBlocked();
1538 dispatcher_->OnWriteBlocked(connection1());
1539 dispatcher_->OnWriteBlocked(connection1());
1540 blocked_list_->erase(connection1());
1541 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1542 dispatcher_->OnCanWrite();
1543
1544 // Make sure a double add does not result in two OnCanWrite calls.
1545 SetBlocked();
1546 dispatcher_->OnWriteBlocked(connection1());
1547 dispatcher_->OnWriteBlocked(connection1());
1548 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1549 dispatcher_->OnCanWrite();
1550}
1551
1552TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
1553 // If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
1554 // into the write blocked list.
1555 InSequence s;
1556 SetBlocked();
1557 dispatcher_->OnWriteBlocked(connection1());
1558 dispatcher_->OnWriteBlocked(connection2());
1559 EXPECT_CALL(*connection1(), OnCanWrite())
1560 .WillOnce(
1561 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1562 EXPECT_CALL(*connection2(), OnCanWrite());
1563 dispatcher_->OnCanWrite();
1564
1565 // connection1 should be still in the write blocked list.
1566 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1567
1568 // Now call OnCanWrite again, connection1 should get its second chance.
1569 EXPECT_CALL(*connection1(), OnCanWrite());
1570 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
1571 dispatcher_->OnCanWrite();
1572 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1573}
1574
1575TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
1576 // If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
1577 // into the write blocked list.
1578 InSequence s;
1579 SetBlocked();
1580 dispatcher_->OnWriteBlocked(connection1());
1581 dispatcher_->OnWriteBlocked(connection2());
1582 EXPECT_CALL(*connection1(), OnCanWrite());
1583 EXPECT_CALL(*connection2(), OnCanWrite())
1584 .WillOnce(
1585 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1586 dispatcher_->OnCanWrite();
1587
1588 // connection2 should be still in the write blocked list.
1589 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1590
1591 // Now call OnCanWrite again, connection2 should get its second chance.
1592 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1593 EXPECT_CALL(*connection2(), OnCanWrite());
1594 dispatcher_->OnCanWrite();
1595 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1596}
1597
1598TEST_F(QuicDispatcherWriteBlockedListTest,
1599 OnCanWriteHandleBlockBothConnections) {
1600 // Both connections get blocked in OnCanWrite, and added back into the write
1601 // blocked list.
1602 InSequence s;
1603 SetBlocked();
1604 dispatcher_->OnWriteBlocked(connection1());
1605 dispatcher_->OnWriteBlocked(connection2());
1606 EXPECT_CALL(*connection1(), OnCanWrite())
1607 .WillOnce(
1608 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1609 EXPECT_CALL(*connection2(), OnCanWrite())
1610 .WillOnce(
1611 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1612 dispatcher_->OnCanWrite();
1613
1614 // Both connections should be still in the write blocked list.
1615 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1616
1617 // Now call OnCanWrite again, both connections should get its second chance.
1618 EXPECT_CALL(*connection1(), OnCanWrite());
1619 EXPECT_CALL(*connection2(), OnCanWrite());
1620 dispatcher_->OnCanWrite();
1621 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1622}
1623
1624TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
1625 // By default, all connections share the same packet writer with the
1626 // dispatcher.
1627 EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
1628 EXPECT_EQ(dispatcher_->writer(), connection2()->writer());
1629
1630 // Test the case where connection1 shares the same packet writer as the
1631 // dispatcher, whereas connection2 owns it's packet writer.
1632 // Change connection2's writer.
1633 connection2()->SetQuicPacketWriter(new BlockingWriter, /*owns_writer=*/true);
1634 EXPECT_NE(dispatcher_->writer(), connection2()->writer());
1635
1636 BlockConnection2();
1637 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1638
1639 EXPECT_CALL(*connection2(), OnCanWrite());
1640 dispatcher_->OnCanWrite();
1641 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1642}
1643
1644TEST_F(QuicDispatcherWriteBlockedListTest,
1645 RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001646 dispatcher_->OnConnectionClosed(connection1()->connection_id(),
1647 QUIC_PACKET_WRITE_ERROR, "Closed by test.",
1648 ConnectionCloseSource::FROM_SELF);
1649
1650 SetBlocked();
1651
1652 ASSERT_FALSE(dispatcher_->HasPendingWrites());
1653 SetBlocked();
1654 dispatcher_->OnWriteBlocked(connection1());
1655 ASSERT_TRUE(dispatcher_->HasPendingWrites());
1656
1657 EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(),
1658 "QuicConnection was in WriteBlockedList before destruction");
1659 MarkSession1Deleted();
1660}
1661
wub0a4b9c52019-05-28 13:18:58 -07001662class BufferedPacketStoreTest : public QuicDispatcherTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001663 public:
1664 BufferedPacketStoreTest()
1665 : QuicDispatcherTest(),
1666 server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
1667 client_addr_(QuicIpAddress::Loopback4(), 1234),
wub0a4b9c52019-05-28 13:18:58 -07001668 signed_config_(new QuicSignedServerConfig) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001669
1670 void SetUp() override {
1671 QuicDispatcherTest::SetUp();
1672 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
1673
1674 QuicTransportVersion version = AllSupportedTransportVersions().front();
1675 CryptoHandshakeMessage chlo =
1676 crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
1677 &crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001678 // Pass an inchoate CHLO.
1679 crypto_test_utils::GenerateFullCHLO(
1680 chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
1681 signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1682 &full_chlo_);
1683 }
1684
vasilvvc48c8712019-03-11 13:38:16 -07001685 std::string SerializeFullCHLO() {
1686 return std::string(full_chlo_.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001687 }
1688
1689 protected:
1690 QuicSocketAddress server_addr_;
1691 QuicSocketAddress client_addr_;
1692 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1693 const QuicClock* clock_;
1694 CryptoHandshakeMessage full_chlo_;
1695};
1696
wub0a4b9c52019-05-28 13:18:58 -07001697TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001698 InSequence s;
1699 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1700 QuicConnectionId conn_id = TestConnectionId(1);
1701 // A bunch of non-CHLO should be buffered upon arrival, and the first one
1702 // should trigger ShouldCreateOrBufferPacketForConnection().
fayang1ed1f762019-06-24 11:40:04 -07001703 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1704 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001705 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
1706 ProcessPacket(client_address, conn_id, true,
1707 QuicStrCat("data packet ", i + 1), CONNECTION_ID_PRESENT,
1708 PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1);
1709 }
1710 EXPECT_EQ(0u, dispatcher_->session_map().size())
1711 << "No session should be created before CHLO arrives.";
1712
1713 // Pop out the last packet as it is also be dropped by the store.
1714 data_connection_map_[conn_id].pop_back();
1715 // When CHLO arrives, a new session should be created, and all packets
1716 // buffered should be delivered to the session.
1717 EXPECT_CALL(*dispatcher_,
1718 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1719 .WillOnce(testing::Return(CreateSession(
1720 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1721 &mock_alarm_factory_, &crypto_config_,
1722 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1723
1724 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
1725 // should be delivered in arrival order.
1726 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1727 ProcessUdpPacket(_, _, _))
1728 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
1729 .WillRepeatedly(
1730 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1731 ValidatePacket(conn_id, packet);
1732 })));
1733 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1734}
1735
wub0a4b9c52019-05-28 13:18:58 -07001736TEST_F(BufferedPacketStoreTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001737 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
1738 InSequence s;
1739 // A bunch of non-CHLO should be buffered upon arrival.
1740 size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
1741 for (size_t i = 1; i <= kNumConnections; ++i) {
1742 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1743 QuicConnectionId conn_id = TestConnectionId(i);
1744 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001745 ShouldCreateOrBufferPacketForConnection(
1746 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001747 ProcessPacket(client_address, conn_id, true,
1748 QuicStrCat("data packet on connection ", i),
1749 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1750 /*packet_number=*/2);
1751 }
1752
1753 // Pop out the packet on last connection as it shouldn't be enqueued in store
1754 // as well.
1755 data_connection_map_[TestConnectionId(kNumConnections)].pop_front();
1756
1757 // Reset session creation counter to ensure processing CHLO can always
1758 // create session.
1759 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
1760 kNumConnections);
1761 // Process CHLOs to create session for these connections.
1762 for (size_t i = 1; i <= kNumConnections; ++i) {
1763 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1764 QuicConnectionId conn_id = TestConnectionId(i);
1765 if (i == kNumConnections) {
1766 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001767 ShouldCreateOrBufferPacketForConnection(
1768 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001769 }
1770 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1771 QuicStringPiece(), _))
1772 .WillOnce(testing::Return(CreateSession(
1773 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1774 &mock_alarm_factory_, &crypto_config_,
1775 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1776 // First |kNumConnections| - 1 connections should have buffered
1777 // a packet in store. The rest should have been dropped.
1778 size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
1779 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1780 ProcessUdpPacket(_, client_address, _))
1781 .Times(num_packet_to_process)
1782 .WillRepeatedly(WithArg<2>(
1783 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1784 ValidatePacket(conn_id, packet);
1785 })));
1786
1787 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1788 }
1789}
1790
1791// Tests that store delivers empty packet list if CHLO arrives firstly.
wub0a4b9c52019-05-28 13:18:58 -07001792TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001793 QuicConnectionId conn_id = TestConnectionId(1);
1794 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
fayang1ed1f762019-06-24 11:40:04 -07001795 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1796 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001797 EXPECT_CALL(*dispatcher_,
1798 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1799 .WillOnce(testing::Return(CreateSession(
1800 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1801 &mock_alarm_factory_, &crypto_config_,
1802 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1803 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1804 ProcessUdpPacket(_, client_address, _));
1805 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1806}
1807
1808// Tests that a retransmitted CHLO arrives after a connection for the
1809// CHLO has been created.
wub0a4b9c52019-05-28 13:18:58 -07001810TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001811 InSequence s;
1812 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1813 QuicConnectionId conn_id = TestConnectionId(1);
1814 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1815 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1816 /*packet_number=*/2);
1817
1818 // When CHLO arrives, a new session should be created, and all packets
1819 // buffered should be delivered to the session.
1820 EXPECT_CALL(*dispatcher_,
1821 CreateQuicSession(conn_id, client_address, QuicStringPiece(), _))
1822 .Times(1) // Only triggered by 1st CHLO.
1823 .WillOnce(testing::Return(CreateSession(
1824 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1825 &mock_alarm_factory_, &crypto_config_,
1826 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1827 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1828 ProcessUdpPacket(_, _, _))
1829 .Times(3) // Triggered by 1 data packet and 2 CHLOs.
1830 .WillRepeatedly(
1831 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1832 ValidatePacket(conn_id, packet);
1833 })));
1834 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1835
1836 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1837}
1838
1839// Tests that expiration of a connection add connection id to time wait list.
wub0a4b9c52019-05-28 13:18:58 -07001840TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001841 InSequence s;
1842 CreateTimeWaitListManager();
1843 QuicBufferedPacketStore* store =
1844 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1845 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
1846
1847 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1848 QuicConnectionId conn_id = TestConnectionId(1);
1849 ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
1850 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1851 /*packet_number=*/2);
1852
1853 mock_helper_.AdvanceTime(
1854 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
1855 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
1856 // Cancel alarm as if it had been fired.
1857 alarm->Cancel();
1858 store->OnExpirationTimeout();
1859 // New arrived CHLO will be dropped because this connection is in time wait
1860 // list.
1861 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
1862 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
1863 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1864}
1865
wub0a4b9c52019-05-28 13:18:58 -07001866TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001867 // Process more than (|kMaxNumSessionsToCreate| +
1868 // |kDefaultMaxConnectionsInStore|) CHLOs,
1869 // the first |kMaxNumSessionsToCreate| should create connections immediately,
1870 // the next |kDefaultMaxConnectionsInStore| should be buffered,
1871 // the rest should be dropped.
1872 QuicBufferedPacketStore* store =
1873 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1874 const size_t kNumCHLOs =
1875 kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
1876 for (uint64_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
fayang1ed1f762019-06-24 11:40:04 -07001877 EXPECT_CALL(
1878 *dispatcher_,
1879 ShouldCreateOrBufferPacketForConnection(
1880 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(conn_id))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001881 if (conn_id <= kMaxNumSessionsToCreate) {
1882 EXPECT_CALL(*dispatcher_,
1883 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1884 QuicStringPiece(), _))
1885 .WillOnce(testing::Return(CreateSession(
1886 dispatcher_.get(), config_, TestConnectionId(conn_id),
1887 client_addr_, &mock_helper_, &mock_alarm_factory_,
1888 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1889 &session1_)));
1890 EXPECT_CALL(
1891 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1892 ProcessUdpPacket(_, _, _))
1893 .WillOnce(WithArg<2>(
1894 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1895 ValidatePacket(TestConnectionId(conn_id), packet);
1896 })));
1897 }
1898 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1899 SerializeFullCHLO());
1900 if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
1901 conn_id > kMaxNumSessionsToCreate) {
1902 EXPECT_TRUE(store->HasChloForConnection(TestConnectionId(conn_id)));
1903 } else {
1904 // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
1905 // connections immediately, and the last CHLO should be dropped as the
1906 // store is full.
1907 EXPECT_FALSE(store->HasChloForConnection(TestConnectionId(conn_id)));
1908 }
1909 }
1910
1911 // Graduately consume buffered CHLOs. The buffered connections should be
1912 // created but the dropped one shouldn't.
1913 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1914 conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
1915 ++conn_id) {
1916 EXPECT_CALL(*dispatcher_,
1917 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1918 QuicStringPiece(), _))
1919 .WillOnce(testing::Return(CreateSession(
1920 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1921 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1922 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1923 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1924 ProcessUdpPacket(_, _, _))
1925 .WillOnce(WithArg<2>(
1926 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1927 ValidatePacket(TestConnectionId(conn_id), packet);
1928 })));
1929 }
1930 EXPECT_CALL(*dispatcher_,
1931 CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
1932 QuicStringPiece(), _))
1933 .Times(0);
1934
1935 while (store->HasChlosBuffered()) {
1936 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1937 }
1938
1939 EXPECT_EQ(TestConnectionId(static_cast<size_t>(kMaxNumSessionsToCreate) +
1940 kDefaultMaxConnectionsInStore),
1941 session1_->connection_id());
1942}
1943
1944// Duplicated CHLO shouldn't be buffered.
wub0a4b9c52019-05-28 13:18:58 -07001945TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001946 for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
1947 ++conn_id) {
1948 // Last CHLO will be buffered. Others will create connection right away.
1949 if (conn_id <= kMaxNumSessionsToCreate) {
1950 EXPECT_CALL(*dispatcher_,
1951 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
1952 QuicStringPiece(), _))
1953 .WillOnce(testing::Return(CreateSession(
1954 dispatcher_.get(), config_, TestConnectionId(conn_id),
1955 client_addr_, &mock_helper_, &mock_alarm_factory_,
1956 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1957 &session1_)));
1958 EXPECT_CALL(
1959 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1960 ProcessUdpPacket(_, _, _))
1961 .WillOnce(WithArg<2>(
1962 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1963 ValidatePacket(TestConnectionId(conn_id), packet);
1964 })));
1965 }
1966 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1967 SerializeFullCHLO());
1968 }
1969 // Retransmit CHLO on last connection should be dropped.
1970 QuicConnectionId last_connection =
1971 TestConnectionId(kMaxNumSessionsToCreate + 1);
1972 ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
1973
1974 size_t packets_buffered = 2;
1975
1976 // Reset counter and process buffered CHLO.
1977 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
1978 QuicStringPiece(), _))
1979 .WillOnce(testing::Return(CreateSession(
1980 dispatcher_.get(), config_, last_connection, client_addr_,
1981 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
1982 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
1983 // Only one packet(CHLO) should be process.
1984 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1985 ProcessUdpPacket(_, _, _))
1986 .Times(packets_buffered)
1987 .WillRepeatedly(WithArg<2>(
1988 Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
1989 ValidatePacket(last_connection, packet);
1990 })));
1991 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1992}
1993
wub0a4b9c52019-05-28 13:18:58 -07001994TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001995 uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
1996 QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
1997 for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
1998 // Last CHLO will be buffered. Others will create connection right away.
1999 if (conn_id <= kMaxNumSessionsToCreate) {
2000 EXPECT_CALL(*dispatcher_,
2001 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2002 QuicStringPiece(), _))
2003 .WillOnce(testing::Return(CreateSession(
2004 dispatcher_.get(), config_, TestConnectionId(conn_id),
2005 client_addr_, &mock_helper_, &mock_alarm_factory_,
2006 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2007 &session1_)));
2008 EXPECT_CALL(
2009 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2010 ProcessUdpPacket(_, _, _))
2011 .WillRepeatedly(WithArg<2>(
2012 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2013 ValidatePacket(TestConnectionId(conn_id), packet);
2014 })));
2015 }
2016 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2017 SerializeFullCHLO());
2018 }
2019
2020 // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
2021 // last one should be dropped.
2022 for (uint64_t packet_number = 2;
2023 packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
2024 ProcessPacket(client_addr_, last_connection_id, true, "data packet");
2025 }
2026
2027 // Reset counter and process buffered CHLO.
2028 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
2029 QuicStringPiece(), _))
2030 .WillOnce(testing::Return(CreateSession(
2031 dispatcher_.get(), config_, last_connection_id, client_addr_,
2032 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2033 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2034 // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
2035 // should be process.
2036 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2037 ProcessUdpPacket(_, _, _))
2038 .Times(kDefaultMaxUndecryptablePackets + 1)
2039 .WillRepeatedly(WithArg<2>(
2040 Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
2041 ValidatePacket(last_connection_id, packet);
2042 })));
2043 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2044}
2045
2046// Tests that when dispatcher's packet buffer is full, a CHLO on connection
2047// which doesn't have buffered CHLO should be buffered.
wub0a4b9c52019-05-28 13:18:58 -07002048TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002049 QuicBufferedPacketStore* store =
2050 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
2051
2052 uint64_t conn_id = 1;
2053 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, "data packet",
2054 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
2055 /*packet_number=*/1);
2056 // Fill packet buffer to full with CHLOs on other connections. Need to feed
2057 // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
2058 // session directly.
2059 for (conn_id = 2;
2060 conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
2061 ++conn_id) {
2062 if (conn_id <= kMaxNumSessionsToCreate + 1) {
2063 EXPECT_CALL(*dispatcher_,
2064 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2065 QuicStringPiece(), _))
2066 .WillOnce(testing::Return(CreateSession(
2067 dispatcher_.get(), config_, TestConnectionId(conn_id),
2068 client_addr_, &mock_helper_, &mock_alarm_factory_,
2069 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2070 &session1_)));
2071 EXPECT_CALL(
2072 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2073 ProcessUdpPacket(_, _, _))
2074 .WillOnce(WithArg<2>(
2075 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2076 ValidatePacket(TestConnectionId(conn_id), packet);
2077 })));
2078 }
2079 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2080 SerializeFullCHLO());
2081 }
2082 EXPECT_FALSE(store->HasChloForConnection(
2083 /*connection_id=*/TestConnectionId(1)));
2084
2085 // CHLO on connection 1 should still be buffered.
2086 ProcessPacket(client_addr_, /*connection_id=*/TestConnectionId(1), true,
2087 SerializeFullCHLO());
2088 EXPECT_TRUE(store->HasChloForConnection(
2089 /*connection_id=*/TestConnectionId(1)));
2090}
2091
2092// Regression test for b/117874922.
wub0a4b9c52019-05-28 13:18:58 -07002093TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002094 // Turn off version 99, such that the preferred version is not supported by
2095 // the server.
2096 SetQuicReloadableFlag(quic_enable_version_99, false);
2097 uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
2098 ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
2099 for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
2100 // Last 5 CHLOs will be buffered. Others will create connection right away.
2101 ParsedQuicVersion version =
2102 supported_versions[(conn_id - 1) % supported_versions.size()];
2103 if (conn_id <= kMaxNumSessionsToCreate) {
2104 EXPECT_CALL(*dispatcher_,
2105 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2106 QuicStringPiece(), version))
2107 .WillOnce(testing::Return(CreateSession(
2108 dispatcher_.get(), config_, TestConnectionId(conn_id),
2109 client_addr_, &mock_helper_, &mock_alarm_factory_,
2110 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
2111 &session1_)));
2112 EXPECT_CALL(
2113 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2114 ProcessUdpPacket(_, _, _))
2115 .WillRepeatedly(WithArg<2>(
2116 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2117 ValidatePacket(TestConnectionId(conn_id), packet);
2118 })));
2119 }
2120 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version,
2121 SerializeFullCHLO(), CONNECTION_ID_PRESENT,
2122 PACKET_4BYTE_PACKET_NUMBER, 1);
2123 }
2124
2125 // Process buffered CHLOs. Verify the version is correct.
2126 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
2127 conn_id <= last_connection_id; ++conn_id) {
2128 ParsedQuicVersion version =
2129 supported_versions[(conn_id - 1) % supported_versions.size()];
2130 EXPECT_CALL(*dispatcher_,
2131 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
2132 QuicStringPiece(), version))
2133 .WillOnce(testing::Return(CreateSession(
2134 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
2135 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
2136 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
2137 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2138 ProcessUdpPacket(_, _, _))
2139 .WillRepeatedly(WithArg<2>(
2140 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2141 ValidatePacket(TestConnectionId(conn_id), packet);
2142 })));
2143 }
2144 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2145}
2146
QUICHE teama6ef0a62019-03-07 20:34:33 -05002147} // namespace
2148} // namespace test
2149} // namespace quic