| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |