gfe-relnote: Move headers streams out of static stream map. Protected by
gfe_reloadable_quic_eliminate_static_stream_map.
Following up this CL, crypto stream will be moved out of static_stream_map too.
PiperOrigin-RevId: 244429772
Change-Id: I5186bc7ab4e6ee9c9f546a3c9456be489a4ddc26
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 36070a4..91d323b 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -61,6 +61,8 @@
config_.GetMaxIncomingDynamicStreamsToSend()),
num_dynamic_incoming_streams_(0),
num_draining_incoming_streams_(0),
+ num_outgoing_static_streams_(0),
+ num_incoming_static_streams_(0),
num_locally_closed_incoming_streams_highest_offset_(0),
error_(QUIC_NO_ERROR),
flow_controller_(
@@ -118,6 +120,20 @@
}
}
+void QuicSession::RegisterStaticStreamNew(std::unique_ptr<QuicStream> stream) {
+ DCHECK(GetQuicReloadableFlag(quic_eliminate_static_stream_map));
+ QuicStreamId stream_id = stream->id();
+ dynamic_stream_map_[stream_id] = std::move(stream);
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ v99_streamid_manager_.RegisterStaticStream(stream_id);
+ }
+ if (IsIncomingStream(stream_id)) {
+ ++num_incoming_static_streams_;
+ } else {
+ ++num_outgoing_static_streams_;
+ }
+}
+
void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
// TODO(rch) deal with the error case of stream id 0.
QuicStreamId stream_id = frame.stream_id;
@@ -152,6 +168,14 @@
}
return;
}
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map) && frame.fin &&
+ handler.stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map, 1, 9);
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
handler.stream->OnStreamFrame(frame);
}
@@ -230,6 +254,19 @@
<< stream_id << ". Ignoring.";
return true;
}
+
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map) &&
+ stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map, 2, 9);
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Received STOP_SENDING for a static stream, id: "
+ << stream_id << " Closing connection";
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+
stream->OnStopSending(frame.application_error_code);
stream->set_stream_error(
@@ -277,6 +314,14 @@
HandleRstOnValidNonexistentStream(frame);
return; // Errors are handled by GetOrCreateStream.
}
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map) &&
+ handler.stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map, 3, 9);
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
handler.stream->OnStreamReset(frame);
}
@@ -317,14 +362,35 @@
error_ = error;
}
- while (!dynamic_stream_map_.empty()) {
- DynamicStreamMap::iterator it = dynamic_stream_map_.begin();
- QuicStreamId id = it->first;
- it->second->OnConnectionClosed(error, source);
- // The stream should call CloseStream as part of OnConnectionClosed.
- if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
- QUIC_BUG << ENDPOINT << "Stream failed to close under OnConnectionClosed";
- CloseStream(id);
+ if (!GetQuicReloadableFlag(quic_eliminate_static_stream_map)) {
+ while (!dynamic_stream_map_.empty()) {
+ DynamicStreamMap::iterator it = dynamic_stream_map_.begin();
+ QuicStreamId id = it->first;
+ it->second->OnConnectionClosed(error, source);
+ // The stream should call CloseStream as part of OnConnectionClosed.
+ if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
+ QUIC_BUG << ENDPOINT << "Stream " << id
+ << " failed to close under OnConnectionClosed";
+ CloseStream(id);
+ }
+ }
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map, 4, 9);
+ // Copy all non static streams in a new map for the ease of deleting.
+ QuicSmallMap<QuicStreamId, QuicStream*, 10> non_static_streams;
+ for (const auto& it : dynamic_stream_map_) {
+ if (!it.second->is_static()) {
+ non_static_streams[it.first] = it.second.get();
+ }
+ }
+ for (const auto& it : non_static_streams) {
+ QuicStreamId id = it.first;
+ it.second->OnConnectionClosed(error, source);
+ if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
+ QUIC_BUG << ENDPOINT << "Stream " << id
+ << " failed to close under OnConnectionClosed";
+ CloseStream(id);
+ }
}
}
@@ -533,7 +599,8 @@
uint64_t QuicSession::GetNumOpenDynamicStreams() const {
return dynamic_stream_map_.size() - draining_streams_.size() +
- locally_closed_streams_highest_offset_.size();
+ locally_closed_streams_highest_offset_.size() -
+ num_incoming_static_streams_ - num_outgoing_static_streams_;
}
void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
@@ -625,6 +692,17 @@
DynamicStreamMap::iterator it = dynamic_stream_map_.find(id);
if (it != dynamic_stream_map_.end()) {
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map) &&
+ it->second->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map, 5, 9);
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Try to send rst for a static stream, id: " << id
+ << " Closing connection";
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Sending rst for a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
QuicStream* stream = it->second.get();
if (stream) {
stream->set_rst_sent(true);
@@ -687,6 +765,17 @@
return;
}
QuicStream* stream = it->second.get();
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map) &&
+ stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map, 6, 9);
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Try to close a static stream, id: " << stream_id
+ << " Closing connection";
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Try to close a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
// Tell the stream that a RST has been sent.
if (locally_reset) {
@@ -1024,6 +1113,7 @@
}
void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
+ DCHECK(!stream->is_static());
QuicStreamId stream_id = stream->id();
QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size()
<< ". activating " << stream_id;
@@ -1245,7 +1335,8 @@
}
size_t QuicSession::GetNumActiveStreams() const {
- return dynamic_stream_map_.size() - draining_streams_.size();
+ return dynamic_stream_map_.size() - draining_streams_.size() -
+ num_incoming_static_streams_ - num_outgoing_static_streams_;
}
size_t QuicSession::GetNumDrainingStreams() const {
@@ -1280,9 +1371,11 @@
size_t QuicSession::GetNumDynamicOutgoingStreams() const {
DCHECK_GE(static_cast<size_t>(dynamic_stream_map_.size() +
pending_stream_map_.size()),
- num_dynamic_incoming_streams_);
+ num_dynamic_incoming_streams_ + num_outgoing_static_streams_ +
+ num_incoming_static_streams_);
return dynamic_stream_map_.size() + pending_stream_map_.size() -
- num_dynamic_incoming_streams_;
+ num_dynamic_incoming_streams_ - num_outgoing_static_streams_ -
+ num_incoming_static_streams_;
}
size_t QuicSession::GetNumDrainingOutgoingStreams() const {