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

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

Issue 131333010: Rename closing_* in WebSocketChannel to received_close_ and do some refactoring (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « net/websockets/websocket_channel.h ('k') | no next file » | 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 <algorithm> 7 #include <algorithm>
8 8
9 #include "base/basictypes.h" // for size_t 9 #include "base/basictypes.h" // for size_t
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 DCHECK_NE(kInvalidRangesEnd, upper); 73 DCHECK_NE(kInvalidRangesEnd, upper);
74 DCHECK_GT(upper, kInvalidRanges); 74 DCHECK_GT(upper, kInvalidRanges);
75 DCHECK_GT(*upper, code); 75 DCHECK_GT(*upper, code);
76 DCHECK_LE(*(upper - 1), code); 76 DCHECK_LE(*(upper - 1), code);
77 return ((upper - kInvalidRanges) % 2) == 0; 77 return ((upper - kInvalidRanges) % 2) == 0;
78 } 78 }
79 79
80 // This function avoids a bunch of boilerplate code. 80 // This function avoids a bunch of boilerplate code.
81 void AllowUnused(ChannelState ALLOW_UNUSED unused) {} 81 void AllowUnused(ChannelState ALLOW_UNUSED unused) {}
82 82
83 // Sets |name| to the name of the frame type for the given |opcode|. Note that
84 // for all of Text, Binary and Continuation opcode, this method returns
85 // "Data frame".
86 void GetFrameTypeForOpcode(WebSocketFrameHeader::OpCode opcode,
87 std::string* name) {
88 switch (opcode) {
89 case WebSocketFrameHeader::kOpCodeText: // fall-thru
90 case WebSocketFrameHeader::kOpCodeBinary: // fall-thru
91 case WebSocketFrameHeader::kOpCodeContinuation:
92 *name = "Data frame";
93 break;
94
95 case WebSocketFrameHeader::kOpCodePing:
96 *name = "Ping";
97 break;
98
99 case WebSocketFrameHeader::kOpCodePong:
100 *name = "Pong";
101 break;
102
103 case WebSocketFrameHeader::kOpCodeClose:
104 *name = "Close";
105 break;
106
107 default:
108 *name = "Unknown frame type";
109 break;
110 }
111
112 return;
113 }
114
83 } // namespace 115 } // namespace
84 116
85 // A class to encapsulate a set of frames and information about the size of 117 // A class to encapsulate a set of frames and information about the size of
86 // those frames. 118 // those frames.
87 class WebSocketChannel::SendBuffer { 119 class WebSocketChannel::SendBuffer {
88 public: 120 public:
89 SendBuffer() : total_bytes_(0) {} 121 SendBuffer() : total_bytes_(0) {}
90 122
91 // Add a WebSocketFrame to the buffer and increase total_bytes_. 123 // Add a WebSocketFrame to the buffer and increase total_bytes_.
92 void AddFrame(scoped_ptr<WebSocketFrame> chunk); 124 void AddFrame(scoped_ptr<WebSocketFrame> chunk);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 250
219 WebSocketChannel::WebSocketChannel( 251 WebSocketChannel::WebSocketChannel(
220 scoped_ptr<WebSocketEventInterface> event_interface, 252 scoped_ptr<WebSocketEventInterface> event_interface,
221 URLRequestContext* url_request_context) 253 URLRequestContext* url_request_context)
222 : event_interface_(event_interface.Pass()), 254 : event_interface_(event_interface.Pass()),
223 url_request_context_(url_request_context), 255 url_request_context_(url_request_context),
224 send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark), 256 send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark),
225 send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark), 257 send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark),
226 current_send_quota_(0), 258 current_send_quota_(0),
227 timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)), 259 timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)),
228 closing_code_(0), 260 received_close_code_(0),
229 state_(FRESHLY_CONSTRUCTED), 261 state_(FRESHLY_CONSTRUCTED),
230 notification_sender_(new HandshakeNotificationSender(this)), 262 notification_sender_(new HandshakeNotificationSender(this)),
231 sending_text_message_(false), 263 sending_text_message_(false),
232 receiving_text_message_(false) {} 264 receiving_text_message_(false) {}
233 265
234 WebSocketChannel::~WebSocketChannel() { 266 WebSocketChannel::~WebSocketChannel() {
235 // The stream may hold a pointer to read_frames_, and so it needs to be 267 // The stream may hold a pointer to read_frames_, and so it needs to be
236 // destroyed first. 268 // destroyed first.
237 stream_.reset(); 269 stream_.reset();
238 // The timer may have a callback pointing back to us, so stop it just in case 270 // The timer may have a callback pointing back to us, so stop it just in case
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 DCHECK_NE(ERR_IO_PENDING, result); 588 DCHECK_NE(ERR_IO_PENDING, result);
557 switch (result) { 589 switch (result) {
558 case OK: 590 case OK:
559 // ReadFrames() must use ERR_CONNECTION_CLOSED for a closed connection 591 // ReadFrames() must use ERR_CONNECTION_CLOSED for a closed connection
560 // with no data read, not an empty response. 592 // with no data read, not an empty response.
561 DCHECK(!read_frames_.empty()) 593 DCHECK(!read_frames_.empty())
562 << "ReadFrames() returned OK, but nothing was read."; 594 << "ReadFrames() returned OK, but nothing was read.";
563 for (size_t i = 0; i < read_frames_.size(); ++i) { 595 for (size_t i = 0; i < read_frames_.size(); ++i) {
564 scoped_ptr<WebSocketFrame> frame(read_frames_[i]); 596 scoped_ptr<WebSocketFrame> frame(read_frames_[i]);
565 read_frames_[i] = NULL; 597 read_frames_[i] = NULL;
566 if (ProcessFrame(frame.Pass()) == CHANNEL_DELETED) 598 if (HandleFrame(frame.Pass()) == CHANNEL_DELETED)
567 return CHANNEL_DELETED; 599 return CHANNEL_DELETED;
568 } 600 }
569 read_frames_.clear(); 601 read_frames_.clear();
570 // There should always be a call to ReadFrames pending. 602 // There should always be a call to ReadFrames pending.
571 // TODO(ricea): Unless we are out of quota. 603 // TODO(ricea): Unless we are out of quota.
572 DCHECK_NE(CLOSED, state_); 604 DCHECK_NE(CLOSED, state_);
573 if (!synchronous) 605 if (!synchronous)
574 return ReadFrames(); 606 return ReadFrames();
575 return CHANNEL_ALIVE; 607 return CHANNEL_ALIVE;
576 608
577 case ERR_WS_PROTOCOL_ERROR: 609 case ERR_WS_PROTOCOL_ERROR:
578 // This could be kWebSocketErrorProtocolError (specifically, non-minimal 610 // This could be kWebSocketErrorProtocolError (specifically, non-minimal
579 // encoding of payload length) or kWebSocketErrorMessageTooBig, or an 611 // encoding of payload length) or kWebSocketErrorMessageTooBig, or an
580 // extension-specific error. 612 // extension-specific error.
581 return FailChannel("Invalid frame header", 613 return FailChannel("Invalid frame header",
582 kWebSocketErrorProtocolError, 614 kWebSocketErrorProtocolError,
583 "WebSocket Protocol Error"); 615 "WebSocket Protocol Error");
584 616
585 default: 617 default:
586 DCHECK_LT(result, 0) 618 DCHECK_LT(result, 0)
587 << "ReadFrames() should only return OK or ERR_ codes"; 619 << "ReadFrames() should only return OK or ERR_ codes";
588 stream_->Close(); 620 stream_->Close();
589 DCHECK_NE(CLOSED, state_); 621 DCHECK_NE(CLOSED, state_);
590 state_ = CLOSED; 622 state_ = CLOSED;
591 uint16 code = kWebSocketErrorAbnormalClosure; 623 uint16 code = kWebSocketErrorAbnormalClosure;
592 std::string reason = ""; 624 std::string reason = "";
593 bool was_clean = false; 625 bool was_clean = false;
594 if (closing_code_ != 0) { 626 if (received_close_code_ != 0) {
595 code = closing_code_; 627 code = received_close_code_;
596 reason = closing_reason_; 628 reason = received_close_reason_;
597 was_clean = (result == ERR_CONNECTION_CLOSED); 629 was_clean = (result == ERR_CONNECTION_CLOSED);
598 } 630 }
599 return DoDropChannel(was_clean, code, reason); 631 return DoDropChannel(was_clean, code, reason);
600 } 632 }
601 } 633 }
602 634
603 ChannelState WebSocketChannel::ProcessFrame(scoped_ptr<WebSocketFrame> frame) { 635 ChannelState WebSocketChannel::HandleFrame(
636 scoped_ptr<WebSocketFrame> frame) {
604 if (frame->header.masked) { 637 if (frame->header.masked) {
605 // RFC6455 Section 5.1 "A client MUST close a connection if it detects a 638 // RFC6455 Section 5.1 "A client MUST close a connection if it detects a
606 // masked frame." 639 // masked frame."
607 return FailChannel( 640 return FailChannel(
608 "A server must not mask any frames that it sends to the " 641 "A server must not mask any frames that it sends to the "
609 "client.", 642 "client.",
610 kWebSocketErrorProtocolError, 643 kWebSocketErrorProtocolError,
611 "Masked frame from server"); 644 "Masked frame from server");
612 } 645 }
613 const WebSocketFrameHeader::OpCode opcode = frame->header.opcode; 646 const WebSocketFrameHeader::OpCode opcode = frame->header.opcode;
614 if (WebSocketFrameHeader::IsKnownControlOpCode(opcode) && 647 if (WebSocketFrameHeader::IsKnownControlOpCode(opcode) &&
615 !frame->header.final) { 648 !frame->header.final) {
616 return FailChannel( 649 return FailChannel(
617 base::StringPrintf("Received fragmented control frame: opcode = %d", 650 base::StringPrintf("Received fragmented control frame: opcode = %d",
618 opcode), 651 opcode),
619 kWebSocketErrorProtocolError, 652 kWebSocketErrorProtocolError,
620 "Control message with FIN bit unset received"); 653 "Control message with FIN bit unset received");
621 } 654 }
622 655
623 // Respond to the frame appropriately to its type. 656 // Respond to the frame appropriately to its type.
624 return HandleFrame( 657 return HandleFrameByState(
625 opcode, frame->header.final, frame->data, frame->header.payload_length); 658 opcode, frame->header.final, frame->data, frame->header.payload_length);
626 } 659 }
627 660
628 ChannelState WebSocketChannel::HandleFrame( 661 ChannelState WebSocketChannel::HandleFrameByState(
629 const WebSocketFrameHeader::OpCode opcode, 662 const WebSocketFrameHeader::OpCode opcode,
630 bool final, 663 bool final,
631 const scoped_refptr<IOBuffer>& data_buffer, 664 const scoped_refptr<IOBuffer>& data_buffer,
632 size_t size) { 665 size_t size) {
633 DCHECK_NE(RECV_CLOSED, state_) 666 DCHECK_NE(RECV_CLOSED, state_)
634 << "HandleFrame() does not support being called re-entrantly from within " 667 << "HandleFrame() does not support being called re-entrantly from within "
635 "SendClose()"; 668 "SendClose()";
636 DCHECK_NE(CLOSED, state_); 669 DCHECK_NE(CLOSED, state_);
637 if (state_ == CLOSE_WAIT) { 670 if (state_ == CLOSE_WAIT) {
638 std::string frame_name; 671 std::string frame_name;
639 switch (opcode) { 672 GetFrameTypeForOpcode(opcode, &frame_name);
640 case WebSocketFrameHeader::kOpCodeText: // fall-thru
641 case WebSocketFrameHeader::kOpCodeBinary: // fall-thru
642 case WebSocketFrameHeader::kOpCodeContinuation:
643 frame_name = "Data frame";
644 break;
645 673
646 case WebSocketFrameHeader::kOpCodePing:
647 frame_name = "Ping";
648 break;
649
650 case WebSocketFrameHeader::kOpCodePong:
651 frame_name = "Pong";
652 break;
653
654 case WebSocketFrameHeader::kOpCodeClose:
655 frame_name = "Close";
656 break;
657
658 default:
659 frame_name = "Unknown frame type";
660 break;
661 }
662 // FailChannel() won't send another Close frame. 674 // FailChannel() won't send another Close frame.
663 return FailChannel( 675 return FailChannel(
664 frame_name + " received after close", kWebSocketErrorProtocolError, ""); 676 frame_name + " received after close", kWebSocketErrorProtocolError, "");
665 } 677 }
666 switch (opcode) { 678 switch (opcode) {
667 case WebSocketFrameHeader::kOpCodeText: // fall-thru 679 case WebSocketFrameHeader::kOpCodeText: // fall-thru
668 case WebSocketFrameHeader::kOpCodeBinary: // fall-thru 680 case WebSocketFrameHeader::kOpCodeBinary: // fall-thru
669 case WebSocketFrameHeader::kOpCodeContinuation: 681 case WebSocketFrameHeader::kOpCodeContinuation:
670 if (state_ == CONNECTED) { 682 if (state_ == CONNECTED) {
671 if (opcode == WebSocketFrameHeader::kOpCodeText || 683 if (opcode == WebSocketFrameHeader::kOpCodeText ||
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 // message (escape control codes and so on). 736 // message (escape control codes and so on).
725 VLOG(1) << "Got Close with code " << code; 737 VLOG(1) << "Got Close with code " << code;
726 switch (state_) { 738 switch (state_) {
727 case CONNECTED: 739 case CONNECTED:
728 state_ = RECV_CLOSED; 740 state_ = RECV_CLOSED;
729 if (SendClose(code, reason) == // Sets state_ to CLOSE_WAIT 741 if (SendClose(code, reason) == // Sets state_ to CLOSE_WAIT
730 CHANNEL_DELETED) 742 CHANNEL_DELETED)
731 return CHANNEL_DELETED; 743 return CHANNEL_DELETED;
732 if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED) 744 if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED)
733 return CHANNEL_DELETED; 745 return CHANNEL_DELETED;
734 closing_code_ = code; 746 received_close_code_ = code;
735 closing_reason_ = reason; 747 received_close_reason_ = reason;
736 break; 748 break;
737 749
738 case SEND_CLOSED: 750 case SEND_CLOSED:
739 state_ = CLOSE_WAIT; 751 state_ = CLOSE_WAIT;
740 // From RFC6455 section 7.1.5: "Each endpoint 752 // From RFC6455 section 7.1.5: "Each endpoint
741 // will see the status code sent by the other end as _The WebSocket 753 // will see the status code sent by the other end as _The WebSocket
742 // Connection Close Code_." 754 // Connection Close Code_."
743 closing_code_ = code; 755 received_close_code_ = code;
744 closing_reason_ = reason; 756 received_close_reason_ = reason;
745 break; 757 break;
746 758
747 default: 759 default:
748 LOG(DFATAL) << "Got Close in unexpected state " << state_; 760 LOG(DFATAL) << "Got Close in unexpected state " << state_;
749 break; 761 break;
750 } 762 }
751 return CHANNEL_ALIVE; 763 return CHANNEL_ALIVE;
752 } 764 }
753 765
754 default: 766 default:
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 919
908 void WebSocketChannel::CloseTimeout() { 920 void WebSocketChannel::CloseTimeout() {
909 stream_->Close(); 921 stream_->Close();
910 DCHECK_NE(CLOSED, state_); 922 DCHECK_NE(CLOSED, state_);
911 state_ = CLOSED; 923 state_ = CLOSED;
912 AllowUnused(DoDropChannel(false, kWebSocketErrorAbnormalClosure, "")); 924 AllowUnused(DoDropChannel(false, kWebSocketErrorAbnormalClosure, ""));
913 // |this| has been deleted. 925 // |this| has been deleted.
914 } 926 }
915 927
916 } // namespace net 928 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_channel.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698