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