OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/quic_frame_list.h" | 5 #include "net/quic/quic_frame_list.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 | 8 |
9 namespace net { | 9 namespace net { |
10 | 10 |
11 QuicFrameList::FrameData::FrameData(QuicStreamOffset offset, | 11 QuicFrameList::FrameData::FrameData(QuicStreamOffset offset, |
12 string segment, | 12 string segment, |
13 const QuicTime timestamp) | 13 const QuicTime timestamp) |
14 : offset(offset), segment(segment), timestamp(timestamp) {} | 14 : offset(offset), segment(segment), timestamp(timestamp) {} |
15 | 15 |
16 QuicFrameList::QuicFrameList() {} | 16 QuicFrameList::QuicFrameList() {} |
17 | 17 |
18 QuicFrameList::~QuicFrameList() { | 18 QuicFrameList::~QuicFrameList() { |
19 Clear(); | 19 Clear(); |
20 } | 20 } |
21 | 21 |
22 QuicErrorCode QuicFrameList::WriteAtOffset(QuicStreamOffset offset, | 22 void QuicFrameList::Clear() { |
23 StringPiece data, | 23 frame_list_.clear(); |
24 QuicTime timestamp, | 24 num_bytes_buffered_ = 0; |
25 size_t* const bytes_written) { | 25 } |
26 *bytes_written = 0; | 26 |
| 27 bool QuicFrameList::Empty() const { |
| 28 return frame_list_.empty(); |
| 29 } |
| 30 |
| 31 QuicErrorCode QuicFrameList::OnStreamData(QuicStreamOffset offset, |
| 32 StringPiece data, |
| 33 QuicTime timestamp, |
| 34 size_t* const bytes_buffered) { |
| 35 *bytes_buffered = 0; |
27 const size_t data_len = data.size(); | 36 const size_t data_len = data.size(); |
28 auto insertion_point = FindInsertionPoint(offset, data_len); | 37 auto insertion_point = FindInsertionPoint(offset, data_len); |
29 if (IsDuplicate(offset, data_len, insertion_point)) { | 38 if (IsDuplicate(offset, data_len, insertion_point)) { |
30 return QUIC_NO_ERROR; | 39 return QUIC_NO_ERROR; |
31 } | 40 } |
32 | 41 |
33 if (FrameOverlapsBufferedData(offset, data_len, insertion_point)) { | 42 if (FrameOverlapsBufferedData(offset, data_len, insertion_point)) { |
34 return QUIC_INVALID_STREAM_DATA; | 43 return QUIC_INVALID_STREAM_DATA; |
35 } | 44 } |
36 | 45 |
37 DVLOG(1) << "Buffering stream data at offset " << offset; | 46 DVLOG(1) << "Buffering stream data at offset " << offset; |
38 // Inserting an empty string and then copying to avoid the extra copy. | 47 // Inserting an empty string and then copying to avoid the extra copy. |
39 insertion_point = | 48 insertion_point = |
40 frame_list_.insert(insertion_point, FrameData(offset, "", timestamp)); | 49 frame_list_.insert(insertion_point, FrameData(offset, "", timestamp)); |
41 data.CopyToString(&insertion_point->segment); | 50 data.CopyToString(&insertion_point->segment); |
42 *bytes_written = data_len; | 51 *bytes_buffered = data_len; |
| 52 num_bytes_buffered_ += data_len; |
43 return QUIC_NO_ERROR; | 53 return QUIC_NO_ERROR; |
44 } | 54 } |
45 | 55 |
46 // Finds the place the frame should be inserted. If an identical frame is | 56 // Finds the place the frame should be inserted. If an identical frame is |
47 // present, stops on the identical frame. | 57 // present, stops on the identical frame. |
48 list<QuicFrameList::FrameData>::iterator QuicFrameList::FindInsertionPoint( | 58 list<QuicFrameList::FrameData>::iterator QuicFrameList::FindInsertionPoint( |
49 QuicStreamOffset offset, | 59 QuicStreamOffset offset, |
50 size_t len) { | 60 size_t len) { |
51 if (frame_list_.empty()) { | 61 if (frame_list_.empty()) { |
52 return frame_list_.begin(); | 62 return frame_list_.begin(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 return index; | 138 return index; |
129 } | 139 } |
130 | 140 |
131 bool QuicFrameList::GetReadableRegion(iovec* iov, QuicTime* timestamp) const { | 141 bool QuicFrameList::GetReadableRegion(iovec* iov, QuicTime* timestamp) const { |
132 list<FrameData>::const_iterator it = frame_list_.begin(); | 142 list<FrameData>::const_iterator it = frame_list_.begin(); |
133 if (it == frame_list_.end() || it->offset != total_bytes_read_) { | 143 if (it == frame_list_.end() || it->offset != total_bytes_read_) { |
134 return false; | 144 return false; |
135 } | 145 } |
136 iov->iov_base = static_cast<void*>(const_cast<char*>(it->segment.data())); | 146 iov->iov_base = static_cast<void*>(const_cast<char*>(it->segment.data())); |
137 iov->iov_len = it->segment.size(); | 147 iov->iov_len = it->segment.size(); |
138 if (timestamp) { | 148 *timestamp = it->timestamp; |
139 *timestamp = it->timestamp; | |
140 } | |
141 return true; | 149 return true; |
142 } | 150 } |
143 | 151 |
144 bool QuicFrameList::IncreaseTotalReadAndInvalidate(size_t bytes_used) { | 152 bool QuicFrameList::MarkConsumed(size_t bytes_used) { |
145 size_t end_offset = total_bytes_read_ + bytes_used; | 153 size_t end_offset = total_bytes_read_ + bytes_used; |
146 while (!frame_list_.empty() && end_offset != total_bytes_read_) { | 154 while (!frame_list_.empty() && end_offset != total_bytes_read_) { |
147 list<FrameData>::iterator it = frame_list_.begin(); | 155 list<FrameData>::iterator it = frame_list_.begin(); |
148 if (it->offset != total_bytes_read_) { | 156 if (it->offset != total_bytes_read_) { |
149 return false; | 157 return false; |
150 } | 158 } |
151 | 159 |
152 if (it->offset + it->segment.length() <= end_offset) { | 160 if (it->offset + it->segment.length() <= end_offset) { |
153 total_bytes_read_ += it->segment.length(); | 161 total_bytes_read_ += it->segment.length(); |
| 162 num_bytes_buffered_ -= it->segment.length(); |
154 // This chunk is entirely consumed. | 163 // This chunk is entirely consumed. |
155 frame_list_.erase(it); | 164 frame_list_.erase(it); |
156 continue; | 165 continue; |
157 } | 166 } |
158 | 167 |
159 // Partially consume this frame. | 168 // Partially consume this frame. |
160 size_t delta = end_offset - it->offset; | 169 size_t delta = end_offset - it->offset; |
161 total_bytes_read_ += delta; | 170 total_bytes_read_ += delta; |
| 171 num_bytes_buffered_ -= delta; |
162 string new_data = it->segment.substr(delta); | 172 string new_data = it->segment.substr(delta); |
163 const QuicTime timestamp = it->timestamp; | 173 const QuicTime timestamp = it->timestamp; |
164 frame_list_.erase(it); | 174 frame_list_.erase(it); |
165 frame_list_.push_front(FrameData(total_bytes_read_, new_data, timestamp)); | 175 frame_list_.push_front(FrameData(total_bytes_read_, new_data, timestamp)); |
166 break; | 176 break; |
167 } | 177 } |
168 return true; | 178 return true; |
169 } | 179 } |
170 | 180 |
171 size_t QuicFrameList::ReadvAndInvalidate(const struct iovec* iov, | 181 size_t QuicFrameList::Readv(const struct iovec* iov, size_t iov_len) { |
172 size_t iov_len) { | |
173 list<FrameData>::iterator it = frame_list_.begin(); | 182 list<FrameData>::iterator it = frame_list_.begin(); |
174 size_t iov_index = 0; | 183 size_t iov_index = 0; |
175 size_t iov_offset = 0; | 184 size_t iov_offset = 0; |
176 size_t frame_offset = 0; | 185 size_t frame_offset = 0; |
177 QuicStreamOffset initial_bytes_consumed = total_bytes_read_; | 186 QuicStreamOffset initial_bytes_consumed = total_bytes_read_; |
178 | 187 |
179 while (iov_index < iov_len && it != frame_list_.end() && | 188 while (iov_index < iov_len && it != frame_list_.end() && |
180 it->offset == total_bytes_read_) { | 189 it->offset == total_bytes_read_) { |
181 int bytes_to_read = std::min(iov[iov_index].iov_len - iov_offset, | 190 int bytes_to_read = std::min(iov[iov_index].iov_len - iov_offset, |
182 it->segment.size() - frame_offset); | 191 it->segment.size() - frame_offset); |
183 | 192 |
184 char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base) + iov_offset; | 193 char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base) + iov_offset; |
185 memcpy(iov_ptr, it->segment.data() + frame_offset, bytes_to_read); | 194 memcpy(iov_ptr, it->segment.data() + frame_offset, bytes_to_read); |
186 frame_offset += bytes_to_read; | 195 frame_offset += bytes_to_read; |
187 iov_offset += bytes_to_read; | 196 iov_offset += bytes_to_read; |
188 | 197 |
189 if (iov[iov_index].iov_len == iov_offset) { | 198 if (iov[iov_index].iov_len == iov_offset) { |
190 // We've filled this buffer. | 199 // We've filled this buffer. |
191 iov_offset = 0; | 200 iov_offset = 0; |
192 ++iov_index; | 201 ++iov_index; |
193 } | 202 } |
194 if (it->segment.size() == frame_offset) { | 203 if (it->segment.size() == frame_offset) { |
195 // We've copied this whole frame | 204 // We've copied this whole frame |
196 total_bytes_read_ += it->segment.size(); | 205 total_bytes_read_ += it->segment.size(); |
| 206 num_bytes_buffered_ -= it->segment.size(); |
197 frame_list_.erase(it); | 207 frame_list_.erase(it); |
198 it = frame_list_.begin(); | 208 it = frame_list_.begin(); |
199 frame_offset = 0; | 209 frame_offset = 0; |
200 } | 210 } |
201 } | 211 } |
202 // Done copying. If there is a partial frame, update it. | 212 // Done copying. If there is a partial frame, update it. |
203 if (frame_offset != 0) { | 213 if (frame_offset != 0) { |
204 frame_list_.push_front(FrameData(it->offset + frame_offset, | 214 frame_list_.push_front(FrameData(it->offset + frame_offset, |
205 it->segment.substr(frame_offset), | 215 it->segment.substr(frame_offset), |
206 it->timestamp)); | 216 it->timestamp)); |
207 frame_list_.erase(it); | 217 frame_list_.erase(it); |
208 total_bytes_read_ += frame_offset; | 218 total_bytes_read_ += frame_offset; |
| 219 num_bytes_buffered_ -= frame_offset; |
209 } | 220 } |
210 return total_bytes_read_ - initial_bytes_consumed; | 221 return total_bytes_read_ - initial_bytes_consumed; |
211 } | 222 } |
212 | 223 |
213 size_t QuicFrameList::FlushBufferedFrames() { | 224 size_t QuicFrameList::FlushBufferedFrames() { |
214 QuicStreamOffset initial_bytes_consumed = total_bytes_read_; | 225 QuicStreamOffset initial_bytes_consumed = total_bytes_read_; |
215 if (!frame_list_.empty()) { | 226 if (!frame_list_.empty()) { |
216 // Consume all of the bytes up to the last byte yet seen, including the | 227 // Consume all of the bytes up to the last byte yet seen, including the |
217 // ones that haven't arrived yet. | 228 // ones that haven't arrived yet. |
218 auto it = frame_list_.back(); | 229 auto it = frame_list_.back(); |
219 total_bytes_read_ = it.offset + it.segment.length(); | 230 total_bytes_read_ = it.offset + it.segment.length(); |
220 frame_list_.clear(); | 231 frame_list_.clear(); |
221 } | 232 } |
222 return total_bytes_read_ - initial_bytes_consumed; | 233 return total_bytes_read_ - initial_bytes_consumed; |
223 } | 234 } |
224 | 235 |
225 bool QuicFrameList::HasBytesToRead() const { | 236 bool QuicFrameList::HasBytesToRead() const { |
226 return !frame_list_.empty() && | 237 return !frame_list_.empty() && |
227 frame_list_.begin()->offset == total_bytes_read_; | 238 frame_list_.begin()->offset == total_bytes_read_; |
228 } | 239 } |
| 240 |
| 241 QuicStreamOffset QuicFrameList::BytesConsumed() const { |
| 242 return total_bytes_read_; |
| 243 } |
| 244 |
| 245 size_t QuicFrameList::BytesBuffered() const { |
| 246 return num_bytes_buffered_; |
| 247 } |
| 248 |
229 } // namespace net_quic | 249 } // namespace net_quic |
OLD | NEW |