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

Side by Side Diff: net/websockets/websocket_channel.cc

Issue 1399303002: net/websockets: Convert int types from basictypes.h to the ones from stdint.h (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: websocket_deflate_stream.cc Created 5 years, 2 months 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 63
64 // Maximum close reason length = max control frame payload - 64 // Maximum close reason length = max control frame payload -
65 // status code length 65 // status code length
66 // = 125 - 2 66 // = 125 - 2
67 const size_t kMaximumCloseReasonLength = 125 - kWebSocketCloseCodeLength; 67 const size_t kMaximumCloseReasonLength = 125 - kWebSocketCloseCodeLength;
68 68
69 // Check a close status code for strict compliance with RFC6455. This is only 69 // Check a close status code for strict compliance with RFC6455. This is only
70 // used for close codes received from a renderer that we are intending to send 70 // used for close codes received from a renderer that we are intending to send
71 // out over the network. See ParseClose() for the restrictions on incoming close 71 // out over the network. See ParseClose() for the restrictions on incoming close
72 // codes. The |code| parameter is type int for convenience of implementation; 72 // codes. The |code| parameter is type int for convenience of implementation;
73 // the real type is uint16. Code 1005 is treated specially; it cannot be set 73 // the real type is uint16_t. Code 1005 is treated specially; it cannot be set
74 // explicitly by Javascript but the renderer uses it to indicate we should send 74 // explicitly by Javascript but the renderer uses it to indicate we should send
75 // a Close frame with no payload. 75 // a Close frame with no payload.
76 bool IsStrictlyValidCloseStatusCode(int code) { 76 bool IsStrictlyValidCloseStatusCode(int code) {
77 static const int kInvalidRanges[] = { 77 static const int kInvalidRanges[] = {
78 // [BAD, OK) 78 // [BAD, OK)
79 0, 1000, // 1000 is the first valid code 79 0, 1000, // 1000 is the first valid code
80 1006, 1007, // 1006 MUST NOT be set. 80 1006, 1007, // 1006 MUST NOT be set.
81 1014, 3000, // 1014 unassigned; 1015 up to 2999 are reserved. 81 1014, 3000, // 1014 unassigned; 1015 up to 2999 are reserved.
82 5000, 65536, // Codes above 5000 are invalid. 82 5000, 65536, // Codes above 5000 are invalid.
83 }; 83 };
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 // Return a pointer to the frames_ for write purposes. 140 // Return a pointer to the frames_ for write purposes.
141 ScopedVector<WebSocketFrame>* frames() { return &frames_; } 141 ScopedVector<WebSocketFrame>* frames() { return &frames_; }
142 142
143 private: 143 private:
144 // The frames_ that will be sent in the next call to WriteFrames(). 144 // The frames_ that will be sent in the next call to WriteFrames().
145 ScopedVector<WebSocketFrame> frames_; 145 ScopedVector<WebSocketFrame> frames_;
146 146
147 // The total size of the payload data in |frames_|. This will be used to 147 // The total size of the payload data in |frames_|. This will be used to
148 // measure the throughput of the link. 148 // measure the throughput of the link.
149 // TODO(ricea): Measure the throughput of the link. 149 // TODO(ricea): Measure the throughput of the link.
150 uint64 total_bytes_; 150 uint64_t total_bytes_;
151 }; 151 };
152 152
153 void WebSocketChannel::SendBuffer::AddFrame(scoped_ptr<WebSocketFrame> frame) { 153 void WebSocketChannel::SendBuffer::AddFrame(scoped_ptr<WebSocketFrame> frame) {
154 total_bytes_ += frame->header.payload_length; 154 total_bytes_ += frame->header.payload_length;
155 frames_.push_back(frame.Pass()); 155 frames_.push_back(frame.Pass());
156 } 156 }
157 157
158 // Implementation of WebSocketStream::ConnectDelegate that simply forwards the 158 // Implementation of WebSocketStream::ConnectDelegate that simply forwards the
159 // calls on to the WebSocketChannel that created it. 159 // calls on to the WebSocketChannel that created it.
160 class WebSocketChannel::ConnectDelegate 160 class WebSocketChannel::ConnectDelegate
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 // there will be no more opening handshake notification. 268 // there will be no more opening handshake notification.
269 } 269 }
270 270
271 return CHANNEL_ALIVE; 271 return CHANNEL_ALIVE;
272 } 272 }
273 273
274 WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame( 274 WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame(
275 bool final, 275 bool final,
276 WebSocketFrameHeader::OpCode opcode, 276 WebSocketFrameHeader::OpCode opcode,
277 const scoped_refptr<IOBuffer>& data, 277 const scoped_refptr<IOBuffer>& data,
278 uint64 offset, 278 uint64_t offset,
279 uint64 size) 279 uint64_t size)
280 : final_(final), 280 : final_(final),
281 opcode_(opcode), 281 opcode_(opcode),
282 data_(data), 282 data_(data),
283 offset_(offset), 283 offset_(offset),
284 size_(size) {} 284 size_(size) {}
285 285
286 WebSocketChannel::PendingReceivedFrame::~PendingReceivedFrame() {} 286 WebSocketChannel::PendingReceivedFrame::~PendingReceivedFrame() {}
287 287
288 void WebSocketChannel::PendingReceivedFrame::ResetOpcode() { 288 void WebSocketChannel::PendingReceivedFrame::ResetOpcode() {
289 DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(opcode_)); 289 DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(opcode_));
290 opcode_ = WebSocketFrameHeader::kOpCodeContinuation; 290 opcode_ = WebSocketFrameHeader::kOpCodeContinuation;
291 } 291 }
292 292
293 void WebSocketChannel::PendingReceivedFrame::DidConsume(uint64 bytes) { 293 void WebSocketChannel::PendingReceivedFrame::DidConsume(uint64_t bytes) {
294 DCHECK_LE(offset_, size_); 294 DCHECK_LE(offset_, size_);
295 DCHECK_LE(bytes, size_ - offset_); 295 DCHECK_LE(bytes, size_ - offset_);
296 offset_ += bytes; 296 offset_ += bytes;
297 } 297 }
298 298
299 WebSocketChannel::WebSocketChannel( 299 WebSocketChannel::WebSocketChannel(
300 scoped_ptr<WebSocketEventInterface> event_interface, 300 scoped_ptr<WebSocketEventInterface> event_interface,
301 URLRequestContext* url_request_context) 301 URLRequestContext* url_request_context)
302 : event_interface_(event_interface.Pass()), 302 : event_interface_(event_interface.Pass()),
303 url_request_context_(url_request_context), 303 url_request_context_(url_request_context),
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 // TODO(ricea): If current_send_quota_ has dropped below 417 // TODO(ricea): If current_send_quota_ has dropped below
418 // send_quota_low_water_mark_, it might be good to increase the "low 418 // send_quota_low_water_mark_, it might be good to increase the "low
419 // water mark" and "high water mark", but only if the link to the WebSocket 419 // water mark" and "high water mark", but only if the link to the WebSocket
420 // server is not saturated. 420 // server is not saturated.
421 scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size())); 421 scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size()));
422 std::copy(data.begin(), data.end(), buffer->data()); 422 std::copy(data.begin(), data.end(), buffer->data());
423 ignore_result(SendFrameFromIOBuffer(fin, op_code, buffer, data.size())); 423 ignore_result(SendFrameFromIOBuffer(fin, op_code, buffer, data.size()));
424 // |this| may have been deleted. 424 // |this| may have been deleted.
425 } 425 }
426 426
427 void WebSocketChannel::SendFlowControl(int64 quota) { 427 void WebSocketChannel::SendFlowControl(int64_t quota) {
428 DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED || 428 DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED ||
429 state_ == CLOSE_WAIT); 429 state_ == CLOSE_WAIT);
430 // TODO(ricea): Kill the renderer if it tries to send us a negative quota 430 // TODO(ricea): Kill the renderer if it tries to send us a negative quota
431 // value or > INT_MAX. 431 // value or > INT_MAX.
432 DCHECK_GE(quota, 0); 432 DCHECK_GE(quota, 0);
433 DCHECK_LE(quota, INT_MAX); 433 DCHECK_LE(quota, INT_MAX);
434 if (!pending_received_frames_.empty()) { 434 if (!pending_received_frames_.empty()) {
435 DCHECK_EQ(0u, current_receive_quota_); 435 DCHECK_EQ(0u, current_receive_quota_);
436 } 436 }
437 while (!pending_received_frames_.empty() && quota > 0) { 437 while (!pending_received_frames_.empty() && quota > 0) {
438 PendingReceivedFrame& front = pending_received_frames_.front(); 438 PendingReceivedFrame& front = pending_received_frames_.front();
439 const uint64 data_size = front.size() - front.offset(); 439 const uint64_t data_size = front.size() - front.offset();
440 const uint64 bytes_to_send = 440 const uint64_t bytes_to_send =
441 std::min(base::checked_cast<uint64>(quota), data_size); 441 std::min(base::checked_cast<uint64_t>(quota), data_size);
442 const bool final = front.final() && data_size == bytes_to_send; 442 const bool final = front.final() && data_size == bytes_to_send;
443 const char* data = 443 const char* data =
444 front.data().get() ? front.data()->data() + front.offset() : NULL; 444 front.data().get() ? front.data()->data() + front.offset() : NULL;
445 DCHECK(!bytes_to_send || data) << "Non empty data should not be null."; 445 DCHECK(!bytes_to_send || data) << "Non empty data should not be null.";
446 const std::vector<char> data_vector(data, data + bytes_to_send); 446 const std::vector<char> data_vector(data, data + bytes_to_send);
447 DVLOG(3) << "Sending frame previously split due to quota to the " 447 DVLOG(3) << "Sending frame previously split due to quota to the "
448 << "renderer: quota=" << quota << " data_size=" << data_size 448 << "renderer: quota=" << quota << " data_size=" << data_size
449 << " bytes_to_send=" << bytes_to_send; 449 << " bytes_to_send=" << bytes_to_send;
450 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) == 450 if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) ==
451 CHANNEL_DELETED) 451 CHANNEL_DELETED)
(...skipping 11 matching lines...) Expand all
463 // operation. 463 // operation.
464 const bool start_read = 464 const bool start_read =
465 current_receive_quota_ == 0 && quota > 0 && 465 current_receive_quota_ == 0 && quota > 0 &&
466 (state_ == CONNECTED || state_ == SEND_CLOSED || state_ == CLOSE_WAIT); 466 (state_ == CONNECTED || state_ == SEND_CLOSED || state_ == CLOSE_WAIT);
467 current_receive_quota_ += quota; 467 current_receive_quota_ += quota;
468 if (start_read) 468 if (start_read)
469 ignore_result(ReadFrames()); 469 ignore_result(ReadFrames());
470 // |this| may have been deleted. 470 // |this| may have been deleted.
471 } 471 }
472 472
473 void WebSocketChannel::StartClosingHandshake(uint16 code, 473 void WebSocketChannel::StartClosingHandshake(uint16_t code,
474 const std::string& reason) { 474 const std::string& reason) {
475 if (InClosingState()) { 475 if (InClosingState()) {
476 // When the associated renderer process is killed while the channel is in 476 // When the associated renderer process is killed while the channel is in
477 // CLOSING state we reach here. 477 // CLOSING state we reach here.
478 DVLOG(1) << "StartClosingHandshake called in state " << state_ 478 DVLOG(1) << "StartClosingHandshake called in state " << state_
479 << ". This may be a bug, or a harmless race."; 479 << ". This may be a bug, or a harmless race.";
480 return; 480 return;
481 } 481 }
482 if (state_ == CONNECTING) { 482 if (state_ == CONNECTING) {
483 // Abort the in-progress handshake and drop the connection immediately. 483 // Abort the in-progress handshake and drop the connection immediately.
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 kWebSocketErrorProtocolError, 761 kWebSocketErrorProtocolError,
762 "WebSocket Protocol Error"); 762 "WebSocket Protocol Error");
763 763
764 default: 764 default:
765 DCHECK_LT(result, 0) 765 DCHECK_LT(result, 0)
766 << "ReadFrames() should only return OK or ERR_ codes"; 766 << "ReadFrames() should only return OK or ERR_ codes";
767 767
768 stream_->Close(); 768 stream_->Close();
769 SetState(CLOSED); 769 SetState(CLOSED);
770 770
771 uint16 code = kWebSocketErrorAbnormalClosure; 771 uint16_t code = kWebSocketErrorAbnormalClosure;
772 std::string reason = ""; 772 std::string reason = "";
773 bool was_clean = false; 773 bool was_clean = false;
774 if (has_received_close_frame_) { 774 if (has_received_close_frame_) {
775 code = received_close_code_; 775 code = received_close_code_;
776 reason = received_close_reason_; 776 reason = received_close_reason_;
777 was_clean = (result == ERR_CONNECTION_CLOSED); 777 was_clean = (result == ERR_CONNECTION_CLOSED);
778 } 778 }
779 779
780 return DoDropChannel(was_clean, code, reason); 780 return DoDropChannel(was_clean, code, reason);
781 } 781 }
(...skipping 26 matching lines...) Expand all
808 808
809 // Respond to the frame appropriately to its type. 809 // Respond to the frame appropriately to its type.
810 return HandleFrameByState( 810 return HandleFrameByState(
811 opcode, frame->header.final, frame->data, frame->header.payload_length); 811 opcode, frame->header.final, frame->data, frame->header.payload_length);
812 } 812 }
813 813
814 ChannelState WebSocketChannel::HandleFrameByState( 814 ChannelState WebSocketChannel::HandleFrameByState(
815 const WebSocketFrameHeader::OpCode opcode, 815 const WebSocketFrameHeader::OpCode opcode,
816 bool final, 816 bool final,
817 const scoped_refptr<IOBuffer>& data_buffer, 817 const scoped_refptr<IOBuffer>& data_buffer,
818 uint64 size) { 818 uint64_t size) {
819 DCHECK_NE(RECV_CLOSED, state_) 819 DCHECK_NE(RECV_CLOSED, state_)
820 << "HandleFrame() does not support being called re-entrantly from within " 820 << "HandleFrame() does not support being called re-entrantly from within "
821 "SendClose()"; 821 "SendClose()";
822 DCHECK_NE(CLOSED, state_); 822 DCHECK_NE(CLOSED, state_);
823 if (state_ == CLOSE_WAIT) { 823 if (state_ == CLOSE_WAIT) {
824 std::string frame_name; 824 std::string frame_name;
825 GetFrameTypeForOpcode(opcode, &frame_name); 825 GetFrameTypeForOpcode(opcode, &frame_name);
826 826
827 // FailChannel() won't send another Close frame. 827 // FailChannel() won't send another Close frame.
828 return FailChannel( 828 return FailChannel(
(...skipping 16 matching lines...) Expand all
845 case WebSocketFrameHeader::kOpCodePong: 845 case WebSocketFrameHeader::kOpCodePong:
846 DVLOG(1) << "Got Pong of size " << size; 846 DVLOG(1) << "Got Pong of size " << size;
847 // There is no need to do anything with pong messages. 847 // There is no need to do anything with pong messages.
848 return CHANNEL_ALIVE; 848 return CHANNEL_ALIVE;
849 849
850 case WebSocketFrameHeader::kOpCodeClose: { 850 case WebSocketFrameHeader::kOpCodeClose: {
851 // TODO(ricea): If there is a message which is queued for transmission to 851 // TODO(ricea): If there is a message which is queued for transmission to
852 // the renderer, then the renderer should not receive an 852 // the renderer, then the renderer should not receive an
853 // OnClosingHandshake or OnDropChannel IPC until the queued message has 853 // OnClosingHandshake or OnDropChannel IPC until the queued message has
854 // been completedly transmitted. 854 // been completedly transmitted.
855 uint16 code = kWebSocketNormalClosure; 855 uint16_t code = kWebSocketNormalClosure;
856 std::string reason; 856 std::string reason;
857 std::string message; 857 std::string message;
858 if (!ParseClose(data_buffer, size, &code, &reason, &message)) { 858 if (!ParseClose(data_buffer, size, &code, &reason, &message)) {
859 return FailChannel(message, code, reason); 859 return FailChannel(message, code, reason);
860 } 860 }
861 // TODO(ricea): Find a way to safely log the message from the close 861 // TODO(ricea): Find a way to safely log the message from the close
862 // message (escape control codes and so on). 862 // message (escape control codes and so on).
863 DVLOG(1) << "Got Close with code " << code; 863 DVLOG(1) << "Got Close with code " << code;
864 switch (state_) { 864 switch (state_) {
865 case CONNECTED: 865 case CONNECTED:
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 base::StringPrintf("Unrecognized frame opcode: %d", opcode), 918 base::StringPrintf("Unrecognized frame opcode: %d", opcode),
919 kWebSocketErrorProtocolError, 919 kWebSocketErrorProtocolError,
920 "Unknown opcode"); 920 "Unknown opcode");
921 } 921 }
922 } 922 }
923 923
924 ChannelState WebSocketChannel::HandleDataFrame( 924 ChannelState WebSocketChannel::HandleDataFrame(
925 WebSocketFrameHeader::OpCode opcode, 925 WebSocketFrameHeader::OpCode opcode,
926 bool final, 926 bool final,
927 const scoped_refptr<IOBuffer>& data_buffer, 927 const scoped_refptr<IOBuffer>& data_buffer,
928 uint64 size) { 928 uint64_t size) {
929 if (state_ != CONNECTED) { 929 if (state_ != CONNECTED) {
930 DVLOG(3) << "Ignored data packet received in state " << state_; 930 DVLOG(3) << "Ignored data packet received in state " << state_;
931 return CHANNEL_ALIVE; 931 return CHANNEL_ALIVE;
932 } 932 }
933 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || 933 DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation ||
934 opcode == WebSocketFrameHeader::kOpCodeText || 934 opcode == WebSocketFrameHeader::kOpCodeText ||
935 opcode == WebSocketFrameHeader::kOpCodeBinary); 935 opcode == WebSocketFrameHeader::kOpCodeBinary);
936 const bool got_continuation = 936 const bool got_continuation =
937 (opcode == WebSocketFrameHeader::kOpCodeContinuation); 937 (opcode == WebSocketFrameHeader::kOpCodeContinuation);
938 if (got_continuation != expecting_to_handle_continuation_) { 938 if (got_continuation != expecting_to_handle_continuation_) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 current_receive_quota_ -= size; 994 current_receive_quota_ -= size;
995 995
996 // Sends the received frame to the renderer process. 996 // Sends the received frame to the renderer process.
997 return event_interface_->OnDataFrame(final, opcode_to_send, data); 997 return event_interface_->OnDataFrame(final, opcode_to_send, data);
998 } 998 }
999 999
1000 ChannelState WebSocketChannel::SendFrameFromIOBuffer( 1000 ChannelState WebSocketChannel::SendFrameFromIOBuffer(
1001 bool fin, 1001 bool fin,
1002 WebSocketFrameHeader::OpCode op_code, 1002 WebSocketFrameHeader::OpCode op_code,
1003 const scoped_refptr<IOBuffer>& buffer, 1003 const scoped_refptr<IOBuffer>& buffer,
1004 uint64 size) { 1004 uint64_t size) {
1005 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED); 1005 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED);
1006 DCHECK(stream_); 1006 DCHECK(stream_);
1007 1007
1008 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code)); 1008 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code));
1009 WebSocketFrameHeader& header = frame->header; 1009 WebSocketFrameHeader& header = frame->header;
1010 header.final = fin; 1010 header.final = fin;
1011 header.masked = true; 1011 header.masked = true;
1012 header.payload_length = size; 1012 header.payload_length = size;
1013 frame->data = buffer; 1013 frame->data = buffer;
1014 1014
1015 if (data_being_sent_) { 1015 if (data_being_sent_) {
1016 // Either the link to the WebSocket server is saturated, or several messages 1016 // Either the link to the WebSocket server is saturated, or several messages
1017 // are being sent in a batch. 1017 // are being sent in a batch.
1018 // TODO(ricea): Keep some statistics to work out the situation and adjust 1018 // TODO(ricea): Keep some statistics to work out the situation and adjust
1019 // quota appropriately. 1019 // quota appropriately.
1020 if (!data_to_send_next_) 1020 if (!data_to_send_next_)
1021 data_to_send_next_.reset(new SendBuffer); 1021 data_to_send_next_.reset(new SendBuffer);
1022 data_to_send_next_->AddFrame(frame.Pass()); 1022 data_to_send_next_->AddFrame(frame.Pass());
1023 return CHANNEL_ALIVE; 1023 return CHANNEL_ALIVE;
1024 } 1024 }
1025 1025
1026 data_being_sent_.reset(new SendBuffer); 1026 data_being_sent_.reset(new SendBuffer);
1027 data_being_sent_->AddFrame(frame.Pass()); 1027 data_being_sent_->AddFrame(frame.Pass());
1028 return WriteFrames(); 1028 return WriteFrames();
1029 } 1029 }
1030 1030
1031 ChannelState WebSocketChannel::FailChannel(const std::string& message, 1031 ChannelState WebSocketChannel::FailChannel(const std::string& message,
1032 uint16 code, 1032 uint16_t code,
1033 const std::string& reason) { 1033 const std::string& reason) {
1034 DCHECK_NE(FRESHLY_CONSTRUCTED, state_); 1034 DCHECK_NE(FRESHLY_CONSTRUCTED, state_);
1035 DCHECK_NE(CONNECTING, state_); 1035 DCHECK_NE(CONNECTING, state_);
1036 DCHECK_NE(CLOSED, state_); 1036 DCHECK_NE(CLOSED, state_);
1037 1037
1038 // TODO(ricea): Logging. 1038 // TODO(ricea): Logging.
1039 if (state_ == CONNECTED) { 1039 if (state_ == CONNECTED) {
1040 if (SendClose(code, reason) == CHANNEL_DELETED) 1040 if (SendClose(code, reason) == CHANNEL_DELETED)
1041 return CHANNEL_DELETED; 1041 return CHANNEL_DELETED;
1042 } 1042 }
1043 1043
1044 // Careful study of RFC6455 section 7.1.7 and 7.1.1 indicates the browser 1044 // Careful study of RFC6455 section 7.1.7 and 7.1.1 indicates the browser
1045 // should close the connection itself without waiting for the closing 1045 // should close the connection itself without waiting for the closing
1046 // handshake. 1046 // handshake.
1047 stream_->Close(); 1047 stream_->Close();
1048 SetState(CLOSED); 1048 SetState(CLOSED);
1049 ChannelState result = event_interface_->OnFailChannel(message); 1049 ChannelState result = event_interface_->OnFailChannel(message);
1050 DCHECK_EQ(CHANNEL_DELETED, result); 1050 DCHECK_EQ(CHANNEL_DELETED, result);
1051 return result; 1051 return result;
1052 } 1052 }
1053 1053
1054 ChannelState WebSocketChannel::SendClose(uint16 code, 1054 ChannelState WebSocketChannel::SendClose(uint16_t code,
1055 const std::string& reason) { 1055 const std::string& reason) {
1056 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED); 1056 DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED);
1057 DCHECK_LE(reason.size(), kMaximumCloseReasonLength); 1057 DCHECK_LE(reason.size(), kMaximumCloseReasonLength);
1058 scoped_refptr<IOBuffer> body; 1058 scoped_refptr<IOBuffer> body;
1059 uint64 size = 0; 1059 uint64_t size = 0;
1060 if (code == kWebSocketErrorNoStatusReceived) { 1060 if (code == kWebSocketErrorNoStatusReceived) {
1061 // Special case: translate kWebSocketErrorNoStatusReceived into a Close 1061 // Special case: translate kWebSocketErrorNoStatusReceived into a Close
1062 // frame with no payload. 1062 // frame with no payload.
1063 DCHECK(reason.empty()); 1063 DCHECK(reason.empty());
1064 body = new IOBuffer(0); 1064 body = new IOBuffer(0);
1065 } else { 1065 } else {
1066 const size_t payload_length = kWebSocketCloseCodeLength + reason.length(); 1066 const size_t payload_length = kWebSocketCloseCodeLength + reason.length();
1067 body = new IOBuffer(payload_length); 1067 body = new IOBuffer(payload_length);
1068 size = payload_length; 1068 size = payload_length;
1069 base::WriteBigEndian(body->data(), code); 1069 base::WriteBigEndian(body->data(), code);
1070 static_assert(sizeof(code) == kWebSocketCloseCodeLength, 1070 static_assert(sizeof(code) == kWebSocketCloseCodeLength,
1071 "they should both be two"); 1071 "they should both be two");
1072 std::copy( 1072 std::copy(
1073 reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength); 1073 reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength);
1074 } 1074 }
1075 if (SendFrameFromIOBuffer( 1075 if (SendFrameFromIOBuffer(
1076 true, WebSocketFrameHeader::kOpCodeClose, body, size) == 1076 true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
1077 CHANNEL_DELETED) 1077 CHANNEL_DELETED)
1078 return CHANNEL_DELETED; 1078 return CHANNEL_DELETED;
1079 return CHANNEL_ALIVE; 1079 return CHANNEL_ALIVE;
1080 } 1080 }
1081 1081
1082 bool WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer, 1082 bool WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer,
1083 uint64 size, 1083 uint64_t size,
1084 uint16* code, 1084 uint16_t* code,
1085 std::string* reason, 1085 std::string* reason,
1086 std::string* message) { 1086 std::string* message) {
1087 reason->clear(); 1087 reason->clear();
1088 if (size < kWebSocketCloseCodeLength) { 1088 if (size < kWebSocketCloseCodeLength) {
1089 if (size == 0U) { 1089 if (size == 0U) {
1090 *code = kWebSocketErrorNoStatusReceived; 1090 *code = kWebSocketErrorNoStatusReceived;
1091 return true; 1091 return true;
1092 } 1092 }
1093 1093
1094 DVLOG(1) << "Close frame with payload size " << size << " received " 1094 DVLOG(1) << "Close frame with payload size " << size << " received "
1095 << "(the first byte is " << std::hex 1095 << "(the first byte is " << std::hex
1096 << static_cast<int>(buffer->data()[0]) << ")"; 1096 << static_cast<int>(buffer->data()[0]) << ")";
1097 *code = kWebSocketErrorProtocolError; 1097 *code = kWebSocketErrorProtocolError;
1098 *message = 1098 *message =
1099 "Received a broken close frame containing an invalid size body."; 1099 "Received a broken close frame containing an invalid size body.";
1100 return false; 1100 return false;
1101 } 1101 }
1102 1102
1103 const char* data = buffer->data(); 1103 const char* data = buffer->data();
1104 uint16 unchecked_code = 0; 1104 uint16_t unchecked_code = 0;
1105 base::ReadBigEndian(data, &unchecked_code); 1105 base::ReadBigEndian(data, &unchecked_code);
1106 static_assert(sizeof(unchecked_code) == kWebSocketCloseCodeLength, 1106 static_assert(sizeof(unchecked_code) == kWebSocketCloseCodeLength,
1107 "they should both be two bytes"); 1107 "they should both be two bytes");
1108 1108
1109 switch (unchecked_code) { 1109 switch (unchecked_code) {
1110 case kWebSocketErrorNoStatusReceived: 1110 case kWebSocketErrorNoStatusReceived:
1111 case kWebSocketErrorAbnormalClosure: 1111 case kWebSocketErrorAbnormalClosure:
1112 case kWebSocketErrorTlsHandshake: 1112 case kWebSocketErrorTlsHandshake:
1113 *code = kWebSocketErrorProtocolError; 1113 *code = kWebSocketErrorProtocolError;
1114 *message = 1114 *message =
(...skipping 11 matching lines...) Expand all
1126 return true; 1126 return true;
1127 } 1127 }
1128 1128
1129 *code = kWebSocketErrorProtocolError; 1129 *code = kWebSocketErrorProtocolError;
1130 *reason = "Invalid UTF-8 in Close frame"; 1130 *reason = "Invalid UTF-8 in Close frame";
1131 *message = "Received a broken close frame containing invalid UTF-8."; 1131 *message = "Received a broken close frame containing invalid UTF-8.";
1132 return false; 1132 return false;
1133 } 1133 }
1134 1134
1135 ChannelState WebSocketChannel::DoDropChannel(bool was_clean, 1135 ChannelState WebSocketChannel::DoDropChannel(bool was_clean,
1136 uint16 code, 1136 uint16_t code,
1137 const std::string& reason) { 1137 const std::string& reason) {
1138 if (CHANNEL_DELETED == 1138 if (CHANNEL_DELETED ==
1139 notification_sender_->SendImmediately(event_interface_.get())) 1139 notification_sender_->SendImmediately(event_interface_.get()))
1140 return CHANNEL_DELETED; 1140 return CHANNEL_DELETED;
1141 ChannelState result = 1141 ChannelState result =
1142 event_interface_->OnDropChannel(was_clean, code, reason); 1142 event_interface_->OnDropChannel(was_clean, code, reason);
1143 DCHECK_EQ(CHANNEL_DELETED, result); 1143 DCHECK_EQ(CHANNEL_DELETED, result);
1144 return result; 1144 return result;
1145 } 1145 }
1146 1146
1147 void WebSocketChannel::CloseTimeout() { 1147 void WebSocketChannel::CloseTimeout() {
1148 stream_->Close(); 1148 stream_->Close();
1149 SetState(CLOSED); 1149 SetState(CLOSED);
1150 DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""); 1150 DoDropChannel(false, kWebSocketErrorAbnormalClosure, "");
1151 // |this| has been deleted. 1151 // |this| has been deleted.
1152 } 1152 }
1153 1153
1154 } // namespace net 1154 } // 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