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