Make time wait list aware of original server connection ID. Also, encrypt INITIAL termination packet with crypter using original server connection ID.
Protected by FLAGS_quic_reloadable_flag_quic_consider_original_connection_id_as_active_pre_handshake.
PiperOrigin-RevId: 448574254
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc
index 019409d..37e302e 100644
--- a/quiche/quic/core/http/end_to_end_test.cc
+++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -4796,14 +4796,8 @@
// Regression test for b/116200989.
TEST_P(EndToEndTest,
SendStatelessResetIfServerConnectionClosedLocallyDuringHandshake) {
- // TODO(b/232285861)
- // This test should probably work when the server issues a new connection ID
- // during the handshake. When the bug is fixed, remove the check below to
- // allow it to run when the client provides a 16B connection ID.
- if (override_server_connection_id_length_ > -1) {
- ASSERT_TRUE(Initialize());
- return;
- }
+ SetQuicReloadableFlag(
+ quic_consider_original_connection_id_as_active_pre_handshake, true);
connect_to_server_on_initialize_ = false;
ASSERT_TRUE(Initialize());
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 1e458c6..49681b7 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -6940,11 +6940,38 @@
std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds()
const {
+ QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective_);
+ std::vector<QuicConnectionId> result;
if (self_issued_cid_manager_ == nullptr) {
- return {default_path_.server_connection_id};
+ result.push_back(default_path_.server_connection_id);
+ } else {
+ QUICHE_DCHECK(version().HasIetfQuicFrames());
+ result = self_issued_cid_manager_->GetUnretiredConnectionIds();
}
- QUICHE_DCHECK(version().HasIetfQuicFrames());
- return self_issued_cid_manager_->GetUnretiredConnectionIds();
+ if (GetQuicReloadableFlag(
+ quic_consider_original_connection_id_as_active_pre_handshake)) {
+ QUIC_RELOADABLE_FLAG_COUNT(
+ quic_consider_original_connection_id_as_active_pre_handshake);
+ if (!IsHandshakeComplete() &&
+ original_destination_connection_id_.has_value()) {
+ // Consider original_destination_connection_id_ as active before handshake
+ // completes.
+ if (std::find(result.begin(), result.end(),
+ original_destination_connection_id_.value()) !=
+ result.end()) {
+ QUIC_BUG(quic_unexpected_original_destination_connection_id)
+ << "original_destination_connection_id: "
+ << original_destination_connection_id_.value()
+ << " is unexpectedly in active "
+ "list";
+ } else {
+ result.insert(result.end(),
+ original_destination_connection_id_.value());
+ }
+ QUIC_CODE_COUNT(quic_active_original_connection_id_pre_handshake);
+ }
+ }
+ return result;
}
void QuicConnection::CreateConnectionIdManager() {
diff --git a/quiche/quic/core/quic_dispatcher.cc b/quiche/quic/core/quic_dispatcher.cc
index 281b584..9166a93 100644
--- a/quiche/quic/core/quic_dispatcher.cc
+++ b/quiche/quic/core/quic_dispatcher.cc
@@ -148,6 +148,7 @@
class StatelessConnectionTerminator {
public:
StatelessConnectionTerminator(QuicConnectionId server_connection_id,
+ QuicConnectionId original_server_connection_id,
const ParsedQuicVersion version,
QuicConnectionHelperInterface* helper,
QuicTimeWaitListManager* time_wait_list_manager)
@@ -159,7 +160,8 @@
creator_(server_connection_id, &framer_, &collector_),
time_wait_list_manager_(time_wait_list_manager) {
framer_.set_data_producer(&collector_);
- framer_.SetInitialObfuscators(server_connection_id);
+ // Always set encrypter with original_server_connection_id.
+ framer_.SetInitialObfuscators(original_server_connection_id);
}
~StatelessConnectionTerminator() {
@@ -902,8 +904,9 @@
// This serializes a connection close termination packet and adds the
// connection to the time wait list.
StatelessConnectionTerminator terminator(
- server_connection_id, connection->version(), helper_.get(),
- time_wait_list_manager_.get());
+ server_connection_id,
+ connection->GetOriginalDestinationConnectionId(),
+ connection->version(), helper_.get(), time_wait_list_manager_.get());
terminator.CloseConnection(
QUIC_HANDSHAKE_FAILED,
"Connection is closed by server before handshake confirmed",
@@ -1138,9 +1141,9 @@
<< version << ", error_code:" << error_code
<< ", error_details:" << error_details;
- StatelessConnectionTerminator terminator(server_connection_id, version,
- helper_.get(),
- time_wait_list_manager_.get());
+ StatelessConnectionTerminator terminator(
+ server_connection_id, server_connection_id, version, helper_.get(),
+ time_wait_list_manager_.get());
// This also adds the connection to time wait list.
terminator.CloseConnection(
error_code, error_details, format != GOOGLE_QUIC_PACKET,
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 688d0a8..ab90711 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -31,6 +31,8 @@
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, true)
// If true, close read side but not write side in QuicSpdyStream::OnStreamReset().
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_on_stream_reset, true)
+// If true, consider original connection ID as active before handshake completes.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_consider_original_connection_id_as_active_pre_handshake, false)
// If true, consolidate more logic into SetRetransmissionAlarm to ensure the logic is applied consistently.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_simplify_set_retransmission_alarm, true)
// If true, default-enable 5RTO blachole detection.