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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/websockets/websocket_channel.h" 5 #include "net/websockets/websocket_channel.h"
6 6
7 #include <limits.h> // for INT_MAX 7 #include <limits.h> // for INT_MAX
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <deque> 10 #include <deque>
(...skipping 26 matching lines...) Expand all
37 37
38 namespace net { 38 namespace net {
39 39
40 namespace { 40 namespace {
41 41
42 using base::StreamingUtf8Validator; 42 using base::StreamingUtf8Validator;
43 43
44 const int kDefaultSendQuotaLowWaterMark = 1 << 16; 44 const int kDefaultSendQuotaLowWaterMark = 1 << 16;
45 const int kDefaultSendQuotaHighWaterMark = 1 << 17; 45 const int kDefaultSendQuotaHighWaterMark = 1 << 17;
46 const size_t kWebSocketCloseCodeLength = 2; 46 const size_t kWebSocketCloseCodeLength = 2;
47 // This timeout is based on TCPMaximumSegmentLifetime * 2 from 47 // Timeout for waiting for the server to acknowledge a closing handshake.
48 // MainThreadWebSocketChannel.cpp in Blink. 48 const int kClosingHandshakeTimeoutSeconds = 60;
49 const int kClosingHandshakeTimeoutSeconds = 2 * 2 * 60; 49 // We wait for the server to close the underlying connection as recommended in
50 // https://tools.ietf.org/html/rfc6455#section-7.1.1
51 // We don't use 2MSL since there're server implementations that don't follow
52 // the recommendation and wait for the client to close the underlying
53 // connection. It leads to unnecessarily long time before CloseEvent
54 // invocation. We want to avoid this rather than strictly following the spec
55 // recommendation.
56 const int kUnderlyingConnectionCloseTimeoutSeconds = 2;
50 57
51 typedef WebSocketEventInterface::ChannelState ChannelState; 58 typedef WebSocketEventInterface::ChannelState ChannelState;
52 const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE; 59 const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
53 const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED; 60 const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED;
54 61
55 // Maximum close reason length = max control frame payload - 62 // Maximum close reason length = max control frame payload -
56 // status code length 63 // status code length
57 // = 125 - 2 64 // = 125 - 2
58 const size_t kMaximumCloseReasonLength = 125 - kWebSocketCloseCodeLength; 65 const size_t kMaximumCloseReasonLength = 125 - kWebSocketCloseCodeLength;
59 66
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 296
290 WebSocketChannel::WebSocketChannel( 297 WebSocketChannel::WebSocketChannel(
291 scoped_ptr<WebSocketEventInterface> event_interface, 298 scoped_ptr<WebSocketEventInterface> event_interface,
292 URLRequestContext* url_request_context) 299 URLRequestContext* url_request_context)
293 : event_interface_(event_interface.Pass()), 300 : event_interface_(event_interface.Pass()),
294 url_request_context_(url_request_context), 301 url_request_context_(url_request_context),
295 send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark), 302 send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark),
296 send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark), 303 send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark),
297 current_send_quota_(0), 304 current_send_quota_(0),
298 current_receive_quota_(0), 305 current_receive_quota_(0),
299 timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)), 306 closing_handshake_timeout_(base::TimeDelta::FromSeconds(
307 kClosingHandshakeTimeoutSeconds)),
308 underlying_connection_close_timeout_(base::TimeDelta::FromSeconds(
309 kUnderlyingConnectionCloseTimeoutSeconds)),
300 has_received_close_frame_(false), 310 has_received_close_frame_(false),
301 received_close_code_(0), 311 received_close_code_(0),
302 state_(FRESHLY_CONSTRUCTED), 312 state_(FRESHLY_CONSTRUCTED),
303 notification_sender_(new HandshakeNotificationSender(this)), 313 notification_sender_(new HandshakeNotificationSender(this)),
304 sending_text_message_(false), 314 sending_text_message_(false),
305 receiving_text_message_(false), 315 receiving_text_message_(false),
306 expecting_to_handle_continuation_(false), 316 expecting_to_handle_continuation_(false),
307 initial_frame_forwarded_(false) {} 317 initial_frame_forwarded_(false) {}
308 318
309 WebSocketChannel::~WebSocketChannel() { 319 WebSocketChannel::~WebSocketChannel() {
310 // The stream may hold a pointer to read_frames_, and so it needs to be 320 // The stream may hold a pointer to read_frames_, and so it needs to be
311 // destroyed first. 321 // destroyed first.
312 stream_.reset(); 322 stream_.reset();
313 // The timer may have a callback pointing back to us, so stop it just in case 323 // The timer may have a callback pointing back to us, so stop it just in case
314 // someone decides to run the event loop from their destructor. 324 // someone decides to run the event loop from their destructor.
315 timer_.Stop(); 325 close_timer_.Stop();
316 } 326 }
317 327
318 void WebSocketChannel::SendAddChannelRequest( 328 void WebSocketChannel::SendAddChannelRequest(
319 const GURL& socket_url, 329 const GURL& socket_url,
320 const std::vector<std::string>& requested_subprotocols, 330 const std::vector<std::string>& requested_subprotocols,
321 const url::Origin& origin) { 331 const url::Origin& origin) {
322 // Delegate to the tested version. 332 // Delegate to the tested version.
323 SendAddChannelRequestWithSuppliedCreator( 333 SendAddChannelRequestWithSuppliedCreator(
324 socket_url, 334 socket_url,
325 requested_subprotocols, 335 requested_subprotocols,
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 // Abort the in-progress handshake and drop the connection immediately. 481 // Abort the in-progress handshake and drop the connection immediately.
472 stream_request_.reset(); 482 stream_request_.reset();
473 SetState(CLOSED); 483 SetState(CLOSED);
474 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); 484 DoDropChannel(false, kWebSocketErrorAbnormalClosure, "");
475 return; 485 return;
476 } 486 }
477 if (state_ != CONNECTED) { 487 if (state_ != CONNECTED) {
478 NOTREACHED() << "StartClosingHandshake() called in state " << state_; 488 NOTREACHED() << "StartClosingHandshake() called in state " << state_;
479 return; 489 return;
480 } 490 }
491
492 DCHECK(!close_timer_.IsRunning());
493 // This use of base::Unretained() is safe because we stop the timer in the
494 // destructor.
495 close_timer_.Start(
496 FROM_HERE,
497 closing_handshake_timeout_,
498 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this)));
499
481 // Javascript actually only permits 1000 and 3000-4999, but the implementation 500 // Javascript actually only permits 1000 and 3000-4999, but the implementation
482 // itself may produce different codes. The length of |reason| is also checked 501 // itself may produce different codes. The length of |reason| is also checked
483 // by Javascript. 502 // by Javascript.
484 if (!IsStrictlyValidCloseStatusCode(code) || 503 if (!IsStrictlyValidCloseStatusCode(code) ||
485 reason.size() > kMaximumCloseReasonLength) { 504 reason.size() > kMaximumCloseReasonLength) {
486 // "InternalServerError" is actually used for errors from any endpoint, per 505 // "InternalServerError" is actually used for errors from any endpoint, per
487 // errata 3227 to RFC6455. If the renderer is sending us an invalid code or 506 // errata 3227 to RFC6455. If the renderer is sending us an invalid code or
488 // reason it must be malfunctioning in some way, and based on that we 507 // reason it must be malfunctioning in some way, and based on that we
489 // interpret this as an internal error. 508 // interpret this as an internal error.
490 if (SendClose(kWebSocketErrorInternalServerError, "") != CHANNEL_DELETED) { 509 if (SendClose(kWebSocketErrorInternalServerError, "") != CHANNEL_DELETED) {
(...skipping 15 matching lines...) Expand all
506 const GURL& socket_url, 525 const GURL& socket_url,
507 const std::vector<std::string>& requested_subprotocols, 526 const std::vector<std::string>& requested_subprotocols,
508 const url::Origin& origin, 527 const url::Origin& origin,
509 const WebSocketStreamCreator& creator) { 528 const WebSocketStreamCreator& creator) {
510 SendAddChannelRequestWithSuppliedCreator( 529 SendAddChannelRequestWithSuppliedCreator(
511 socket_url, requested_subprotocols, origin, creator); 530 socket_url, requested_subprotocols, origin, creator);
512 } 531 }
513 532
514 void WebSocketChannel::SetClosingHandshakeTimeoutForTesting( 533 void WebSocketChannel::SetClosingHandshakeTimeoutForTesting(
515 base::TimeDelta delay) { 534 base::TimeDelta delay) {
516 timeout_ = delay; 535 closing_handshake_timeout_ = delay;
536 }
537
538 void WebSocketChannel::SetUnderlyingConnectionCloseTimeoutForTesting(
539 base::TimeDelta delay) {
540 underlying_connection_close_timeout_ = delay;
517 } 541 }
518 542
519 void WebSocketChannel::SendAddChannelRequestWithSuppliedCreator( 543 void WebSocketChannel::SendAddChannelRequestWithSuppliedCreator(
520 const GURL& socket_url, 544 const GURL& socket_url,
521 const std::vector<std::string>& requested_subprotocols, 545 const std::vector<std::string>& requested_subprotocols,
522 const url::Origin& origin, 546 const url::Origin& origin,
523 const WebSocketStreamCreator& creator) { 547 const WebSocketStreamCreator& creator) {
524 DCHECK_EQ(FRESHLY_CONSTRUCTED, state_); 548 DCHECK_EQ(FRESHLY_CONSTRUCTED, state_);
525 if (!socket_url.SchemeIsWSOrWSS()) { 549 if (!socket_url.SchemeIsWSOrWSS()) {
526 // TODO(ricea): Kill the renderer (this error should have been caught by 550 // TODO(ricea): Kill the renderer (this error should have been caught by
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
832 std::string message; 856 std::string message;
833 if (!ParseClose(data_buffer, size, &code, &reason, &message)) { 857 if (!ParseClose(data_buffer, size, &code, &reason, &message)) {
834 return FailChannel(message, code, reason); 858 return FailChannel(message, code, reason);
835 } 859 }
836 // TODO(ricea): Find a way to safely log the message from the close 860 // TODO(ricea): Find a way to safely log the message from the close
837 // message (escape control codes and so on). 861 // message (escape control codes and so on).
838 DVLOG(1) << "Got Close with code " << code; 862 DVLOG(1) << "Got Close with code " << code;
839 switch (state_) { 863 switch (state_) {
840 case CONNECTED: 864 case CONNECTED:
841 SetState(RECV_CLOSED); 865 SetState(RECV_CLOSED);
866
842 if (SendClose(code, reason) == CHANNEL_DELETED) 867 if (SendClose(code, reason) == CHANNEL_DELETED)
843 return CHANNEL_DELETED; 868 return CHANNEL_DELETED;
844 DCHECK_EQ(RECV_CLOSED, state_); 869 DCHECK_EQ(RECV_CLOSED, state_);
870
845 SetState(CLOSE_WAIT); 871 SetState(CLOSE_WAIT);
872 DCHECK(!close_timer_.IsRunning());
873 // This use of base::Unretained() is safe because we stop the timer
874 // in the destructor.
875 close_timer_.Start(
876 FROM_HERE,
877 underlying_connection_close_timeout_,
878 base::Bind(
879 &WebSocketChannel::CloseTimeout, base::Unretained(this)));
846 880
847 if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED) 881 if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED)
848 return CHANNEL_DELETED; 882 return CHANNEL_DELETED;
849 has_received_close_frame_ = true; 883 has_received_close_frame_ = true;
850 received_close_code_ = code; 884 received_close_code_ = code;
851 received_close_reason_ = reason; 885 received_close_reason_ = reason;
852 break; 886 break;
853 887
854 case SEND_CLOSED: 888 case SEND_CLOSED:
855 SetState(CLOSE_WAIT); 889 SetState(CLOSE_WAIT);
890 DCHECK(close_timer_.IsRunning());
891 close_timer_.Stop();
892 // This use of base::Unretained() is safe because we stop the timer
893 // in the destructor.
894 close_timer_.Start(
895 FROM_HERE,
896 underlying_connection_close_timeout_,
897 base::Bind(
898 &WebSocketChannel::CloseTimeout, base::Unretained(this)));
899
856 // From RFC6455 section 7.1.5: "Each endpoint 900 // From RFC6455 section 7.1.5: "Each endpoint
857 // will see the status code sent by the other end as _The WebSocket 901 // will see the status code sent by the other end as _The WebSocket
858 // Connection Close Code_." 902 // Connection Close Code_."
859 has_received_close_frame_ = true; 903 has_received_close_frame_ = true;
860 received_close_code_ = code; 904 received_close_code_ = code;
861 received_close_reason_ = reason; 905 received_close_reason_ = reason;
862 break; 906 break;
863 907
864 default: 908 default:
865 LOG(DFATAL) << "Got Close in unexpected state " << state_; 909 LOG(DFATAL) << "Got Close in unexpected state " << state_;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 } else { 1064 } else {
1021 const size_t payload_length = kWebSocketCloseCodeLength + reason.length(); 1065 const size_t payload_length = kWebSocketCloseCodeLength + reason.length();
1022 body = new IOBuffer(payload_length); 1066 body = new IOBuffer(payload_length);
1023 size = payload_length; 1067 size = payload_length;
1024 base::WriteBigEndian(body->data(), code); 1068 base::WriteBigEndian(body->data(), code);
1025 COMPILE_ASSERT(sizeof(code) == kWebSocketCloseCodeLength, 1069 COMPILE_ASSERT(sizeof(code) == kWebSocketCloseCodeLength,
1026 they_should_both_be_two); 1070 they_should_both_be_two);
1027 std::copy( 1071 std::copy(
1028 reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength); 1072 reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength);
1029 } 1073 }
1030 // This use of base::Unretained() is safe because we stop the timer in the
1031 // destructor.
1032 timer_.Start(
1033 FROM_HERE,
1034 timeout_,
1035 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this)));
1036 if (SendFrameFromIOBuffer( 1074 if (SendFrameFromIOBuffer(
1037 true, WebSocketFrameHeader::kOpCodeClose, body, size) == 1075 true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
1038 CHANNEL_DELETED) 1076 CHANNEL_DELETED)
1039 return CHANNEL_DELETED; 1077 return CHANNEL_DELETED;
1040 return CHANNEL_ALIVE; 1078 return CHANNEL_ALIVE;
1041 } 1079 }
1042 1080
1043 bool WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer, 1081 bool WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer,
1044 uint64 size, 1082 uint64 size,
1045 uint16* code, 1083 uint16* code,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 } 1144 }
1107 1145
1108 void WebSocketChannel::CloseTimeout() { 1146 void WebSocketChannel::CloseTimeout() {
1109 stream_->Close(); 1147 stream_->Close();
1110 SetState(CLOSED); 1148 SetState(CLOSED);
1111 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); 1149 DoDropChannel(false, kWebSocketErrorAbnormalClosure, "");
1112 // |this| has been deleted. 1150 // |this| has been deleted.
1113 } 1151 }
1114 1152
1115 } // namespace net 1153 } // namespace net
OLDNEW
« 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