• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 #ifndef NET_BASE_IO_BUFFER_H_
11 #define NET_BASE_IO_BUFFER_H_
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <memory>
17 #include <string>
18 
19 #include "base/containers/heap_array.h"
20 #include "base/containers/span.h"
21 #include "base/memory/free_deleter.h"
22 #include "base/memory/raw_ptr.h"
23 #include "base/memory/ref_counted.h"
24 #include "base/pickle.h"
25 #include "net/base/net_export.h"
26 
27 namespace net {
28 
29 // IOBuffers are reference counted data buffers used for easier asynchronous
30 // IO handling.
31 //
32 // They are often used as the destination buffers for Read() operations, or as
33 // the source buffers for Write() operations.
34 //
35 // IMPORTANT: Never re-use an IOBuffer after cancelling the IO operation that
36 //            was using it, since this may lead to memory corruption!
37 //
38 // -----------------------
39 // Ownership of IOBuffers:
40 // -----------------------
41 //
42 // Although IOBuffers are RefCountedThreadSafe, they are not intended to be
43 // used as a shared buffer, nor should they be used simultaneously across
44 // threads. The fact that they are reference counted is an implementation
45 // detail for allowing them to outlive cancellation of asynchronous
46 // operations.
47 //
48 // Instead, think of the underlying |char*| buffer contained by the IOBuffer
49 // as having exactly one owner at a time.
50 //
51 // Whenever you call an asynchronous operation that takes an IOBuffer,
52 // ownership is implicitly transferred to the called function, until the
53 // operation has completed (at which point it transfers back to the caller).
54 //
55 //     ==> The IOBuffer's data should NOT be manipulated, destroyed, or read
56 //         until the operation has completed.
57 //
58 //     ==> Cancellation does NOT count as completion. If an operation using
59 //         an IOBuffer is cancelled, the caller should release their
60 //         reference to this IOBuffer at the time of cancellation since
61 //         they can no longer use it.
62 //
63 // For instance, if you were to call a Read() operation on some class which
64 // takes an IOBuffer, and then delete that class (which generally will
65 // trigger cancellation), the IOBuffer which had been passed to Read() should
66 // never be re-used.
67 //
68 // This usage contract is assumed by any API which takes an IOBuffer, even
69 // though it may not be explicitly mentioned in the function's comments.
70 //
71 // -----------------------
72 // Motivation
73 // -----------------------
74 //
75 // The motivation for transferring ownership during cancellation is
76 // to make it easier to work with un-cancellable operations.
77 //
78 // For instance, let's say under the hood your API called out to the
79 // operating system's synchronous ReadFile() function on a worker thread.
80 // When cancelling through our asynchronous interface, we have no way of
81 // actually aborting the in progress ReadFile(). We must let it keep running,
82 // and hence the buffer it was reading into must remain alive. Using
83 // reference counting we can add a reference to the IOBuffer and make sure
84 // it is not destroyed until after the synchronous operation has completed.
85 
86 // Base class, never instantiated, does not own the buffer.
87 class NET_EXPORT IOBuffer : public base::RefCountedThreadSafe<IOBuffer> {
88  public:
size()89   int size() const { return size_; }
90 
data()91   char* data() { return data_; }
data()92   const char* data() const { return data_; }
93 
bytes()94   uint8_t* bytes() { return reinterpret_cast<uint8_t*>(data()); }
bytes()95   const uint8_t* bytes() const {
96     return reinterpret_cast<const uint8_t*>(data());
97   }
98 
span()99   base::span<uint8_t> span() {
100     return base::span(bytes(), static_cast<size_t>(size_));
101   }
span()102   base::span<const uint8_t> span() const {
103     return base::span(bytes(), static_cast<size_t>(size_));
104   }
105 
106  protected:
107   friend class base::RefCountedThreadSafe<IOBuffer>;
108 
109   static void AssertValidBufferSize(size_t size);
110 
111   IOBuffer();
112   explicit IOBuffer(base::span<char> data);
113   explicit IOBuffer(base::span<uint8_t> data);
114 
115   virtual ~IOBuffer();
116 
117   raw_ptr<char, AllowPtrArithmetic> data_ = nullptr;
118   int size_ = 0;
119 };
120 
121 // Class which owns its buffer and manages its destruction.
122 class NET_EXPORT IOBufferWithSize : public IOBuffer {
123  public:
124   IOBufferWithSize();
125   explicit IOBufferWithSize(size_t size);
126 
127  protected:
128   ~IOBufferWithSize() override;
129 
130  private:
131   base::HeapArray<char> storage_;
132 };
133 
134 // This is a read only IOBuffer.  The data is stored in a string and
135 // the IOBuffer interface does not provide a proper way to modify it.
136 class NET_EXPORT StringIOBuffer : public IOBuffer {
137  public:
138   explicit StringIOBuffer(std::string s);
139 
140  private:
141   ~StringIOBuffer() override;
142 
143   std::string string_data_;
144 };
145 
146 // This version wraps an existing IOBuffer and provides convenient functions
147 // to progressively read all the data.
148 //
149 // DrainableIOBuffer is useful when you have an IOBuffer that contains data
150 // to be written progressively, and Write() function takes an IOBuffer rather
151 // than char*. DrainableIOBuffer can be used as follows:
152 //
153 // // payload is the IOBuffer containing the data to be written.
154 // buf = base::MakeRefCounted<DrainableIOBuffer>(payload, payload_size);
155 //
156 // while (buf->BytesRemaining() > 0) {
157 //   // Write() takes an IOBuffer. If it takes char*, we could
158 //   // simply use the regular IOBuffer like payload->data() + offset.
159 //   int bytes_written = Write(buf, buf->BytesRemaining());
160 //   buf->DidConsume(bytes_written);
161 // }
162 //
163 class NET_EXPORT DrainableIOBuffer : public IOBuffer {
164  public:
165   DrainableIOBuffer(scoped_refptr<IOBuffer> base, size_t size);
166 
167   // DidConsume() changes the |data_| pointer so that |data_| always points
168   // to the first unconsumed byte.
169   void DidConsume(int bytes);
170 
171   // Returns the number of unconsumed bytes.
172   int BytesRemaining() const;
173 
174   // Returns the number of consumed bytes.
175   int BytesConsumed() const;
176 
177   // Seeks to an arbitrary point in the buffer. The notion of bytes consumed
178   // and remaining are updated appropriately.
179   void SetOffset(int bytes);
180 
181  private:
182   ~DrainableIOBuffer() override;
183 
184   scoped_refptr<IOBuffer> base_;
185   int used_ = 0;
186 };
187 
188 // This version provides a resizable buffer and a changeable offset.
189 //
190 // GrowableIOBuffer is useful when you read data progressively without
191 // knowing the total size in advance. GrowableIOBuffer can be used as
192 // follows:
193 //
194 // buf = base::MakeRefCounted<GrowableIOBuffer>();
195 // buf->SetCapacity(1024);  // Initial capacity.
196 //
197 // while (!some_stream->IsEOF()) {
198 //   // Double the capacity if the remaining capacity is empty.
199 //   if (buf->RemainingCapacity() == 0)
200 //     buf->SetCapacity(buf->capacity() * 2);
201 //   int bytes_read = some_stream->Read(buf, buf->RemainingCapacity());
202 //   buf->set_offset(buf->offset() + bytes_read);
203 // }
204 //
205 class NET_EXPORT GrowableIOBuffer : public IOBuffer {
206  public:
207   GrowableIOBuffer();
208 
209   // realloc memory to the specified capacity.
210   void SetCapacity(int capacity);
capacity()211   int capacity() { return capacity_; }
212 
213   // |offset| moves the |data_| pointer, allowing "seeking" in the data.
214   void set_offset(int offset);
offset()215   int offset() { return offset_; }
216 
217   int RemainingCapacity();
218 
219   // Returns the entire buffer, including the bytes before the `offset()`.
220   //
221   // The `span()` method in the base class only gives the part of the buffer
222   // after `offset()`.
223   base::span<uint8_t> everything();
224   base::span<const uint8_t> everything() const;
225 
226   // Return a span before the `offset()`.
227   base::span<uint8_t> span_before_offset();
228   base::span<const uint8_t> span_before_offset() const;
229 
230  private:
231   ~GrowableIOBuffer() override;
232 
233   // TODO(329476354): Convert to std::vector, use reserve()+resize() to make
234   // exact reallocs, and remove `capacity_`. Possibly with an allocator the
235   // default-initializes, if it's important to not initialize the new memory?
236   std::unique_ptr<char, base::FreeDeleter> real_data_;
237   int capacity_ = 0;
238   int offset_ = 0;
239 };
240 
241 // This versions allows a pickle to be used as the storage for a write-style
242 // operation, avoiding an extra data copy.
243 class NET_EXPORT PickledIOBuffer : public IOBuffer {
244  public:
245   PickledIOBuffer();
246 
pickle()247   base::Pickle* pickle() { return &pickle_; }
248 
249   // Signals that we are done writing to the pickle and we can use it for a
250   // write-style IO operation.
251   void Done();
252 
253  private:
254   ~PickledIOBuffer() override;
255 
256   base::Pickle pickle_;
257 };
258 
259 // This class allows the creation of a temporary IOBuffer that doesn't really
260 // own the underlying buffer. Please use this class only as a last resort.
261 // A good example is the buffer for a synchronous operation, where we can be
262 // sure that nobody is keeping an extra reference to this object so the lifetime
263 // of the buffer can be completely managed by its intended owner.
264 // This is now nearly the same as the base IOBuffer class, except that it
265 // accepts const data as constructor arguments.
266 class NET_EXPORT WrappedIOBuffer : public IOBuffer {
267  public:
268   explicit WrappedIOBuffer(base::span<const char> data);
269   explicit WrappedIOBuffer(base::span<const uint8_t> data);
270 
271  protected:
272   ~WrappedIOBuffer() override;
273 };
274 
275 }  // namespace net
276 
277 #endif  // NET_BASE_IO_BUFFER_H_
278