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