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