| 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 |