Set client CID in the packets sent by QuicBufferedPacketStore.

Protected by quic_reloadable_flag_quic_buffered_store_set_client_cid.

PiperOrigin-RevId: 700077952
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h
index 11b419d..ec1183e 100755
--- a/quiche/common/quiche_feature_flags_list.h
+++ b/quiche/common/quiche_feature_flags_list.h
@@ -17,6 +17,7 @@
 QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_probe_two_rounds, true, true, "When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP.")
 QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_simplify_inflight_hi, true, true, "When true, the BBHI copt causes QUIC BBRv2 to use a simpler algorithm for raising inflight_hi in PROBE_UP.")
 QUICHE_FLAG(bool, quiche_reloadable_flag_quic_block_until_settings_received_copt, true, true, "If enabled and a BSUS connection is received, blocks server connections until SETTINGS frame is received.")
+QUICHE_FLAG(bool, quiche_reloadable_flag_quic_buffered_store_set_client_cid, false, false, "If true, QuicBufferedPacketStore will set client CID in packets it generates.")
 QUICHE_FLAG(bool, quiche_reloadable_flag_quic_can_send_ack_frequency, true, true, "If true, ack frequency frame can be sent from server to client.")
 QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_bursts, false, false, "If true, set burst token to 2 in cwnd bootstrapping experiment.")
 QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false, false, "If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.")
diff --git a/quiche/quic/core/quic_buffered_packet_store.cc b/quiche/quic/core/quic_buffered_packet_store.cc
index 4421b66..42d00ff 100644
--- a/quiche/quic/core/quic_buffered_packet_store.cc
+++ b/quiche/quic/core/quic_buffered_packet_store.cc
@@ -313,6 +313,11 @@
   PacketCollector collector(&send_buffer_allocator);
   QuicPacketCreator creator(server_connection_id, &framer, &collector);
 
+  if (GetQuicReloadableFlag(quic_buffered_store_set_client_cid)) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_buffered_store_set_client_cid);
+    creator.SetClientConnectionId(packet_info.source_connection_id);
+  }
+
   if (!dispatcher_sent_packets.empty()) {
     // Sets the *last sent* packet number, creator will derive the next sending
     // packet number accordingly.
diff --git a/quiche/quic/core/quic_buffered_packet_store_test.cc b/quiche/quic/core/quic_buffered_packet_store_test.cc
index 60495dc..d3400f0 100644
--- a/quiche/quic/core/quic_buffered_packet_store_test.cc
+++ b/quiche/quic/core/quic_buffered_packet_store_test.cc
@@ -14,6 +14,9 @@
 #include <utility>
 #include <vector>
 
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/transport_parameters.h"
@@ -117,13 +120,31 @@
         packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)),
         packet_(packet_content_.data(), packet_content_.size(), packet_time_),
         invalid_version_(UnsupportedQuicVersion()),
-        valid_version_(CurrentSupportedVersions().front()) {}
+        valid_version_(CurrentSupportedVersions().front()) {
+    store_.set_writer(&mock_packet_writer_);
+
+    EXPECT_CALL(mock_packet_writer_, IsWriteBlocked())
+        .WillRepeatedly(Return(false));
+    EXPECT_CALL(mock_packet_writer_, WritePacket(_, _, _, _, _, _))
+        .WillRepeatedly(testing::Invoke(
+            [&](const char* buffer, size_t buf_len, const QuicIpAddress&,
+                const QuicSocketAddress&, PerPacketOptions*,
+                const QuicPacketWriterParams&) {
+              // This packet is sent by the store and "received" by the client.
+              client_received_packets_.push_back(
+                  std::make_unique<ClientReceivedPacket>(
+                      buffer, buf_len, peer_address_, self_address_));
+              return WriteResult(WRITE_STATUS_OK, buf_len);
+            }));
+  }
 
  protected:
   QuicDispatcherStats stats_;
   QuicBufferedPacketStoreVisitor visitor_;
   MockClock clock_;
   MockAlarmFactory alarm_factory_;
+  // Mock the sending of the INITIAL ACK packets.
+  MockPacketWriter mock_packet_writer_;
   QuicBufferedPacketStore store_;
   QuicSocketAddress self_address_;
   QuicSocketAddress peer_address_;
