OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_stream_sequencer.h" | 5 #include "net/quic/quic_stream_sequencer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/metrics/sparse_histogram.h" | 11 #include "base/metrics/sparse_histogram.h" |
12 #include "net/quic/reliable_quic_stream.h" | 12 #include "net/quic/reliable_quic_stream.h" |
13 | 13 |
14 using std::make_pair; | |
15 using std::min; | 14 using std::min; |
16 using std::numeric_limits; | 15 using std::numeric_limits; |
17 using std::string; | 16 using std::string; |
18 | 17 |
19 namespace net { | 18 namespace net { |
20 | 19 |
21 QuicStreamSequencer::QuicStreamSequencer(ReliableQuicStream* quic_stream) | 20 QuicStreamSequencer::QuicStreamSequencer(ReliableQuicStream* quic_stream) |
22 : stream_(quic_stream), | 21 : stream_(quic_stream), |
23 num_bytes_consumed_(0), | 22 num_bytes_consumed_(0), |
24 close_offset_(numeric_limits<QuicStreamOffset>::max()), | 23 close_offset_(numeric_limits<QuicStreamOffset>::max()), |
25 blocked_(false), | 24 blocked_(false), |
26 num_bytes_buffered_(0), | 25 num_bytes_buffered_(0), |
27 num_frames_received_(0), | 26 num_frames_received_(0), |
28 num_duplicate_frames_received_(0) { | 27 num_duplicate_frames_received_(0), |
| 28 num_early_frames_received_(0) { |
29 } | 29 } |
30 | 30 |
31 QuicStreamSequencer::~QuicStreamSequencer() { | 31 QuicStreamSequencer::~QuicStreamSequencer() { |
32 } | 32 } |
33 | 33 |
34 void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) { | 34 void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) { |
35 ++num_frames_received_; | 35 ++num_frames_received_; |
36 if (IsDuplicate(frame)) { | 36 if (IsDuplicate(frame)) { |
37 ++num_duplicate_frames_received_; | 37 ++num_duplicate_frames_received_; |
38 // Silently ignore duplicates. | 38 // Silently ignore duplicates. |
(...skipping 18 matching lines...) Expand all Loading... |
57 if (frame.fin) { | 57 if (frame.fin) { |
58 CloseStreamAtOffset(frame.offset + data_len); | 58 CloseStreamAtOffset(frame.offset + data_len); |
59 if (data_len == 0) { | 59 if (data_len == 0) { |
60 return; | 60 return; |
61 } | 61 } |
62 } | 62 } |
63 | 63 |
64 IOVector data; | 64 IOVector data; |
65 data.AppendIovec(frame.data.iovec(), frame.data.Size()); | 65 data.AppendIovec(frame.data.iovec(), frame.data.Size()); |
66 | 66 |
| 67 if (byte_offset > num_bytes_consumed_) { |
| 68 ++num_early_frames_received_; |
| 69 } |
| 70 |
67 // If the frame has arrived in-order then we can process it immediately, only | 71 // If the frame has arrived in-order then we can process it immediately, only |
68 // buffering if the stream is unable to process it. | 72 // buffering if the stream is unable to process it. |
69 if (!blocked_ && byte_offset == num_bytes_consumed_) { | 73 if (!blocked_ && byte_offset == num_bytes_consumed_) { |
70 DVLOG(1) << "Processing byte offset " << byte_offset; | 74 DVLOG(1) << "Processing byte offset " << byte_offset; |
71 size_t bytes_consumed = 0; | 75 size_t bytes_consumed = 0; |
72 for (size_t i = 0; i < data.Size(); ++i) { | 76 for (size_t i = 0; i < data.Size(); ++i) { |
73 bytes_consumed += stream_->ProcessRawData( | 77 bytes_consumed += stream_->ProcessRawData( |
74 static_cast<char*>(data.iovec()[i].iov_base), | 78 static_cast<char*>(data.iovec()[i].iov_base), |
75 data.iovec()[i].iov_len); | 79 data.iovec()[i].iov_len); |
76 } | 80 } |
(...skipping 14 matching lines...) Expand all Loading... |
91 data_len -= bytes_consumed; | 95 data_len -= bytes_consumed; |
92 data.Consume(bytes_consumed); | 96 data.Consume(bytes_consumed); |
93 byte_offset += bytes_consumed; | 97 byte_offset += bytes_consumed; |
94 } | 98 } |
95 } | 99 } |
96 | 100 |
97 // Buffer any remaining data to be consumed by the stream when ready. | 101 // Buffer any remaining data to be consumed by the stream when ready. |
98 for (size_t i = 0; i < data.Size(); ++i) { | 102 for (size_t i = 0; i < data.Size(); ++i) { |
99 DVLOG(1) << "Buffering stream data at offset " << byte_offset; | 103 DVLOG(1) << "Buffering stream data at offset " << byte_offset; |
100 const iovec& iov = data.iovec()[i]; | 104 const iovec& iov = data.iovec()[i]; |
101 buffered_frames_.insert(make_pair( | 105 buffered_frames_.insert(std::make_pair( |
102 byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len))); | 106 byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len))); |
103 byte_offset += iov.iov_len; | 107 byte_offset += iov.iov_len; |
104 num_bytes_buffered_ += iov.iov_len; | 108 num_bytes_buffered_ += iov.iov_len; |
105 } | 109 } |
106 return; | 110 return; |
107 } | 111 } |
108 | 112 |
109 void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) { | 113 void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) { |
110 const QuicStreamOffset kMaxOffset = numeric_limits<QuicStreamOffset>::max(); | 114 const QuicStreamOffset kMaxOffset = numeric_limits<QuicStreamOffset>::max(); |
111 | 115 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 if (it->second.size() == frame_offset) { | 187 if (it->second.size() == frame_offset) { |
184 // We've copied this whole frame | 188 // We've copied this whole frame |
185 RecordBytesConsumed(it->second.size()); | 189 RecordBytesConsumed(it->second.size()); |
186 buffered_frames_.erase(it); | 190 buffered_frames_.erase(it); |
187 it = buffered_frames_.begin(); | 191 it = buffered_frames_.begin(); |
188 frame_offset = 0; | 192 frame_offset = 0; |
189 } | 193 } |
190 } | 194 } |
191 // We've finished copying. If we have a partial frame, update it. | 195 // We've finished copying. If we have a partial frame, update it. |
192 if (frame_offset != 0) { | 196 if (frame_offset != 0) { |
193 buffered_frames_.insert( | 197 buffered_frames_.insert(std::make_pair(it->first + frame_offset, |
194 make_pair(it->first + frame_offset, it->second.substr(frame_offset))); | 198 it->second.substr(frame_offset))); |
195 buffered_frames_.erase(buffered_frames_.begin()); | 199 buffered_frames_.erase(buffered_frames_.begin()); |
196 RecordBytesConsumed(frame_offset); | 200 RecordBytesConsumed(frame_offset); |
197 } | 201 } |
198 return static_cast<int>(num_bytes_consumed_ - initial_bytes_consumed); | 202 return static_cast<int>(num_bytes_consumed_ - initial_bytes_consumed); |
199 } | 203 } |
200 | 204 |
201 bool QuicStreamSequencer::HasBytesToRead() const { | 205 bool QuicStreamSequencer::HasBytesToRead() const { |
202 FrameMap::const_iterator it = buffered_frames_.begin(); | 206 FrameMap::const_iterator it = buffered_frames_.begin(); |
203 | 207 |
204 return it != buffered_frames_.end() && it->first == num_bytes_consumed_; | 208 return it != buffered_frames_.end() && it->first == num_bytes_consumed_; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 } | 275 } |
272 if (bytes_consumed > data->size()) { | 276 if (bytes_consumed > data->size()) { |
273 stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); // Programming error | 277 stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); // Programming error |
274 return; | 278 return; |
275 } else if (bytes_consumed == data->size()) { | 279 } else if (bytes_consumed == data->size()) { |
276 buffered_frames_.erase(it); | 280 buffered_frames_.erase(it); |
277 it = buffered_frames_.find(num_bytes_consumed_); | 281 it = buffered_frames_.find(num_bytes_consumed_); |
278 } else { | 282 } else { |
279 string new_data = it->second.substr(bytes_consumed); | 283 string new_data = it->second.substr(bytes_consumed); |
280 buffered_frames_.erase(it); | 284 buffered_frames_.erase(it); |
281 buffered_frames_.insert(make_pair(num_bytes_consumed_, new_data)); | 285 buffered_frames_.insert(std::make_pair(num_bytes_consumed_, new_data)); |
282 return; | 286 return; |
283 } | 287 } |
284 } | 288 } |
285 MaybeCloseStream(); | 289 MaybeCloseStream(); |
286 } | 290 } |
287 | 291 |
288 void QuicStreamSequencer::RecordBytesConsumed(size_t bytes_consumed) { | 292 void QuicStreamSequencer::RecordBytesConsumed(size_t bytes_consumed) { |
289 num_bytes_consumed_ += bytes_consumed; | 293 num_bytes_consumed_ += bytes_consumed; |
290 num_bytes_buffered_ -= bytes_consumed; | 294 num_bytes_buffered_ -= bytes_consumed; |
291 | 295 |
292 stream_->AddBytesConsumed(bytes_consumed); | 296 stream_->AddBytesConsumed(bytes_consumed); |
293 } | 297 } |
294 | 298 |
295 } // namespace net | 299 } // namespace net |
OLD | NEW |