Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: net/quic/quic_frame_list.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_frame_list.h ('k') | net/quic/quic_framer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #include "net/quic/quic_frame_list.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10
11 using std::list;
12 using std::string;
13
14 namespace net {
15
16 QuicFrameList::FrameData::FrameData(QuicStreamOffset offset,
17 string segment,
18 const QuicTime timestamp)
19 : offset(offset), segment(segment), timestamp(timestamp) {}
20
21 QuicFrameList::QuicFrameList() {}
22
23 QuicFrameList::~QuicFrameList() {
24 Clear();
25 }
26
27 void QuicFrameList::Clear() {
28 frame_list_.clear();
29 num_bytes_buffered_ = 0;
30 }
31
32 bool QuicFrameList::Empty() const {
33 return frame_list_.empty();
34 }
35
36 QuicErrorCode QuicFrameList::OnStreamData(QuicStreamOffset offset,
37 base::StringPiece data,
38 QuicTime timestamp,
39 size_t* const bytes_buffered) {
40 *bytes_buffered = 0;
41 const size_t data_len = data.size();
42 auto insertion_point = FindInsertionPoint(offset, data_len);
43 if (IsDuplicate(offset, data_len, insertion_point)) {
44 return QUIC_NO_ERROR;
45 }
46
47 if (FrameOverlapsBufferedData(offset, data_len, insertion_point)) {
48 return QUIC_INVALID_STREAM_DATA;
49 }
50
51 DVLOG(1) << "Buffering stream data at offset " << offset;
52 // Inserting an empty string and then copying to avoid the extra copy.
53 insertion_point =
54 frame_list_.insert(insertion_point, FrameData(offset, "", timestamp));
55 data.CopyToString(&insertion_point->segment);
56 *bytes_buffered = data_len;
57 num_bytes_buffered_ += data_len;
58 return QUIC_NO_ERROR;
59 }
60
61 // Finds the place the frame should be inserted. If an identical frame is
62 // present, stops on the identical frame.
63 list<QuicFrameList::FrameData>::iterator QuicFrameList::FindInsertionPoint(
64 QuicStreamOffset offset,
65 size_t len) {
66 if (frame_list_.empty()) {
67 return frame_list_.begin();
68 }
69 // If it's after all buffered_frames, return the end.
70 if (offset >=
71 (frame_list_.rbegin()->offset + frame_list_.rbegin()->segment.length())) {
72 return frame_list_.end();
73 }
74 auto iter = frame_list_.begin();
75 // Only advance the iterator if the data begins after the already received
76 // frame. If the new frame overlaps with an existing frame, the iterator will
77 // still point to the frame it overlaps with.
78 while (iter != frame_list_.end() &&
79 offset >= iter->offset + iter->segment.length()) {
80 ++iter;
81 }
82 return iter;
83 }
84
85 // Returns true if |frame| contains data which overlaps buffered data
86 // (indicating an invalid stream frame has been received).
87 bool QuicFrameList::FrameOverlapsBufferedData(
88 QuicStreamOffset offset,
89 size_t data_len,
90 list<FrameData>::const_iterator insertion_point) const {
91 if (frame_list_.empty() || insertion_point == frame_list_.end()) {
92 return false;
93 }
94 // If there is a buffered frame with a higher starting offset, then check to
95 // see if the new frame overlaps the beginning of the higher frame.
96 if (offset < insertion_point->offset &&
97 offset + data_len > insertion_point->offset) {
98 DVLOG(1) << "New frame overlaps next frame: " << offset << " + " << data_len
99 << " > " << insertion_point->offset;
100 return true;
101 }
102 // If there is a buffered frame with a lower starting offset, then check to
103 // see if the buffered frame runs into the new frame.
104 if (offset >= insertion_point->offset &&
105 offset < insertion_point->offset + insertion_point->segment.length()) {
106 DVLOG(1) << "Preceeding frame overlaps new frame: "
107 << insertion_point->offset << " + "
108 << insertion_point->segment.length() << " > " << offset;
109 return true;
110 }
111
112 return false;
113 }
114
115 // Returns true if the sequencer has received this frame before.
116 bool QuicFrameList::IsDuplicate(
117 QuicStreamOffset offset,
118 size_t data_len,
119 list<FrameData>::const_iterator insertion_point) const {
120 // A frame is duplicate if the frame offset is smaller than the bytes consumed
121 // or identical to an already received frame.
122 return offset < total_bytes_read_ || (insertion_point != frame_list_.end() &&
123 offset == insertion_point->offset);
124 }
125
126 int QuicFrameList::GetReadableRegions(struct iovec* iov, int iov_len) const {
127 list<FrameData>::const_iterator it = frame_list_.begin();
128 int index = 0;
129 QuicStreamOffset offset = total_bytes_read_;
130 while (it != frame_list_.end() && index < iov_len) {
131 if (it->offset != offset) {
132 return index;
133 }
134
135 iov[index].iov_base =
136 static_cast<void*>(const_cast<char*>(it->segment.data()));
137 iov[index].iov_len = it->segment.size();
138 offset += it->segment.size();
139
140 ++index;
141 ++it;
142 }
143 return index;
144 }
145
146 bool QuicFrameList::GetReadableRegion(iovec* iov, QuicTime* timestamp) const {
147 list<FrameData>::const_iterator it = frame_list_.begin();
148 if (it == frame_list_.end() || it->offset != total_bytes_read_) {
149 return false;
150 }
151 iov->iov_base = static_cast<void*>(const_cast<char*>(it->segment.data()));
152 iov->iov_len = it->segment.size();
153 *timestamp = it->timestamp;
154 return true;
155 }
156
157 bool QuicFrameList::MarkConsumed(size_t bytes_used) {
158 size_t end_offset = total_bytes_read_ + bytes_used;
159 while (!frame_list_.empty() && end_offset != total_bytes_read_) {
160 list<FrameData>::iterator it = frame_list_.begin();
161 if (it->offset != total_bytes_read_) {
162 return false;
163 }
164
165 if (it->offset + it->segment.length() <= end_offset) {
166 total_bytes_read_ += it->segment.length();
167 num_bytes_buffered_ -= it->segment.length();
168 // This chunk is entirely consumed.
169 frame_list_.erase(it);
170 continue;
171 }
172
173 // Partially consume this frame.
174 size_t delta = end_offset - it->offset;
175 total_bytes_read_ += delta;
176 num_bytes_buffered_ -= delta;
177 string new_data = it->segment.substr(delta);
178 const QuicTime timestamp = it->timestamp;
179 frame_list_.erase(it);
180 frame_list_.push_front(FrameData(total_bytes_read_, new_data, timestamp));
181 break;
182 }
183 return true;
184 }
185
186 size_t QuicFrameList::Readv(const struct iovec* iov, size_t iov_len) {
187 list<FrameData>::iterator it = frame_list_.begin();
188 size_t iov_index = 0;
189 size_t iov_offset = 0;
190 size_t frame_offset = 0;
191 QuicStreamOffset initial_bytes_consumed = total_bytes_read_;
192
193 while (iov_index < iov_len && it != frame_list_.end() &&
194 it->offset == total_bytes_read_) {
195 int bytes_to_read = std::min(iov[iov_index].iov_len - iov_offset,
196 it->segment.size() - frame_offset);
197
198 char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base) + iov_offset;
199 memcpy(iov_ptr, it->segment.data() + frame_offset, bytes_to_read);
200 frame_offset += bytes_to_read;
201 iov_offset += bytes_to_read;
202
203 if (iov[iov_index].iov_len == iov_offset) {
204 // We've filled this buffer.
205 iov_offset = 0;
206 ++iov_index;
207 }
208 if (it->segment.size() == frame_offset) {
209 // We've copied this whole frame
210 total_bytes_read_ += it->segment.size();
211 num_bytes_buffered_ -= it->segment.size();
212 frame_list_.erase(it);
213 it = frame_list_.begin();
214 frame_offset = 0;
215 }
216 }
217 // Done copying. If there is a partial frame, update it.
218 if (frame_offset != 0) {
219 frame_list_.push_front(FrameData(it->offset + frame_offset,
220 it->segment.substr(frame_offset),
221 it->timestamp));
222 frame_list_.erase(it);
223 total_bytes_read_ += frame_offset;
224 num_bytes_buffered_ -= frame_offset;
225 }
226 return total_bytes_read_ - initial_bytes_consumed;
227 }
228
229 size_t QuicFrameList::FlushBufferedFrames() {
230 QuicStreamOffset initial_bytes_consumed = total_bytes_read_;
231 if (!frame_list_.empty()) {
232 // Consume all of the bytes up to the last byte yet seen, including the
233 // ones that haven't arrived yet.
234 auto it = frame_list_.back();
235 total_bytes_read_ = it.offset + it.segment.length();
236 frame_list_.clear();
237 }
238 return total_bytes_read_ - initial_bytes_consumed;
239 }
240
241 bool QuicFrameList::HasBytesToRead() const {
242 return !frame_list_.empty() &&
243 frame_list_.begin()->offset == total_bytes_read_;
244 }
245
246 QuicStreamOffset QuicFrameList::BytesConsumed() const {
247 return total_bytes_read_;
248 }
249
250 size_t QuicFrameList::BytesBuffered() const {
251 return num_bytes_buffered_;
252 }
253
254 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_frame_list.h ('k') | net/quic/quic_framer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698