Index: net/websockets/websocket_channel.cc |
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc |
index 9e255ab1f7a0fa5ad918896e8dc9ccd3fd44bb4e..d75c0a3728d19636ba445d8d144f3454e0baff1c 100644 |
--- a/net/websockets/websocket_channel.cc |
+++ b/net/websockets/websocket_channel.cc |
@@ -229,7 +229,8 @@ WebSocketChannel::WebSocketChannel( |
state_(FRESHLY_CONSTRUCTED), |
notification_sender_(new HandshakeNotificationSender(this)), |
sending_text_message_(false), |
- receiving_text_message_(false) {} |
+ receiving_text_message_(false), |
+ expecting_to_handle_continuation_(false) {} |
WebSocketChannel::~WebSocketChannel() { |
// The stream may hold a pointer to read_frames_, and so it needs to be |
@@ -665,40 +666,9 @@ ChannelState WebSocketChannel::HandleFrame( |
} |
switch (opcode) { |
case WebSocketFrameHeader::kOpCodeText: // fall-thru |
- case WebSocketFrameHeader::kOpCodeBinary: // fall-thru |
+ case WebSocketFrameHeader::kOpCodeBinary: |
case WebSocketFrameHeader::kOpCodeContinuation: |
- if (state_ == CONNECTED) { |
- if (opcode == WebSocketFrameHeader::kOpCodeText || |
- (opcode == WebSocketFrameHeader::kOpCodeContinuation && |
- receiving_text_message_)) { |
- // This call is not redundant when size == 0 because it tells us what |
- // the current state is. |
- StreamingUtf8Validator::State state = |
- incoming_utf8_validator_.AddBytes( |
- size ? data_buffer->data() : NULL, size); |
- if (state == StreamingUtf8Validator::INVALID || |
- (state == StreamingUtf8Validator::VALID_MIDPOINT && final)) { |
- return FailChannel("Could not decode a text frame as UTF-8.", |
- kWebSocketErrorProtocolError, |
- "Invalid UTF-8 in text frame"); |
- } |
- receiving_text_message_ = !final; |
- DCHECK(!final || state == StreamingUtf8Validator::VALID_ENDPOINT); |
- } |
- // TODO(ricea): Can this copy be eliminated? |
- const char* const data_begin = size ? data_buffer->data() : NULL; |
- const char* const data_end = data_begin + size; |
- const std::vector<char> data(data_begin, data_end); |
- // TODO(ricea): Handle the case when ReadFrames returns far |
- // more data at once than should be sent in a single IPC. This needs to |
- // be handled carefully, as an overloaded IO thread is one possible |
- // cause of receiving very large chunks. |
- |
- // Sends the received frame to the renderer process. |
- return event_interface_->OnDataFrame(final, opcode, data); |
- } |
- VLOG(3) << "Ignored data packet received in state " << state_; |
- return CHANNEL_ALIVE; |
+ return HandleDataFrame(opcode, final, data_buffer, size); |
case WebSocketFrameHeader::kOpCodePing: |
VLOG(1) << "Got Ping of size " << size; |
@@ -759,6 +729,59 @@ ChannelState WebSocketChannel::HandleFrame( |
} |
} |
+ChannelState WebSocketChannel::HandleDataFrame( |
+ const WebSocketFrameHeader::OpCode opcode, |
+ bool final, |
+ const scoped_refptr<IOBuffer>& data_buffer, |
+ size_t size) { |
+ if (state_ != CONNECTED) { |
+ DVLOG(3) << "Ignored data packet received in state " << state_; |
+ return CHANNEL_ALIVE; |
+ } |
+ DCHECK(opcode == WebSocketFrameHeader::kOpCodeContinuation || |
+ opcode == WebSocketFrameHeader::kOpCodeText || |
+ opcode == WebSocketFrameHeader::kOpCodeBinary); |
+ const bool got_continuation = |
+ (opcode == WebSocketFrameHeader::kOpCodeContinuation); |
+ if (got_continuation != expecting_to_handle_continuation_) { |
+ const std::string console_log = got_continuation |
+ ? "Received unexpected continuation frame." |
+ : "Received start of new message but previous message is unfinished."; |
+ const std::string reason = got_continuation |
+ ? "Unexpected continuation" |
+ : "Previous data frame unfinished"; |
+ return FailChannel(console_log, kWebSocketErrorProtocolError, reason); |
+ } |
+ expecting_to_handle_continuation_ = !final; |
+ if (opcode == WebSocketFrameHeader::kOpCodeText || |
+ (opcode == WebSocketFrameHeader::kOpCodeContinuation && |
+ receiving_text_message_)) { |
+ // This call is not redundant when size == 0 because it tells us what |
+ // the current state is. |
+ StreamingUtf8Validator::State state = incoming_utf8_validator_.AddBytes( |
+ size ? data_buffer->data() : NULL, size); |
+ if (state == StreamingUtf8Validator::INVALID || |
+ (state == StreamingUtf8Validator::VALID_MIDPOINT && final)) { |
+ return FailChannel("Could not decode a text frame as UTF-8.", |
+ kWebSocketErrorProtocolError, |
+ "Invalid UTF-8 in text frame"); |
+ } |
+ receiving_text_message_ = !final; |
+ DCHECK(!final || state == StreamingUtf8Validator::VALID_ENDPOINT); |
+ } |
+ // TODO(ricea): Can this copy be eliminated? |
+ const char* const data_begin = size ? data_buffer->data() : NULL; |
+ const char* const data_end = data_begin + size; |
+ const std::vector<char> data(data_begin, data_end); |
+ // TODO(ricea): Handle the case when ReadFrames returns far |
+ // more data at once than should be sent in a single IPC. This needs to |
+ // be handled carefully, as an overloaded IO thread is one possible |
+ // cause of receiving very large chunks. |
+ |
+ // Sends the received frame to the renderer process. |
+ return event_interface_->OnDataFrame(final, opcode, data); |
+} |
+ |
ChannelState WebSocketChannel::SendIOBuffer( |
bool fin, |
WebSocketFrameHeader::OpCode op_code, |