1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 #include <limits> 7 8 #include "net/websockets/websocket_frame_handler.h" 9 10 #include "net/base/io_buffer.h" 11 #include "net/base/net_errors.h" 12 13 namespace net { 14 15 WebSocketFrameHandler::WebSocketFrameHandler() 16 : current_buffer_size_(0), 17 original_current_buffer_size_(0) { 18 } 19 20 WebSocketFrameHandler::~WebSocketFrameHandler() { 21 } 22 23 void WebSocketFrameHandler::AppendData(const char* data, int length) { 24 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(length); 25 memcpy(buffer->data(), data, length); 26 pending_buffers_.push_back(buffer); 27 } 28 29 int WebSocketFrameHandler::UpdateCurrentBuffer(bool buffered) { 30 if (current_buffer_) 31 return 0; 32 DCHECK(!current_buffer_size_); 33 DCHECK(!original_current_buffer_size_); 34 35 if (pending_buffers_.empty()) 36 return 0; 37 scoped_refptr<IOBufferWithSize> buffer = pending_buffers_.front(); 38 39 int buffer_size = 0; 40 if (buffered) { 41 std::vector<FrameInfo> frame_info; 42 buffer_size = 43 ParseWebSocketFrame(buffer->data(), buffer->size(), &frame_info); 44 if (buffer_size <= 0) 45 return buffer_size; 46 47 original_current_buffer_size_ = buffer_size; 48 49 // TODO(ukai): filter(e.g. compress or decompress) frame messages. 50 } else { 51 original_current_buffer_size_ = buffer->size(); 52 buffer_size = buffer->size(); 53 } 54 55 current_buffer_ = buffer; 56 current_buffer_size_ = buffer_size; 57 return buffer_size; 58 } 59 60 void WebSocketFrameHandler::ReleaseCurrentBuffer() { 61 DCHECK(!pending_buffers_.empty()); 62 scoped_refptr<IOBufferWithSize> front_buffer = pending_buffers_.front(); 63 pending_buffers_.pop_front(); 64 int remaining_size = front_buffer->size() - original_current_buffer_size_; 65 if (remaining_size > 0) { 66 scoped_refptr<IOBufferWithSize> next_buffer = NULL; 67 int buffer_size = remaining_size; 68 if (!pending_buffers_.empty()) { 69 next_buffer = pending_buffers_.front(); 70 buffer_size += next_buffer->size(); 71 pending_buffers_.pop_front(); 72 } 73 // TODO(ukai): don't copy data. 74 scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(buffer_size); 75 memcpy(buffer->data(), front_buffer->data() + original_current_buffer_size_, 76 remaining_size); 77 if (next_buffer) 78 memcpy(buffer->data() + remaining_size, 79 next_buffer->data(), next_buffer->size()); 80 pending_buffers_.push_front(buffer); 81 } 82 current_buffer_ = NULL; 83 current_buffer_size_ = 0; 84 original_current_buffer_size_ = 0; 85 } 86 87 /* static */ 88 int WebSocketFrameHandler::ParseWebSocketFrame( 89 const char* buffer, int size, std::vector<FrameInfo>* frame_info) { 90 const char* end = buffer + size; 91 const char* p = buffer; 92 int buffer_size = 0; 93 while (p < end) { 94 FrameInfo frame; 95 frame.frame_start = p; 96 frame.message_length = -1; 97 unsigned char frame_byte = static_cast<unsigned char>(*p++); 98 if ((frame_byte & 0x80) == 0x80) { 99 int length = 0; 100 while (p < end) { 101 // Note: might overflow later if numeric_limits<int>::max() is not 102 // n*128-1. 103 if (length > std::numeric_limits<int>::max() / 128) { 104 // frame length overflow. 105 return ERR_INSUFFICIENT_RESOURCES; 106 } 107 unsigned char c = static_cast<unsigned char>(*p); 108 length = length * 128 + (c & 0x7f); 109 ++p; 110 if ((c & 0x80) != 0x80) 111 break; 112 } 113 if (end - p >= length) { 114 frame.message_start = p; 115 frame.message_length = length; 116 p += length; 117 } else { 118 break; 119 } 120 } else { 121 frame.message_start = p; 122 while (p < end && *p != '\xff') 123 ++p; 124 if (p < end && *p == '\xff') { 125 frame.message_length = p - frame.message_start; 126 ++p; 127 } else { 128 break; 129 } 130 } 131 if (frame.message_length >= 0 && p <= end) { 132 frame.frame_length = p - frame.frame_start; 133 buffer_size += frame.frame_length; 134 frame_info->push_back(frame); 135 } 136 } 137 return buffer_size; 138 } 139 140 } // namespace net 141