| 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 DCHECK_LT(code, 65536); | 79 DCHECK_LT(code, 65536); |
| 80 const int* upper = std::upper_bound(kInvalidRanges, kInvalidRangesEnd, code); | 80 const int* upper = std::upper_bound(kInvalidRanges, kInvalidRangesEnd, code); |
| 81 DCHECK_NE(kInvalidRangesEnd, upper); | 81 DCHECK_NE(kInvalidRangesEnd, upper); |
| 82 DCHECK_GT(upper, kInvalidRanges); | 82 DCHECK_GT(upper, kInvalidRanges); |
| 83 DCHECK_GT(*upper, code); | 83 DCHECK_GT(*upper, code); |
| 84 DCHECK_LE(*(upper - 1), code); | 84 DCHECK_LE(*(upper - 1), code); |
| 85 return ((upper - kInvalidRanges) % 2) == 0; | 85 return ((upper - kInvalidRanges) % 2) == 0; |
| 86 } | 86 } |
| 87 | 87 |
| 88 // This function avoids a bunch of boilerplate code. | 88 // This function avoids a bunch of boilerplate code. |
| 89 void AllowUnused(ChannelState ALLOW_UNUSED unused) {} | 89 void AllowUnused(ChannelState ALLOW_UNUSED unused) { |
| 90 } |
| 90 | 91 |
| 91 // Sets |name| to the name of the frame type for the given |opcode|. Note that | 92 // Sets |name| to the name of the frame type for the given |opcode|. Note that |
| 92 // for all of Text, Binary and Continuation opcode, this method returns | 93 // for all of Text, Binary and Continuation opcode, this method returns |
| 93 // "Data frame". | 94 // "Data frame". |
| 94 void GetFrameTypeForOpcode(WebSocketFrameHeader::OpCode opcode, | 95 void GetFrameTypeForOpcode(WebSocketFrameHeader::OpCode opcode, |
| 95 std::string* name) { | 96 std::string* name) { |
| 96 switch (opcode) { | 97 switch (opcode) { |
| 97 case WebSocketFrameHeader::kOpCodeText: // fall-thru | 98 case WebSocketFrameHeader::kOpCodeText: // fall-thru |
| 98 case WebSocketFrameHeader::kOpCodeBinary: // fall-thru | 99 case WebSocketFrameHeader::kOpCodeBinary: // fall-thru |
| 99 case WebSocketFrameHeader::kOpCodeContinuation: | 100 case WebSocketFrameHeader::kOpCodeContinuation: |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 } | 216 } |
| 216 | 217 |
| 217 private: | 218 private: |
| 218 WebSocketChannel* owner_; | 219 WebSocketChannel* owner_; |
| 219 scoped_ptr<WebSocketHandshakeRequestInfo> handshake_request_info_; | 220 scoped_ptr<WebSocketHandshakeRequestInfo> handshake_request_info_; |
| 220 scoped_ptr<WebSocketHandshakeResponseInfo> handshake_response_info_; | 221 scoped_ptr<WebSocketHandshakeResponseInfo> handshake_response_info_; |
| 221 }; | 222 }; |
| 222 | 223 |
| 223 WebSocketChannel::HandshakeNotificationSender::HandshakeNotificationSender( | 224 WebSocketChannel::HandshakeNotificationSender::HandshakeNotificationSender( |
| 224 WebSocketChannel* channel) | 225 WebSocketChannel* channel) |
| 225 : owner_(channel) {} | 226 : owner_(channel) { |
| 227 } |
| 226 | 228 |
| 227 WebSocketChannel::HandshakeNotificationSender::~HandshakeNotificationSender() {} | 229 WebSocketChannel::HandshakeNotificationSender::~HandshakeNotificationSender() { |
| 230 } |
| 228 | 231 |
| 229 void WebSocketChannel::HandshakeNotificationSender::Send( | 232 void WebSocketChannel::HandshakeNotificationSender::Send( |
| 230 base::WeakPtr<HandshakeNotificationSender> sender) { | 233 base::WeakPtr<HandshakeNotificationSender> sender) { |
| 231 // Do nothing if |sender| is already destructed. | 234 // Do nothing if |sender| is already destructed. |
| 232 if (sender) { | 235 if (sender) { |
| 233 WebSocketChannel* channel = sender->owner_; | 236 WebSocketChannel* channel = sender->owner_; |
| 234 AllowUnused(sender->SendImmediately(channel->event_interface_.get())); | 237 AllowUnused(sender->SendImmediately(channel->event_interface_.get())); |
| 235 } | 238 } |
| 236 } | 239 } |
| 237 | 240 |
| 238 ChannelState WebSocketChannel::HandshakeNotificationSender::SendImmediately( | 241 ChannelState WebSocketChannel::HandshakeNotificationSender::SendImmediately( |
| 239 WebSocketEventInterface* event_interface) { | 242 WebSocketEventInterface* event_interface) { |
| 240 | |
| 241 if (handshake_request_info_.get()) { | 243 if (handshake_request_info_.get()) { |
| 242 if (CHANNEL_DELETED == event_interface->OnStartOpeningHandshake( | 244 if (CHANNEL_DELETED == |
| 243 handshake_request_info_.Pass())) | 245 event_interface->OnStartOpeningHandshake( |
| 246 handshake_request_info_.Pass())) |
| 244 return CHANNEL_DELETED; | 247 return CHANNEL_DELETED; |
| 245 } | 248 } |
| 246 | 249 |
| 247 if (handshake_response_info_.get()) { | 250 if (handshake_response_info_.get()) { |
| 248 if (CHANNEL_DELETED == event_interface->OnFinishOpeningHandshake( | 251 if (CHANNEL_DELETED == |
| 249 handshake_response_info_.Pass())) | 252 event_interface->OnFinishOpeningHandshake( |
| 253 handshake_response_info_.Pass())) |
| 250 return CHANNEL_DELETED; | 254 return CHANNEL_DELETED; |
| 251 | 255 |
| 252 // TODO(yhirano): We can release |this| to save memory because | 256 // TODO(yhirano): We can release |this| to save memory because |
| 253 // there will be no more opening handshake notification. | 257 // there will be no more opening handshake notification. |
| 254 } | 258 } |
| 255 | 259 |
| 256 return CHANNEL_ALIVE; | 260 return CHANNEL_ALIVE; |
| 257 } | 261 } |
| 258 | 262 |
| 259 WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame( | 263 WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame( |
| 260 bool final, | 264 bool final, |
| 261 WebSocketFrameHeader::OpCode opcode, | 265 WebSocketFrameHeader::OpCode opcode, |
| 262 const scoped_refptr<IOBuffer>& data, | 266 const scoped_refptr<IOBuffer>& data, |
| 263 size_t offset, | 267 size_t offset, |
| 264 size_t size) | 268 size_t size) |
| 265 : final_(final), | 269 : final_(final), |
| 266 opcode_(opcode), | 270 opcode_(opcode), |
| 267 data_(data), | 271 data_(data), |
| 268 offset_(offset), | 272 offset_(offset), |
| 269 size_(size) {} | 273 size_(size) { |
| 274 } |
| 270 | 275 |
| 271 WebSocketChannel::PendingReceivedFrame::~PendingReceivedFrame() {} | 276 WebSocketChannel::PendingReceivedFrame::~PendingReceivedFrame() { |
| 277 } |
| 272 | 278 |
| 273 void WebSocketChannel::PendingReceivedFrame::ResetOpcode() { | 279 void WebSocketChannel::PendingReceivedFrame::ResetOpcode() { |
| 274 DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(opcode_)); | 280 DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(opcode_)); |
| 275 opcode_ = WebSocketFrameHeader::kOpCodeContinuation; | 281 opcode_ = WebSocketFrameHeader::kOpCodeContinuation; |
| 276 } | 282 } |
| 277 | 283 |
| 278 void WebSocketChannel::PendingReceivedFrame::DidConsume(size_t bytes) { | 284 void WebSocketChannel::PendingReceivedFrame::DidConsume(size_t bytes) { |
| 279 DCHECK_LE(offset_, size_); | 285 DCHECK_LE(offset_, size_); |
| 280 DCHECK_LE(bytes, size_ - offset_); | 286 DCHECK_LE(bytes, size_ - offset_); |
| 281 offset_ += bytes; | 287 offset_ += bytes; |
| 282 } | 288 } |
| 283 | 289 |
| 284 WebSocketChannel::WebSocketChannel( | 290 WebSocketChannel::WebSocketChannel( |
| 285 scoped_ptr<WebSocketEventInterface> event_interface, | 291 scoped_ptr<WebSocketEventInterface> event_interface, |
| 286 URLRequestContext* url_request_context) | 292 URLRequestContext* url_request_context) |
| 287 : event_interface_(event_interface.Pass()), | 293 : event_interface_(event_interface.Pass()), |
| 288 url_request_context_(url_request_context), | 294 url_request_context_(url_request_context), |
| 289 send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark), | 295 send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark), |
| 290 send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark), | 296 send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark), |
| 291 current_send_quota_(0), | 297 current_send_quota_(0), |
| 292 current_receive_quota_(0), | 298 current_receive_quota_(0), |
| 293 timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)), | 299 timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)), |
| 294 received_close_code_(0), | 300 received_close_code_(0), |
| 295 state_(FRESHLY_CONSTRUCTED), | 301 state_(FRESHLY_CONSTRUCTED), |
| 296 notification_sender_(new HandshakeNotificationSender(this)), | 302 notification_sender_(new HandshakeNotificationSender(this)), |
| 297 sending_text_message_(false), | 303 sending_text_message_(false), |
| 298 receiving_text_message_(false), | 304 receiving_text_message_(false), |
| 299 expecting_to_handle_continuation_(false), | 305 expecting_to_handle_continuation_(false), |
| 300 initial_frame_forwarded_(false) {} | 306 initial_frame_forwarded_(false) { |
| 307 } |
| 301 | 308 |
| 302 WebSocketChannel::~WebSocketChannel() { | 309 WebSocketChannel::~WebSocketChannel() { |
| 303 // The stream may hold a pointer to read_frames_, and so it needs to be | 310 // The stream may hold a pointer to read_frames_, and so it needs to be |
| 304 // destroyed first. | 311 // destroyed first. |
| 305 stream_.reset(); | 312 stream_.reset(); |
| 306 // The timer may have a callback pointing back to us, so stop it just in case | 313 // The timer may have a callback pointing back to us, so stop it just in case |
| 307 // someone decides to run the event loop from their destructor. | 314 // someone decides to run the event loop from their destructor. |
| 308 timer_.Stop(); | 315 timer_.Stop(); |
| 309 } | 316 } |
| 310 | 317 |
| 311 void WebSocketChannel::SendAddChannelRequest( | 318 void WebSocketChannel::SendAddChannelRequest( |
| 312 const GURL& socket_url, | 319 const GURL& socket_url, |
| 313 const std::vector<std::string>& requested_subprotocols, | 320 const std::vector<std::string>& requested_subprotocols, |
| 314 const url::Origin& origin) { | 321 const url::Origin& origin) { |
| 315 // Delegate to the tested version. | 322 // Delegate to the tested version. |
| 316 SendAddChannelRequestWithSuppliedCreator( | 323 SendAddChannelRequestWithSuppliedCreator( |
| 317 socket_url, | 324 socket_url, |
| 318 requested_subprotocols, | 325 requested_subprotocols, |
| 319 origin, | 326 origin, |
| 320 base::Bind(&WebSocketStream::CreateAndConnectStream)); | 327 base::Bind(&WebSocketStream::CreateAndConnectStream)); |
| 321 } | 328 } |
| 322 | 329 |
| 323 void WebSocketChannel::SetState(State new_state) { | 330 void WebSocketChannel::SetState(State new_state) { |
| 324 DCHECK_NE(state_, new_state); | 331 DCHECK_NE(state_, new_state); |
| 325 | 332 |
| 326 if (new_state == CONNECTED) | 333 if (new_state == CONNECTED) |
| 327 established_on_ = base::TimeTicks::Now(); | 334 established_on_ = base::TimeTicks::Now(); |
| 328 if (state_ == CONNECTED && !established_on_.is_null()) { | 335 if (state_ == CONNECTED && !established_on_.is_null()) { |
| 329 UMA_HISTOGRAM_LONG_TIMES( | 336 UMA_HISTOGRAM_LONG_TIMES("Net.WebSocket.Duration", |
| 330 "Net.WebSocket.Duration", base::TimeTicks::Now() - established_on_); | 337 base::TimeTicks::Now() - established_on_); |
| 331 } | 338 } |
| 332 | 339 |
| 333 state_ = new_state; | 340 state_ = new_state; |
| 334 } | 341 } |
| 335 | 342 |
| 336 bool WebSocketChannel::InClosingState() const { | 343 bool WebSocketChannel::InClosingState() const { |
| 337 // The state RECV_CLOSED is not supported here, because it is only used in one | 344 // The state RECV_CLOSED is not supported here, because it is only used in one |
| 338 // code path and should not leak into the code in general. | 345 // code path and should not leak into the code in general. |
| 339 DCHECK_NE(RECV_CLOSED, state_) | 346 DCHECK_NE(RECV_CLOSED, state_) |
| 340 << "InClosingState called with state_ == RECV_CLOSED"; | 347 << "InClosingState called with state_ == RECV_CLOSED"; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 DCHECK_LE(quota, INT_MAX); | 421 DCHECK_LE(quota, INT_MAX); |
| 415 if (!pending_received_frames_.empty()) { | 422 if (!pending_received_frames_.empty()) { |
| 416 DCHECK_EQ(0, current_receive_quota_); | 423 DCHECK_EQ(0, current_receive_quota_); |
| 417 } | 424 } |
| 418 while (!pending_received_frames_.empty() && quota > 0) { | 425 while (!pending_received_frames_.empty() && quota > 0) { |
| 419 PendingReceivedFrame& front = pending_received_frames_.front(); | 426 PendingReceivedFrame& front = pending_received_frames_.front(); |
| 420 const size_t data_size = front.size() - front.offset(); | 427 const size_t data_size = front.size() - front.offset(); |
| 421 const size_t bytes_to_send = | 428 const size_t bytes_to_send = |
| 422 std::min(base::checked_cast<size_t>(quota), data_size); | 429 std::min(base::checked_cast<size_t>(quota), data_size); |
| 423 const bool final = front.final() && data_size == bytes_to_send; | 430 const bool final = front.final() && data_size == bytes_to_send; |
| 424 const char* data = front.data() ? | 431 const char* data = |
| 425 front.data()->data() + front.offset() : NULL; | 432 front.data() ? front.data()->data() + front.offset() : NULL; |
| 426 DCHECK(!bytes_to_send || data) << "Non empty data should not be null."; | 433 DCHECK(!bytes_to_send || data) << "Non empty data should not be null."; |
| 427 const std::vector<char> data_vector(data, data + bytes_to_send); | 434 const std::vector<char> data_vector(data, data + bytes_to_send); |
| 428 DVLOG(3) << "Sending frame previously split due to quota to the " | 435 DVLOG(3) << "Sending frame previously split due to quota to the " |
| 429 << "renderer: quota=" << quota << " data_size=" << data_size | 436 << "renderer: quota=" << quota << " data_size=" << data_size |
| 430 << " bytes_to_send=" << bytes_to_send; | 437 << " bytes_to_send=" << bytes_to_send; |
| 431 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) == | 438 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) == |
| 432 CHANNEL_DELETED) | 439 CHANNEL_DELETED) |
| 433 return; | 440 return; |
| 434 if (bytes_to_send < data_size) { | 441 if (bytes_to_send < data_size) { |
| 435 front.DidConsume(bytes_to_send); | 442 front.DidConsume(bytes_to_send); |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || | 874 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || |
| 868 opcode == WebSocketFrameHeader::kOpCodeText || | 875 opcode == WebSocketFrameHeader::kOpCodeText || |
| 869 opcode == WebSocketFrameHeader::kOpCodeBinary); | 876 opcode == WebSocketFrameHeader::kOpCodeBinary); |
| 870 const bool got_continuation = | 877 const bool got_continuation = |
| 871 (opcode == WebSocketFrameHeader::kOpCodeContinuation); | 878 (opcode == WebSocketFrameHeader::kOpCodeContinuation); |
| 872 if (got_continuation != expecting_to_handle_continuation_) { | 879 if (got_continuation != expecting_to_handle_continuation_) { |
| 873 const std::string console_log = got_continuation | 880 const std::string console_log = got_continuation |
| 874 ? "Received unexpected continuation frame." | 881 ? "Received unexpected continuation frame." |
| 875 : "Received start of new message but previous message is unfinished."; | 882 : "Received start of new message but previous message is unfinished."; |
| 876 const std::string reason = got_continuation | 883 const std::string reason = got_continuation |
| 877 ? "Unexpected continuation" | 884 ? "Unexpected continuation" |
| 878 : "Previous data frame unfinished"; | 885 : "Previous data frame unfinished"; |
| 879 return FailChannel(console_log, kWebSocketErrorProtocolError, reason); | 886 return FailChannel(console_log, kWebSocketErrorProtocolError, reason); |
| 880 } | 887 } |
| 881 expecting_to_handle_continuation_ = !final; | 888 expecting_to_handle_continuation_ = !final; |
| 882 WebSocketFrameHeader::OpCode opcode_to_send = opcode; | 889 WebSocketFrameHeader::OpCode opcode_to_send = opcode; |
| 883 if (!initial_frame_forwarded_ && | 890 if (!initial_frame_forwarded_ && |
| 884 opcode == WebSocketFrameHeader::kOpCodeContinuation) { | 891 opcode == WebSocketFrameHeader::kOpCodeContinuation) { |
| 885 opcode_to_send = receiving_text_message_ | 892 opcode_to_send = receiving_text_message_ |
| 886 ? WebSocketFrameHeader::kOpCodeText | 893 ? WebSocketFrameHeader::kOpCodeText |
| 887 : WebSocketFrameHeader::kOpCodeBinary; | 894 : WebSocketFrameHeader::kOpCodeBinary; |
| 888 } | 895 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 if (size < kWebSocketCloseCodeLength) { | 1035 if (size < kWebSocketCloseCodeLength) { |
| 1029 if (size == 0U) { | 1036 if (size == 0U) { |
| 1030 *code = kWebSocketErrorNoStatusReceived; | 1037 *code = kWebSocketErrorNoStatusReceived; |
| 1031 return true; | 1038 return true; |
| 1032 } | 1039 } |
| 1033 | 1040 |
| 1034 DVLOG(1) << "Close frame with payload size " << size << " received " | 1041 DVLOG(1) << "Close frame with payload size " << size << " received " |
| 1035 << "(the first byte is " << std::hex | 1042 << "(the first byte is " << std::hex |
| 1036 << static_cast<int>(buffer->data()[0]) << ")"; | 1043 << static_cast<int>(buffer->data()[0]) << ")"; |
| 1037 *code = kWebSocketErrorProtocolError; | 1044 *code = kWebSocketErrorProtocolError; |
| 1038 *message = | 1045 *message = "Received a broken close frame containing an invalid size body."; |
| 1039 "Received a broken close frame containing an invalid size body."; | |
| 1040 return false; | 1046 return false; |
| 1041 } | 1047 } |
| 1042 | 1048 |
| 1043 const char* data = buffer->data(); | 1049 const char* data = buffer->data(); |
| 1044 uint16 unchecked_code = 0; | 1050 uint16 unchecked_code = 0; |
| 1045 base::ReadBigEndian(data, &unchecked_code); | 1051 base::ReadBigEndian(data, &unchecked_code); |
| 1046 COMPILE_ASSERT(sizeof(unchecked_code) == kWebSocketCloseCodeLength, | 1052 COMPILE_ASSERT(sizeof(unchecked_code) == kWebSocketCloseCodeLength, |
| 1047 they_should_both_be_two_bytes); | 1053 they_should_both_be_two_bytes); |
| 1048 | 1054 |
| 1049 switch (unchecked_code) { | 1055 switch (unchecked_code) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 } | 1091 } |
| 1086 | 1092 |
| 1087 void WebSocketChannel::CloseTimeout() { | 1093 void WebSocketChannel::CloseTimeout() { |
| 1088 stream_->Close(); | 1094 stream_->Close(); |
| 1089 SetState(CLOSED); | 1095 SetState(CLOSED); |
| 1090 AllowUnused(DoDropChannel(false, kWebSocketErrorAbnormalClosure, "")); | 1096 AllowUnused(DoDropChannel(false, kWebSocketErrorAbnormalClosure, "")); |
| 1091 // |this| has been deleted. | 1097 // |this| has been deleted. |
| 1092 } | 1098 } |
| 1093 | 1099 |
| 1094 } // namespace net | 1100 } // namespace net |
| OLD | NEW |