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_basic_stream.h" | 5 #include "net/websockets/websocket_basic_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 const scoped_refptr<GrowableIOBuffer>& http_read_buffer, | 72 const scoped_refptr<GrowableIOBuffer>& http_read_buffer, |
73 const std::string& sub_protocol, | 73 const std::string& sub_protocol, |
74 const std::string& extensions) | 74 const std::string& extensions) |
75 : read_buffer_(new IOBufferWithSize(kReadBufferSize)), | 75 : read_buffer_(new IOBufferWithSize(kReadBufferSize)), |
76 connection_(connection.Pass()), | 76 connection_(connection.Pass()), |
77 http_read_buffer_(http_read_buffer), | 77 http_read_buffer_(http_read_buffer), |
78 sub_protocol_(sub_protocol), | 78 sub_protocol_(sub_protocol), |
79 extensions_(extensions), | 79 extensions_(extensions), |
80 generate_websocket_masking_key_(&GenerateWebSocketMaskingKey) { | 80 generate_websocket_masking_key_(&GenerateWebSocketMaskingKey) { |
81 // http_read_buffer_ should not be set if it contains no data. | 81 // http_read_buffer_ should not be set if it contains no data. |
82 if (http_read_buffer_ && http_read_buffer_->offset() == 0) | 82 if (http_read_buffer_.get() && http_read_buffer_->offset() == 0) |
83 http_read_buffer_ = NULL; | 83 http_read_buffer_ = NULL; |
84 DCHECK(connection_->is_initialized()); | 84 DCHECK(connection_->is_initialized()); |
85 } | 85 } |
86 | 86 |
87 WebSocketBasicStream::~WebSocketBasicStream() { Close(); } | 87 WebSocketBasicStream::~WebSocketBasicStream() { Close(); } |
88 | 88 |
89 int WebSocketBasicStream::ReadFrames(ScopedVector<WebSocketFrame>* frames, | 89 int WebSocketBasicStream::ReadFrames(ScopedVector<WebSocketFrame>* frames, |
90 const CompletionCallback& callback) { | 90 const CompletionCallback& callback) { |
91 DCHECK(frames->empty()); | 91 DCHECK(frames->empty()); |
92 // If there is data left over after parsing the HTTP headers, attempt to parse | 92 // If there is data left over after parsing the HTTP headers, attempt to parse |
93 // it as WebSocket frames. | 93 // it as WebSocket frames. |
94 if (http_read_buffer_) { | 94 if (http_read_buffer_.get()) { |
95 DCHECK_GE(http_read_buffer_->offset(), 0); | 95 DCHECK_GE(http_read_buffer_->offset(), 0); |
96 // We cannot simply copy the data into read_buffer_, as it might be too | 96 // We cannot simply copy the data into read_buffer_, as it might be too |
97 // large. | 97 // large. |
98 scoped_refptr<GrowableIOBuffer> buffered_data; | 98 scoped_refptr<GrowableIOBuffer> buffered_data; |
99 buffered_data.swap(http_read_buffer_); | 99 buffered_data.swap(http_read_buffer_); |
100 DCHECK(http_read_buffer_.get() == NULL); | 100 DCHECK(http_read_buffer_.get() == NULL); |
101 ScopedVector<WebSocketFrameChunk> frame_chunks; | 101 ScopedVector<WebSocketFrameChunk> frame_chunks; |
102 if (!parser_.Decode(buffered_data->StartOfBuffer(), | 102 if (!parser_.Decode(buffered_data->StartOfBuffer(), |
103 buffered_data->offset(), | 103 buffered_data->offset(), |
104 &frame_chunks)) | 104 &frame_chunks)) |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 const char* const frame_data = frame->data->data(); | 163 const char* const frame_data = frame->data->data(); |
164 std::copy(frame_data, frame_data + frame_size, dest); | 164 std::copy(frame_data, frame_data + frame_size, dest); |
165 MaskWebSocketFramePayload(mask, 0, dest, frame_size); | 165 MaskWebSocketFramePayload(mask, 0, dest, frame_size); |
166 dest += frame_size; | 166 dest += frame_size; |
167 remaining_size -= frame_size; | 167 remaining_size -= frame_size; |
168 } | 168 } |
169 } | 169 } |
170 DCHECK_EQ(0, remaining_size) << "Buffer size calculation was wrong; " | 170 DCHECK_EQ(0, remaining_size) << "Buffer size calculation was wrong; " |
171 << remaining_size << " bytes left over."; | 171 << remaining_size << " bytes left over."; |
172 scoped_refptr<DrainableIOBuffer> drainable_buffer( | 172 scoped_refptr<DrainableIOBuffer> drainable_buffer( |
173 new DrainableIOBuffer(combined_buffer, total_size)); | 173 new DrainableIOBuffer(combined_buffer.get(), total_size)); |
174 return WriteEverything(drainable_buffer, callback); | 174 return WriteEverything(drainable_buffer, callback); |
175 } | 175 } |
176 | 176 |
177 void WebSocketBasicStream::Close() { connection_->socket()->Disconnect(); } | 177 void WebSocketBasicStream::Close() { connection_->socket()->Disconnect(); } |
178 | 178 |
179 std::string WebSocketBasicStream::GetSubProtocol() const { | 179 std::string WebSocketBasicStream::GetSubProtocol() const { |
180 return sub_protocol_; | 180 return sub_protocol_; |
181 } | 181 } |
182 | 182 |
183 std::string WebSocketBasicStream::GetExtensions() const { return extensions_; } | 183 std::string WebSocketBasicStream::GetExtensions() const { return extensions_; } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 scoped_ptr<WebSocketFrame>* frame) { | 278 scoped_ptr<WebSocketFrame>* frame) { |
279 DCHECK(frame->get() == NULL); | 279 DCHECK(frame->get() == NULL); |
280 bool is_first_chunk = false; | 280 bool is_first_chunk = false; |
281 if (chunk->header) { | 281 if (chunk->header) { |
282 DCHECK(current_frame_header_ == NULL) | 282 DCHECK(current_frame_header_ == NULL) |
283 << "Received the header for a new frame without notification that " | 283 << "Received the header for a new frame without notification that " |
284 << "the previous frame was complete (bug in WebSocketFrameParser?)"; | 284 << "the previous frame was complete (bug in WebSocketFrameParser?)"; |
285 is_first_chunk = true; | 285 is_first_chunk = true; |
286 current_frame_header_.swap(chunk->header); | 286 current_frame_header_.swap(chunk->header); |
287 } | 287 } |
288 const int chunk_size = chunk->data ? chunk->data->size() : 0; | 288 const int chunk_size = chunk->data.get() ? chunk->data->size() : 0; |
289 DCHECK(current_frame_header_) << "Unexpected header-less chunk received " | 289 DCHECK(current_frame_header_) << "Unexpected header-less chunk received " |
290 << "(final_chunk = " << chunk->final_chunk | 290 << "(final_chunk = " << chunk->final_chunk |
291 << ", data size = " << chunk_size | 291 << ", data size = " << chunk_size |
292 << ") (bug in WebSocketFrameParser?)"; | 292 << ") (bug in WebSocketFrameParser?)"; |
293 scoped_refptr<IOBufferWithSize> data_buffer; | 293 scoped_refptr<IOBufferWithSize> data_buffer; |
294 data_buffer.swap(chunk->data); | 294 data_buffer.swap(chunk->data); |
295 const bool is_final_chunk = chunk->final_chunk; | 295 const bool is_final_chunk = chunk->final_chunk; |
296 const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode; | 296 const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode; |
297 if (WebSocketFrameHeader::IsKnownControlOpCode(opcode)) { | 297 if (WebSocketFrameHeader::IsKnownControlOpCode(opcode)) { |
298 bool protocol_error = false; | 298 bool protocol_error = false; |
299 if (!current_frame_header_->final) { | 299 if (!current_frame_header_->final) { |
300 DVLOG(1) << "WebSocket protocol error. Control frame, opcode=" << opcode | 300 DVLOG(1) << "WebSocket protocol error. Control frame, opcode=" << opcode |
301 << " received with FIN bit unset."; | 301 << " received with FIN bit unset."; |
302 protocol_error = true; | 302 protocol_error = true; |
303 } | 303 } |
304 if (current_frame_header_->payload_length > kMaxControlFramePayload) { | 304 if (current_frame_header_->payload_length > kMaxControlFramePayload) { |
305 DVLOG(1) << "WebSocket protocol error. Control frame, opcode=" << opcode | 305 DVLOG(1) << "WebSocket protocol error. Control frame, opcode=" << opcode |
306 << ", payload_length=" << current_frame_header_->payload_length | 306 << ", payload_length=" << current_frame_header_->payload_length |
307 << " exceeds maximum payload length for a control message."; | 307 << " exceeds maximum payload length for a control message."; |
308 protocol_error = true; | 308 protocol_error = true; |
309 } | 309 } |
310 if (protocol_error) { | 310 if (protocol_error) { |
311 current_frame_header_.reset(); | 311 current_frame_header_.reset(); |
312 return ERR_WS_PROTOCOL_ERROR; | 312 return ERR_WS_PROTOCOL_ERROR; |
313 } | 313 } |
314 if (!is_final_chunk) { | 314 if (!is_final_chunk) { |
315 DVLOG(2) << "Encountered a split control frame, opcode " << opcode; | 315 DVLOG(2) << "Encountered a split control frame, opcode " << opcode; |
316 if (incomplete_control_frame_body_) { | 316 if (incomplete_control_frame_body_.get()) { |
317 DVLOG(3) << "Appending to an existing split control frame."; | 317 DVLOG(3) << "Appending to an existing split control frame."; |
318 AddToIncompleteControlFrameBody(data_buffer); | 318 AddToIncompleteControlFrameBody(data_buffer); |
319 } else { | 319 } else { |
320 DVLOG(3) << "Creating new storage for an incomplete control frame."; | 320 DVLOG(3) << "Creating new storage for an incomplete control frame."; |
321 incomplete_control_frame_body_ = new GrowableIOBuffer(); | 321 incomplete_control_frame_body_ = new GrowableIOBuffer(); |
322 // This method checks for oversize control frames above, so as long as | 322 // This method checks for oversize control frames above, so as long as |
323 // the frame parser is working correctly, this won't overflow. If a bug | 323 // the frame parser is working correctly, this won't overflow. If a bug |
324 // does cause it to overflow, it will CHECK() in | 324 // does cause it to overflow, it will CHECK() in |
325 // AddToIncompleteControlFrameBody() without writing outside the buffer. | 325 // AddToIncompleteControlFrameBody() without writing outside the buffer. |
326 incomplete_control_frame_body_->SetCapacity(kMaxControlFramePayload); | 326 incomplete_control_frame_body_->SetCapacity(kMaxControlFramePayload); |
327 AddToIncompleteControlFrameBody(data_buffer); | 327 AddToIncompleteControlFrameBody(data_buffer); |
328 } | 328 } |
329 return OK; | 329 return OK; |
330 } | 330 } |
331 if (incomplete_control_frame_body_) { | 331 if (incomplete_control_frame_body_.get()) { |
332 DVLOG(2) << "Rejoining a split control frame, opcode " << opcode; | 332 DVLOG(2) << "Rejoining a split control frame, opcode " << opcode; |
333 AddToIncompleteControlFrameBody(data_buffer); | 333 AddToIncompleteControlFrameBody(data_buffer); |
334 const int body_size = incomplete_control_frame_body_->offset(); | 334 const int body_size = incomplete_control_frame_body_->offset(); |
335 DCHECK_EQ(body_size, | 335 DCHECK_EQ(body_size, |
336 static_cast<int>(current_frame_header_->payload_length)); | 336 static_cast<int>(current_frame_header_->payload_length)); |
337 scoped_refptr<IOBufferWithSize> body = new IOBufferWithSize(body_size); | 337 scoped_refptr<IOBufferWithSize> body = new IOBufferWithSize(body_size); |
338 memcpy(body->data(), | 338 memcpy(body->data(), |
339 incomplete_control_frame_body_->StartOfBuffer(), | 339 incomplete_control_frame_body_->StartOfBuffer(), |
340 body_size); | 340 body_size); |
341 incomplete_control_frame_body_ = NULL; // Frame now complete. | 341 incomplete_control_frame_body_ = NULL; // Frame now complete. |
(...skipping 16 matching lines...) Expand all Loading... |
358 *frame = CreateFrame(is_final_chunk, data_buffer); | 358 *frame = CreateFrame(is_final_chunk, data_buffer); |
359 return OK; | 359 return OK; |
360 } | 360 } |
361 | 361 |
362 scoped_ptr<WebSocketFrame> WebSocketBasicStream::CreateFrame( | 362 scoped_ptr<WebSocketFrame> WebSocketBasicStream::CreateFrame( |
363 bool is_final_chunk, | 363 bool is_final_chunk, |
364 const scoped_refptr<IOBufferWithSize>& data) { | 364 const scoped_refptr<IOBufferWithSize>& data) { |
365 scoped_ptr<WebSocketFrame> result_frame; | 365 scoped_ptr<WebSocketFrame> result_frame; |
366 const bool is_final_chunk_in_message = | 366 const bool is_final_chunk_in_message = |
367 is_final_chunk && current_frame_header_->final; | 367 is_final_chunk && current_frame_header_->final; |
368 const int data_size = data ? data->size() : 0; | 368 const int data_size = data.get() ? data->size() : 0; |
369 const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode; | 369 const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode; |
370 // Empty frames convey no useful information unless they are the first frame | 370 // Empty frames convey no useful information unless they are the first frame |
371 // (containing the type and flags) or have the "final" bit set. | 371 // (containing the type and flags) or have the "final" bit set. |
372 if (is_final_chunk_in_message || data_size > 0 || | 372 if (is_final_chunk_in_message || data_size > 0 || |
373 current_frame_header_->opcode != | 373 current_frame_header_->opcode != |
374 WebSocketFrameHeader::kOpCodeContinuation) { | 374 WebSocketFrameHeader::kOpCodeContinuation) { |
375 result_frame.reset(new WebSocketFrame(opcode)); | 375 result_frame.reset(new WebSocketFrame(opcode)); |
376 result_frame->header.CopyFrom(*current_frame_header_); | 376 result_frame->header.CopyFrom(*current_frame_header_); |
377 result_frame->header.final = is_final_chunk_in_message; | 377 result_frame->header.final = is_final_chunk_in_message; |
378 result_frame->header.payload_length = data_size; | 378 result_frame->header.payload_length = data_size; |
(...skipping 12 matching lines...) Expand all Loading... |
391 } | 391 } |
392 // Make sure that a frame header is not applied to any chunks that do not | 392 // Make sure that a frame header is not applied to any chunks that do not |
393 // belong to it. | 393 // belong to it. |
394 if (is_final_chunk) | 394 if (is_final_chunk) |
395 current_frame_header_.reset(); | 395 current_frame_header_.reset(); |
396 return result_frame.Pass(); | 396 return result_frame.Pass(); |
397 } | 397 } |
398 | 398 |
399 void WebSocketBasicStream::AddToIncompleteControlFrameBody( | 399 void WebSocketBasicStream::AddToIncompleteControlFrameBody( |
400 const scoped_refptr<IOBufferWithSize>& data_buffer) { | 400 const scoped_refptr<IOBufferWithSize>& data_buffer) { |
401 if (!data_buffer) | 401 if (!data_buffer.get()) |
402 return; | 402 return; |
403 const int new_offset = | 403 const int new_offset = |
404 incomplete_control_frame_body_->offset() + data_buffer->size(); | 404 incomplete_control_frame_body_->offset() + data_buffer->size(); |
405 CHECK_GE(incomplete_control_frame_body_->capacity(), new_offset) | 405 CHECK_GE(incomplete_control_frame_body_->capacity(), new_offset) |
406 << "Control frame body larger than frame header indicates; frame parser " | 406 << "Control frame body larger than frame header indicates; frame parser " |
407 "bug?"; | 407 "bug?"; |
408 memcpy(incomplete_control_frame_body_->data(), | 408 memcpy(incomplete_control_frame_body_->data(), |
409 data_buffer->data(), | 409 data_buffer->data(), |
410 data_buffer->size()); | 410 data_buffer->size()); |
411 incomplete_control_frame_body_->set_offset(new_offset); | 411 incomplete_control_frame_body_->set_offset(new_offset); |
412 } | 412 } |
413 | 413 |
414 void WebSocketBasicStream::OnReadComplete(ScopedVector<WebSocketFrame>* frames, | 414 void WebSocketBasicStream::OnReadComplete(ScopedVector<WebSocketFrame>* frames, |
415 const CompletionCallback& callback, | 415 const CompletionCallback& callback, |
416 int result) { | 416 int result) { |
417 result = HandleReadResult(result, frames); | 417 result = HandleReadResult(result, frames); |
418 if (result == ERR_IO_PENDING) | 418 if (result == ERR_IO_PENDING) |
419 result = ReadFrames(frames, callback); | 419 result = ReadFrames(frames, callback); |
420 if (result != ERR_IO_PENDING) | 420 if (result != ERR_IO_PENDING) |
421 callback.Run(result); | 421 callback.Run(result); |
422 } | 422 } |
423 | 423 |
424 } // namespace net | 424 } // namespace net |
OLD | NEW |