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" |
(...skipping 12 matching lines...) Expand all Loading... |
23 close_offset_(numeric_limits<QuicStreamOffset>::max()), | 23 close_offset_(numeric_limits<QuicStreamOffset>::max()), |
24 blocked_(false), | 24 blocked_(false), |
25 num_bytes_buffered_(0), | 25 num_bytes_buffered_(0), |
26 num_frames_received_(0), | 26 num_frames_received_(0), |
27 num_duplicate_frames_received_(0) { | 27 num_duplicate_frames_received_(0) { |
28 } | 28 } |
29 | 29 |
30 QuicStreamSequencer::~QuicStreamSequencer() { | 30 QuicStreamSequencer::~QuicStreamSequencer() { |
31 } | 31 } |
32 | 32 |
33 bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) { | 33 void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) { |
34 ++num_frames_received_; | 34 ++num_frames_received_; |
35 if (IsDuplicate(frame)) { | 35 if (IsDuplicate(frame)) { |
36 ++num_duplicate_frames_received_; | 36 ++num_duplicate_frames_received_; |
37 // Silently ignore duplicates. | 37 // Silently ignore duplicates. |
38 return true; | 38 return; |
39 } | 39 } |
40 | 40 |
41 if (FrameOverlapsBufferedData(frame)) { | 41 if (FrameOverlapsBufferedData(frame)) { |
42 stream_->CloseConnectionWithDetails( | 42 stream_->CloseConnectionWithDetails( |
43 QUIC_INVALID_STREAM_FRAME, "Stream frame overlaps with buffered data."); | 43 QUIC_INVALID_STREAM_FRAME, "Stream frame overlaps with buffered data."); |
44 return false; | 44 return; |
45 } | 45 } |
46 | 46 |
47 QuicStreamOffset byte_offset = frame.offset; | 47 QuicStreamOffset byte_offset = frame.offset; |
48 size_t data_len = frame.data.TotalBufferSize(); | 48 size_t data_len = frame.data.TotalBufferSize(); |
49 if (data_len == 0 && !frame.fin) { | 49 if (data_len == 0 && !frame.fin) { |
50 // Stream frames must have data or a fin flag. | 50 // Stream frames must have data or a fin flag. |
51 stream_->CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, | 51 stream_->CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, |
52 "Empty stream frame without FIN set."); | 52 "Empty stream frame without FIN set."); |
53 return false; | 53 return; |
54 } | 54 } |
55 | 55 |
56 if (frame.fin) { | 56 if (frame.fin) { |
57 CloseStreamAtOffset(frame.offset + data_len); | 57 CloseStreamAtOffset(frame.offset + data_len); |
58 if (data_len == 0) { | 58 if (data_len == 0) { |
59 return true; | 59 return; |
60 } | 60 } |
61 } | 61 } |
62 | 62 |
63 IOVector data; | 63 IOVector data; |
64 data.AppendIovec(frame.data.iovec(), frame.data.Size()); | 64 data.AppendIovec(frame.data.iovec(), frame.data.Size()); |
65 | 65 |
66 // If the frame has arrived in-order then we can process it immediately, only | 66 // If the frame has arrived in-order then we can process it immediately, only |
67 // buffering if the stream is unable to process it. | 67 // buffering if the stream is unable to process it. |
68 if (!blocked_ && byte_offset == num_bytes_consumed_) { | 68 if (!blocked_ && byte_offset == num_bytes_consumed_) { |
69 DVLOG(1) << "Processing byte offset " << byte_offset; | 69 DVLOG(1) << "Processing byte offset " << byte_offset; |
70 size_t bytes_consumed = 0; | 70 size_t bytes_consumed = 0; |
71 for (size_t i = 0; i < data.Size(); ++i) { | 71 for (size_t i = 0; i < data.Size(); ++i) { |
72 bytes_consumed += stream_->ProcessRawData( | 72 bytes_consumed += stream_->ProcessRawData( |
73 static_cast<char*>(data.iovec()[i].iov_base), | 73 static_cast<char*>(data.iovec()[i].iov_base), |
74 data.iovec()[i].iov_len); | 74 data.iovec()[i].iov_len); |
75 } | 75 } |
76 num_bytes_consumed_ += bytes_consumed; | 76 num_bytes_consumed_ += bytes_consumed; |
77 stream_->AddBytesConsumed(bytes_consumed); | 77 stream_->AddBytesConsumed(bytes_consumed); |
78 | 78 |
79 if (MaybeCloseStream()) { | 79 if (MaybeCloseStream()) { |
80 return true; | 80 return; |
81 } | 81 } |
82 if (bytes_consumed > data_len) { | 82 if (bytes_consumed > data_len) { |
83 stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); | 83 stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); |
84 return false; | 84 return; |
85 } else if (bytes_consumed == data_len) { | 85 } else if (bytes_consumed == data_len) { |
86 FlushBufferedFrames(); | 86 FlushBufferedFrames(); |
87 return true; // it's safe to ack this frame. | 87 return; // it's safe to ack this frame. |
88 } else { | 88 } else { |
89 // Set ourselves up to buffer what's left. | 89 // Set ourselves up to buffer what's left. |
90 data_len -= bytes_consumed; | 90 data_len -= bytes_consumed; |
91 data.Consume(bytes_consumed); | 91 data.Consume(bytes_consumed); |
92 byte_offset += bytes_consumed; | 92 byte_offset += bytes_consumed; |
93 } | 93 } |
94 } | 94 } |
95 | 95 |
96 // Buffer any remaining data to be consumed by the stream when ready. | 96 // Buffer any remaining data to be consumed by the stream when ready. |
97 for (size_t i = 0; i < data.Size(); ++i) { | 97 for (size_t i = 0; i < data.Size(); ++i) { |
98 DVLOG(1) << "Buffering stream data at offset " << byte_offset; | 98 DVLOG(1) << "Buffering stream data at offset " << byte_offset; |
99 const iovec& iov = data.iovec()[i]; | 99 const iovec& iov = data.iovec()[i]; |
100 buffered_frames_.insert(make_pair( | 100 buffered_frames_.insert(make_pair( |
101 byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len))); | 101 byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len))); |
102 byte_offset += iov.iov_len; | 102 byte_offset += iov.iov_len; |
103 num_bytes_buffered_ += iov.iov_len; | 103 num_bytes_buffered_ += iov.iov_len; |
104 } | 104 } |
105 return true; | 105 return; |
106 } | 106 } |
107 | 107 |
108 void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) { | 108 void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) { |
109 const QuicStreamOffset kMaxOffset = numeric_limits<QuicStreamOffset>::max(); | 109 const QuicStreamOffset kMaxOffset = numeric_limits<QuicStreamOffset>::max(); |
110 | 110 |
111 // If we have a scheduled termination or close, any new offset should match | 111 // If we have a scheduled termination or close, any new offset should match |
112 // it. | 112 // it. |
113 if (close_offset_ != kMaxOffset && offset != close_offset_) { | 113 if (close_offset_ != kMaxOffset && offset != close_offset_) { |
114 stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS); | 114 stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS); |
115 return; | 115 return; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 } | 285 } |
286 | 286 |
287 void QuicStreamSequencer::RecordBytesConsumed(size_t bytes_consumed) { | 287 void QuicStreamSequencer::RecordBytesConsumed(size_t bytes_consumed) { |
288 num_bytes_consumed_ += bytes_consumed; | 288 num_bytes_consumed_ += bytes_consumed; |
289 num_bytes_buffered_ -= bytes_consumed; | 289 num_bytes_buffered_ -= bytes_consumed; |
290 | 290 |
291 stream_->AddBytesConsumed(bytes_consumed); | 291 stream_->AddBytesConsumed(bytes_consumed); |
292 } | 292 } |
293 | 293 |
294 } // namespace net | 294 } // namespace net |
OLD | NEW |