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