1// Copyright (c) 2013 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 "net/spdy/spdy_buffer.h" 6 7#include <cstring> 8 9#include "base/callback.h" 10#include "base/logging.h" 11#include "net/base/io_buffer.h" 12#include "net/spdy/spdy_protocol.h" 13 14namespace net { 15 16namespace { 17 18// Makes a SpdyFrame with |size| bytes of data copied from 19// |data|. |data| must be non-NULL and |size| must be positive. 20scoped_ptr<SpdyFrame> MakeSpdyFrame(const char* data, size_t size) { 21 DCHECK(data); 22 DCHECK_GT(size, 0u); 23 scoped_ptr<char[]> frame_data(new char[size]); 24 std::memcpy(frame_data.get(), data, size); 25 scoped_ptr<SpdyFrame> frame( 26 new SpdyFrame(frame_data.release(), size, true /* owns_buffer */)); 27 return frame.Pass(); 28} 29 30} // namespace 31 32// This class is an IOBuffer implementation that simply holds a 33// reference to a SharedFrame object and a fixed offset. Used by 34// SpdyBuffer::GetIOBufferForRemainingData(). 35class SpdyBuffer::SharedFrameIOBuffer : public IOBuffer { 36 public: 37 SharedFrameIOBuffer(const scoped_refptr<SharedFrame>& shared_frame, 38 size_t offset) 39 : IOBuffer(shared_frame->data->data() + offset), 40 shared_frame_(shared_frame), 41 offset_(offset) {} 42 43 private: 44 virtual ~SharedFrameIOBuffer() { 45 // Prevent ~IOBuffer() from trying to delete |data_|. 46 data_ = NULL; 47 } 48 49 const scoped_refptr<SharedFrame> shared_frame_; 50 const size_t offset_; 51 52 DISALLOW_COPY_AND_ASSIGN(SharedFrameIOBuffer); 53}; 54 55SpdyBuffer::SpdyBuffer(scoped_ptr<SpdyFrame> frame) 56 : shared_frame_(new SharedFrame()), 57 offset_(0) { 58 shared_frame_->data = frame.Pass(); 59} 60 61// The given data may not be strictly a SPDY frame; we (ab)use 62// |frame_| just as a container. 63SpdyBuffer::SpdyBuffer(const char* data, size_t size) : 64 shared_frame_(new SharedFrame()), 65 offset_(0) { 66 shared_frame_->data = MakeSpdyFrame(data, size); 67} 68 69SpdyBuffer::~SpdyBuffer() { 70 if (GetRemainingSize() > 0) 71 ConsumeHelper(GetRemainingSize(), DISCARD); 72} 73 74const char* SpdyBuffer::GetRemainingData() const { 75 return shared_frame_->data->data() + offset_; 76} 77 78size_t SpdyBuffer::GetRemainingSize() const { 79 return shared_frame_->data->size() - offset_; 80} 81 82void SpdyBuffer::AddConsumeCallback(const ConsumeCallback& consume_callback) { 83 consume_callbacks_.push_back(consume_callback); 84} 85 86void SpdyBuffer::Consume(size_t consume_size) { 87 ConsumeHelper(consume_size, CONSUME); 88}; 89 90IOBuffer* SpdyBuffer::GetIOBufferForRemainingData() { 91 return new SharedFrameIOBuffer(shared_frame_, offset_); 92} 93 94void SpdyBuffer::ConsumeHelper(size_t consume_size, 95 ConsumeSource consume_source) { 96 DCHECK_GE(consume_size, 1u); 97 DCHECK_LE(consume_size, GetRemainingSize()); 98 offset_ += consume_size; 99 for (std::vector<ConsumeCallback>::const_iterator it = 100 consume_callbacks_.begin(); it != consume_callbacks_.end(); ++it) { 101 it->Run(consume_size, consume_source); 102 } 103}; 104 105} // namespace net 106