• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/spdy/spdy_buffer.h"
11 
12 #include <cstring>
13 #include <utility>
14 
15 #include "base/check_op.h"
16 #include "base/functional/callback.h"
17 #include "base/trace_event/memory_usage_estimator.h"
18 #include "net/base/io_buffer.h"
19 #include "net/third_party/quiche/src/quiche/http2/core/spdy_protocol.h"
20 
21 namespace net {
22 
23 namespace {
24 
25 // Bound on largest frame any SPDY version has allowed.
26 const size_t kMaxSpdyFrameSize = 0x00ffffff;
27 
28 // Makes a spdy::SpdySerializedFrame with |size| bytes of data copied from
29 // |data|. |data| must be non-NULL and |size| must be positive.
MakeSpdySerializedFrame(const char * data,size_t size)30 std::unique_ptr<spdy::SpdySerializedFrame> MakeSpdySerializedFrame(
31     const char* data,
32     size_t size) {
33   DCHECK(data);
34   CHECK_GT(size, 0u);
35   CHECK_LE(size, kMaxSpdyFrameSize);
36 
37   auto frame_data = std::make_unique<char[]>(size);
38   std::memcpy(frame_data.get(), data, size);
39   return std::make_unique<spdy::SpdySerializedFrame>(std::move(frame_data),
40                                                      size);
41 }
42 
43 }  // namespace
44 
45 // This class is an IOBuffer implementation that simply holds a
46 // reference to a SharedFrame object and a fixed offset. Used by
47 // SpdyBuffer::GetIOBufferForRemainingData().
48 class SpdyBuffer::SharedFrameIOBuffer : public IOBuffer {
49  public:
SharedFrameIOBuffer(const scoped_refptr<SharedFrame> & shared_frame,size_t offset)50   SharedFrameIOBuffer(const scoped_refptr<SharedFrame>& shared_frame,
51                       size_t offset)
52       : IOBuffer(base::span(*shared_frame->data).subspan(offset)),
53         shared_frame_(shared_frame) {}
54 
55   SharedFrameIOBuffer(const SharedFrameIOBuffer&) = delete;
56   SharedFrameIOBuffer& operator=(const SharedFrameIOBuffer&) = delete;
57 
58  private:
~SharedFrameIOBuffer()59   ~SharedFrameIOBuffer() override {
60     // Prevent `data_` from dangling should this destructor remove the
61     // last reference to `shared_frame`.
62     data_ = nullptr;
63   }
64 
65   const scoped_refptr<SharedFrame> shared_frame_;
66 };
67 
SpdyBuffer(std::unique_ptr<spdy::SpdySerializedFrame> frame)68 SpdyBuffer::SpdyBuffer(std::unique_ptr<spdy::SpdySerializedFrame> frame)
69     : shared_frame_(base::MakeRefCounted<SharedFrame>(std::move(frame))) {}
70 
71 // The given data may not be strictly a SPDY frame; we (ab)use
72 // |frame_| just as a container.
SpdyBuffer(const char * data,size_t size)73 SpdyBuffer::SpdyBuffer(const char* data, size_t size)
74     : shared_frame_(base::MakeRefCounted<SharedFrame>()) {
75   CHECK_GT(size, 0u);
76   CHECK_LE(size, kMaxSpdyFrameSize);
77   shared_frame_->data = MakeSpdySerializedFrame(data, size);
78 }
79 
~SpdyBuffer()80 SpdyBuffer::~SpdyBuffer() {
81   if (GetRemainingSize() > 0)
82     ConsumeHelper(GetRemainingSize(), DISCARD);
83 }
84 
GetRemainingData() const85 const char* SpdyBuffer::GetRemainingData() const {
86   return shared_frame_->data->data() + offset_;
87 }
88 
GetRemainingSize() const89 size_t SpdyBuffer::GetRemainingSize() const {
90   return shared_frame_->data->size() - offset_;
91 }
92 
AddConsumeCallback(const ConsumeCallback & consume_callback)93 void SpdyBuffer::AddConsumeCallback(const ConsumeCallback& consume_callback) {
94   consume_callbacks_.push_back(consume_callback);
95 }
96 
Consume(size_t consume_size)97 void SpdyBuffer::Consume(size_t consume_size) {
98   ConsumeHelper(consume_size, CONSUME);
99 }
100 
GetIOBufferForRemainingData()101 scoped_refptr<IOBuffer> SpdyBuffer::GetIOBufferForRemainingData() {
102   return base::MakeRefCounted<SharedFrameIOBuffer>(shared_frame_, offset_);
103 }
104 
ConsumeHelper(size_t consume_size,ConsumeSource consume_source)105 void SpdyBuffer::ConsumeHelper(size_t consume_size,
106                                ConsumeSource consume_source) {
107   DCHECK_GE(consume_size, 1u);
108   DCHECK_LE(consume_size, GetRemainingSize());
109   offset_ += consume_size;
110   for (std::vector<ConsumeCallback>::const_iterator it =
111            consume_callbacks_.begin(); it != consume_callbacks_.end(); ++it) {
112     it->Run(consume_size, consume_source);
113   }
114 }
115 
116 }  // namespace net
117