1 // Copyright 2013 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 "quiche/quic/core/quic_time_wait_list_manager.h"
6
7 #include <cerrno>
8 #include <memory>
9 #include <ostream>
10 #include <utility>
11
12 #include "quiche/quic/core/crypto/crypto_protocol.h"
13 #include "quiche/quic/core/crypto/null_encrypter.h"
14 #include "quiche/quic/core/crypto/quic_decrypter.h"
15 #include "quiche/quic/core/crypto/quic_encrypter.h"
16 #include "quiche/quic/core/quic_connection_id.h"
17 #include "quiche/quic/core/quic_data_reader.h"
18 #include "quiche/quic/core/quic_framer.h"
19 #include "quiche/quic/core/quic_packet_writer.h"
20 #include "quiche/quic/core/quic_packets.h"
21 #include "quiche/quic/core/quic_utils.h"
22 #include "quiche/quic/platform/api/quic_expect_bug.h"
23 #include "quiche/quic/platform/api/quic_flags.h"
24 #include "quiche/quic/platform/api/quic_test.h"
25 #include "quiche/quic/test_tools/mock_quic_session_visitor.h"
26 #include "quiche/quic/test_tools/quic_test_utils.h"
27 #include "quiche/quic/test_tools/quic_time_wait_list_manager_peer.h"
28
29 using testing::_;
30 using testing::Args;
31 using testing::Assign;
32 using testing::DoAll;
33 using testing::Matcher;
34 using testing::NiceMock;
35 using testing::Return;
36 using testing::ReturnPointee;
37 using testing::StrictMock;
38 using testing::Truly;
39
40 namespace quic {
41 namespace test {
42 namespace {
43
44 const size_t kTestPacketSize = 100;
45
46 class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor {
47 public:
FramerVisitorCapturingPublicReset(QuicConnectionId connection_id)48 FramerVisitorCapturingPublicReset(QuicConnectionId connection_id)
49 : connection_id_(connection_id) {}
50 ~FramerVisitorCapturingPublicReset() override = default;
51
OnPublicResetPacket(const QuicPublicResetPacket & public_reset)52 void OnPublicResetPacket(const QuicPublicResetPacket& public_reset) override {
53 public_reset_packet_ = public_reset;
54 }
55
public_reset_packet()56 const QuicPublicResetPacket public_reset_packet() {
57 return public_reset_packet_;
58 }
59
IsValidStatelessResetToken(const StatelessResetToken & token) const60 bool IsValidStatelessResetToken(
61 const StatelessResetToken& token) const override {
62 return token == QuicUtils::GenerateStatelessResetToken(connection_id_);
63 }
64
OnAuthenticatedIetfStatelessResetPacket(const QuicIetfStatelessResetPacket & packet)65 void OnAuthenticatedIetfStatelessResetPacket(
66 const QuicIetfStatelessResetPacket& packet) override {
67 stateless_reset_packet_ = packet;
68 }
69
stateless_reset_packet()70 const QuicIetfStatelessResetPacket stateless_reset_packet() {
71 return stateless_reset_packet_;
72 }
73
74 private:
75 QuicPublicResetPacket public_reset_packet_;
76 QuicIetfStatelessResetPacket stateless_reset_packet_;
77 QuicConnectionId connection_id_;
78 };
79
80 class MockAlarmFactory;
81 class MockAlarm : public QuicAlarm {
82 public:
MockAlarm(QuicArenaScopedPtr<Delegate> delegate,int alarm_index,MockAlarmFactory * factory)83 explicit MockAlarm(QuicArenaScopedPtr<Delegate> delegate, int alarm_index,
84 MockAlarmFactory* factory)
85 : QuicAlarm(std::move(delegate)),
86 alarm_index_(alarm_index),
87 factory_(factory) {}
~MockAlarm()88 virtual ~MockAlarm() {}
89
90 void SetImpl() override;
91 void CancelImpl() override;
92
93 private:
94 int alarm_index_;
95 MockAlarmFactory* factory_;
96 };
97
98 class MockAlarmFactory : public QuicAlarmFactory {
99 public:
~MockAlarmFactory()100 ~MockAlarmFactory() override {}
101
102 // Creates a new platform-specific alarm which will be configured to notify
103 // |delegate| when the alarm fires. Returns an alarm allocated on the heap.
104 // Caller takes ownership of the new alarm, which will not yet be "set" to
105 // fire.
CreateAlarm(QuicAlarm::Delegate * delegate)106 QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
107 return new MockAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate),
108 alarm_index_++, this);
109 }
CreateAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,QuicConnectionArena * arena)110 QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
111 QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
112 QuicConnectionArena* arena) override {
113 if (arena != nullptr) {
114 return arena->New<MockAlarm>(std::move(delegate), alarm_index_++, this);
115 }
116 return QuicArenaScopedPtr<MockAlarm>(
117 new MockAlarm(std::move(delegate), alarm_index_++, this));
118 }
119 MOCK_METHOD(void, OnAlarmSet, (int, QuicTime), ());
120 MOCK_METHOD(void, OnAlarmCancelled, (int), ());
121
122 private:
123 int alarm_index_ = 0;
124 };
125
SetImpl()126 void MockAlarm::SetImpl() { factory_->OnAlarmSet(alarm_index_, deadline()); }
127
CancelImpl()128 void MockAlarm::CancelImpl() { factory_->OnAlarmCancelled(alarm_index_); }
129
130 class QuicTimeWaitListManagerTest : public QuicTest {
131 protected:
QuicTimeWaitListManagerTest()132 QuicTimeWaitListManagerTest()
133 : time_wait_list_manager_(&writer_, &visitor_, &clock_, &alarm_factory_),
134 connection_id_(TestConnectionId(45)),
135 peer_address_(TestPeerIPAddress(), kTestPort),
136 writer_is_blocked_(false) {}
137
138 ~QuicTimeWaitListManagerTest() override = default;
139
SetUp()140 void SetUp() override {
141 EXPECT_CALL(writer_, IsWriteBlocked())
142 .WillRepeatedly(ReturnPointee(&writer_is_blocked_));
143 }
144
AddConnectionId(QuicConnectionId connection_id,QuicTimeWaitListManager::TimeWaitAction action)145 void AddConnectionId(QuicConnectionId connection_id,
146 QuicTimeWaitListManager::TimeWaitAction action) {
147 AddConnectionId(connection_id, QuicVersionMax(), action, nullptr);
148 }
149
AddStatelessConnectionId(QuicConnectionId connection_id)150 void AddStatelessConnectionId(QuicConnectionId connection_id) {
151 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
152 termination_packets.push_back(std::unique_ptr<QuicEncryptedPacket>(
153 new QuicEncryptedPacket(nullptr, 0, false)));
154 time_wait_list_manager_.AddConnectionIdToTimeWait(
155 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
156 TimeWaitConnectionInfo(false, &termination_packets, {connection_id}));
157 }
158
AddConnectionId(QuicConnectionId connection_id,ParsedQuicVersion version,QuicTimeWaitListManager::TimeWaitAction action,std::vector<std::unique_ptr<QuicEncryptedPacket>> * packets)159 void AddConnectionId(
160 QuicConnectionId connection_id, ParsedQuicVersion version,
161 QuicTimeWaitListManager::TimeWaitAction action,
162 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets) {
163 time_wait_list_manager_.AddConnectionIdToTimeWait(
164 action, TimeWaitConnectionInfo(version.HasIetfInvariantHeader(),
165 packets, {connection_id}));
166 }
167
IsConnectionIdInTimeWait(QuicConnectionId connection_id)168 bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) {
169 return time_wait_list_manager_.IsConnectionIdInTimeWait(connection_id);
170 }
171
ProcessPacket(QuicConnectionId connection_id)172 void ProcessPacket(QuicConnectionId connection_id) {
173 time_wait_list_manager_.ProcessPacket(
174 self_address_, peer_address_, connection_id, GOOGLE_QUIC_PACKET,
175 kTestPacketSize, std::make_unique<QuicPerPacketContext>());
176 }
177
ConstructEncryptedPacket(QuicConnectionId destination_connection_id,QuicConnectionId source_connection_id,uint64_t packet_number)178 QuicEncryptedPacket* ConstructEncryptedPacket(
179 QuicConnectionId destination_connection_id,
180 QuicConnectionId source_connection_id, uint64_t packet_number) {
181 return quic::test::ConstructEncryptedPacket(destination_connection_id,
182 source_connection_id, false,
183 false, packet_number, "data");
184 }
185
186 MockClock clock_;
187 MockAlarmFactory alarm_factory_;
188 NiceMock<MockPacketWriter> writer_;
189 StrictMock<MockQuicSessionVisitor> visitor_;
190 QuicTimeWaitListManager time_wait_list_manager_;
191 QuicConnectionId connection_id_;
192 QuicSocketAddress self_address_;
193 QuicSocketAddress peer_address_;
194 bool writer_is_blocked_;
195 };
196
ValidPublicResetPacketPredicate(QuicConnectionId expected_connection_id,const std::tuple<const char *,int> & packet_buffer)197 bool ValidPublicResetPacketPredicate(
198 QuicConnectionId expected_connection_id,
199 const std::tuple<const char*, int>& packet_buffer) {
200 FramerVisitorCapturingPublicReset visitor(expected_connection_id);
201 QuicFramer framer(AllSupportedVersions(), QuicTime::Zero(),
202 Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
203 framer.set_visitor(&visitor);
204 QuicEncryptedPacket encrypted(std::get<0>(packet_buffer),
205 std::get<1>(packet_buffer));
206 framer.ProcessPacket(encrypted);
207 QuicPublicResetPacket packet = visitor.public_reset_packet();
208 bool public_reset_is_valid =
209 expected_connection_id == packet.connection_id &&
210 TestPeerIPAddress() == packet.client_address.host() &&
211 kTestPort == packet.client_address.port();
212
213 QuicIetfStatelessResetPacket stateless_reset =
214 visitor.stateless_reset_packet();
215
216 StatelessResetToken expected_stateless_reset_token =
217 QuicUtils::GenerateStatelessResetToken(expected_connection_id);
218
219 bool stateless_reset_is_valid =
220 stateless_reset.stateless_reset_token == expected_stateless_reset_token;
221
222 return public_reset_is_valid || stateless_reset_is_valid;
223 }
224
PublicResetPacketEq(QuicConnectionId connection_id)225 Matcher<const std::tuple<const char*, int>> PublicResetPacketEq(
226 QuicConnectionId connection_id) {
227 return Truly(
228 [connection_id](const std::tuple<const char*, int> packet_buffer) {
229 return ValidPublicResetPacketPredicate(connection_id, packet_buffer);
230 });
231 }
232
TEST_F(QuicTimeWaitListManagerTest,CheckConnectionIdInTimeWait)233 TEST_F(QuicTimeWaitListManagerTest, CheckConnectionIdInTimeWait) {
234 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_));
235 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
236 AddConnectionId(connection_id_, QuicTimeWaitListManager::DO_NOTHING);
237 EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
238 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
239 }
240
TEST_F(QuicTimeWaitListManagerTest,CheckStatelessConnectionIdInTimeWait)241 TEST_F(QuicTimeWaitListManagerTest, CheckStatelessConnectionIdInTimeWait) {
242 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_));
243 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
244 AddStatelessConnectionId(connection_id_);
245 EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
246 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
247 }
248
TEST_F(QuicTimeWaitListManagerTest,SendVersionNegotiationPacket)249 TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) {
250 std::unique_ptr<QuicEncryptedPacket> packet(
251 QuicFramer::BuildVersionNegotiationPacket(
252 connection_id_, EmptyQuicConnectionId(), /*ietf_quic=*/false,
253 /*use_length_prefix=*/false, AllSupportedVersions()));
254 EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
255 peer_address_, _))
256 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
257
258 time_wait_list_manager_.SendVersionNegotiationPacket(
259 connection_id_, EmptyQuicConnectionId(), /*ietf_quic=*/false,
260 /*use_length_prefix=*/false, AllSupportedVersions(), self_address_,
261 peer_address_, std::make_unique<QuicPerPacketContext>());
262 EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
263 }
264
TEST_F(QuicTimeWaitListManagerTest,SendIetfVersionNegotiationPacketWithoutLengthPrefix)265 TEST_F(QuicTimeWaitListManagerTest,
266 SendIetfVersionNegotiationPacketWithoutLengthPrefix) {
267 std::unique_ptr<QuicEncryptedPacket> packet(
268 QuicFramer::BuildVersionNegotiationPacket(
269 connection_id_, EmptyQuicConnectionId(), /*ietf_quic=*/true,
270 /*use_length_prefix=*/false, AllSupportedVersions()));
271 EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
272 peer_address_, _))
273 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
274
275 time_wait_list_manager_.SendVersionNegotiationPacket(
276 connection_id_, EmptyQuicConnectionId(), /*ietf_quic=*/true,
277 /*use_length_prefix=*/false, AllSupportedVersions(), self_address_,
278 peer_address_, std::make_unique<QuicPerPacketContext>());
279 EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
280 }
281
TEST_F(QuicTimeWaitListManagerTest,SendIetfVersionNegotiationPacket)282 TEST_F(QuicTimeWaitListManagerTest, SendIetfVersionNegotiationPacket) {
283 std::unique_ptr<QuicEncryptedPacket> packet(
284 QuicFramer::BuildVersionNegotiationPacket(
285 connection_id_, EmptyQuicConnectionId(), /*ietf_quic=*/true,
286 /*use_length_prefix=*/true, AllSupportedVersions()));
287 EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
288 peer_address_, _))
289 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
290
291 time_wait_list_manager_.SendVersionNegotiationPacket(
292 connection_id_, EmptyQuicConnectionId(), /*ietf_quic=*/true,
293 /*use_length_prefix=*/true, AllSupportedVersions(), self_address_,
294 peer_address_, std::make_unique<QuicPerPacketContext>());
295 EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
296 }
297
TEST_F(QuicTimeWaitListManagerTest,SendIetfVersionNegotiationPacketWithClientConnectionId)298 TEST_F(QuicTimeWaitListManagerTest,
299 SendIetfVersionNegotiationPacketWithClientConnectionId) {
300 std::unique_ptr<QuicEncryptedPacket> packet(
301 QuicFramer::BuildVersionNegotiationPacket(
302 connection_id_, TestConnectionId(0x33), /*ietf_quic=*/true,
303 /*use_length_prefix=*/true, AllSupportedVersions()));
304 EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
305 peer_address_, _))
306 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
307
308 time_wait_list_manager_.SendVersionNegotiationPacket(
309 connection_id_, TestConnectionId(0x33), /*ietf_quic=*/true,
310 /*use_length_prefix=*/true, AllSupportedVersions(), self_address_,
311 peer_address_, std::make_unique<QuicPerPacketContext>());
312 EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
313 }
314
TEST_F(QuicTimeWaitListManagerTest,SendConnectionClose)315 TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) {
316 const size_t kConnectionCloseLength = 100;
317 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
318 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
319 termination_packets.push_back(
320 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
321 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
322 AddConnectionId(connection_id_, QuicVersionMax(),
323 QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS,
324 &termination_packets);
325 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
326 self_address_.host(), peer_address_, _))
327 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
328
329 ProcessPacket(connection_id_);
330 }
331
TEST_F(QuicTimeWaitListManagerTest,SendTwoConnectionCloses)332 TEST_F(QuicTimeWaitListManagerTest, SendTwoConnectionCloses) {
333 const size_t kConnectionCloseLength = 100;
334 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
335 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
336 termination_packets.push_back(
337 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
338 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
339 termination_packets.push_back(
340 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
341 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
342 AddConnectionId(connection_id_, QuicVersionMax(),
343 QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS,
344 &termination_packets);
345 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
346 self_address_.host(), peer_address_, _))
347 .Times(2)
348 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
349
350 ProcessPacket(connection_id_);
351 }
352
TEST_F(QuicTimeWaitListManagerTest,SendPublicReset)353 TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) {
354 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
355 AddConnectionId(connection_id_,
356 QuicTimeWaitListManager::SEND_STATELESS_RESET);
357 EXPECT_CALL(writer_,
358 WritePacket(_, _, self_address_.host(), peer_address_, _))
359 .With(Args<0, 1>(PublicResetPacketEq(connection_id_)))
360 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
361
362 ProcessPacket(connection_id_);
363 }
364
TEST_F(QuicTimeWaitListManagerTest,SendPublicResetWithExponentialBackOff)365 TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) {
366 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
367 AddConnectionId(connection_id_,
368 QuicTimeWaitListManager::SEND_STATELESS_RESET);
369 EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
370 for (int packet_number = 1; packet_number < 101; ++packet_number) {
371 if ((packet_number & (packet_number - 1)) == 0) {
372 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _))
373 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
374 }
375 ProcessPacket(connection_id_);
376 // Send public reset with exponential back off.
377 if ((packet_number & (packet_number - 1)) == 0) {
378 EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
379 &time_wait_list_manager_, packet_number));
380 } else {
381 EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
382 &time_wait_list_manager_, packet_number));
383 }
384 }
385 }
386
TEST_F(QuicTimeWaitListManagerTest,NoPublicResetForStatelessConnections)387 TEST_F(QuicTimeWaitListManagerTest, NoPublicResetForStatelessConnections) {
388 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
389 AddStatelessConnectionId(connection_id_);
390
391 EXPECT_CALL(writer_,
392 WritePacket(_, _, self_address_.host(), peer_address_, _))
393 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
394
395 ProcessPacket(connection_id_);
396 }
397
TEST_F(QuicTimeWaitListManagerTest,CleanUpOldConnectionIds)398 TEST_F(QuicTimeWaitListManagerTest, CleanUpOldConnectionIds) {
399 const size_t kConnectionIdCount = 100;
400 const size_t kOldConnectionIdCount = 31;
401
402 // Add connection_ids such that their expiry time is time_wait_period_.
403 for (uint64_t conn_id = 1; conn_id <= kOldConnectionIdCount; ++conn_id) {
404 QuicConnectionId connection_id = TestConnectionId(conn_id);
405 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id));
406 AddConnectionId(connection_id, QuicTimeWaitListManager::DO_NOTHING);
407 }
408 EXPECT_EQ(kOldConnectionIdCount, time_wait_list_manager_.num_connections());
409
410 // Add remaining connection_ids such that their add time is
411 // 2 * time_wait_period_.
412 const QuicTime::Delta time_wait_period =
413 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
414 clock_.AdvanceTime(time_wait_period);
415 for (uint64_t conn_id = kOldConnectionIdCount + 1;
416 conn_id <= kConnectionIdCount; ++conn_id) {
417 QuicConnectionId connection_id = TestConnectionId(conn_id);
418 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id));
419 AddConnectionId(connection_id, QuicTimeWaitListManager::DO_NOTHING);
420 }
421 EXPECT_EQ(kConnectionIdCount, time_wait_list_manager_.num_connections());
422
423 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39);
424 // Now set the current time as time_wait_period + offset usecs.
425 clock_.AdvanceTime(offset);
426 // After all the old connection_ids are cleaned up, check the next alarm
427 // interval.
428 QuicTime next_alarm_time = clock_.Now() + time_wait_period - offset;
429 EXPECT_CALL(alarm_factory_, OnAlarmSet(_, next_alarm_time));
430
431 time_wait_list_manager_.CleanUpOldConnectionIds();
432 for (uint64_t conn_id = 1; conn_id <= kConnectionIdCount; ++conn_id) {
433 QuicConnectionId connection_id = TestConnectionId(conn_id);
434 EXPECT_EQ(conn_id > kOldConnectionIdCount,
435 IsConnectionIdInTimeWait(connection_id))
436 << "kOldConnectionIdCount: " << kOldConnectionIdCount
437 << " connection_id: " << connection_id;
438 }
439 EXPECT_EQ(kConnectionIdCount - kOldConnectionIdCount,
440 time_wait_list_manager_.num_connections());
441 }
442
TEST_F(QuicTimeWaitListManagerTest,CleanUpOldConnectionIdsForMultipleConnectionIdsPerConnection)443 TEST_F(QuicTimeWaitListManagerTest,
444 CleanUpOldConnectionIdsForMultipleConnectionIdsPerConnection) {
445 connection_id_ = TestConnectionId(7);
446 const size_t kConnectionCloseLength = 100;
447 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
448 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(TestConnectionId(8)));
449 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
450 termination_packets.push_back(
451 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
452 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
453
454 // Add a CONNECTION_CLOSE termination packet.
455 std::vector<QuicConnectionId> active_connection_ids{connection_id_,
456 TestConnectionId(8)};
457 time_wait_list_manager_.AddConnectionIdToTimeWait(
458 QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS,
459 TimeWaitConnectionInfo(/*ietf_quic=*/true, &termination_packets,
460 active_connection_ids, QuicTime::Delta::Zero()));
461
462 EXPECT_TRUE(
463 time_wait_list_manager_.IsConnectionIdInTimeWait(TestConnectionId(7)));
464 EXPECT_TRUE(
465 time_wait_list_manager_.IsConnectionIdInTimeWait(TestConnectionId(8)));
466
467 // Remove these IDs.
468 const QuicTime::Delta time_wait_period =
469 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
470 clock_.AdvanceTime(time_wait_period);
471 time_wait_list_manager_.CleanUpOldConnectionIds();
472
473 EXPECT_FALSE(
474 time_wait_list_manager_.IsConnectionIdInTimeWait(TestConnectionId(7)));
475 EXPECT_FALSE(
476 time_wait_list_manager_.IsConnectionIdInTimeWait(TestConnectionId(8)));
477 }
478
TEST_F(QuicTimeWaitListManagerTest,SendQueuedPackets)479 TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
480 QuicConnectionId connection_id = TestConnectionId(1);
481 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id));
482 AddConnectionId(connection_id, QuicTimeWaitListManager::SEND_STATELESS_RESET);
483 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
484 connection_id, EmptyQuicConnectionId(), /*packet_number=*/234));
485 // Let first write through.
486 EXPECT_CALL(writer_,
487 WritePacket(_, _, self_address_.host(), peer_address_, _))
488 .With(Args<0, 1>(PublicResetPacketEq(connection_id)))
489 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
490 ProcessPacket(connection_id);
491
492 // write block for the next packet.
493 EXPECT_CALL(writer_,
494 WritePacket(_, _, self_address_.host(), peer_address_, _))
495 .With(Args<0, 1>(PublicResetPacketEq(connection_id)))
496 .WillOnce(DoAll(Assign(&writer_is_blocked_, true),
497 Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
498 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
499 ProcessPacket(connection_id);
500 // 3rd packet. No public reset should be sent;
501 ProcessPacket(connection_id);
502
503 // write packet should not be called since we are write blocked but the
504 // should be queued.
505 QuicConnectionId other_connection_id = TestConnectionId(2);
506 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id));
507 AddConnectionId(other_connection_id,
508 QuicTimeWaitListManager::SEND_STATELESS_RESET);
509 std::unique_ptr<QuicEncryptedPacket> other_packet(ConstructEncryptedPacket(
510 other_connection_id, EmptyQuicConnectionId(), /*packet_number=*/23423));
511 EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0);
512 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
513 ProcessPacket(other_connection_id);
514 EXPECT_EQ(2u, time_wait_list_manager_.num_connections());
515
516 // Now expect all the write blocked public reset packets to be sent again.
517 writer_is_blocked_ = false;
518 EXPECT_CALL(writer_,
519 WritePacket(_, _, self_address_.host(), peer_address_, _))
520 .With(Args<0, 1>(PublicResetPacketEq(connection_id)))
521 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
522 EXPECT_CALL(writer_,
523 WritePacket(_, _, self_address_.host(), peer_address_, _))
524 .With(Args<0, 1>(PublicResetPacketEq(other_connection_id)))
525 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
526 time_wait_list_manager_.OnBlockedWriterCanWrite();
527 }
528
TEST_F(QuicTimeWaitListManagerTest,AddConnectionIdTwice)529 TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) {
530 // Add connection_ids such that their expiry time is time_wait_period_.
531 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
532 AddConnectionId(connection_id_, QuicTimeWaitListManager::DO_NOTHING);
533 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
534 const size_t kConnectionCloseLength = 100;
535 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
536 termination_packets.push_back(
537 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
538 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
539 AddConnectionId(connection_id_, QuicVersionMax(),
540 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
541 &termination_packets);
542 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
543 EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
544
545 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
546 self_address_.host(), peer_address_, _))
547 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
548
549 ProcessPacket(connection_id_);
550
551 const QuicTime::Delta time_wait_period =
552 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
553
554 QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39);
555 clock_.AdvanceTime(offset + time_wait_period);
556 // Now set the current time as time_wait_period + offset usecs.
557 QuicTime next_alarm_time = clock_.Now() + time_wait_period;
558 EXPECT_CALL(alarm_factory_, OnAlarmSet(_, next_alarm_time));
559
560 time_wait_list_manager_.CleanUpOldConnectionIds();
561 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_));
562 EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
563 }
564
TEST_F(QuicTimeWaitListManagerTest,ConnectionIdsOrderedByTime)565 TEST_F(QuicTimeWaitListManagerTest, ConnectionIdsOrderedByTime) {
566 // Simple randomization: the values of connection_ids are randomly swapped.
567 // If the container is broken, the test will be 50% flaky.
568 const uint64_t conn_id1 = QuicRandom::GetInstance()->RandUint64() % 2;
569 const QuicConnectionId connection_id1 = TestConnectionId(conn_id1);
570 const QuicConnectionId connection_id2 = TestConnectionId(1 - conn_id1);
571
572 // 1 will hash lower than 2, but we add it later. They should come out in the
573 // add order, not hash order.
574 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id1));
575 AddConnectionId(connection_id1, QuicTimeWaitListManager::DO_NOTHING);
576 clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(10));
577 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id2));
578 AddConnectionId(connection_id2, QuicTimeWaitListManager::DO_NOTHING);
579 EXPECT_EQ(2u, time_wait_list_manager_.num_connections());
580
581 const QuicTime::Delta time_wait_period =
582 QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
583 clock_.AdvanceTime(time_wait_period - QuicTime::Delta::FromMicroseconds(9));
584
585 EXPECT_CALL(alarm_factory_, OnAlarmSet(_, _));
586
587 time_wait_list_manager_.CleanUpOldConnectionIds();
588 EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id1));
589 EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id2));
590 EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
591 }
592
TEST_F(QuicTimeWaitListManagerTest,MaxConnectionsTest)593 TEST_F(QuicTimeWaitListManagerTest, MaxConnectionsTest) {
594 // Basically, shut off time-based eviction.
595 SetQuicFlag(quic_time_wait_list_seconds, 10000000000);
596 SetQuicFlag(quic_time_wait_list_max_connections, 5);
597
598 uint64_t current_conn_id = 0;
599 const int64_t kMaxConnections =
600 GetQuicFlag(quic_time_wait_list_max_connections);
601 // Add exactly the maximum number of connections
602 for (int64_t i = 0; i < kMaxConnections; ++i) {
603 ++current_conn_id;
604 QuicConnectionId current_connection_id = TestConnectionId(current_conn_id);
605 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id));
606 EXPECT_CALL(visitor_,
607 OnConnectionAddedToTimeWaitList(current_connection_id));
608 AddConnectionId(current_connection_id, QuicTimeWaitListManager::DO_NOTHING);
609 EXPECT_EQ(current_conn_id, time_wait_list_manager_.num_connections());
610 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id));
611 }
612
613 // Now keep adding. Since we're already at the max, every new connection-id
614 // will evict the oldest one.
615 for (int64_t i = 0; i < kMaxConnections; ++i) {
616 ++current_conn_id;
617 QuicConnectionId current_connection_id = TestConnectionId(current_conn_id);
618 const QuicConnectionId id_to_evict =
619 TestConnectionId(current_conn_id - kMaxConnections);
620 EXPECT_TRUE(IsConnectionIdInTimeWait(id_to_evict));
621 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id));
622 EXPECT_CALL(visitor_,
623 OnConnectionAddedToTimeWaitList(current_connection_id));
624 AddConnectionId(current_connection_id, QuicTimeWaitListManager::DO_NOTHING);
625 EXPECT_EQ(static_cast<size_t>(kMaxConnections),
626 time_wait_list_manager_.num_connections());
627 EXPECT_FALSE(IsConnectionIdInTimeWait(id_to_evict));
628 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id));
629 }
630 }
631
TEST_F(QuicTimeWaitListManagerTest,ZeroMaxConnections)632 TEST_F(QuicTimeWaitListManagerTest, ZeroMaxConnections) {
633 // Basically, shut off time-based eviction.
634 SetQuicFlag(quic_time_wait_list_seconds, 10000000000);
635 // Keep time wait list empty.
636 SetQuicFlag(quic_time_wait_list_max_connections, 0);
637
638 uint64_t current_conn_id = 0;
639 // Add exactly the maximum number of connections
640 for (int64_t i = 0; i < 10; ++i) {
641 ++current_conn_id;
642 QuicConnectionId current_connection_id = TestConnectionId(current_conn_id);
643 EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id));
644 EXPECT_CALL(visitor_,
645 OnConnectionAddedToTimeWaitList(current_connection_id));
646 AddConnectionId(current_connection_id, QuicTimeWaitListManager::DO_NOTHING);
647 // Verify time wait list always has 1 connection.
648 EXPECT_EQ(1u, time_wait_list_manager_.num_connections());
649 EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id));
650 }
651 }
652
653 // Regression test for b/116200989.
TEST_F(QuicTimeWaitListManagerTest,SendStatelessResetInResponseToShortHeaders)654 TEST_F(QuicTimeWaitListManagerTest,
655 SendStatelessResetInResponseToShortHeaders) {
656 // This test mimics a scenario where an ENCRYPTION_INITIAL connection close is
657 // added as termination packet for an IETF connection ID. However, a short
658 // header packet is received later.
659 const size_t kConnectionCloseLength = 100;
660 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
661 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
662 termination_packets.push_back(
663 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
664 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
665 time_wait_list_manager_.AddConnectionIdToTimeWait(
666 QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
667 TimeWaitConnectionInfo(/*ietf_quic=*/true, &termination_packets,
668 {connection_id_}));
669
670 // Termination packet is not encrypted, instead, send stateless reset.
671 EXPECT_CALL(writer_,
672 WritePacket(_, _, self_address_.host(), peer_address_, _))
673 .With(Args<0, 1>(PublicResetPacketEq(connection_id_)))
674 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
675 // Processes IETF short header packet.
676 time_wait_list_manager_.ProcessPacket(
677 self_address_, peer_address_, connection_id_,
678 IETF_QUIC_SHORT_HEADER_PACKET, kTestPacketSize,
679 std::make_unique<QuicPerPacketContext>());
680 }
681
TEST_F(QuicTimeWaitListManagerTest,SendConnectionClosePacketsInResponseToShortHeaders)682 TEST_F(QuicTimeWaitListManagerTest,
683 SendConnectionClosePacketsInResponseToShortHeaders) {
684 const size_t kConnectionCloseLength = 100;
685 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
686 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
687 termination_packets.push_back(
688 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
689 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
690 // Add a CONNECTION_CLOSE termination packet.
691 time_wait_list_manager_.AddConnectionIdToTimeWait(
692 QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS,
693 TimeWaitConnectionInfo(/*ietf_quic=*/true, &termination_packets,
694 {connection_id_}));
695 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
696 self_address_.host(), peer_address_, _))
697 .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
698
699 // Processes IETF short header packet.
700 time_wait_list_manager_.ProcessPacket(
701 self_address_, peer_address_, connection_id_,
702 IETF_QUIC_SHORT_HEADER_PACKET, kTestPacketSize,
703 std::make_unique<QuicPerPacketContext>());
704 }
705
TEST_F(QuicTimeWaitListManagerTest,SendConnectionClosePacketsForMultipleConnectionIds)706 TEST_F(QuicTimeWaitListManagerTest,
707 SendConnectionClosePacketsForMultipleConnectionIds) {
708 connection_id_ = TestConnectionId(7);
709 const size_t kConnectionCloseLength = 100;
710 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
711 EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(TestConnectionId(8)));
712 std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
713 termination_packets.push_back(
714 std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
715 new char[kConnectionCloseLength], kConnectionCloseLength, true)));
716
717 // Add a CONNECTION_CLOSE termination packet.
718 std::vector<QuicConnectionId> active_connection_ids{connection_id_,
719 TestConnectionId(8)};
720 time_wait_list_manager_.AddConnectionIdToTimeWait(
721 QuicTimeWaitListManager::SEND_CONNECTION_CLOSE_PACKETS,
722 TimeWaitConnectionInfo(/*ietf_quic=*/true, &termination_packets,
723 active_connection_ids, QuicTime::Delta::Zero()));
724
725 EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
726 self_address_.host(), peer_address_, _))
727 .Times(2)
728 .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 1)));
729 // Processes IETF short header packet.
730 for (auto const& cid : active_connection_ids) {
731 time_wait_list_manager_.ProcessPacket(
732 self_address_, peer_address_, cid, IETF_QUIC_SHORT_HEADER_PACKET,
733 kTestPacketSize, std::make_unique<QuicPerPacketContext>());
734 }
735 }
736
737 // Regression test for b/184053898.
TEST_F(QuicTimeWaitListManagerTest,DonotCrashOnNullStatelessReset)738 TEST_F(QuicTimeWaitListManagerTest, DonotCrashOnNullStatelessReset) {
739 // Received a packet with length <
740 // QuicFramer::GetMinStatelessResetPacketLength(), and this will result in a
741 // null stateless reset.
742 time_wait_list_manager_.SendPublicReset(
743 self_address_, peer_address_, TestConnectionId(1),
744 /*ietf_quic=*/true,
745 /*received_packet_length=*/
746 QuicFramer::GetMinStatelessResetPacketLength() - 1,
747 /*packet_context=*/nullptr);
748 }
749
TEST_F(QuicTimeWaitListManagerTest,SendOrQueueNullPacket)750 TEST_F(QuicTimeWaitListManagerTest, SendOrQueueNullPacket) {
751 QuicTimeWaitListManagerPeer::SendOrQueuePacket(&time_wait_list_manager_,
752 nullptr, nullptr);
753 }
754
TEST_F(QuicTimeWaitListManagerTest,TooManyPendingPackets)755 TEST_F(QuicTimeWaitListManagerTest, TooManyPendingPackets) {
756 SetQuicFlag(quic_time_wait_list_max_pending_packets, 5);
757 const size_t kNumOfUnProcessablePackets = 2048;
758 EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_))
759 .Times(testing::AnyNumber());
760 // Write block for the next packets.
761 EXPECT_CALL(writer_,
762 WritePacket(_, _, self_address_.host(), peer_address_, _))
763 .With(Args<0, 1>(PublicResetPacketEq(TestConnectionId(1))))
764 .WillOnce(DoAll(Assign(&writer_is_blocked_, true),
765 Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
766 for (size_t i = 0; i < kNumOfUnProcessablePackets; ++i) {
767 time_wait_list_manager_.SendPublicReset(
768 self_address_, peer_address_, TestConnectionId(1),
769 /*ietf_quic=*/true,
770 /*received_packet_length=*/
771 QuicFramer::GetMinStatelessResetPacketLength() + 1,
772 /*packet_context=*/nullptr);
773 }
774 // Verify pending packet queue size is limited.
775 EXPECT_EQ(5u, QuicTimeWaitListManagerPeer::PendingPacketsQueueSize(
776 &time_wait_list_manager_));
777 }
778
779 } // namespace
780 } // namespace test
781 } // namespace quic
782