Commit cce7ad62 authored by landell's avatar landell Committed by Commit bot

Avoid sending double responding close control frames in WebSockets

This avoids sending a second ack close frame when we get a flow
control request from the renderer while waiting for the connection to
be closed.

BUG=

Review-Url: https://codereview.chromium.org/2845033002
Cr-Commit-Position: refs/heads/master@{#467964}
parent bc4bd9df
......@@ -477,7 +477,8 @@ ChannelState WebSocketChannel::SendFlowControl(int64_t quota) {
pending_received_frames_.pop();
}
if (pending_received_frames_.empty() && has_received_close_frame_) {
if (!InClosingState() && pending_received_frames_.empty() &&
has_received_close_frame_) {
// We've been waiting for the client to consume the frames before
// responding to the closing handshake initiated by the server.
return RespondToClosingHandshake();
......
......@@ -2542,6 +2542,39 @@ TEST_F(WebSocketChannelFlowControlTest, CloseFrameShouldNotOvertakeDataFrames) {
checkpoint.Call(4);
}
// SendFlowControl calls should not trigger multiple close respond frames.
TEST_F(WebSocketChannelFlowControlTest, DoNotSendMultipleCloseRespondFrames) {
std::unique_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
static constexpr InitFrame frames[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
"FIRST SECOND"},
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
CLOSE_DATA(NORMAL_CLOSURE, "GOOD BYE")},
};
stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
set_stream(std::move(stream));
Checkpoint checkpoint;
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST ")));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("SECOND")));
EXPECT_CALL(*event_interface_, OnClosingHandshake());
EXPECT_CALL(checkpoint, Call(2));
CreateChannelAndConnectWithQuota(6);
checkpoint.Call(1);
ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(6));
checkpoint.Call(2);
ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(6));
}
// RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
// WebSocketChannel actually only sets the mask bit in the header, it doesn't
// perform masking itself (not all transports actually use masking).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment