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 14 namespace net { 15 16 namespace { 17 18 // Makes a SpdyFrame with |size| bytes of data copied from 19 // |data|. |data| must be non-NULL and |size| must be positive. 20 scoped_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(). 35 class 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 55 SpdyBuffer::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. 63 SpdyBuffer::SpdyBuffer(const char* data, size_t size) : 64 shared_frame_(new SharedFrame()), 65 offset_(0) { 66 shared_frame_->data = MakeSpdyFrame(data, size); 67 } 68 69 SpdyBuffer::~SpdyBuffer() { 70 if (GetRemainingSize() > 0) 71 ConsumeHelper(GetRemainingSize(), DISCARD); 72 } 73 74 const char* SpdyBuffer::GetRemainingData() const { 75 return shared_frame_->data->data() + offset_; 76 } 77 78 size_t SpdyBuffer::GetRemainingSize() const { 79 return shared_frame_->data->size() - offset_; 80 } 81 82 void SpdyBuffer::AddConsumeCallback(const ConsumeCallback& consume_callback) { 83 consume_callbacks_.push_back(consume_callback); 84 } 85 86 void SpdyBuffer::Consume(size_t consume_size) { 87 ConsumeHelper(consume_size, CONSUME); 88 }; 89 90 IOBuffer* SpdyBuffer::GetIOBufferForRemainingData() { 91 return new SharedFrameIOBuffer(shared_frame_, offset_); 92 } 93 94 void 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