Do not SendInResponseToPacket or return true in CanWrite when connection ID is required but missing in the packet creator.
Protected by FLAGS_quic_reloadable_flag_quic_do_not_write_when_no_client_cid_available.
PiperOrigin-RevId: 533120959
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index b68aad0..adb6e87 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -47,6 +47,7 @@
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/common/platform/api/quiche_flag_utils.h"
+#include "quiche/common/platform/api/quiche_testvalue.h"
#include "quiche/common/quiche_text_utils.h"
namespace quic {
@@ -2455,6 +2456,16 @@
return;
}
+ if (GetQuicReloadableFlag(quic_do_not_write_when_no_client_cid_available)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_do_not_write_when_no_client_cid_available,
+ 1, 3);
+ if (IsMissingDestinationConnectionID()) {
+ QUICHE_RELOADABLE_FLAG_COUNT_N(
+ quic_do_not_write_when_no_client_cid_available, 2, 3);
+ return;
+ }
+ }
+
// If the writer is blocked, don't attempt to send packets now or in the send
// alarm. When the writer unblocks, OnCanWrite() will be called for this
// connection to send.
@@ -3186,14 +3197,18 @@
}
}
+bool QuicConnection::IsMissingDestinationConnectionID() const {
+ return peer_issued_cid_manager_ != nullptr &&
+ packet_creator_.GetDestinationConnectionId().IsEmpty();
+}
+
bool QuicConnection::ShouldGeneratePacket(
HasRetransmittableData retransmittable, IsHandshake handshake) {
QUICHE_DCHECK(handshake != IS_HANDSHAKE ||
QuicVersionUsesCryptoFrames(transport_version()))
<< ENDPOINT
<< "Handshake in STREAM frames should not check ShouldGeneratePacket";
- if (peer_issued_cid_manager_ != nullptr &&
- packet_creator_.GetDestinationConnectionId().IsEmpty()) {
+ if (IsMissingDestinationConnectionID()) {
QUICHE_DCHECK(version().HasIetfQuicFrames());
QUIC_CODE_COUNT(quic_generate_packet_blocked_by_no_connection_id);
QUIC_BUG_IF(quic_bug_90265_1, perspective_ == Perspective::IS_CLIENT);
@@ -3256,6 +3271,14 @@
return false;
}
+ if (GetQuicReloadableFlag(quic_do_not_write_when_no_client_cid_available)) {
+ if (IsMissingDestinationConnectionID()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_do_not_write_when_no_client_cid_available, 3, 3);
+ return false;
+ }
+ }
+
if (version().CanSendCoalescedPackets() &&
framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL) &&
framer_.is_processing_packet()) {
@@ -6282,9 +6305,15 @@
kMinNumOfActiveConnectionIds, client_connection_id, clock_,
alarm_factory_, this, context());
} else {
+ bool create_client_self_issued_cid_manager = true;
+ quiche::AdjustTestValue(
+ "quic::QuicConnection::create_cid_manager_when_set_client_cid",
+ &create_client_self_issued_cid_manager);
// Note in Chromium client, set_client_connection_id is not called and
// thus self_issued_cid_manager_ should be null.
- self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
+ if (create_client_self_issued_cid_manager) {
+ self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
+ }
}
}
QUIC_DLOG(INFO) << ENDPOINT << "setting client connection ID to "
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index fbfd952..f739644 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -725,6 +725,9 @@
override;
std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
+ // Whether destination connection ID is required but missing in the packet
+ // creator.
+ bool IsMissingDestinationConnectionID() const;
// QuicPacketCreator::DelegateInterface
bool ShouldGeneratePacket(HasRetransmittableData retransmittable,
IsHandshake handshake) override;
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 5023083..7f6ba62 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -47,6 +47,8 @@
QUIC_FLAG(quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true)
// If true, do not issue a new connection ID that has been claimed by another connection.
QUIC_FLAG(quic_reloadable_flag_quic_check_cid_collision_when_issue_new_cid, true)
+// If true, do not write when client CID is requried but missing in the packet creator.
+QUIC_FLAG(quic_reloadable_flag_quic_do_not_write_when_no_client_cid_available, true)
// If true, enable server retransmittable on wire PING.
QUIC_FLAG(quic_reloadable_flag_quic_enable_server_on_wire_ping, true)
// If true, flush pending frames as well as pending padding bytes on connection migration.