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 |