xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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