| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
| 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_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_ | |
| 6 #define NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_ | |
| 7 | |
| 8 // QuicStreamSequencerBuffer implements QuicStreamSequencerBufferInterface. | |
| 9 // It is a circular stream buffer with random write and | |
| 10 // in-sequence read. It consists of a vector of pointers pointing | |
| 11 // to memory blocks created as needed and a list of Gaps to indicate | |
| 12 // the missing data between the data already written into the buffer. | |
| 13 // - Data are written in with offset indicating where it should be in the | |
| 14 // stream, and the buffer grown as needed (up to the maximum buffer capacity), | |
| 15 // without expensive copying (extra blocks are allocated). | |
| 16 // - Data can be read from the buffer if there is no gap before it, | |
| 17 // and the buffer shrinks as the data are consumed. | |
| 18 // - An upper limit on the number of blocks in the buffer provides an upper | |
| 19 // bound on memory use. | |
| 20 // | |
| 21 // This class is thread-unsafe. | |
| 22 // | |
| 23 // QuicStreamSequencerBuffer maintains a concept of the readable region, which | |
| 24 // contains all written data that has not been read. | |
| 25 // It promises stability of the underlying memory addresses in the readable | |
| 26 // region, so pointers into it can be maintained, and the offset of a pointer | |
| 27 // from the start of the read region can be calculated. | |
| 28 // | |
| 29 // Expected Use: | |
| 30 // QuicStreamSequencerBuffer buffer(2.5 * 8 * 1024); | |
| 31 // std::string source(1024, 'a'); | |
| 32 // base::StringPiece std::string_piece(source.data(), source.size()); | |
| 33 // size_t written = 0; | |
| 34 // buffer.OnStreamData(800, std::string_piece, GetEpollClockNow(), &written); | |
| 35 // source = std::string{800, 'b'}; | |
| 36 // base::StringPiece std::string_piece1(source.data(), 800); | |
| 37 // // Try to write to [1, 801), but should fail due to overlapping, | |
| 38 // // res should be QUIC_INVALID_STREAM_DATA | |
| 39 // auto res = buffer.OnStreamData(1, std::string_piece1, &written)); | |
| 40 // // write to [0, 800), res should be QUIC_NO_ERROR | |
| 41 // auto res = buffer.OnStreamData(0, std::string_piece1, GetEpollClockNow(), | |
| 42 // &written); | |
| 43 // | |
| 44 // // Read into a iovec array with total capacity of 120 bytes. | |
| 45 // char dest[120]; | |
| 46 // iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, | |
| 47 // iovec{dest + 80, 40}}; | |
| 48 // size_t read = buffer.Readv(iovecs, 3); | |
| 49 // | |
| 50 // // Get single readable region with timestamp. | |
| 51 // QuicTime t; | |
| 52 // iovec iov; | |
| 53 // buffer.GetReadableRegion(iov, &t); | |
| 54 // | |
| 55 // // Get readable regions from [256, 1024) and consume some of it. | |
| 56 // iovec iovs[2]; | |
| 57 // int iov_count = buffer.GetReadableRegions(iovs, 2); | |
| 58 // // Consume some bytes in iovs, returning number of bytes having been | |
| 59 // consumed. | |
| 60 // size_t consumed = consume_iovs(iovs, iov_count); | |
| 61 // buffer.MarkConsumed(consumed); | |
| 62 | |
| 63 #include <stddef.h> | |
| 64 | |
| 65 #include <functional> | |
| 66 #include <list> | |
| 67 #include <memory> | |
| 68 | |
| 69 #include "base/macros.h" | |
| 70 #include "net/quic/quic_protocol.h" | |
| 71 | |
| 72 namespace net { | |
| 73 | |
| 74 namespace test { | |
| 75 class QuicStreamSequencerBufferPeer; | |
| 76 } // namespace test | |
| 77 | |
| 78 class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer { | |
| 79 public: | |
| 80 // A Gap indicates a missing chunk of bytes between | |
| 81 // [begin_offset, end_offset) in the stream | |
| 82 struct NET_EXPORT_PRIVATE Gap { | |
| 83 Gap(QuicStreamOffset begin_offset, QuicStreamOffset end_offset); | |
| 84 QuicStreamOffset begin_offset; | |
| 85 QuicStreamOffset end_offset; | |
| 86 }; | |
| 87 | |
| 88 // A FrameInfo stores the length of a frame and the time it arrived. | |
| 89 struct NET_EXPORT_PRIVATE FrameInfo { | |
| 90 FrameInfo(); | |
| 91 FrameInfo(size_t length, QuicTime timestamp); | |
| 92 | |
| 93 size_t length; | |
| 94 QuicTime timestamp; | |
| 95 }; | |
| 96 | |
| 97 // Size of blocks used by this buffer. | |
| 98 // Choose 8K to make block large enough to hold multiple frames, each of | |
| 99 // which could be up to 1.5 KB. | |
| 100 static const size_t kBlockSizeBytes = 8 * 1024; // 8KB | |
| 101 | |
| 102 // The basic storage block used by this buffer. | |
| 103 struct BufferBlock { | |
| 104 char buffer[kBlockSizeBytes]; | |
| 105 }; | |
| 106 | |
| 107 explicit QuicStreamSequencerBuffer(size_t max_capacity_bytes); | |
| 108 ~QuicStreamSequencerBuffer(); | |
| 109 | |
| 110 // Free the space used to buffer data. | |
| 111 void Clear(); | |
| 112 | |
| 113 // Returns true if there is nothing to read in this buffer. | |
| 114 bool Empty() const; | |
| 115 | |
| 116 // Called to buffer new data received for this stream. If the data was | |
| 117 // successfully buffered, returns QUIC_NO_ERROR and stores the number of | |
| 118 // bytes buffered in |bytes_buffered|. Returns an error otherwise. | |
| 119 // |timestamp| is the time the data arrived. | |
| 120 QuicErrorCode OnStreamData(QuicStreamOffset offset, | |
| 121 base::StringPiece data, | |
| 122 QuicTime timestamp, | |
| 123 size_t* bytes_buffered, | |
| 124 std::string* error_details); | |
| 125 | |
| 126 // Reads from this buffer into given iovec array, up to number of iov_len | |
| 127 // iovec objects and returns the number of bytes read. | |
| 128 size_t Readv(const struct iovec* dest_iov, size_t dest_count); | |
| 129 | |
| 130 // Returns the readable region of valid data in iovec format. The readable | |
| 131 // region is the buffer region where there is valid data not yet read by | |
| 132 // client. | |
| 133 // Returns the number of iovec entries in |iov| which were populated. | |
| 134 // If the region is empty, one iovec entry with 0 length | |
| 135 // is returned, and the function returns 0. If there are more readable | |
| 136 // regions than iov_size, the function only processes the first | |
| 137 // iov_size of them. | |
| 138 int GetReadableRegions(struct iovec* iov, int iov_len) const; | |
| 139 | |
| 140 // Fills in one iovec with data which all arrived at the same time from the | |
| 141 // next readable region. | |
| 142 // Populates |timestamp| with the time that this data arrived. | |
| 143 // Returns false if there is no readable region available. | |
| 144 bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const; | |
| 145 | |
| 146 // Called after GetReadableRegions() to free up |bytes_used| space if these | |
| 147 // bytes are processed. | |
| 148 // Pre-requisite: bytes_used <= available bytes to read. | |
| 149 bool MarkConsumed(size_t bytes_buffered); | |
| 150 | |
| 151 // Deletes and records as consumed any buffered data and clear the buffer. | |
| 152 // (To be called only after sequencer's StopReading has been called.) | |
| 153 size_t FlushBufferedFrames(); | |
| 154 | |
| 155 // Whether there are bytes can be read out. | |
| 156 bool HasBytesToRead() const; | |
| 157 | |
| 158 // Count how many bytes have been consumed (read out of buffer). | |
| 159 QuicStreamOffset BytesConsumed() const; | |
| 160 | |
| 161 // Count how many bytes are in buffer at this moment. | |
| 162 size_t BytesBuffered() const; | |
| 163 | |
| 164 private: | |
| 165 friend class test::QuicStreamSequencerBufferPeer; | |
| 166 | |
| 167 // Dispose the given buffer block. | |
| 168 // After calling this method, blocks_[index] is set to nullptr | |
| 169 // in order to indicate that no memory set is allocated for that block. | |
| 170 void RetireBlock(size_t index); | |
| 171 | |
| 172 // Should only be called after the indexed block is read till the end of the | |
| 173 // block or a gap has been reached. | |
| 174 // If the block at |block_index| contains no buffered data, then the block is | |
| 175 // retired. | |
| 176 void RetireBlockIfEmpty(size_t block_index); | |
| 177 | |
| 178 // Called within OnStreamData() to update the gap OnStreamData() writes into | |
| 179 // (remove, split or change begin/end offset). | |
| 180 void UpdateGapList(std::list<Gap>::iterator gap_with_new_data_written, | |
| 181 QuicStreamOffset start_offset, | |
| 182 size_t bytes_written); | |
| 183 | |
| 184 // Calculate the capacity of block at specified index. | |
| 185 // Return value should be either kBlockSizeBytes for non-trailing blocks and | |
| 186 // max_buffer_capacity % kBlockSizeBytes for trailing block. | |
| 187 size_t GetBlockCapacity(size_t index) const; | |
| 188 | |
| 189 // Does not check if offset is within reasonable range. | |
| 190 size_t GetBlockIndex(QuicStreamOffset offset) const; | |
| 191 | |
| 192 // Given an offset in the stream, return the offset from the beginning of the | |
| 193 // block which contains this data. | |
| 194 size_t GetInBlockOffset(QuicStreamOffset offset) const; | |
| 195 | |
| 196 // Get offset relative to index 0 in logical 1st block to start next read. | |
| 197 size_t ReadOffset() const; | |
| 198 | |
| 199 // Get the index of the logical 1st block to start next read. | |
| 200 size_t NextBlockToRead() const; | |
| 201 | |
| 202 // Returns number of bytes available to be read out. | |
| 203 size_t ReadableBytes() const; | |
| 204 | |
| 205 // Called after Readv() and MarkConsumed() to keep frame_arrival_time_map_ | |
| 206 // up to date. | |
| 207 // |offset| is the byte next read should start from. All frames before it | |
| 208 // should be removed from the map. | |
| 209 void UpdateFrameArrivalMap(QuicStreamOffset offset); | |
| 210 | |
| 211 // Return |gaps_| as a std::string: [1024, 1500) [1800, 2048)... for | |
| 212 // debugging. | |
| 213 std::string GapsDebugString(); | |
| 214 | |
| 215 // Return all received frames as a std::string in same format as | |
| 216 // GapsDebugString(); | |
| 217 std::string ReceivedFramesDebugString(); | |
| 218 | |
| 219 // The maximum total capacity of this buffer in byte, as constructed. | |
| 220 const size_t max_buffer_capacity_bytes_; | |
| 221 | |
| 222 // How many blocks this buffer would need when it reaches full capacity. | |
| 223 const size_t blocks_count_; | |
| 224 | |
| 225 // Number of bytes read out of buffer. | |
| 226 QuicStreamOffset total_bytes_read_; | |
| 227 | |
| 228 // Contains Gaps which represents currently missing data. | |
| 229 std::list<Gap> gaps_; | |
| 230 | |
| 231 // An ordered, variable-length list of blocks, with the length limited | |
| 232 // such that the number of blocks never exceeds blocks_count_. | |
| 233 // Each list entry can hold up to kBlockSizeBytes bytes. | |
| 234 std::vector<BufferBlock*> blocks_; | |
| 235 | |
| 236 // Number of bytes in buffer. | |
| 237 size_t num_bytes_buffered_; | |
| 238 | |
| 239 // Stores all the buffered frames' start offset, length and arrival time. | |
| 240 std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_; | |
| 241 | |
| 242 DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBuffer); | |
| 243 }; | |
| 244 } // namespace net | |
| 245 | |
| 246 #endif // NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_ | |
| OLD | NEW |