gfe-relnote: Check for partial write when crypto frame gets retransmitted. This only affects T099 which supports amplification factor.

PiperOrigin-RevId: 272518334
Change-Id: Ia79b1ae533824e0c4a06de53a24451ea5f697e2b
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index 3081516..d62417f 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -256,6 +256,9 @@
       size_t bytes_consumed = session()->connection()->SendCryptoData(
           level, pending.length, pending.offset);
       send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
+      if (bytes_consumed < pending.length) {
+        break;
+      }
     }
   }
   session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
@@ -401,6 +404,9 @@
         crypto_frame->level, retransmission_length, retransmission_offset);
     send_buffer->OnStreamDataRetransmitted(retransmission_offset,
                                            bytes_consumed);
+    if (bytes_consumed < retransmission_length) {
+      break;
+    }
   }
   session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
 }
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc
index 095e2b7..4b2e2f7 100644
--- a/quic/core/quic_crypto_stream_test.cc
+++ b/quic/core/quic_crypto_stream_test.cc
@@ -586,6 +586,38 @@
       QuicCryptoFrame(ENCRYPTION_INITIAL, offset, large_frame));
 }
 
+TEST_F(QuicCryptoStreamTest, RetransmitCryptoFramesAndPartialWrite) {
+  if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+    return;
+  }
+
+  EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
+  InSequence s;
+  // Send [0, 1350) in ENCRYPTION_INITIAL.
+  EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
+  std::string data(1350, 'a');
+  EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 1350, 0))
+      .WillOnce(Invoke(connection_,
+                       &MockQuicConnection::QuicConnection_SendCryptoData));
+  stream_->WriteCryptoData(ENCRYPTION_INITIAL, data);
+
+  // Lost [0, 1000).
+  QuicCryptoFrame lost_frame(ENCRYPTION_INITIAL, 0, 1000);
+  stream_->OnCryptoFrameLost(&lost_frame);
+  EXPECT_TRUE(stream_->HasPendingCryptoRetransmission());
+  // Simulate connection is constrained by amplification restriction.
+  EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 1000, 0))
+      .WillOnce(Return(0));
+  stream_->WritePendingCryptoRetransmission();
+  EXPECT_TRUE(stream_->HasPendingCryptoRetransmission());
+  // Connection gets unblocked.
+  EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_INITIAL, 1000, 0))
+      .WillOnce(Invoke(connection_,
+                       &MockQuicConnection::QuicConnection_SendCryptoData));
+  stream_->WritePendingCryptoRetransmission();
+  EXPECT_FALSE(stream_->HasPendingCryptoRetransmission());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 01d2f79..223780b 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -85,8 +85,8 @@
 }
 
 bool ParsedQuicVersion::SupportsAntiAmplificationLimit() const {
-  // TODO(b/141944763) Enable this for version T099 once issue is resolved.
-  return false;
+  return transport_version == QUIC_VERSION_99 &&
+         handshake_protocol == PROTOCOL_TLS1_3;
 }
 
 bool VersionHasLengthPrefixedConnectionIds(