Move stream static checks from QuicSession to QuicStream.

This change is to encourage the rule of "If session needs to hand over things to the stream, let the stream do as much as it can".

gfe-relnote: no behavior change. not protected.
PiperOrigin-RevId: 298695625
Change-Id: I808702aec0f688cb1d2d83e8e84f85a4f73fa1c7
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc
index dbf9e66..575011e 100644
--- a/quic/core/quic_stream.cc
+++ b/quic/core/quic_stream.cc
@@ -390,6 +390,12 @@
 
   DCHECK(!(read_side_closed_ && write_side_closed_));
 
+  if (frame.fin && is_static_) {
+    OnUnrecoverableError(QUIC_INVALID_STREAM_ID,
+                         "Attempt to close a static stream");
+    return;
+  }
+
   if (type_ == WRITE_UNIDIRECTIONAL) {
     OnUnrecoverableError(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM,
                          "Data received on write unidirectional stream");
@@ -460,6 +466,28 @@
   sequencer_.OnStreamFrame(frame);
 }
 
+bool QuicStream::OnStopSending(uint16_t code) {
+  // Do not reset the stream if all data has been sent and acknowledged.
+  if (write_side_closed() && !IsWaitingForAcks()) {
+    QUIC_DVLOG(1) << ENDPOINT
+                  << "Ignoring STOP_SENDING for a write closed stream, id: "
+                  << id_;
+    return false;
+  }
+
+  if (is_static_) {
+    QUIC_DVLOG(1) << ENDPOINT
+                  << "Received STOP_SENDING for a static stream, id: " << id_
+                  << " Closing connection";
+    OnUnrecoverableError(QUIC_INVALID_STREAM_ID,
+                         "Received STOP_SENDING for a static stream");
+    return false;
+  }
+
+  stream_error_ = static_cast<QuicRstStreamErrorCode>(code);
+  return true;
+}
+
 int QuicStream::num_frames_received() const {
   return sequencer_.num_frames_received();
 }