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