gfe-relnote: No longer send a RESET_STREAM in response to a STOP_SENDING if the stream is write closed. Protected by disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 293529515
Change-Id: I0a837b79a776233d7a21fb8f87dbb7e173241a26
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 5bfa76b..153c787 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -1623,10 +1623,8 @@
QUIC_STREAM_CANCELLED, kByteOffset);
session_.OnRstStream(rst_frame);
if (VersionHasIetfQuicFrames(transport_version())) {
- // The test is predicated on the stream being fully closed. For IETF QUIC,
- // the RST_STREAM only does one side (the read side from the perspective of
- // the node receiving the RST_STREAM). This is needed to fully close the
- // stream and therefore fulfill all of the expects.
+ // The test requires the stream to be fully closed in both directions. For
+ // IETF QUIC, the RST_STREAM only closes one side.
QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -2138,10 +2136,8 @@
stream2->OnStreamReset(rst_frame);
if (VersionHasIetfQuicFrames(transport_version())) {
- // The test is predicated on the stream being fully closed. For IETF QUIC,
- // the RST_STREAM only does one side (the read side from the perspective of
- // the node receiving the RST_STREAM). This is needed to fully close the
- // stream and therefore fulfill all of the expects.
+ // The test requires the stream to be fully closed in both directions. For
+ // IETF QUIC, the RST_STREAM only closes one side.
QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
QUIC_STREAM_CANCELLED);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -2641,15 +2637,12 @@
session_.OnStreamFrame(unidirectional_stream_frame);
}
-// Check that the OnStopSendingFrame upcall handles bad input properly
-// First test checks that invalid stream ids are handled.
-TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
+// Checks that invalid stream ids are handled.
+TEST_P(QuicSessionTestServer, OnStopSendingInvalidStreamId) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}
// Check that "invalid" stream ids are rejected.
- // Note that the notion of an invalid stream id is Google-specific.
QuicStopSendingFrame frame(1, -1, 123);
EXPECT_CALL(
*connection_,
@@ -2658,11 +2651,22 @@
session_.OnStopSendingFrame(frame);
}
-// Second test, streams in the static stream map are not subject to
-// STOP_SENDING; it's ignored.
-TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
+TEST_P(QuicSessionTestServer, OnStopSendingReadUnidirectional) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
+ return;
+ }
+ // It's illegal to send STOP_SENDING with a stream ID that is read-only.
+ QuicStopSendingFrame frame(1, GetNthClientInitiatedUnidirectionalId(1), 123);
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Received STOP_SENDING for a read-only stream", _));
+ session_.OnStopSendingFrame(frame);
+}
+
+// Static streams ignore STOP_SENDING.
+TEST_P(QuicSessionTestServer, OnStopSendingStaticStreams) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
return;
}
QuicStreamId stream_id = 0;
@@ -2670,7 +2674,6 @@
stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
QuicSessionPeer::ActivateStream(&session_, std::move(fake_static_stream));
// Check that a stream id in the static stream map is ignored.
- // Note that the notion of a static stream is Google-specific.
QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
@@ -2678,31 +2681,41 @@
session_.OnStopSendingFrame(frame);
}
-// Third test, if stream id specifies a closed stream:
-// return true and do not close the connection.
-TEST_P(QuicSessionTestServer, OnStopSendingInputClosedStream) {
+// If stream is write closed, do not send a RESET_STREAM frame.
+TEST_P(QuicSessionTestServer, OnStopSendingForWriteClosedStream) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
QuicStreamId stream_id = stream->id();
- // Expect these as side effect of the close operations.
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(_, _));
stream->CloseWriteSide();
- stream->CloseReadSide();
+ EXPECT_TRUE(stream->write_side_closed());
QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
session_.OnStopSendingFrame(frame);
}
-// Fourth test, if stream id specifies a nonexistent stream, return false and
-// close the connection
+// If stream is closed, return true and do not close the connection.
+TEST_P(QuicSessionTestServer, OnStopSendingClosedStream) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
+ }
+
+ TestStream* stream = session_.CreateOutgoingBidirectionalStream();
+ QuicStreamId stream_id = stream->id();
+ // Expect these as side effect of closing the stream.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(_, _));
+ session_.CloseStream(stream_id);
+ QuicStopSendingFrame frame(1, stream_id, 123);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_.OnStopSendingFrame(frame);
+}
+
+// If stream id is a nonexistent stream, return false and close the connection.
TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentStream) {
if (!VersionHasIetfQuicFrames(transport_version())) {
- // Applicable only to IETF QUIC
return;
}