OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_frame_parser.h" | 5 #include "net/websockets/websocket_frame_parser.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 const uint64 kPayloadLengthWithTwoByteExtendedLengthField = 126; | 29 const uint64 kPayloadLengthWithTwoByteExtendedLengthField = 126; |
30 const uint64 kPayloadLengthWithEightByteExtendedLengthField = 127; | 30 const uint64 kPayloadLengthWithEightByteExtendedLengthField = 127; |
31 | 31 |
32 } // Unnamed namespace. | 32 } // Unnamed namespace. |
33 | 33 |
34 namespace net { | 34 namespace net { |
35 | 35 |
36 WebSocketFrameParser::WebSocketFrameParser() | 36 WebSocketFrameParser::WebSocketFrameParser() |
37 : current_read_pos_(0), | 37 : current_read_pos_(0), |
38 frame_offset_(0), | 38 frame_offset_(0), |
39 failed_(false) { | 39 websocket_error_(WEB_SOCKET_OK) { |
40 std::fill(masking_key_, | 40 std::fill(masking_key_, |
41 masking_key_ + WebSocketFrameHeader::kMaskingKeyLength, | 41 masking_key_ + WebSocketFrameHeader::kMaskingKeyLength, |
42 '\0'); | 42 '\0'); |
43 } | 43 } |
44 | 44 |
45 WebSocketFrameParser::~WebSocketFrameParser() { | 45 WebSocketFrameParser::~WebSocketFrameParser() { |
46 } | 46 } |
47 | 47 |
48 bool WebSocketFrameParser::Decode( | 48 bool WebSocketFrameParser::Decode( |
49 const char* data, | 49 const char* data, |
50 size_t length, | 50 size_t length, |
51 ScopedVector<WebSocketFrameChunk>* frame_chunks) { | 51 ScopedVector<WebSocketFrameChunk>* frame_chunks) { |
52 if (failed_) | 52 if (websocket_error_ != WEB_SOCKET_OK) |
53 return false; | 53 return false; |
54 if (!length) | 54 if (!length) |
55 return true; | 55 return true; |
56 | 56 |
57 // TODO(yutak): Remove copy. | 57 // TODO(yutak): Remove copy. |
58 buffer_.insert(buffer_.end(), data, data + length); | 58 buffer_.insert(buffer_.end(), data, data + length); |
59 | 59 |
60 while (current_read_pos_ < buffer_.size()) { | 60 while (current_read_pos_ < buffer_.size()) { |
61 bool first_chunk = false; | 61 bool first_chunk = false; |
62 if (!current_frame_header_.get()) { | 62 if (!current_frame_header_.get()) { |
63 DecodeFrameHeader(); | 63 DecodeFrameHeader(); |
64 if (failed_) | 64 if (websocket_error_ != WEB_SOCKET_OK) |
65 return false; | 65 return false; |
66 // If frame header is incomplete, then carry over the remaining | 66 // If frame header is incomplete, then carry over the remaining |
67 // data to the next round of Decode(). | 67 // data to the next round of Decode(). |
68 if (!current_frame_header_.get()) | 68 if (!current_frame_header_.get()) |
69 break; | 69 break; |
70 first_chunk = true; | 70 first_chunk = true; |
71 } | 71 } |
72 | 72 |
73 scoped_ptr<WebSocketFrameChunk> frame_chunk = | 73 scoped_ptr<WebSocketFrameChunk> frame_chunk = |
74 DecodeFramePayload(first_chunk); | 74 DecodeFramePayload(first_chunk); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 uint8 second_byte = *current++; | 114 uint8 second_byte = *current++; |
115 | 115 |
116 bool final = (first_byte & kFinalBit) != 0; | 116 bool final = (first_byte & kFinalBit) != 0; |
117 bool reserved1 = (first_byte & kReserved1Bit) != 0; | 117 bool reserved1 = (first_byte & kReserved1Bit) != 0; |
118 bool reserved2 = (first_byte & kReserved2Bit) != 0; | 118 bool reserved2 = (first_byte & kReserved2Bit) != 0; |
119 bool reserved3 = (first_byte & kReserved3Bit) != 0; | 119 bool reserved3 = (first_byte & kReserved3Bit) != 0; |
120 OpCode opcode = first_byte & kOpCodeMask; | 120 OpCode opcode = first_byte & kOpCodeMask; |
121 | 121 |
122 bool masked = (second_byte & kMaskBit) != 0; | 122 bool masked = (second_byte & kMaskBit) != 0; |
123 uint64 payload_length = second_byte & kPayloadLengthMask; | 123 uint64 payload_length = second_byte & kPayloadLengthMask; |
124 bool valid_length_format = true; | |
125 bool message_too_big = false; | |
126 if (payload_length == kPayloadLengthWithTwoByteExtendedLengthField) { | 124 if (payload_length == kPayloadLengthWithTwoByteExtendedLengthField) { |
127 if (end - current < 2) | 125 if (end - current < 2) |
128 return; | 126 return; |
129 uint16 payload_length_16; | 127 uint16 payload_length_16; |
130 ReadBigEndian(current, &payload_length_16); | 128 ReadBigEndian(current, &payload_length_16); |
131 current += 2; | 129 current += 2; |
132 payload_length = payload_length_16; | 130 payload_length = payload_length_16; |
133 if (payload_length <= kMaxPayloadLengthWithoutExtendedLengthField) | 131 if (payload_length <= kMaxPayloadLengthWithoutExtendedLengthField) |
134 valid_length_format = false; | 132 websocket_error_ = WEB_SOCKET_ERR_PROTOCOL_ERROR; |
135 } else if (payload_length == kPayloadLengthWithEightByteExtendedLengthField) { | 133 } else if (payload_length == kPayloadLengthWithEightByteExtendedLengthField) { |
136 if (end - current < 8) | 134 if (end - current < 8) |
137 return; | 135 return; |
138 ReadBigEndian(current, &payload_length); | 136 ReadBigEndian(current, &payload_length); |
139 current += 8; | 137 current += 8; |
140 if (payload_length <= kuint16max || | 138 if (payload_length <= kuint16max || |
141 payload_length > static_cast<uint64>(kint64max)) { | 139 payload_length > static_cast<uint64>(kint64max)) { |
142 valid_length_format = false; | 140 websocket_error_ = WEB_SOCKET_ERR_PROTOCOL_ERROR; |
| 141 } else if (payload_length > static_cast<uint64>(kint32max)) { |
| 142 websocket_error_ = WEB_SOCKET_ERR_MESSAGE_TOO_BIG; |
143 } | 143 } |
144 if (payload_length > static_cast<uint64>(kint32max)) | |
145 message_too_big = true; | |
146 } | 144 } |
147 if (!valid_length_format || message_too_big) { | 145 if (websocket_error_ != WEB_SOCKET_OK) { |
148 failed_ = true; | |
149 buffer_.clear(); | 146 buffer_.clear(); |
150 current_read_pos_ = 0; | 147 current_read_pos_ = 0; |
151 current_frame_header_.reset(); | 148 current_frame_header_.reset(); |
152 frame_offset_ = 0; | 149 frame_offset_ = 0; |
153 return; | 150 return; |
154 } | 151 } |
155 | 152 |
156 if (masked) { | 153 if (masked) { |
157 if (end - current < kMaskingKeyLength) | 154 if (end - current < kMaskingKeyLength) |
158 return; | 155 return; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 if (frame_offset_ == current_frame_header_->payload_length) { | 212 if (frame_offset_ == current_frame_header_->payload_length) { |
216 frame_chunk->final_chunk = true; | 213 frame_chunk->final_chunk = true; |
217 current_frame_header_.reset(); | 214 current_frame_header_.reset(); |
218 frame_offset_ = 0; | 215 frame_offset_ = 0; |
219 } | 216 } |
220 | 217 |
221 return frame_chunk.Pass(); | 218 return frame_chunk.Pass(); |
222 } | 219 } |
223 | 220 |
224 } // namespace net | 221 } // namespace net |
OLD | NEW |