Remove static stream checks in QuicSession::OnRstStream() and let static sub-streams handle it.

The advantage of having sub stream classes override rather than QuicStream base class sanity check is that HTTP/3 streams are now able to throw HTTP/3 specific errors.

gfe-relnote: no behavior change. not protected.
PiperOrigin-RevId: 299190484
Change-Id: Icaa957f91eba4acb3518515b75d205bc22001ddc
diff --git a/quic/core/http/quic_headers_stream.cc b/quic/core/http/quic_headers_stream.cc
index 1e7feb3..8157dae 100644
--- a/quic/core/http/quic_headers_stream.cc
+++ b/quic/core/http/quic_headers_stream.cc
@@ -155,4 +155,9 @@
   }
 }
 
+void QuicHeadersStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
+  stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
+                                   "Attempt to reset headers stream");
+}
+
 }  // namespace quic
diff --git a/quic/core/http/quic_headers_stream.h b/quic/core/http/quic_headers_stream.h
index e97a78d..3786ddf 100644
--- a/quic/core/http/quic_headers_stream.h
+++ b/quic/core/http/quic_headers_stream.h
@@ -50,6 +50,8 @@
                                   QuicByteCount data_length,
                                   bool fin_retransmitted) override;
 
+  void OnStreamReset(const QuicRstStreamFrame& frame) override;
+
  private:
   friend class test::QuicHeadersStreamPeer;
 
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 2e46a5c..bd62260 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -1171,6 +1171,7 @@
 
 TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
   QuicStreamId id;
+  std::string error_message;
   // Initialize HTTP/3 control stream.
   if (VersionUsesHttp3(transport_version())) {
     id = GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
@@ -1178,17 +1179,19 @@
 
     QuicStreamFrame data1(id, false, 0, quiche::QuicheStringPiece(type, 1));
     session_.OnStreamFrame(data1);
+    error_message = "Attempt to reset receive control stream";
   } else {
     id = QuicUtils::GetHeadersStreamId(transport_version());
+    error_message = "Attempt to reset headers stream";
   }
 
   // Send two bytes of payload.
   QuicRstStreamFrame rst1(kInvalidControlFrameId, id,
                           QUIC_ERROR_PROCESSING_STREAM, 0);
-  EXPECT_CALL(*connection_,
-              CloseConnection(
-                  QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
-                  ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+  EXPECT_CALL(
+      *connection_,
+      CloseConnection(QUIC_INVALID_STREAM_ID, error_message,
+                      ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
   session_.OnRstStream(rst1);
 }
 
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index b368b61..094613c 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -194,6 +194,11 @@
   return newly_acked_length > 0;
 }
 
+void QuicCryptoStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
+  stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
+                                   "Attempt to reset crypto stream");
+}
+
 void QuicCryptoStream::NeuterUnencryptedStreamData() {
   if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
     for (const auto& interval : bytes_consumed_[ENCRYPTION_INITIAL]) {
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h
index 425d8c6..82f81fe 100644
--- a/quic/core/quic_crypto_stream.h
+++ b/quic/core/quic_crypto_stream.h
@@ -57,6 +57,8 @@
   bool OnCryptoFrameAcked(const QuicCryptoFrame& frame,
                           QuicTime::Delta ack_delay_time);
 
+  void OnStreamReset(const QuicRstStreamFrame& frame) override;
+
   // Performs key extraction to derive a new secret of |result_len| bytes
   // dependent on |label|, |context|, and the stream's negotiated subkey secret.
   // Returns false if the handshake has not been confirmed or the parameters are
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index e6f1aa7..0ca240e 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -366,12 +366,6 @@
     HandleRstOnValidNonexistentStream(frame);
     return;  // Errors are handled by GetOrCreateStream.
   }
-  if (stream->is_static()) {
-    connection()->CloseConnection(
-        QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
-    return;
-  }
   stream->OnStreamReset(frame);
 }
 
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 152e159..4f8dd4f 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -1472,27 +1472,6 @@
   session_.OnStreamFrame(data1);
 }
 
-TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
-  if (VersionUsesHttp3(connection_->transport_version())) {
-    // The test relies on headers stream, which no longer exists in IETF QUIC.
-    return;
-  }
-  QuicStreamId headers_stream_id =
-      QuicUtils::GetHeadersStreamId(connection_->transport_version());
-  std::unique_ptr<TestStream> fake_headers_stream =
-      std::make_unique<TestStream>(headers_stream_id, &session_,
-                                   /*is_static*/ true, BIDIRECTIONAL);
-  QuicSessionPeer::ActivateStream(&session_, std::move(fake_headers_stream));
-  // Send two bytes of payload.
-  QuicRstStreamFrame rst1(kInvalidControlFrameId, headers_stream_id,
-                          QUIC_ERROR_PROCESSING_STREAM, 0);
-  EXPECT_CALL(*connection_,
-              CloseConnection(
-                  QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
-                  ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
-  session_.OnRstStream(rst1);
-}
-
 TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
   // Send two bytes of payload.
   QuicStreamFrame data1(
diff --git a/quic/qbone/qbone_control_stream.cc b/quic/qbone/qbone_control_stream.cc
index 31a5070..0b453a7 100644
--- a/quic/qbone/qbone_control_stream.cc
+++ b/quic/qbone/qbone_control_stream.cc
@@ -65,4 +65,10 @@
   return true;
 }
 
+void QboneControlStreamBase::OnStreamReset(
+    const QuicRstStreamFrame& /*frame*/) {
+  stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
+                                   "Attempt to reset control stream");
+}
+
 }  // namespace quic
diff --git a/quic/qbone/qbone_control_stream.h b/quic/qbone/qbone_control_stream.h
index 0f4127b..10da82c 100644
--- a/quic/qbone/qbone_control_stream.h
+++ b/quic/qbone/qbone_control_stream.h
@@ -19,6 +19,8 @@
 
   void OnDataAvailable() override;
 
+  void OnStreamReset(const QuicRstStreamFrame& frame) override;
+
  protected:
   virtual void OnMessage(const std::string& data) = 0;
   bool SendMessage(const proto2::Message& proto);