Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Unified Diff: net/websockets/websocket_channel.cc

Issue 723343002: Update from https://crrev.com/304121 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/websockets/websocket_channel.h ('k') | net/websockets/websocket_channel_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/websockets/websocket_channel.cc
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc
index 598b5e64363ec1f7953c22a1875cad55c75a4344..30abb2db90fe8eb8c67fa3dc898d26a5a6003b61 100644
--- a/net/websockets/websocket_channel.cc
+++ b/net/websockets/websocket_channel.cc
@@ -44,9 +44,16 @@ using base::StreamingUtf8Validator;
const int kDefaultSendQuotaLowWaterMark = 1 << 16;
const int kDefaultSendQuotaHighWaterMark = 1 << 17;
const size_t kWebSocketCloseCodeLength = 2;
-// This timeout is based on TCPMaximumSegmentLifetime * 2 from
-// MainThreadWebSocketChannel.cpp in Blink.
-const int kClosingHandshakeTimeoutSeconds = 2 * 2 * 60;
+// Timeout for waiting for the server to acknowledge a closing handshake.
+const int kClosingHandshakeTimeoutSeconds = 60;
+// We wait for the server to close the underlying connection as recommended in
+// https://tools.ietf.org/html/rfc6455#section-7.1.1
+// We don't use 2MSL since there're server implementations that don't follow
+// the recommendation and wait for the client to close the underlying
+// connection. It leads to unnecessarily long time before CloseEvent
+// invocation. We want to avoid this rather than strictly following the spec
+// recommendation.
+const int kUnderlyingConnectionCloseTimeoutSeconds = 2;
typedef WebSocketEventInterface::ChannelState ChannelState;
const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
@@ -296,7 +303,10 @@ WebSocketChannel::WebSocketChannel(
send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark),
current_send_quota_(0),
current_receive_quota_(0),
- timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)),
+ closing_handshake_timeout_(base::TimeDelta::FromSeconds(
+ kClosingHandshakeTimeoutSeconds)),
+ underlying_connection_close_timeout_(base::TimeDelta::FromSeconds(
+ kUnderlyingConnectionCloseTimeoutSeconds)),
has_received_close_frame_(false),
received_close_code_(0),
state_(FRESHLY_CONSTRUCTED),
@@ -312,7 +322,7 @@ WebSocketChannel::~WebSocketChannel() {
stream_.reset();
// The timer may have a callback pointing back to us, so stop it just in case
// someone decides to run the event loop from their destructor.
- timer_.Stop();
+ close_timer_.Stop();
}
void WebSocketChannel::SendAddChannelRequest(
@@ -478,6 +488,15 @@ void WebSocketChannel::StartClosingHandshake(uint16 code,
NOTREACHED() << "StartClosingHandshake() called in state " << state_;
return;
}
+
+ DCHECK(!close_timer_.IsRunning());
+ // This use of base::Unretained() is safe because we stop the timer in the
+ // destructor.
+ close_timer_.Start(
+ FROM_HERE,
+ closing_handshake_timeout_,
+ base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this)));
+
// Javascript actually only permits 1000 and 3000-4999, but the implementation
// itself may produce different codes. The length of |reason| is also checked
// by Javascript.
@@ -513,7 +532,12 @@ void WebSocketChannel::SendAddChannelRequestForTesting(
void WebSocketChannel::SetClosingHandshakeTimeoutForTesting(
base::TimeDelta delay) {
- timeout_ = delay;
+ closing_handshake_timeout_ = delay;
+}
+
+void WebSocketChannel::SetUnderlyingConnectionCloseTimeoutForTesting(
+ base::TimeDelta delay) {
+ underlying_connection_close_timeout_ = delay;
}
void WebSocketChannel::SendAddChannelRequestWithSuppliedCreator(
@@ -839,10 +863,20 @@ ChannelState WebSocketChannel::HandleFrameByState(
switch (state_) {
case CONNECTED:
SetState(RECV_CLOSED);
+
if (SendClose(code, reason) == CHANNEL_DELETED)
return CHANNEL_DELETED;
DCHECK_EQ(RECV_CLOSED, state_);
+
SetState(CLOSE_WAIT);
+ DCHECK(!close_timer_.IsRunning());
+ // This use of base::Unretained() is safe because we stop the timer
+ // in the destructor.
+ close_timer_.Start(
+ FROM_HERE,
+ underlying_connection_close_timeout_,
+ base::Bind(
+ &WebSocketChannel::CloseTimeout, base::Unretained(this)));
if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED)
return CHANNEL_DELETED;
@@ -853,6 +887,16 @@ ChannelState WebSocketChannel::HandleFrameByState(
case SEND_CLOSED:
SetState(CLOSE_WAIT);
+ DCHECK(close_timer_.IsRunning());
+ close_timer_.Stop();
+ // This use of base::Unretained() is safe because we stop the timer
+ // in the destructor.
+ close_timer_.Start(
+ FROM_HERE,
+ underlying_connection_close_timeout_,
+ base::Bind(
+ &WebSocketChannel::CloseTimeout, base::Unretained(this)));
+
// From RFC6455 section 7.1.5: "Each endpoint
// will see the status code sent by the other end as _The WebSocket
// Connection Close Code_."
@@ -1027,12 +1071,6 @@ ChannelState WebSocketChannel::SendClose(uint16 code,
std::copy(
reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength);
}
- // This use of base::Unretained() is safe because we stop the timer in the
- // destructor.
- timer_.Start(
- FROM_HERE,
- timeout_,
- base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this)));
if (SendFrameFromIOBuffer(
true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
CHANNEL_DELETED)
« no previous file with comments | « net/websockets/websocket_channel.h ('k') | net/websockets/websocket_channel_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698