Fix quic::GetPacketHeaderSize when QuicVersionHasLongHeaderLengths is false

gfe-relnote: Bugfix in quic::GetPacketHeaderSize protected by gfe2_reloadable_flag_quic_fix_get_packet_header_size
PiperOrigin-RevId: 256043642
Change-Id: I1f943400e15a684b5cb84f2a11cbb294859f669e
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 749b3b6..3c5daa9 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1141,8 +1141,10 @@
     if (level == ENCRYPTION_INITIAL &&
         peer_framer_.version().KnowsWhichDecrypterToUse()) {
       header.version_flag = true;
-      header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
-      header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+      if (QuicVersionHasLongHeaderLengths(peer_framer_.transport_version())) {
+        header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+        header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+      }
     }
     if ((GetQuicRestartFlag(quic_do_not_override_connection_id) ||
          (level == ENCRYPTION_INITIAL &&
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc
index e0229bc..12fc9a2 100644
--- a/quic/core/quic_crypto_client_stream_test.cc
+++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -315,6 +315,7 @@
 }
 
 TEST_F(QuicCryptoClientStreamTest, PreferredVersion) {
+  SetQuicReloadableFlag(quic_fix_get_packet_header_size, true);
   // This mimics the case where client receives version negotiation packet, such
   // that, the preferred version is different from the packets' version.
   connection_ = new PacketSavingConnection(
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index f95a491..395b490 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -51,6 +51,16 @@
     QuicTransportVersion version,
     QuicConnectionId connection_id) {
   DCHECK(QuicUtils::IsConnectionIdValidForVersion(connection_id, version));
+  QuicVariableLengthIntegerLength retry_token_length_length =
+      VARIABLE_LENGTH_INTEGER_LENGTH_1;
+  QuicVariableLengthIntegerLength length_length =
+      VARIABLE_LENGTH_INTEGER_LENGTH_2;
+  if (!QuicVersionHasLongHeaderLengths(version) &&
+      GetQuicReloadableFlag(quic_fix_get_packet_header_size)) {
+    retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+    length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+    QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_get_packet_header_size, 2, 3);
+  }
   return QuicPacketCreator::StreamFramePacketOverhead(
       version, static_cast<QuicConnectionIdLength>(connection_id.length()),
       PACKET_0BYTE_CONNECTION_ID,
@@ -58,7 +68,7 @@
       /*include_diversification_nonce=*/true,
       VersionHasIetfInvariantHeader(version) ? PACKET_4BYTE_PACKET_NUMBER
                                              : PACKET_1BYTE_PACKET_NUMBER,
-      VARIABLE_LENGTH_INTEGER_LENGTH_1, VARIABLE_LENGTH_INTEGER_LENGTH_2,
+      retry_token_length_length, length_length,
       /*offset=*/0);
 }
 
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc
index 96b2760..dd4450e 100644
--- a/quic/core/quic_crypto_stream_test.cc
+++ b/quic/core/quic_crypto_stream_test.cc
@@ -512,6 +512,23 @@
   EXPECT_TRUE(session_.HasUnackedCryptoData());
 }
 
+// Regression test for bugfix of GetPacketHeaderSize.
+TEST_F(QuicCryptoStreamTest, CryptoMessageFramingOverhead) {
+  SetQuicReloadableFlag(quic_fix_get_packet_header_size, true);
+  for (auto version : AllSupportedTransportVersions()) {
+    SCOPED_TRACE(version);
+    QuicByteCount expected_overhead = 48;
+    if (VersionHasIetfInvariantHeader(version)) {
+      expected_overhead = 52;
+    }
+    if (QuicVersionHasLongHeaderLengths(version)) {
+      expected_overhead = 55;
+    }
+    EXPECT_EQ(expected_overhead, QuicCryptoStream::CryptoMessageFramingOverhead(
+                                     version, TestConnectionId()));
+  }
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index b29dacb..00dbaf0 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -84,7 +84,9 @@
               false),
       pending_padding_bytes_(0),
       needs_full_padding_(false),
-      can_set_transmission_type_(false) {
+      can_set_transmission_type_(false),
+      fix_get_packet_header_size_(
+          GetQuicReloadableFlag(quic_fix_get_packet_header_size)) {
   SetMaxPacketLength(kDefaultMaxPacketSize);
 }
 
@@ -1109,9 +1111,15 @@
       framer_->perspective() == Perspective::IS_SERVER;
   // IETF QUIC long headers include a length on client 0RTT packets.
   QuicVariableLengthIntegerLength length_length =
-      framer_->perspective() == Perspective::IS_CLIENT
-          ? VARIABLE_LENGTH_INTEGER_LENGTH_2
-          : VARIABLE_LENGTH_INTEGER_LENGTH_0;
+      VARIABLE_LENGTH_INTEGER_LENGTH_0;
+  if (framer_->perspective() == Perspective::IS_CLIENT) {
+    length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+  }
+  if (!QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
+      fix_get_packet_header_size_) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_get_packet_header_size, 3, 3);
+    length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+  }
   const size_t packet_header_size = GetPacketHeaderSize(
       framer_->transport_version(), GetDestinationConnectionIdLength(),
       // Assume CID lengths don't change, but version may be present.
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
index d2c94ef..2c2fffb 100644
--- a/quic/core/quic_packet_creator.h
+++ b/quic/core/quic_packet_creator.h
@@ -431,6 +431,9 @@
   // If true, packet_'s transmission type is only set by
   // SetPacketTransmissionType and does not get cleared in ClearPacket.
   bool can_set_transmission_type_;
+
+  // Latched value of quic_fix_get_packet_header_size flag.
+  bool fix_get_packet_header_size_;
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 3a4978c..802c07b 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -154,6 +154,7 @@
         data_("foo"),
         creator_(connection_id_, &client_framer_, &delegate_, &producer_),
         serialized_packet_(creator_.NoPacket()) {
+    QuicPacketCreatorPeer::EnableGetPacketHeaderSizeBugFix(&creator_);
     EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
     creator_.SetEncrypter(ENCRYPTION_HANDSHAKE, QuicMakeUnique<NullEncrypter>(
                                                     Perspective::IS_CLIENT));
@@ -1809,6 +1810,20 @@
   }
 }
 
+// Regression test for bugfix of GetPacketHeaderSize.
+TEST_P(QuicPacketCreatorTest, GetGuaranteedLargestMessagePayload) {
+  QuicTransportVersion version = GetParam().version.transport_version;
+  if (!VersionSupportsMessageFrames(version)) {
+    return;
+  }
+  QuicPacketLength expected_largest_payload = 1319;
+  if (QuicVersionHasLongHeaderLengths(version)) {
+    expected_largest_payload -= 2;
+  }
+  EXPECT_EQ(expected_largest_payload,
+            creator_.GetGuaranteedLargestMessagePayload());
+}
+
 TEST_P(QuicPacketCreatorTest, PacketTransmissionType) {
   creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
   creator_.set_can_set_transmission_type(true);
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc
index 7abf303..c6cef78 100644
--- a/quic/core/quic_packets.cc
+++ b/quic/core/quic_packets.cc
@@ -125,13 +125,24 @@
   if (VersionHasIetfInvariantHeader(version)) {
     if (include_version) {
       // Long header.
-      return kPacketHeaderTypeSize + kConnectionIdLengthSize +
-             destination_connection_id_length + source_connection_id_length +
-             (version > QUIC_VERSION_44 ? packet_number_length
-                                        : PACKET_4BYTE_PACKET_NUMBER) +
-             kQuicVersionSize +
-             (include_diversification_nonce ? kDiversificationNonceSize : 0) +
-             retry_token_length_length + retry_token_length + length_length;
+      size_t size = kPacketHeaderTypeSize + kConnectionIdLengthSize +
+                    destination_connection_id_length +
+                    source_connection_id_length +
+                    (version > QUIC_VERSION_44 ? packet_number_length
+                                               : PACKET_4BYTE_PACKET_NUMBER) +
+                    kQuicVersionSize;
+      if (include_diversification_nonce) {
+        size += kDiversificationNonceSize;
+      }
+      DCHECK(QuicVersionHasLongHeaderLengths(version) ||
+             retry_token_length_length + retry_token_length + length_length ==
+                 0);
+      if (QuicVersionHasLongHeaderLengths(version) ||
+          !GetQuicReloadableFlag(quic_fix_get_packet_header_size)) {
+        QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_get_packet_header_size, 1, 3);
+        size += retry_token_length_length + retry_token_length + length_length;
+      }
+      return size;
     }
     // Short header.
     return kPacketHeaderTypeSize + destination_connection_id_length +
diff --git a/quic/quartc/quartc_factory.cc b/quic/quartc/quartc_factory.cc
index 53eb34b..e609d65 100644
--- a/quic/quartc/quartc_factory.cc
+++ b/quic/quartc/quartc_factory.cc
@@ -82,6 +82,9 @@
   SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);   // Enable BBR6,7,8.
   SetQuicReloadableFlag(quic_unified_iw_options, true);   // Enable IWXX opts.
   SetQuicReloadableFlag(quic_bbr_flexible_app_limited, true);  // Enable BBR9.
+
+  // Fix GetPacketHeaderSize
+  SetQuicReloadableFlag(quic_fix_get_packet_header_size, true);
 }
 
 QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
diff --git a/quic/test_tools/quic_packet_creator_peer.cc b/quic/test_tools/quic_packet_creator_peer.cc
index e7af2d5..85c7687 100644
--- a/quic/test_tools/quic_packet_creator_peer.cc
+++ b/quic/test_tools/quic_packet_creator_peer.cc
@@ -137,5 +137,11 @@
   return creator->framer_;
 }
 
+// static
+void QuicPacketCreatorPeer::EnableGetPacketHeaderSizeBugFix(
+    QuicPacketCreator* creator) {
+  creator->fix_get_packet_header_size_ = true;
+}
+
 }  // namespace test
 }  // namespace quic
diff --git a/quic/test_tools/quic_packet_creator_peer.h b/quic/test_tools/quic_packet_creator_peer.h
index e040090..f8f3d59 100644
--- a/quic/test_tools/quic_packet_creator_peer.h
+++ b/quic/test_tools/quic_packet_creator_peer.h
@@ -57,6 +57,7 @@
 
   static EncryptionLevel GetEncryptionLevel(QuicPacketCreator* creator);
   static QuicFramer* framer(QuicPacketCreator* creator);
+  static void EnableGetPacketHeaderSizeBugFix(QuicPacketCreator* creator);
 };
 
 }  // namespace test