WebSocket over H2: Detect stream close correctly
Previously WebSocket over HTTP/2 didn't handle the case when a server
half-closes the stream after sending the Close frame correctly. It would
fail to detect the half-close and timeout after 2 seconds, considering
the close to be unclean.
Modify WebSocketSpdyStreamAdapter::OnDataReceived to close the stream
when a half-close is detected.
Also modify SpdyStream to notify its delegate when a half close is
detected. This was already the documented behaviour.
BUG=1151393
Change-Id: I668d6ae0dc5a3926efade1c28f16ca379f5b1566
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2721519
Auto-Submit: Adam Rice <[email protected]>
Commit-Queue: Bence Béky <[email protected]>
Reviewed-by: Bence Béky <[email protected]>
Cr-Commit-Position: refs/heads/master@{#858542}
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index ffbb1591..bba60fa 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -1856,6 +1856,57 @@
EXPECT_TRUE(data.AllWriteDataConsumed());
}
+TEST_F(SpdyStreamTest, DelegateIsInformedOfEOF) {
+ spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
+ kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
+ AddWrite(req);
+
+ spdy::Http2HeaderBlock response_headers;
+ response_headers[spdy::kHttp2StatusHeader] = "200";
+ spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(response_headers), /* fin = */ true));
+ AddRead(resp);
+
+ spdy::SpdySerializedFrame data_frame(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true));
+ AddRead(data_frame);
+
+ spdy::SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_STREAM_CLOSED));
+ AddWrite(rst);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+ EXPECT_EQ(kDefaultUrl, stream->url().spec());
+
+ StreamDelegateDetectEOF delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ spdy::Http2HeaderBlock headers(
+ spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
+ EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
+ IsError(ERR_IO_PENDING));
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(delegate.eof_detected());
+
+ EXPECT_TRUE(data.AllReadDataConsumed());
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+}
+
} // namespace test
} // namespace net