In quic, include minplaintextpacketsize when deterine whether removing soft limit for crypto frames. protected by enabled gfe2_reloadable_flag_quic_fix_min_crypto_frame_size.
PiperOrigin-RevId: 317743102
Change-Id: I43d56a2b3daea603cac4d2746f58426610875b0f
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index affd89f..d0f38a5 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -11345,6 +11345,44 @@
}
}
+// Regresstion test for b/156232673.
+TEST_P(QuicConnectionTest, CoalescePacketOfLowerEncryptionLevel) {
+ if (!connection_.version().CanSendCoalescedPackets()) {
+ return;
+ }
+ if (GetQuicReloadableFlag(quic_fix_min_crypto_frame_size)) {
+ EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(0);
+ }
+ {
+ QuicConnection::ScopedPacketFlusher flusher(&connection_);
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ SendStreamDataToPeer(2, string(1286, 'a'), 0, NO_FIN, nullptr);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+ // Try to coalesce a HANDSHAKE packet after 1-RTT packet.
+ if (GetQuicReloadableFlag(quic_fix_min_crypto_frame_size)) {
+ // Verify soft max packet length gets resumed and handshake packet gets
+ // successfully sent.
+ connection_.SendCryptoDataWithString("a", 0, ENCRYPTION_HANDSHAKE);
+ } else {
+ // Problematic: creator thinks there is space to consume 1-byte, however,
+ // extra paddings make the serialization fail because of
+ // MinPlaintextPacketSize.
+ EXPECT_CALL(visitor_,
+ OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
+ EXPECT_QUIC_BUG(
+ connection_.SendCryptoDataWithString("a", 0, ENCRYPTION_HANDSHAKE),
+ "AppendPaddingFrame of 3 failed");
+ }
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index 82b4a27..7672a37 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -198,6 +198,8 @@
}
if (framer_->GetMaxPlaintextSize(length) <
PacketHeaderSize() + MinPlaintextPacketSize(framer_->version())) {
+ // Please note: this would not guarantee to fit next packet if the size of
+ // packet header increases (e.g., encryption level changes).
QUIC_DLOG(INFO) << length << " is too small to fit packet header";
return;
}
@@ -423,8 +425,17 @@
QuicFrame* frame) {
size_t min_frame_size =
QuicFramer::GetMinCryptoFrameSize(write_length, offset);
- if (BytesFree() <= min_frame_size &&
- (!RemoveSoftMaxPacketLength() || BytesFree() <= min_frame_size)) {
+ size_t min_plaintext_bytes = min_frame_size;
+ if (fix_min_crypto_frame_size_ && queued_frames_.empty()) {
+ // TODO(fayang): to make this more general, we need to move the checking
+ // when trying to add a frame when GetSerializedFrameLength. Remove soft
+ // limit if current packet needs extra padding and the space is too small.
+ QUIC_RELOADABLE_FLAG_COUNT(quic_fix_min_crypto_frame_size);
+ min_plaintext_bytes =
+ std::max(min_frame_size, MinPlaintextPacketSize(framer_->version()));
+ }
+ if (BytesFree() <= min_plaintext_bytes &&
+ (!RemoveSoftMaxPacketLength() || BytesFree() <= min_plaintext_bytes)) {
return false;
}
size_t max_write_length = BytesFree() - min_frame_size;
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
index c25d8f6..743e46e 100644
--- a/quic/core/quic_packet_creator.h
+++ b/quic/core/quic_packet_creator.h
@@ -601,6 +601,9 @@
const bool avoid_leak_writer_buffer_ =
GetQuicReloadableFlag(quic_avoid_leak_writer_buffer);
+
+ const bool fix_min_crypto_frame_size_ =
+ GetQuicReloadableFlag(quic_fix_min_crypto_frame_size);
};
} // namespace quic