In GFE QUIC, add a TCS record for statelessly closed connections.
Protected by FLAGS_quic_restart_flag_quic_tcs_logging_for_statelessly_closed_connections.
PiperOrigin-RevId: 567703047
diff --git a/quiche/quic/core/quic_dispatcher.cc b/quiche/quic/core/quic_dispatcher.cc
index 5beeeff..bdc339a 100644
--- a/quiche/quic/core/quic_dispatcher.cc
+++ b/quiche/quic/core/quic_dispatcher.cc
@@ -547,6 +547,7 @@
// By adding the connection to time wait list, following packets on this
// connection will not reach ShouldAcceptNewConnections().
StatelesslyTerminateConnection(
+ packet_info.self_address, packet_info.peer_address,
packet_info.destination_connection_id, packet_info.form,
packet_info.version_flag, packet_info.use_length_prefix,
packet_info.version, QUIC_HANDSHAKE_FAILED,
@@ -650,6 +651,7 @@
tls_alert_error_detail.empty() ? "Reject connection"
: tls_alert_error_detail;
StatelesslyTerminateConnection(
+ packet_info->self_address, packet_info->peer_address,
server_connection_id, packet_info->form, packet_info->version_flag,
packet_info->use_length_prefix, packet_info->version,
connection_close_error_code, connection_close_error_detail,
@@ -1038,6 +1040,8 @@
}
void QuicDispatcher::StatelesslyTerminateConnection(
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
QuicConnectionId server_connection_id, PacketHeaderFormat format,
bool version_flag, bool use_length_prefix, ParsedQuicVersion version,
QuicErrorCode error_code, const std::string& error_details,
@@ -1071,6 +1075,9 @@
QUIC_CODE_COUNT(quic_dispatcher_generated_connection_close);
QuicSession::RecordConnectionCloseAtServer(
error_code, ConnectionCloseSource::FROM_SELF);
+ OnStatelessConnectionCloseGenerated(self_address, peer_address,
+ server_connection_id, version,
+ error_code, error_details);
return;
}
@@ -1108,8 +1115,13 @@
quic_new_error_code_when_packets_buffered_too_long);
error_code = QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG;
}
+ QuicSocketAddress self_address, peer_address;
+ if (!early_arrived_packets.buffered_packets.empty()) {
+ self_address = early_arrived_packets.buffered_packets.front().self_address;
+ peer_address = early_arrived_packets.buffered_packets.front().peer_address;
+ }
StatelesslyTerminateConnection(
- server_connection_id,
+ self_address, peer_address, server_connection_id,
early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
: GOOGLE_QUIC_PACKET,
/*version_flag=*/true,
@@ -1286,7 +1298,8 @@
// The original connection ID does not correspond to an existing
// session. It is safe to send CONNECTION_CLOSE and add to TIME_WAIT.
StatelesslyTerminateConnection(
- original_connection_id, IETF_QUIC_LONG_HEADER_PACKET,
+ self_address, peer_address, original_connection_id,
+ IETF_QUIC_LONG_HEADER_PACKET,
/*version_flag=*/true, version.HasLengthPrefixedConnectionIds(),
version, QUIC_HANDSHAKE_FAILED,
"Connection ID collision, please retry",
diff --git a/quiche/quic/core/quic_dispatcher.h b/quiche/quic/core/quic_dispatcher.h
index 7f06b78..183b335 100644
--- a/quiche/quic/core/quic_dispatcher.h
+++ b/quiche/quic/core/quic_dispatcher.h
@@ -300,7 +300,11 @@
// 1) send connection close with |error_code| and |error_details| and add
// connection to time wait list or 2) directly add connection to time wait
// list with |action|.
+ // |self_address| and |peer_address| are passed to
+ // |OnStatelessConnectionCloseSent| when a connection close is sent.
void StatelesslyTerminateConnection(
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
QuicConnectionId server_connection_id, PacketHeaderFormat format,
bool version_flag, bool use_length_prefix, ParsedQuicVersion version,
QuicErrorCode error_code, const std::string& error_details,
@@ -330,6 +334,14 @@
// Called if a packet from an unseen connection is reset or rejected.
virtual void OnNewConnectionRejected() {}
+ // Called by |StatelesslyTerminateConnection| when a connection close packet
+ // is generated.
+ virtual void OnStatelessConnectionCloseGenerated(
+ const QuicSocketAddress& /*self_address*/,
+ const QuicSocketAddress& /*peer_address*/,
+ QuicConnectionId /*connection_id*/, ParsedQuicVersion /*version*/,
+ QuicErrorCode /*error_code*/, const std::string& /*error_details*/) {}
+
// Selects the preferred ALPN from a vector of ALPNs.
// This runs through the list of ALPNs provided by the client and picks the
// first one it supports. If no supported versions are found, the first
diff --git a/quiche/quic/test_tools/packet_dropping_test_writer.cc b/quiche/quic/test_tools/packet_dropping_test_writer.cc
index ac9625f..5987338 100644
--- a/quiche/quic/test_tools/packet_dropping_test_writer.cc
+++ b/quiche/quic/test_tools/packet_dropping_test_writer.cc
@@ -52,6 +52,7 @@
: clock_(nullptr),
cur_buffer_size_(0),
num_calls_to_write_(0),
+ passthrough_for_next_n_packets_(0),
// Do not require any number of successful writes before the first dropped
// packet.
num_consecutive_succesful_writes_(kMinSuccesfulWritesAfterPacketLoss),
@@ -94,6 +95,12 @@
ReleaseOldPackets();
QuicWriterMutexLock lock(&config_mutex_);
+ if (passthrough_for_next_n_packets_ > 0) {
+ --passthrough_for_next_n_packets_;
+ return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address,
+ peer_address, options, params);
+ }
+
if (fake_drop_first_n_packets_ > 0 &&
num_calls_to_write_ <=
static_cast<uint64_t>(fake_drop_first_n_packets_)) {
diff --git a/quiche/quic/test_tools/packet_dropping_test_writer.h b/quiche/quic/test_tools/packet_dropping_test_writer.h
index dd83cb3..2b05005 100644
--- a/quiche/quic/test_tools/packet_dropping_test_writer.h
+++ b/quiche/quic/test_tools/packet_dropping_test_writer.h
@@ -84,6 +84,15 @@
fake_packet_loss_percentage_ = fake_packet_loss_percentage;
}
+ // Once called, the next |passthrough_for_next_n_packets_| WritePacket() calls
+ // will always send the packets immediately, without being affected by the
+ // simulated error conditions.
+ void set_passthrough_for_next_n_packets(
+ uint32_t passthrough_for_next_n_packets) {
+ QuicWriterMutexLock lock(&config_mutex_);
+ passthrough_for_next_n_packets_ = passthrough_for_next_n_packets;
+ }
+
// Simulate dropping the first n packets unconditionally.
// Subsequent packets will be lost at fake_packet_loss_percentage_ if set.
void set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets) {
@@ -170,6 +179,7 @@
DelayedPacketList delayed_packets_;
QuicByteCount cur_buffer_size_;
uint64_t num_calls_to_write_;
+ uint32_t passthrough_for_next_n_packets_ QUIC_GUARDED_BY(config_mutex_);
int32_t num_consecutive_succesful_writes_;
QuicMutex config_mutex_;
diff --git a/quiche/quic/tools/quic_client_base.h b/quiche/quic/tools/quic_client_base.h
index d17503f..8e73acc 100644
--- a/quiche/quic/tools/quic_client_base.h
+++ b/quiche/quic/tools/quic_client_base.h
@@ -277,6 +277,8 @@
QuicConnectionHelperInterface* helper() { return helper_.get(); }
+ QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
+
NetworkHelper* network_helper();
const NetworkHelper* network_helper() const;
@@ -365,8 +367,6 @@
// Returns the client connection ID to use.
virtual QuicConnectionId GetClientConnectionId();
- QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
-
// Subclasses may need to explicitly clear the session on destruction
// if they create it with objects that will be destroyed before this is.
// You probably want to call this if you override CreateQuicSpdyClientSession.