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 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 break; | 121 break; |
122 | 122 |
123 default: | 123 default: |
124 *name = "Unknown frame type"; | 124 *name = "Unknown frame type"; |
125 break; | 125 break; |
126 } | 126 } |
127 | 127 |
128 return; | 128 return; |
129 } | 129 } |
130 | 130 |
131 class DependentIOBuffer : public WrappedIOBuffer { | |
132 public: | |
133 DependentIOBuffer(const scoped_refptr<IOBuffer>& buffer, size_t offset) | |
yhirano
2016/09/06 12:19:48
I think |const scoped_refptr<T>&| is discouraged.
| |
134 : WrappedIOBuffer(buffer->data() + offset), buffer_(buffer) {} | |
135 private: | |
136 ~DependentIOBuffer() override {} | |
137 scoped_refptr<net::IOBuffer> buffer_; | |
138 }; | |
139 | |
131 } // namespace | 140 } // namespace |
132 | 141 |
133 // A class to encapsulate a set of frames and information about the size of | 142 // A class to encapsulate a set of frames and information about the size of |
134 // those frames. | 143 // those frames. |
135 class WebSocketChannel::SendBuffer { | 144 class WebSocketChannel::SendBuffer { |
136 public: | 145 public: |
137 SendBuffer() : total_bytes_(0) {} | 146 SendBuffer() : total_bytes_(0) {} |
138 | 147 |
139 // Add a WebSocketFrame to the buffer and increase total_bytes_. | 148 // Add a WebSocketFrame to the buffer and increase total_bytes_. |
140 void AddFrame(std::unique_ptr<WebSocketFrame> chunk); | 149 void AddFrame(std::unique_ptr<WebSocketFrame> chunk); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 // The state RECV_CLOSED is not supported here, because it is only used in one | 372 // The state RECV_CLOSED is not supported here, because it is only used in one |
364 // code path and should not leak into the code in general. | 373 // code path and should not leak into the code in general. |
365 DCHECK_NE(RECV_CLOSED, state_) | 374 DCHECK_NE(RECV_CLOSED, state_) |
366 << "InClosingState called with state_ == RECV_CLOSED"; | 375 << "InClosingState called with state_ == RECV_CLOSED"; |
367 return state_ == SEND_CLOSED || state_ == CLOSE_WAIT || state_ == CLOSED; | 376 return state_ == SEND_CLOSED || state_ == CLOSE_WAIT || state_ == CLOSED; |
368 } | 377 } |
369 | 378 |
370 WebSocketChannel::ChannelState WebSocketChannel::SendFrame( | 379 WebSocketChannel::ChannelState WebSocketChannel::SendFrame( |
371 bool fin, | 380 bool fin, |
372 WebSocketFrameHeader::OpCode op_code, | 381 WebSocketFrameHeader::OpCode op_code, |
373 const std::vector<char>& data) { | 382 scoped_refptr<IOBuffer> buffer, |
374 if (data.size() > INT_MAX) { | 383 size_t buffer_size) { |
384 if (buffer_size > INT_MAX) { | |
375 NOTREACHED() << "Frame size sanity check failed"; | 385 NOTREACHED() << "Frame size sanity check failed"; |
376 return CHANNEL_ALIVE; | 386 return CHANNEL_ALIVE; |
377 } | 387 } |
378 if (stream_ == NULL) { | 388 if (stream_ == NULL) { |
379 LOG(DFATAL) << "Got SendFrame without a connection established; " | 389 LOG(DFATAL) << "Got SendFrame without a connection established; " |
380 << "misbehaving renderer? fin=" << fin << " op_code=" << op_code | 390 << "misbehaving renderer? fin=" << fin << " op_code=" << op_code |
381 << " data.size()=" << data.size(); | 391 << " buffer_size=" << buffer_size; |
382 return CHANNEL_ALIVE; | 392 return CHANNEL_ALIVE; |
383 } | 393 } |
384 if (InClosingState()) { | 394 if (InClosingState()) { |
385 DVLOG(1) << "SendFrame called in state " << state_ | 395 DVLOG(1) << "SendFrame called in state " << state_ |
386 << ". This may be a bug, or a harmless race."; | 396 << ". This may be a bug, or a harmless race."; |
387 return CHANNEL_ALIVE; | 397 return CHANNEL_ALIVE; |
388 } | 398 } |
389 if (state_ != CONNECTED) { | 399 if (state_ != CONNECTED) { |
390 NOTREACHED() << "SendFrame() called in state " << state_; | 400 NOTREACHED() << "SendFrame() called in state " << state_; |
391 return CHANNEL_ALIVE; | 401 return CHANNEL_ALIVE; |
392 } | 402 } |
393 if (data.size() > base::checked_cast<size_t>(current_send_quota_)) { | 403 if (buffer_size > base::checked_cast<size_t>(current_send_quota_)) { |
394 // TODO(ricea): Kill renderer. | 404 // TODO(ricea): Kill renderer. |
395 return FailChannel("Send quota exceeded", kWebSocketErrorGoingAway, ""); | 405 return FailChannel("Send quota exceeded", kWebSocketErrorGoingAway, ""); |
396 // |this| has been deleted. | 406 // |this| has been deleted. |
397 } | 407 } |
398 if (!WebSocketFrameHeader::IsKnownDataOpCode(op_code)) { | 408 if (!WebSocketFrameHeader::IsKnownDataOpCode(op_code)) { |
399 LOG(DFATAL) << "Got SendFrame with bogus op_code " << op_code | 409 LOG(DFATAL) << "Got SendFrame with bogus op_code " << op_code |
400 << "; misbehaving renderer? fin=" << fin | 410 << "; misbehaving renderer? fin=" << fin |
401 << " data.size()=" << data.size(); | 411 << " buffer_size=" << buffer_size; |
402 return CHANNEL_ALIVE; | 412 return CHANNEL_ALIVE; |
403 } | 413 } |
404 if (op_code == WebSocketFrameHeader::kOpCodeText || | 414 if (op_code == WebSocketFrameHeader::kOpCodeText || |
405 (op_code == WebSocketFrameHeader::kOpCodeContinuation && | 415 (op_code == WebSocketFrameHeader::kOpCodeContinuation && |
406 sending_text_message_)) { | 416 sending_text_message_)) { |
407 StreamingUtf8Validator::State state = | 417 StreamingUtf8Validator::State state = |
408 outgoing_utf8_validator_.AddBytes(data.data(), data.size()); | 418 outgoing_utf8_validator_.AddBytes(buffer->data(), buffer_size); |
409 if (state == StreamingUtf8Validator::INVALID || | 419 if (state == StreamingUtf8Validator::INVALID || |
410 (state == StreamingUtf8Validator::VALID_MIDPOINT && fin)) { | 420 (state == StreamingUtf8Validator::VALID_MIDPOINT && fin)) { |
411 // TODO(ricea): Kill renderer. | 421 // TODO(ricea): Kill renderer. |
412 return FailChannel("Browser sent a text frame containing invalid UTF-8", | 422 return FailChannel("Browser sent a text frame containing invalid UTF-8", |
413 kWebSocketErrorGoingAway, ""); | 423 kWebSocketErrorGoingAway, ""); |
414 // |this| has been deleted. | 424 // |this| has been deleted. |
415 } | 425 } |
416 sending_text_message_ = !fin; | 426 sending_text_message_ = !fin; |
417 DCHECK(!fin || state == StreamingUtf8Validator::VALID_ENDPOINT); | 427 DCHECK(!fin || state == StreamingUtf8Validator::VALID_ENDPOINT); |
418 } | 428 } |
419 current_send_quota_ -= data.size(); | 429 current_send_quota_ -= buffer_size; |
420 // TODO(ricea): If current_send_quota_ has dropped below | 430 // TODO(ricea): If current_send_quota_ has dropped below |
421 // send_quota_low_water_mark_, it might be good to increase the "low | 431 // send_quota_low_water_mark_, it might be good to increase the "low |
422 // water mark" and "high water mark", but only if the link to the WebSocket | 432 // water mark" and "high water mark", but only if the link to the WebSocket |
423 // server is not saturated. | 433 // server is not saturated. |
424 scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size())); | 434 return SendFrameFromIOBuffer(fin, op_code, std::move(buffer), buffer_size); |
yhirano
2016/09/06 12:19:48
With this change SendFrame also takes an IOBuffer.
| |
425 std::copy(data.begin(), data.end(), buffer->data()); | |
426 return SendFrameFromIOBuffer(fin, op_code, buffer, data.size()); | |
427 // |this| may have been deleted. | 435 // |this| may have been deleted. |
428 } | 436 } |
429 | 437 |
430 ChannelState WebSocketChannel::SendFlowControl(int64_t quota) { | 438 ChannelState WebSocketChannel::SendFlowControl(int64_t quota) { |
431 DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED || | 439 DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED || |
432 state_ == CLOSE_WAIT); | 440 state_ == CLOSE_WAIT); |
433 // TODO(ricea): Kill the renderer if it tries to send us a negative quota | 441 // TODO(ricea): Kill the renderer if it tries to send us a negative quota |
434 // value or > INT_MAX. | 442 // value or > INT_MAX. |
435 DCHECK_GE(quota, 0); | 443 DCHECK_GE(quota, 0); |
436 DCHECK_LE(quota, INT_MAX); | 444 DCHECK_LE(quota, INT_MAX); |
437 if (!pending_received_frames_.empty()) { | 445 if (!pending_received_frames_.empty()) { |
438 DCHECK_EQ(0u, current_receive_quota_); | 446 DCHECK_EQ(0u, current_receive_quota_); |
439 } | 447 } |
440 while (!pending_received_frames_.empty() && quota > 0) { | 448 while (!pending_received_frames_.empty() && quota > 0) { |
441 PendingReceivedFrame& front = pending_received_frames_.front(); | 449 PendingReceivedFrame& front = pending_received_frames_.front(); |
442 const uint64_t data_size = front.size() - front.offset(); | 450 const uint64_t data_size = front.size() - front.offset(); |
443 const uint64_t bytes_to_send = | 451 const uint64_t bytes_to_send = |
444 std::min(base::checked_cast<uint64_t>(quota), data_size); | 452 std::min(base::checked_cast<uint64_t>(quota), data_size); |
445 const bool final = front.final() && data_size == bytes_to_send; | 453 const bool final = front.final() && data_size == bytes_to_send; |
446 const char* data = | 454 scoped_refptr<IOBuffer> buffer_to_pass; |
447 front.data().get() ? front.data()->data() + front.offset() : NULL; | 455 if (front.data().get()) { |
Ryan Sleevi
2016/08/30 08:07:39
The .get() here is superfluous due to the bool ope
| |
448 DCHECK(!bytes_to_send || data) << "Non empty data should not be null."; | 456 buffer_to_pass = new DependentIOBuffer(front.data(), front.offset()); |
449 const std::vector<char> data_vector(data, data + bytes_to_send); | 457 } else { |
458 DCHECK(!bytes_to_send) << "Non empty data should not be null."; | |
459 } | |
450 DVLOG(3) << "Sending frame previously split due to quota to the " | 460 DVLOG(3) << "Sending frame previously split due to quota to the " |
451 << "renderer: quota=" << quota << " data_size=" << data_size | 461 << "renderer: quota=" << quota << " data_size=" << data_size |
452 << " bytes_to_send=" << bytes_to_send; | 462 << " bytes_to_send=" << bytes_to_send; |
453 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) == | 463 if (event_interface_->OnDataFrame( |
454 CHANNEL_DELETED) | 464 final, front.opcode(), std::move(buffer_to_pass), bytes_to_send) == |
465 CHANNEL_DELETED) | |
455 return CHANNEL_DELETED; | 466 return CHANNEL_DELETED; |
456 if (bytes_to_send < data_size) { | 467 if (bytes_to_send < data_size) { |
457 front.DidConsume(bytes_to_send); | 468 front.DidConsume(bytes_to_send); |
458 front.ResetOpcode(); | 469 front.ResetOpcode(); |
459 return CHANNEL_ALIVE; | 470 return CHANNEL_ALIVE; |
460 } | 471 } |
461 quota -= bytes_to_send; | 472 quota -= bytes_to_send; |
462 | 473 |
463 pending_received_frames_.pop(); | 474 pending_received_frames_.pop(); |
464 } | 475 } |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 "One or more reserved bits are on: reserved1 = %d, " | 836 "One or more reserved bits are on: reserved1 = %d, " |
826 "reserved2 = %d, reserved3 = %d", | 837 "reserved2 = %d, reserved3 = %d", |
827 static_cast<int>(frame->header.reserved1), | 838 static_cast<int>(frame->header.reserved1), |
828 static_cast<int>(frame->header.reserved2), | 839 static_cast<int>(frame->header.reserved2), |
829 static_cast<int>(frame->header.reserved3)), | 840 static_cast<int>(frame->header.reserved3)), |
830 kWebSocketErrorProtocolError, | 841 kWebSocketErrorProtocolError, |
831 "Invalid reserved bit"); | 842 "Invalid reserved bit"); |
832 } | 843 } |
833 | 844 |
834 // Respond to the frame appropriately to its type. | 845 // Respond to the frame appropriately to its type. |
835 return HandleFrameByState( | 846 return HandleFrameByState(opcode, frame->header.final, std::move(frame->data), |
836 opcode, frame->header.final, frame->data, frame->header.payload_length); | 847 frame->header.payload_length); |
837 } | 848 } |
838 | 849 |
839 ChannelState WebSocketChannel::HandleFrameByState( | 850 ChannelState WebSocketChannel::HandleFrameByState( |
840 const WebSocketFrameHeader::OpCode opcode, | 851 const WebSocketFrameHeader::OpCode opcode, |
841 bool final, | 852 bool final, |
842 const scoped_refptr<IOBuffer>& data_buffer, | 853 scoped_refptr<IOBuffer> data_buffer, |
843 uint64_t size) { | 854 uint64_t size) { |
844 DCHECK_NE(RECV_CLOSED, state_) | 855 DCHECK_NE(RECV_CLOSED, state_) |
845 << "HandleFrame() does not support being called re-entrantly from within " | 856 << "HandleFrame() does not support being called re-entrantly from within " |
846 "SendClose()"; | 857 "SendClose()"; |
847 DCHECK_NE(CLOSED, state_); | 858 DCHECK_NE(CLOSED, state_); |
848 if (state_ == CLOSE_WAIT) { | 859 if (state_ == CLOSE_WAIT) { |
849 std::string frame_name; | 860 std::string frame_name; |
850 GetFrameTypeForOpcode(opcode, &frame_name); | 861 GetFrameTypeForOpcode(opcode, &frame_name); |
851 | 862 |
852 // FailChannel() won't send another Close frame. | 863 // FailChannel() won't send another Close frame. |
853 return FailChannel( | 864 return FailChannel( |
854 frame_name + " received after close", kWebSocketErrorProtocolError, ""); | 865 frame_name + " received after close", kWebSocketErrorProtocolError, ""); |
855 } | 866 } |
856 switch (opcode) { | 867 switch (opcode) { |
857 case WebSocketFrameHeader::kOpCodeText: // fall-thru | 868 case WebSocketFrameHeader::kOpCodeText: // fall-thru |
858 case WebSocketFrameHeader::kOpCodeBinary: | 869 case WebSocketFrameHeader::kOpCodeBinary: |
859 case WebSocketFrameHeader::kOpCodeContinuation: | 870 case WebSocketFrameHeader::kOpCodeContinuation: |
860 return HandleDataFrame(opcode, final, data_buffer, size); | 871 return HandleDataFrame(opcode, final, std::move(data_buffer), size); |
861 | 872 |
862 case WebSocketFrameHeader::kOpCodePing: | 873 case WebSocketFrameHeader::kOpCodePing: |
863 DVLOG(1) << "Got Ping of size " << size; | 874 DVLOG(1) << "Got Ping of size " << size; |
864 if (state_ == CONNECTED) | 875 if (state_ == CONNECTED) |
865 return SendFrameFromIOBuffer( | 876 return SendFrameFromIOBuffer( |
866 true, WebSocketFrameHeader::kOpCodePong, data_buffer, size); | 877 true, WebSocketFrameHeader::kOpCodePong, std::move(data_buffer), |
878 size); | |
867 DVLOG(3) << "Ignored ping in state " << state_; | 879 DVLOG(3) << "Ignored ping in state " << state_; |
868 return CHANNEL_ALIVE; | 880 return CHANNEL_ALIVE; |
869 | 881 |
870 case WebSocketFrameHeader::kOpCodePong: | 882 case WebSocketFrameHeader::kOpCodePong: |
871 DVLOG(1) << "Got Pong of size " << size; | 883 DVLOG(1) << "Got Pong of size " << size; |
872 // There is no need to do anything with pong messages. | 884 // There is no need to do anything with pong messages. |
873 return CHANNEL_ALIVE; | 885 return CHANNEL_ALIVE; |
874 | 886 |
875 case WebSocketFrameHeader::kOpCodeClose: { | 887 case WebSocketFrameHeader::kOpCodeClose: { |
876 uint16_t code = kWebSocketNormalClosure; | 888 uint16_t code = kWebSocketNormalClosure; |
877 std::string reason; | 889 std::string reason; |
878 std::string message; | 890 std::string message; |
879 if (!ParseClose(data_buffer, size, &code, &reason, &message)) { | 891 if (!ParseClose(std::move(data_buffer), size, &code, &reason, &message)) { |
880 return FailChannel(message, code, reason); | 892 return FailChannel(message, code, reason); |
881 } | 893 } |
882 // TODO(ricea): Find a way to safely log the message from the close | 894 // TODO(ricea): Find a way to safely log the message from the close |
883 // message (escape control codes and so on). | 895 // message (escape control codes and so on). |
884 DVLOG(1) << "Got Close with code " << code; | 896 DVLOG(1) << "Got Close with code " << code; |
885 return HandleCloseFrame(code, reason); | 897 return HandleCloseFrame(code, reason); |
886 } | 898 } |
887 | 899 |
888 default: | 900 default: |
889 return FailChannel( | 901 return FailChannel( |
890 base::StringPrintf("Unrecognized frame opcode: %d", opcode), | 902 base::StringPrintf("Unrecognized frame opcode: %d", opcode), |
891 kWebSocketErrorProtocolError, | 903 kWebSocketErrorProtocolError, |
892 "Unknown opcode"); | 904 "Unknown opcode"); |
893 } | 905 } |
894 } | 906 } |
895 | 907 |
896 ChannelState WebSocketChannel::HandleDataFrame( | 908 ChannelState WebSocketChannel::HandleDataFrame( |
897 WebSocketFrameHeader::OpCode opcode, | 909 WebSocketFrameHeader::OpCode opcode, |
898 bool final, | 910 bool final, |
899 const scoped_refptr<IOBuffer>& data_buffer, | 911 scoped_refptr<IOBuffer> data_buffer, |
900 uint64_t size) { | 912 uint64_t size) { |
901 if (state_ != CONNECTED) { | 913 if (state_ != CONNECTED) { |
902 DVLOG(3) << "Ignored data packet received in state " << state_; | 914 DVLOG(3) << "Ignored data packet received in state " << state_; |
903 return CHANNEL_ALIVE; | 915 return CHANNEL_ALIVE; |
904 } | 916 } |
905 if (has_received_close_frame_) { | 917 if (has_received_close_frame_) { |
906 DVLOG(3) << "Ignored data packet as we've received a close frame."; | 918 DVLOG(3) << "Ignored data packet as we've received a close frame."; |
907 return CHANNEL_ALIVE; | 919 return CHANNEL_ALIVE; |
908 } | 920 } |
909 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || | 921 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
956 WebSocketFrameHeader::OpCode opcode_to_queue = | 968 WebSocketFrameHeader::OpCode opcode_to_queue = |
957 no_quota ? opcode_to_send : WebSocketFrameHeader::kOpCodeContinuation; | 969 no_quota ? opcode_to_send : WebSocketFrameHeader::kOpCodeContinuation; |
958 pending_received_frames_.push(PendingReceivedFrame( | 970 pending_received_frames_.push(PendingReceivedFrame( |
959 final, opcode_to_queue, data_buffer, current_receive_quota_, size)); | 971 final, opcode_to_queue, data_buffer, current_receive_quota_, size)); |
960 if (no_quota) | 972 if (no_quota) |
961 return CHANNEL_ALIVE; | 973 return CHANNEL_ALIVE; |
962 size = current_receive_quota_; | 974 size = current_receive_quota_; |
963 final = false; | 975 final = false; |
964 } | 976 } |
965 | 977 |
966 // TODO(ricea): Can this copy be eliminated? | |
967 const char* const data_begin = size ? data_buffer->data() : NULL; | |
968 const char* const data_end = data_begin + size; | |
969 const std::vector<char> data(data_begin, data_end); | |
970 current_receive_quota_ -= size; | 978 current_receive_quota_ -= size; |
971 | 979 |
972 // Sends the received frame to the renderer process. | 980 // Sends the received frame to the renderer process. |
973 return event_interface_->OnDataFrame(final, opcode_to_send, data); | 981 return event_interface_->OnDataFrame( |
982 final, opcode_to_send, std::move(data_buffer), size); | |
974 } | 983 } |
975 | 984 |
976 ChannelState WebSocketChannel::HandleCloseFrame(uint16_t code, | 985 ChannelState WebSocketChannel::HandleCloseFrame(uint16_t code, |
977 const std::string& reason) { | 986 const std::string& reason) { |
978 DVLOG(1) << "Got Close with code " << code; | 987 DVLOG(1) << "Got Close with code " << code; |
979 switch (state_) { | 988 switch (state_) { |
980 case CONNECTED: | 989 case CONNECTED: |
981 has_received_close_frame_ = true; | 990 has_received_close_frame_ = true; |
982 received_close_code_ = code; | 991 received_close_code_ = code; |
983 received_close_reason_ = reason; | 992 received_close_reason_ = reason; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1029 close_timer_.Start( | 1038 close_timer_.Start( |
1030 FROM_HERE, underlying_connection_close_timeout_, | 1039 FROM_HERE, underlying_connection_close_timeout_, |
1031 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this))); | 1040 base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this))); |
1032 | 1041 |
1033 return event_interface_->OnClosingHandshake(); | 1042 return event_interface_->OnClosingHandshake(); |
1034 } | 1043 } |
1035 | 1044 |
1036 ChannelState WebSocketChannel::SendFrameFromIOBuffer( | 1045 ChannelState WebSocketChannel::SendFrameFromIOBuffer( |
1037 bool fin, | 1046 bool fin, |
1038 WebSocketFrameHeader::OpCode op_code, | 1047 WebSocketFrameHeader::OpCode op_code, |
1039 const scoped_refptr<IOBuffer>& buffer, | 1048 scoped_refptr<IOBuffer> buffer, |
1040 uint64_t size) { | 1049 uint64_t size) { |
1041 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED); | 1050 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED); |
1042 DCHECK(stream_); | 1051 DCHECK(stream_); |
1043 | 1052 |
1044 std::unique_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code)); | 1053 std::unique_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code)); |
1045 WebSocketFrameHeader& header = frame->header; | 1054 WebSocketFrameHeader& header = frame->header; |
1046 header.final = fin; | 1055 header.final = fin; |
1047 header.masked = true; | 1056 header.masked = true; |
1048 header.payload_length = size; | 1057 header.payload_length = size; |
1049 frame->data = buffer; | 1058 frame->data = std::move(buffer); |
1050 | 1059 |
1051 if (data_being_sent_) { | 1060 if (data_being_sent_) { |
1052 // Either the link to the WebSocket server is saturated, or several messages | 1061 // Either the link to the WebSocket server is saturated, or several messages |
1053 // are being sent in a batch. | 1062 // are being sent in a batch. |
1054 // TODO(ricea): Keep some statistics to work out the situation and adjust | 1063 // TODO(ricea): Keep some statistics to work out the situation and adjust |
1055 // quota appropriately. | 1064 // quota appropriately. |
1056 if (!data_to_send_next_) | 1065 if (!data_to_send_next_) |
1057 data_to_send_next_.reset(new SendBuffer); | 1066 data_to_send_next_.reset(new SendBuffer); |
1058 data_to_send_next_->AddFrame(std::move(frame)); | 1067 data_to_send_next_->AddFrame(std::move(frame)); |
1059 return CHANNEL_ALIVE; | 1068 return CHANNEL_ALIVE; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1102 const size_t payload_length = kWebSocketCloseCodeLength + reason.length(); | 1111 const size_t payload_length = kWebSocketCloseCodeLength + reason.length(); |
1103 body = new IOBuffer(payload_length); | 1112 body = new IOBuffer(payload_length); |
1104 size = payload_length; | 1113 size = payload_length; |
1105 base::WriteBigEndian(body->data(), code); | 1114 base::WriteBigEndian(body->data(), code); |
1106 static_assert(sizeof(code) == kWebSocketCloseCodeLength, | 1115 static_assert(sizeof(code) == kWebSocketCloseCodeLength, |
1107 "they should both be two"); | 1116 "they should both be two"); |
1108 std::copy( | 1117 std::copy( |
1109 reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength); | 1118 reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength); |
1110 } | 1119 } |
1111 if (SendFrameFromIOBuffer( | 1120 if (SendFrameFromIOBuffer( |
1112 true, WebSocketFrameHeader::kOpCodeClose, body, size) == | 1121 true, WebSocketFrameHeader::kOpCodeClose, std::move(body), size) == |
1113 CHANNEL_DELETED) | 1122 CHANNEL_DELETED) |
1114 return CHANNEL_DELETED; | 1123 return CHANNEL_DELETED; |
1115 return CHANNEL_ALIVE; | 1124 return CHANNEL_ALIVE; |
1116 } | 1125 } |
1117 | 1126 |
1118 bool WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer, | 1127 bool WebSocketChannel::ParseClose(scoped_refptr<IOBuffer> buffer, |
1119 uint64_t size, | 1128 uint64_t size, |
1120 uint16_t* code, | 1129 uint16_t* code, |
1121 std::string* reason, | 1130 std::string* reason, |
1122 std::string* message) { | 1131 std::string* message) { |
1123 reason->clear(); | 1132 reason->clear(); |
1124 if (size < kWebSocketCloseCodeLength) { | 1133 if (size < kWebSocketCloseCodeLength) { |
1125 if (size == 0U) { | 1134 if (size == 0U) { |
1126 *code = kWebSocketErrorNoStatusReceived; | 1135 *code = kWebSocketErrorNoStatusReceived; |
1127 return true; | 1136 return true; |
1128 } | 1137 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1181 } | 1190 } |
1182 | 1191 |
1183 void WebSocketChannel::CloseTimeout() { | 1192 void WebSocketChannel::CloseTimeout() { |
1184 stream_->Close(); | 1193 stream_->Close(); |
1185 SetState(CLOSED); | 1194 SetState(CLOSED); |
1186 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); | 1195 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); |
1187 // |this| has been deleted. | 1196 // |this| has been deleted. |
1188 } | 1197 } |
1189 | 1198 |
1190 } // namespace net | 1199 } // namespace net |
OLD | NEW |