@@ -133,6 +154,35 @@
   const ParsedQuicVersion invalid_version_;
   const ParsedQuicVersion valid_version_;
   MockConnectionIdGenerator connection_id_generator_;
+
+  // A packet that is sent by the store and "received" by the client.
+  struct ClientReceivedPacket {
+    ClientReceivedPacket(const char* buffer, size_t buf_len,
+                         const QuicSocketAddress& client_address,
+                         const QuicSocketAddress& server_address)
+        : self_address(client_address),
+          peer_address(server_address),
+          packet(QuicReceivedPacket(buffer, buf_len, QuicTime::Zero()).Clone()),
+          packet_info(self_address, peer_address, *packet) {
+      std::string detailed_error;
+      MockConnectionIdGenerator unused_generator;
+      if (QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown(
+              *packet, &packet_info.form, &packet_info.long_packet_type,
+              &packet_info.version_flag, &packet_info.use_length_prefix,
+              &packet_info.version_label, &packet_info.version,
+              &packet_info.destination_connection_id,
+              &packet_info.source_connection_id, &packet_info.retry_token,
+              &detailed_error, unused_generator) != QUIC_NO_ERROR) {
+        ADD_FAILURE() << "Failed to parse packet header: " << detailed_error;
+      }
+    }
+
+    const QuicSocketAddress self_address;
+    const QuicSocketAddress peer_address;
+    std::unique_ptr<QuicReceivedPacket> packet;
+    ReceivedPacketInfo packet_info;
+  };
+  std::vector<std::unique_ptr<ClientReceivedPacket>> client_received_packets_;
 };
 
 TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
@@ -837,6 +887,49 @@
   }
 }
 
+TEST_F(QuicBufferedPacketStoreTest, InitialAckHasClientConnectionId) {
+  const QuicConnectionId kDCID = TestConnectionId(1);
+  const QuicConnectionId kSCID = TestConnectionId(42);
+  const std::string crypto_data = "crypto_data";
+  ParsedQuicVersionVector versions = {ParsedQuicVersion::RFCv1()};
+  std::unique_ptr<QuicEncryptedPacket> client_initial_packet(
+      ConstructEncryptedPacket(
+          kDCID, kSCID, /*version_flag=*/true, /*reset_flag=*/false,
+          /*packet_number=*/1, crypto_data, /*full_padding=*/true,
+          CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
+          PACKET_4BYTE_PACKET_NUMBER, &versions, Perspective::IS_CLIENT));
+
+  QuicReceivedPacket received_client_initial(client_initial_packet->data(),
+                                             client_initial_packet->length(),
+                                             QuicTime::Zero());
+  ReceivedPacketInfo packet_info(self_address_, peer_address_,
+                                 received_client_initial);
+  std::string detailed_error;
+  ASSERT_EQ(QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown(
+                received_client_initial, &packet_info.form,
+                &packet_info.long_packet_type, &packet_info.version_flag,
+                &packet_info.use_length_prefix, &packet_info.version_label,
+                &packet_info.version, &packet_info.destination_connection_id,
+                &packet_info.source_connection_id, &packet_info.retry_token,
+                &detailed_error, connection_id_generator_),
+            QUIC_NO_ERROR)
+      << detailed_error;
+  store_.EnqueuePacket(packet_info, kNoParsedChlo, connection_id_generator_);
+  ASSERT_EQ(client_received_packets_.size(), 1u);
+
+  const ReceivedPacketInfo& client_received_packet_info =
+      client_received_packets_[0]->packet_info;
+  // From the client's perspective, the destination connection ID is kSCID and
+  // the source connection ID is kDCID.
+  if (GetQuicReloadableFlag(quic_buffered_store_set_client_cid)) {
+    EXPECT_EQ(client_received_packet_info.destination_connection_id, kSCID);
+  } else {
+    EXPECT_EQ(client_received_packet_info.destination_connection_id,
+              EmptyQuicConnectionId());
+  }
+  EXPECT_EQ(client_received_packet_info.source_connection_id, kDCID);
+}
+
 TEST_F(QuicBufferedPacketStoreTest, EmptyBufferedPacketList) {
   BufferedPacketList packet_list;
   EXPECT_TRUE(packet_list.buffered_packets.empty());