1 // Copyright (c) 2016 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_buffered_packet_store.h"
6
7 #include <cstddef>
8 #include <cstdint>
9 #include <list>
10 #include <memory>
11 #include <optional>
12 #include <string>
13 #include <utility>
14
15 #include "absl/strings/string_view.h"
16 #include "quiche/quic/core/connection_id_generator.h"
17 #include "quiche/quic/core/crypto/transport_parameters.h"
18 #include "quiche/quic/core/quic_connection_id.h"
19 #include "quiche/quic/core/quic_constants.h"
20 #include "quiche/quic/core/quic_error_codes.h"
21 #include "quiche/quic/core/quic_framer.h"
22 #include "quiche/quic/core/quic_packets.h"
23 #include "quiche/quic/core/quic_time.h"
24 #include "quiche/quic/core/quic_types.h"
25 #include "quiche/quic/core/quic_versions.h"
26 #include "quiche/quic/platform/api/quic_ip_address.h"
27 #include "quiche/quic/platform/api/quic_socket_address.h"
28 #include "quiche/quic/platform/api/quic_test.h"
29 #include "quiche/quic/test_tools/first_flight.h"
30 #include "quiche/quic/test_tools/mock_clock.h"
31 #include "quiche/quic/test_tools/mock_connection_id_generator.h"
32 #include "quiche/quic/test_tools/quic_buffered_packet_store_peer.h"
33 #include "quiche/quic/test_tools/quic_test_utils.h"
34
35 namespace quic {
36 static const size_t kDefaultMaxConnectionsInStore = 100;
37 static const size_t kMaxConnectionsWithoutCHLO =
38 kDefaultMaxConnectionsInStore / 2;
39
40 namespace test {
41 namespace {
42
43 const std::optional<ParsedClientHello> kNoParsedChlo;
44 const std::optional<ParsedClientHello> kDefaultParsedChlo =
45 absl::make_optional<ParsedClientHello>();
46
47 using BufferedPacket = QuicBufferedPacketStore::BufferedPacket;
48 using BufferedPacketList = QuicBufferedPacketStore::BufferedPacketList;
49 using EnqueuePacketResult = QuicBufferedPacketStore::EnqueuePacketResult;
50 using ::testing::A;
51 using ::testing::Conditional;
52 using ::testing::Each;
53 using ::testing::ElementsAre;
54 using ::testing::Ne;
55 using ::testing::SizeIs;
56 using ::testing::Truly;
57
58 class QuicBufferedPacketStoreVisitor
59 : public QuicBufferedPacketStore::VisitorInterface {
60 public:
QuicBufferedPacketStoreVisitor()61 QuicBufferedPacketStoreVisitor() {}
62
~QuicBufferedPacketStoreVisitor()63 ~QuicBufferedPacketStoreVisitor() override {}
64
OnExpiredPackets(QuicConnectionId,BufferedPacketList early_arrived_packets)65 void OnExpiredPackets(QuicConnectionId /*connection_id*/,
66 BufferedPacketList early_arrived_packets) override {
67 last_expired_packet_queue_ = std::move(early_arrived_packets);
68 }
69
70 // The packets queue for most recently expirect connection.
71 BufferedPacketList last_expired_packet_queue_;
72 };
73
74 class QuicBufferedPacketStoreTest : public QuicTest {
75 public:
QuicBufferedPacketStoreTest()76 QuicBufferedPacketStoreTest()
77 : store_(&visitor_, &clock_, &alarm_factory_),
78 self_address_(QuicIpAddress::Any6(), 65535),
79 peer_address_(QuicIpAddress::Any6(), 65535),
80 packet_content_("some encrypted content"),
81 packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)),
82 packet_(packet_content_.data(), packet_content_.size(), packet_time_),
83 invalid_version_(UnsupportedQuicVersion()),
84 valid_version_(CurrentSupportedVersions().front()) {}
85
86 protected:
87 QuicBufferedPacketStoreVisitor visitor_;
88 MockClock clock_;
89 MockAlarmFactory alarm_factory_;
90 QuicBufferedPacketStore store_;
91 QuicSocketAddress self_address_;
92 QuicSocketAddress peer_address_;
93 std::string packet_content_;
94 QuicTime packet_time_;
95 QuicReceivedPacket packet_;
96 const ParsedQuicVersion invalid_version_;
97 const ParsedQuicVersion valid_version_;
98 MockConnectionIdGenerator connection_id_generator_;
99 };
100
TEST_F(QuicBufferedPacketStoreTest,SimpleEnqueueAndDeliverPacket)101 TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
102 QuicConnectionId connection_id = TestConnectionId(1);
103 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
104 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
105 EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
106 auto packets = store_.DeliverPackets(connection_id);
107 const std::list<BufferedPacket>& queue = packets.buffered_packets;
108 ASSERT_EQ(1u, queue.size());
109 ASSERT_FALSE(packets.parsed_chlo.has_value());
110 // There is no valid version because CHLO has not arrived.
111 EXPECT_EQ(invalid_version_, packets.version);
112 // Check content of the only packet in the queue.
113 EXPECT_EQ(packet_content_, queue.front().packet->AsStringPiece());
114 EXPECT_EQ(packet_time_, queue.front().packet->receipt_time());
115 EXPECT_EQ(peer_address_, queue.front().peer_address);
116 EXPECT_EQ(self_address_, queue.front().self_address);
117 // No more packets on connection 1 should remain in the store.
118 EXPECT_TRUE(store_.DeliverPackets(connection_id).buffered_packets.empty());
119 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
120 }
121
TEST_F(QuicBufferedPacketStoreTest,DifferentPacketAddressOnOneConnection)122 TEST_F(QuicBufferedPacketStoreTest, DifferentPacketAddressOnOneConnection) {
123 QuicSocketAddress addr_with_new_port(QuicIpAddress::Any4(), 256);
124 QuicConnectionId connection_id = TestConnectionId(1);
125 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
126 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
127 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
128 addr_with_new_port, invalid_version_, kNoParsedChlo,
129 nullptr);
130 std::list<BufferedPacket> queue =
131 store_.DeliverPackets(connection_id).buffered_packets;
132 ASSERT_EQ(2u, queue.size());
133 // The address migration path should be preserved.
134 EXPECT_EQ(peer_address_, queue.front().peer_address);
135 EXPECT_EQ(addr_with_new_port, queue.back().peer_address);
136 }
137
TEST_F(QuicBufferedPacketStoreTest,EnqueueAndDeliverMultiplePacketsOnMultipleConnections)138 TEST_F(QuicBufferedPacketStoreTest,
139 EnqueueAndDeliverMultiplePacketsOnMultipleConnections) {
140 size_t num_connections = 10;
141 for (uint64_t conn_id = 1; conn_id <= num_connections; ++conn_id) {
142 QuicConnectionId connection_id = TestConnectionId(conn_id);
143 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
144 peer_address_, invalid_version_, kNoParsedChlo,
145 nullptr);
146 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
147 peer_address_, invalid_version_, kNoParsedChlo,
148 nullptr);
149 }
150
151 // Deliver packets in reversed order.
152 for (uint64_t conn_id = num_connections; conn_id > 0; --conn_id) {
153 QuicConnectionId connection_id = TestConnectionId(conn_id);
154 std::list<BufferedPacket> queue =
155 store_.DeliverPackets(connection_id).buffered_packets;
156 ASSERT_EQ(2u, queue.size());
157 }
158 }
159
TEST_F(QuicBufferedPacketStoreTest,FailToBufferTooManyPacketsOnExistingConnection)160 TEST_F(QuicBufferedPacketStoreTest,
161 FailToBufferTooManyPacketsOnExistingConnection) {
162 // Tests that for one connection, only limited number of packets can be
163 // buffered.
164 size_t num_packets = kDefaultMaxUndecryptablePackets + 1;
165 QuicConnectionId connection_id = TestConnectionId(1);
166 // Arrived CHLO packet shouldn't affect how many non-CHLO pacekts store can
167 // keep.
168 EXPECT_EQ(QuicBufferedPacketStore::SUCCESS,
169 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
170 peer_address_, valid_version_,
171 kDefaultParsedChlo, nullptr));
172 for (size_t i = 1; i <= num_packets; ++i) {
173 // Only first |kDefaultMaxUndecryptablePackets packets| will be buffered.
174 EnqueuePacketResult result = store_.EnqueuePacket(
175 connection_id, false, packet_, self_address_, peer_address_,
176 invalid_version_, kNoParsedChlo, nullptr);
177 if (i <= kDefaultMaxUndecryptablePackets) {
178 EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
179 } else {
180 EXPECT_EQ(EnqueuePacketResult::TOO_MANY_PACKETS, result);
181 }
182 }
183
184 // Only first |kDefaultMaxUndecryptablePackets| non-CHLO packets and CHLO are
185 // buffered.
186 EXPECT_EQ(kDefaultMaxUndecryptablePackets + 1,
187 store_.DeliverPackets(connection_id).buffered_packets.size());
188 }
189
TEST_F(QuicBufferedPacketStoreTest,ReachNonChloConnectionUpperLimit)190 TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
191 // Tests that store can only keep early arrived packets for limited number of
192 // connections.
193 const size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
194 for (uint64_t conn_id = 1; conn_id <= kNumConnections; ++conn_id) {
195 QuicConnectionId connection_id = TestConnectionId(conn_id);
196 EnqueuePacketResult result = store_.EnqueuePacket(
197 connection_id, false, packet_, self_address_, peer_address_,
198 invalid_version_, kNoParsedChlo, nullptr);
199 if (conn_id <= kMaxConnectionsWithoutCHLO) {
200 EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
201 } else {
202 EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, result);
203 }
204 }
205 // Store only keeps early arrived packets upto |kNumConnections| connections.
206 for (uint64_t conn_id = 1; conn_id <= kNumConnections; ++conn_id) {
207 QuicConnectionId connection_id = TestConnectionId(conn_id);
208 std::list<BufferedPacket> queue =
209 store_.DeliverPackets(connection_id).buffered_packets;
210 if (conn_id <= kMaxConnectionsWithoutCHLO) {
211 EXPECT_EQ(1u, queue.size());
212 } else {
213 EXPECT_EQ(0u, queue.size());
214 }
215 }
216 }
217
TEST_F(QuicBufferedPacketStoreTest,FullStoreFailToBufferDataPacketOnNewConnection)218 TEST_F(QuicBufferedPacketStoreTest,
219 FullStoreFailToBufferDataPacketOnNewConnection) {
220 // Send enough CHLOs so that store gets full before number of connections
221 // without CHLO reaches its upper limit.
222 size_t num_chlos =
223 kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO + 1;
224 for (uint64_t conn_id = 1; conn_id <= num_chlos; ++conn_id) {
225 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
226 store_.EnqueuePacket(TestConnectionId(conn_id), false, packet_,
227 self_address_, peer_address_, valid_version_,
228 kDefaultParsedChlo, nullptr));
229 }
230
231 // Send data packets on another |kMaxConnectionsWithoutCHLO| connections.
232 // Store should only be able to buffer till it's full.
233 for (uint64_t conn_id = num_chlos + 1;
234 conn_id <= (kDefaultMaxConnectionsInStore + 1); ++conn_id) {
235 QuicConnectionId connection_id = TestConnectionId(conn_id);
236 EnqueuePacketResult result = store_.EnqueuePacket(
237 connection_id, false, packet_, self_address_, peer_address_,
238 valid_version_, kDefaultParsedChlo, nullptr);
239 if (conn_id <= kDefaultMaxConnectionsInStore) {
240 EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
241 } else {
242 EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, result);
243 }
244 }
245 }
246
TEST_F(QuicBufferedPacketStoreTest,BasicGeneratorBuffering)247 TEST_F(QuicBufferedPacketStoreTest, BasicGeneratorBuffering) {
248 EXPECT_EQ(
249 EnqueuePacketResult::SUCCESS,
250 store_.EnqueuePacket(TestConnectionId(1), false, packet_, self_address_,
251 peer_address_, valid_version_, kDefaultParsedChlo,
252 &connection_id_generator_));
253 QuicConnectionId delivered_conn_id;
254 BufferedPacketList packet_list =
255 store_.DeliverPacketsForNextConnection(&delivered_conn_id);
256 EXPECT_EQ(1u, packet_list.buffered_packets.size());
257 EXPECT_EQ(delivered_conn_id, TestConnectionId(1));
258 EXPECT_EQ(&connection_id_generator_, packet_list.connection_id_generator);
259 }
260
TEST_F(QuicBufferedPacketStoreTest,NullGeneratorOk)261 TEST_F(QuicBufferedPacketStoreTest, NullGeneratorOk) {
262 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
263 store_.EnqueuePacket(TestConnectionId(1), false, packet_,
264 self_address_, peer_address_, valid_version_,
265 kDefaultParsedChlo, nullptr));
266 QuicConnectionId delivered_conn_id;
267 BufferedPacketList packet_list =
268 store_.DeliverPacketsForNextConnection(&delivered_conn_id);
269 EXPECT_EQ(1u, packet_list.buffered_packets.size());
270 EXPECT_EQ(delivered_conn_id, TestConnectionId(1));
271 EXPECT_EQ(packet_list.connection_id_generator, nullptr);
272 }
273
TEST_F(QuicBufferedPacketStoreTest,GeneratorIgnoredForNonChlo)274 TEST_F(QuicBufferedPacketStoreTest, GeneratorIgnoredForNonChlo) {
275 MockConnectionIdGenerator generator2;
276 EXPECT_EQ(
277 EnqueuePacketResult::SUCCESS,
278 store_.EnqueuePacket(TestConnectionId(1), false, packet_, self_address_,
279 peer_address_, valid_version_, kDefaultParsedChlo,
280 &connection_id_generator_));
281 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
282 store_.EnqueuePacket(TestConnectionId(1), false, packet_,
283 self_address_, peer_address_, valid_version_,
284 kNoParsedChlo, &generator2));
285 QuicConnectionId delivered_conn_id;
286 BufferedPacketList packet_list =
287 store_.DeliverPacketsForNextConnection(&delivered_conn_id);
288 EXPECT_EQ(2u, packet_list.buffered_packets.size());
289 EXPECT_EQ(delivered_conn_id, TestConnectionId(1));
290 EXPECT_EQ(packet_list.connection_id_generator, &connection_id_generator_);
291 }
292
TEST_F(QuicBufferedPacketStoreTest,EnqueueChloOnTooManyDifferentConnections)293 TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
294 // Buffer data packets on different connections upto limit.
295 for (uint64_t conn_id = 1; conn_id <= kMaxConnectionsWithoutCHLO; ++conn_id) {
296 QuicConnectionId connection_id = TestConnectionId(conn_id);
297 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
298 // connection_id_generator_ will be ignored because the chlo has
299 // not been parsed.
300 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
301 peer_address_, invalid_version_,
302 kNoParsedChlo, &connection_id_generator_));
303 }
304
305 // Buffer CHLOs on other connections till store is full.
306 for (size_t i = kMaxConnectionsWithoutCHLO + 1;
307 i <= kDefaultMaxConnectionsInStore + 1; ++i) {
308 QuicConnectionId connection_id = TestConnectionId(i);
309 EnqueuePacketResult rs = store_.EnqueuePacket(
310 connection_id, false, packet_, self_address_, peer_address_,
311 valid_version_, kDefaultParsedChlo, &connection_id_generator_);
312 if (i <= kDefaultMaxConnectionsInStore) {
313 EXPECT_EQ(EnqueuePacketResult::SUCCESS, rs);
314 EXPECT_TRUE(store_.HasChloForConnection(connection_id));
315 } else {
316 // Last CHLO can't be buffered because store is full.
317 EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, rs);
318 EXPECT_FALSE(store_.HasChloForConnection(connection_id));
319 }
320 }
321
322 // But buffering a CHLO belonging to a connection already has data packet
323 // buffered in the store should success. This is the connection should be
324 // delivered at last.
325 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
326 store_.EnqueuePacket(
327 /*connection_id=*/TestConnectionId(1), false, packet_,
328 self_address_, peer_address_, valid_version_,
329 kDefaultParsedChlo, &connection_id_generator_));
330 EXPECT_TRUE(store_.HasChloForConnection(
331 /*connection_id=*/TestConnectionId(1)));
332
333 QuicConnectionId delivered_conn_id;
334 for (size_t i = 0;
335 i < kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO + 1;
336 ++i) {
337 BufferedPacketList packet_list =
338 store_.DeliverPacketsForNextConnection(&delivered_conn_id);
339 if (i < kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO) {
340 // Only CHLO is buffered.
341 EXPECT_EQ(1u, packet_list.buffered_packets.size());
342 EXPECT_EQ(TestConnectionId(i + kMaxConnectionsWithoutCHLO + 1),
343 delivered_conn_id);
344 } else {
345 EXPECT_EQ(2u, packet_list.buffered_packets.size());
346 EXPECT_EQ(TestConnectionId(1u), delivered_conn_id);
347 }
348 EXPECT_EQ(packet_list.connection_id_generator, &connection_id_generator_);
349 }
350 EXPECT_FALSE(store_.HasChlosBuffered());
351 }
352
353 // Tests that store expires long-staying connections appropriately for
354 // connections both with and without CHLOs.
TEST_F(QuicBufferedPacketStoreTest,PacketQueueExpiredBeforeDelivery)355 TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
356 QuicConnectionId connection_id = TestConnectionId(1);
357 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
358 peer_address_, invalid_version_, kNoParsedChlo,
359 &connection_id_generator_);
360 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
361 store_.EnqueuePacket(
362 connection_id, false, packet_, self_address_, peer_address_,
363 valid_version_, kDefaultParsedChlo, &connection_id_generator_));
364 QuicConnectionId connection_id2 = TestConnectionId(2);
365 EXPECT_EQ(EnqueuePacketResult::SUCCESS,
366 store_.EnqueuePacket(connection_id2, false, packet_, self_address_,
367 peer_address_, invalid_version_, kNoParsedChlo,
368 &connection_id_generator_));
369
370 // CHLO on connection 3 arrives 1ms later.
371 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
372 QuicConnectionId connection_id3 = TestConnectionId(3);
373 // Use different client address to differentiate packets from different
374 // connections.
375 QuicSocketAddress another_client_address(QuicIpAddress::Any4(), 255);
376 store_.EnqueuePacket(connection_id3, false, packet_, self_address_,
377 another_client_address, valid_version_,
378 kDefaultParsedChlo, &connection_id_generator_);
379
380 // Advance clock to the time when connection 1 and 2 expires.
381 clock_.AdvanceTime(
382 QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
383 clock_.ApproximateNow());
384 ASSERT_GE(clock_.ApproximateNow(),
385 QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline());
386 // Fire alarm to remove long-staying connection 1 and 2 packets.
387 alarm_factory_.FireAlarm(
388 QuicBufferedPacketStorePeer::expiration_alarm(&store_));
389 EXPECT_EQ(1u, visitor_.last_expired_packet_queue_.buffered_packets.size());
390 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
391 EXPECT_FALSE(store_.HasBufferedPackets(connection_id2));
392
393 // Try to deliver packets, but packet queue has been removed so no
394 // packets can be returned.
395 ASSERT_EQ(0u, store_.DeliverPackets(connection_id).buffered_packets.size());
396 ASSERT_EQ(0u, store_.DeliverPackets(connection_id2).buffered_packets.size());
397 QuicConnectionId delivered_conn_id;
398 BufferedPacketList packet_list =
399 store_.DeliverPacketsForNextConnection(&delivered_conn_id);
400
401 // Connection 3 is the next to be delivered as connection 1 already expired.
402 EXPECT_EQ(connection_id3, delivered_conn_id);
403 EXPECT_EQ(packet_list.connection_id_generator, &connection_id_generator_);
404 ASSERT_EQ(1u, packet_list.buffered_packets.size());
405 // Packets in connection 3 should use another peer address.
406 EXPECT_EQ(another_client_address,
407 packet_list.buffered_packets.front().peer_address);
408
409 // Test the alarm is reset by enqueueing 2 packets for 4th connection and wait
410 // for them to expire.
411 QuicConnectionId connection_id4 = TestConnectionId(4);
412 store_.EnqueuePacket(connection_id4, false, packet_, self_address_,
413 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
414 store_.EnqueuePacket(connection_id4, false, packet_, self_address_,
415 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
416 clock_.AdvanceTime(
417 QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
418 clock_.ApproximateNow());
419 alarm_factory_.FireAlarm(
420 QuicBufferedPacketStorePeer::expiration_alarm(&store_));
421 // |last_expired_packet_queue_| should be updated.
422 EXPECT_EQ(2u, visitor_.last_expired_packet_queue_.buffered_packets.size());
423 }
424
TEST_F(QuicBufferedPacketStoreTest,SimpleDiscardPackets)425 TEST_F(QuicBufferedPacketStoreTest, SimpleDiscardPackets) {
426 QuicConnectionId connection_id = TestConnectionId(1);
427
428 // Enqueue some packets
429 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
430 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
431 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
432 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
433 EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
434 EXPECT_FALSE(store_.HasChlosBuffered());
435
436 // Dicard the packets
437 store_.DiscardPackets(connection_id);
438
439 // No packets on connection 1 should remain in the store
440 EXPECT_TRUE(store_.DeliverPackets(connection_id).buffered_packets.empty());
441 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
442 EXPECT_FALSE(store_.HasChlosBuffered());
443
444 // Check idempotency
445 store_.DiscardPackets(connection_id);
446 EXPECT_TRUE(store_.DeliverPackets(connection_id).buffered_packets.empty());
447 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
448 EXPECT_FALSE(store_.HasChlosBuffered());
449 }
450
TEST_F(QuicBufferedPacketStoreTest,DiscardWithCHLOs)451 TEST_F(QuicBufferedPacketStoreTest, DiscardWithCHLOs) {
452 QuicConnectionId connection_id = TestConnectionId(1);
453
454 // Enqueue some packets, which include a CHLO
455 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
456 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
457 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
458 peer_address_, valid_version_, kDefaultParsedChlo,
459 nullptr);
460 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
461 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
462 EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
463 EXPECT_TRUE(store_.HasChlosBuffered());
464
465 // Dicard the packets
466 store_.DiscardPackets(connection_id);
467
468 // No packets on connection 1 should remain in the store
469 EXPECT_TRUE(store_.DeliverPackets(connection_id).buffered_packets.empty());
470 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
471 EXPECT_FALSE(store_.HasChlosBuffered());
472
473 // Check idempotency
474 store_.DiscardPackets(connection_id);
475 EXPECT_TRUE(store_.DeliverPackets(connection_id).buffered_packets.empty());
476 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
477 EXPECT_FALSE(store_.HasChlosBuffered());
478 }
479
TEST_F(QuicBufferedPacketStoreTest,MultipleDiscardPackets)480 TEST_F(QuicBufferedPacketStoreTest, MultipleDiscardPackets) {
481 QuicConnectionId connection_id_1 = TestConnectionId(1);
482 QuicConnectionId connection_id_2 = TestConnectionId(2);
483
484 // Enqueue some packets for two connection IDs
485 store_.EnqueuePacket(connection_id_1, false, packet_, self_address_,
486 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
487 store_.EnqueuePacket(connection_id_1, false, packet_, self_address_,
488 peer_address_, invalid_version_, kNoParsedChlo, nullptr);
489
490 ParsedClientHello parsed_chlo;
491 parsed_chlo.alpns.push_back("h3");
492 parsed_chlo.sni = TestHostname();
493 store_.EnqueuePacket(connection_id_2, false, packet_, self_address_,
494 peer_address_, valid_version_, parsed_chlo, nullptr);
495 EXPECT_TRUE(store_.HasBufferedPackets(connection_id_1));
496 EXPECT_TRUE(store_.HasBufferedPackets(connection_id_2));
497 EXPECT_TRUE(store_.HasChlosBuffered());
498
499 // Discard the packets for connection 1
500 store_.DiscardPackets(connection_id_1);
501
502 // No packets on connection 1 should remain in the store
503 EXPECT_TRUE(store_.DeliverPackets(connection_id_1).buffered_packets.empty());
504 EXPECT_FALSE(store_.HasBufferedPackets(connection_id_1));
505 EXPECT_TRUE(store_.HasChlosBuffered());
506
507 // Packets on connection 2 should remain
508 EXPECT_TRUE(store_.HasBufferedPackets(connection_id_2));
509 auto packets = store_.DeliverPackets(connection_id_2);
510 EXPECT_EQ(1u, packets.buffered_packets.size());
511 ASSERT_EQ(1u, packets.parsed_chlo->alpns.size());
512 EXPECT_EQ("h3", packets.parsed_chlo->alpns[0]);
513 EXPECT_EQ(TestHostname(), packets.parsed_chlo->sni);
514 // Since connection_id_2's chlo arrives, verify version is set.
515 EXPECT_EQ(valid_version_, packets.version);
516 EXPECT_TRUE(store_.HasChlosBuffered());
517
518 // Discard the packets for connection 2
519 store_.DiscardPackets(connection_id_2);
520 EXPECT_FALSE(store_.HasChlosBuffered());
521 }
522
TEST_F(QuicBufferedPacketStoreTest,DiscardPacketsEmpty)523 TEST_F(QuicBufferedPacketStoreTest, DiscardPacketsEmpty) {
524 // Check that DiscardPackets on an unknown connection ID is safe and does
525 // nothing.
526 QuicConnectionId connection_id = TestConnectionId(11235);
527 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
528 EXPECT_FALSE(store_.HasChlosBuffered());
529 store_.DiscardPackets(connection_id);
530 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
531 EXPECT_FALSE(store_.HasChlosBuffered());
532 }
533
TEST_F(QuicBufferedPacketStoreTest,IngestPacketForTlsChloExtraction)534 TEST_F(QuicBufferedPacketStoreTest, IngestPacketForTlsChloExtraction) {
535 QuicConnectionId connection_id = TestConnectionId(1);
536 std::vector<std::string> alpns;
537 std::vector<uint16_t> supported_groups;
538 std::string sni;
539 bool resumption_attempted = false;
540 bool early_data_attempted = false;
541 QuicConfig config;
542 std::optional<uint8_t> tls_alert;
543
544 EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
545 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
546 peer_address_, valid_version_, kNoParsedChlo, nullptr);
547 EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
548
549 // The packet in 'packet_' is not a TLS CHLO packet.
550 EXPECT_FALSE(store_.IngestPacketForTlsChloExtraction(
551 connection_id, valid_version_, packet_, &supported_groups, &alpns, &sni,
552 &resumption_attempted, &early_data_attempted, &tls_alert));
553
554 store_.DiscardPackets(connection_id);
555
556 // Force the TLS CHLO to span multiple packets.
557 constexpr auto kCustomParameterId =
558 static_cast<TransportParameters::TransportParameterId>(0xff33);
559 std::string kCustomParameterValue(2000, '-');
560 config.custom_transport_parameters_to_send()[kCustomParameterId] =
561 kCustomParameterValue;
562 auto packets = GetFirstFlightOfPackets(valid_version_, config);
563 ASSERT_EQ(packets.size(), 2u);
564
565 store_.EnqueuePacket(connection_id, false, *packets[0], self_address_,
566 peer_address_, valid_version_, kNoParsedChlo, nullptr);
567 store_.EnqueuePacket(connection_id, false, *packets[1], self_address_,
568 peer_address_, valid_version_, kNoParsedChlo, nullptr);
569
570 EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
571 EXPECT_FALSE(store_.IngestPacketForTlsChloExtraction(
572 connection_id, valid_version_, *packets[0], &supported_groups, &alpns,
573 &sni, &resumption_attempted, &early_data_attempted, &tls_alert));
574 EXPECT_TRUE(store_.IngestPacketForTlsChloExtraction(
575 connection_id, valid_version_, *packets[1], &supported_groups, &alpns,
576 &sni, &resumption_attempted, &early_data_attempted, &tls_alert));
577
578 EXPECT_THAT(alpns, ElementsAre(AlpnForVersion(valid_version_)));
579 EXPECT_FALSE(supported_groups.empty());
580 EXPECT_EQ(sni, TestHostname());
581
582 EXPECT_FALSE(resumption_attempted);
583 EXPECT_FALSE(early_data_attempted);
584 }
585
TEST_F(QuicBufferedPacketStoreTest,DeliverInitialPacketsFirst)586 TEST_F(QuicBufferedPacketStoreTest, DeliverInitialPacketsFirst) {
587 QuicConfig config;
588 QuicConnectionId connection_id = TestConnectionId(1);
589
590 // Force the TLS CHLO to span multiple packets.
591 constexpr auto kCustomParameterId =
592 static_cast<TransportParameters::TransportParameterId>(0xff33);
593 std::string custom_parameter_value(2000, '-');
594 config.custom_transport_parameters_to_send()[kCustomParameterId] =
595 custom_parameter_value;
596 auto initial_packets = GetFirstFlightOfPackets(valid_version_, config);
597 ASSERT_THAT(initial_packets, SizeIs(2));
598
599 // Verify that the packets generated are INITIAL packets.
600 EXPECT_THAT(
601 initial_packets,
602 Each(Truly([](const std::unique_ptr<QuicReceivedPacket>& packet) {
603 QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
604 PacketHeaderFormat unused_format;
605 bool unused_version_flag;
606 bool unused_use_length_prefix;
607 QuicVersionLabel unused_version_label;
608 ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion();
609 QuicConnectionId unused_destination_connection_id;
610 QuicConnectionId unused_source_connection_id;
611 std::optional<absl::string_view> unused_retry_token;
612 std::string unused_detailed_error;
613 QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
614 *packet, kQuicDefaultConnectionIdLength, &unused_format,
615 &long_packet_type, &unused_version_flag, &unused_use_length_prefix,
616 &unused_version_label, &unused_parsed_version,
617 &unused_destination_connection_id, &unused_source_connection_id,
618 &unused_retry_token, &unused_detailed_error);
619 return error_code == QUIC_NO_ERROR && long_packet_type == INITIAL;
620 })));
621
622 QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
623 PacketHeaderFormat unused_format;
624 bool unused_version_flag;
625 bool unused_use_length_prefix;
626 QuicVersionLabel unused_version_label;
627 ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion();
628 QuicConnectionId unused_destination_connection_id;
629 QuicConnectionId unused_source_connection_id;
630 std::optional<absl::string_view> unused_retry_token;
631 std::string unused_detailed_error;
632 QuicErrorCode error_code = QUIC_NO_ERROR;
633
634 // Verify that packet_ is not an INITIAL packet.
635 error_code = QuicFramer::ParsePublicHeaderDispatcher(
636 packet_, kQuicDefaultConnectionIdLength, &unused_format,
637 &long_packet_type, &unused_version_flag, &unused_use_length_prefix,
638 &unused_version_label, &unused_parsed_version,
639 &unused_destination_connection_id, &unused_source_connection_id,
640 &unused_retry_token, &unused_detailed_error);
641 EXPECT_THAT(error_code, IsQuicNoError());
642 EXPECT_NE(long_packet_type, INITIAL);
643
644 store_.EnqueuePacket(connection_id, false, packet_, self_address_,
645 peer_address_, valid_version_, kNoParsedChlo, nullptr);
646 store_.EnqueuePacket(connection_id, false, *initial_packets[0], self_address_,
647 peer_address_, valid_version_, kNoParsedChlo, nullptr);
648 store_.EnqueuePacket(connection_id, false, *initial_packets[1], self_address_,
649 peer_address_, valid_version_, kNoParsedChlo, nullptr);
650
651 BufferedPacketList delivered_packets = store_.DeliverPackets(connection_id);
652 EXPECT_THAT(delivered_packets.buffered_packets, SizeIs(3));
653
654 QuicLongHeaderType previous_packet_type = INITIAL;
655 for (const auto& packet : delivered_packets.buffered_packets) {
656 error_code = QuicFramer::ParsePublicHeaderDispatcher(
657 *packet.packet, kQuicDefaultConnectionIdLength, &unused_format,
658 &long_packet_type, &unused_version_flag, &unused_use_length_prefix,
659 &unused_version_label, &unused_parsed_version,
660 &unused_destination_connection_id, &unused_source_connection_id,
661 &unused_retry_token, &unused_detailed_error);
662 EXPECT_THAT(error_code, IsQuicNoError());
663
664 // INITIAL packets should not follow a non-INITIAL packet.
665 EXPECT_THAT(long_packet_type,
666 Conditional(previous_packet_type == INITIAL,
667 A<QuicLongHeaderType>(), Ne(INITIAL)));
668 previous_packet_type = long_packet_type;
669 }
670 }
671
672 // Test for b/316633326.
TEST_F(QuicBufferedPacketStoreTest,BufferedPacketRetainsEcn)673 TEST_F(QuicBufferedPacketStoreTest, BufferedPacketRetainsEcn) {
674 QuicConnectionId connection_id = TestConnectionId(1);
675 QuicReceivedPacket ect1_packet(packet_content_.data(), packet_content_.size(),
676 packet_time_, false, 0, true, nullptr, 0,
677 false, ECN_ECT1);
678 store_.EnqueuePacket(connection_id, false, ect1_packet, self_address_,
679 peer_address_, valid_version_, kNoParsedChlo, nullptr);
680 BufferedPacketList delivered_packets = store_.DeliverPackets(connection_id);
681 EXPECT_THAT(delivered_packets.buffered_packets, SizeIs(1));
682 for (const auto& packet : delivered_packets.buffered_packets) {
683 EXPECT_EQ(packet.packet->ecn_codepoint(), ECN_ECT1);
684 }
685 }
686
687 } // namespace
688 } // namespace test
689 } // namespace quic
690