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/core/quic_stream_sequencer_buffer.h" | 5 #include "net/quic/core/quic_stream_sequencer_buffer.h" |
6 | 6 |
7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "net/quic/core/quic_bug_tracker.h" | 11 #include "net/quic/core/quic_bug_tracker.h" |
12 #include "net/quic/core/quic_flags.h" | 12 #include "net/quic/core/quic_flags.h" |
13 #include "net/quic/platform/api/quic_str_cat.h" | 13 #include "net/quic/platform/api/quic_str_cat.h" |
14 | 14 |
15 using base::StringPrintf; | 15 using base::StringPrintf; |
16 using std::string; | 16 using std::string; |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 namespace { | 19 namespace { |
20 | 20 |
21 // Upper limit of how many gaps allowed in buffer, which ensures a reasonable | 21 // Upper limit of how many gaps allowed in buffer, which ensures a reasonable |
22 // number of iterations needed to find the right gap to fill when a frame | 22 // number of iterations needed to find the right gap to fill when a frame |
23 // arrives. | 23 // arrives. |
24 const size_t kMaxNumGapsAllowed = 2 * kMaxPacketGap; | 24 const size_t kMaxNumGapsAllowed = 2 * kMaxPacketGap; |
25 | 25 |
26 } // namespace | 26 } // namespace |
27 | 27 |
28 namespace { | |
29 | |
30 string RangeDebugString(QuicStreamOffset start, QuicStreamOffset end) { | |
31 return std::string("[") + base::Uint64ToString(start) + ", " + | |
32 base::Uint64ToString(end) + ") "; | |
33 } | |
34 | |
35 } // namespace | |
36 | |
37 QuicStreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset, | 28 QuicStreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset, |
38 QuicStreamOffset end_offset) | 29 QuicStreamOffset end_offset) |
39 : begin_offset(begin_offset), end_offset(end_offset) {} | 30 : begin_offset(begin_offset), end_offset(end_offset) {} |
40 | 31 |
41 QuicStreamSequencerBuffer::FrameInfo::FrameInfo() | 32 QuicStreamSequencerBuffer::FrameInfo::FrameInfo() |
42 : length(1), timestamp(QuicTime::Zero()) {} | 33 : length(1), timestamp(QuicTime::Zero()) {} |
43 | 34 |
44 QuicStreamSequencerBuffer::FrameInfo::FrameInfo(size_t length, | 35 QuicStreamSequencerBuffer::FrameInfo::FrameInfo(size_t length, |
45 QuicTime timestamp) | 36 QuicTime timestamp) |
46 : length(length), timestamp(timestamp) {} | 37 : length(length), timestamp(timestamp) {} |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // In both cases, don't write the data, | 115 // In both cases, don't write the data, |
125 // and allow the caller of this method to handle the result. | 116 // and allow the caller of this method to handle the result. |
126 if (offset < current_gap->begin_offset && | 117 if (offset < current_gap->begin_offset && |
127 offset + size <= current_gap->begin_offset) { | 118 offset + size <= current_gap->begin_offset) { |
128 DVLOG(1) << "Duplicated data at offset: " << offset << " length: " << size; | 119 DVLOG(1) << "Duplicated data at offset: " << offset << " length: " << size; |
129 return QUIC_NO_ERROR; | 120 return QUIC_NO_ERROR; |
130 } | 121 } |
131 if (offset < current_gap->begin_offset && | 122 if (offset < current_gap->begin_offset && |
132 offset + size > current_gap->begin_offset) { | 123 offset + size > current_gap->begin_offset) { |
133 // Beginning of new data overlaps data before current gap. | 124 // Beginning of new data overlaps data before current gap. |
| 125 string prefix(data.data(), data.length() < 128 ? data.length() : 128); |
134 *error_details = | 126 *error_details = |
135 string("Beginning of received data overlaps with buffered data.\n") + | 127 QuicStrCat("Beginning of received data overlaps with buffered data.\n", |
136 "New frame range " + RangeDebugString(offset, offset + size) + | 128 "New frame range [", offset, ", ", offset + size, |
137 " with first 128 bytes: " + | 129 ") with first 128 bytes: ", prefix, "\n", |
138 string(data.data(), data.length() < 128 ? data.length() : 128) + | 130 "Currently received frames: ", GapsDebugString(), "\n", |
139 "\nCurrently received frames: " + ReceivedFramesDebugString() + | 131 "Current gaps: ", ReceivedFramesDebugString()); |
140 "\nCurrent gaps: " + GapsDebugString(); | |
141 return QUIC_OVERLAPPING_STREAM_DATA; | 132 return QUIC_OVERLAPPING_STREAM_DATA; |
142 } | 133 } |
143 if (offset + size > current_gap->end_offset) { | 134 if (offset + size > current_gap->end_offset) { |
144 // End of new data overlaps with data after current gap. | 135 // End of new data overlaps with data after current gap. |
145 *error_details = | 136 string prefix(data.data(), data.length() < 128 ? data.length() : 128); |
146 string("End of received data overlaps with buffered data.\n") + | 137 *error_details = QuicStrCat( |
147 "New frame range " + RangeDebugString(offset, offset + size) + | 138 "End of received data overlaps with buffered data.\nNew frame range [", |
148 " with first 128 bytes: " + | 139 offset, ", ", offset + size, ") with first 128 bytes: ", prefix, "\n", |
149 string(data.data(), data.length() < 128 ? data.length() : 128) + | 140 "Currently received frames: ", ReceivedFramesDebugString(), "\n", |
150 "\nCurrently received frames: " + ReceivedFramesDebugString() + | 141 "Current gaps: ", GapsDebugString()); |
151 "\nCurrent gaps: " + GapsDebugString(); | |
152 return QUIC_OVERLAPPING_STREAM_DATA; | 142 return QUIC_OVERLAPPING_STREAM_DATA; |
153 } | 143 } |
154 | 144 |
155 // Write beyond the current range this buffer is covering. | 145 // Write beyond the current range this buffer is covering. |
156 if (offset + size > total_bytes_read_ + max_buffer_capacity_bytes_) { | 146 if (offset + size > total_bytes_read_ + max_buffer_capacity_bytes_) { |
157 *error_details = "Received data beyond available range."; | 147 *error_details = "Received data beyond available range."; |
158 return QUIC_INTERNAL_ERROR; | 148 return QUIC_INTERNAL_ERROR; |
159 } | 149 } |
160 | 150 |
161 if (current_gap->begin_offset != starting_offset && | 151 if (current_gap->begin_offset != starting_offset && |
(...skipping 29 matching lines...) Expand all Loading... |
191 blocks_.reset(new BufferBlock*[blocks_count_]()); | 181 blocks_.reset(new BufferBlock*[blocks_count_]()); |
192 for (size_t i = 0; i < blocks_count_; ++i) { | 182 for (size_t i = 0; i < blocks_count_; ++i) { |
193 blocks_[i] = nullptr; | 183 blocks_[i] = nullptr; |
194 } | 184 } |
195 } | 185 } |
196 | 186 |
197 if (write_block_num >= blocks_count_) { | 187 if (write_block_num >= blocks_count_) { |
198 *error_details = QuicStrCat( | 188 *error_details = QuicStrCat( |
199 "QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds." | 189 "QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds." |
200 "write offset = ", | 190 "write offset = ", |
201 offset, " write_block_num = ", write_block_num, " blocks_count_ = ", | 191 offset, " write_block_num = ", write_block_num, |
202 blocks_count_); | 192 " blocks_count_ = ", blocks_count_); |
203 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 193 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
204 } | 194 } |
205 if (blocks_ == nullptr) { | 195 if (blocks_ == nullptr) { |
206 *error_details = | 196 *error_details = |
207 "QuicStreamSequencerBuffer error: OnStreamData() blocks_ is null"; | 197 "QuicStreamSequencerBuffer error: OnStreamData() blocks_ is null"; |
208 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 198 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
209 } | 199 } |
210 if (blocks_[write_block_num] == nullptr) { | 200 if (blocks_[write_block_num] == nullptr) { |
211 // TODO(danzh): Investigate if using a freelist would improve performance. | 201 // TODO(danzh): Investigate if using a freelist would improve performance. |
212 // Same as RetireBlock(). | 202 // Same as RetireBlock(). |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 size_t block_capacity = GetBlockCapacity(block_idx); | 282 size_t block_capacity = GetBlockCapacity(block_idx); |
293 size_t bytes_available_in_block = std::min<size_t>( | 283 size_t bytes_available_in_block = std::min<size_t>( |
294 ReadableBytes(), block_capacity - start_offset_in_block); | 284 ReadableBytes(), block_capacity - start_offset_in_block); |
295 size_t bytes_to_copy = | 285 size_t bytes_to_copy = |
296 std::min<size_t>(bytes_available_in_block, dest_remaining); | 286 std::min<size_t>(bytes_available_in_block, dest_remaining); |
297 DCHECK_GT(bytes_to_copy, 0UL); | 287 DCHECK_GT(bytes_to_copy, 0UL); |
298 if (blocks_[block_idx] == nullptr || dest == nullptr) { | 288 if (blocks_[block_idx] == nullptr || dest == nullptr) { |
299 *error_details = QuicStrCat( | 289 *error_details = QuicStrCat( |
300 "QuicStreamSequencerBuffer error:" | 290 "QuicStreamSequencerBuffer error:" |
301 " Readv() dest == nullptr: ", | 291 " Readv() dest == nullptr: ", |
302 (dest == nullptr), " blocks_[", block_idx, "] == nullptr: ", | 292 (dest == nullptr), " blocks_[", block_idx, |
303 (blocks_[block_idx] == nullptr), " Gaps: ", GapsDebugString(), | 293 "] == nullptr: ", (blocks_[block_idx] == nullptr), |
| 294 " Gaps: ", GapsDebugString(), |
304 " Remaining frames: ", ReceivedFramesDebugString(), | 295 " Remaining frames: ", ReceivedFramesDebugString(), |
305 " total_bytes_read_ = ", total_bytes_read_); | 296 " total_bytes_read_ = ", total_bytes_read_); |
306 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 297 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
307 } | 298 } |
308 memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, | 299 memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, |
309 bytes_to_copy); | 300 bytes_to_copy); |
310 dest += bytes_to_copy; | 301 dest += bytes_to_copy; |
311 dest_remaining -= bytes_to_copy; | 302 dest_remaining -= bytes_to_copy; |
312 num_bytes_buffered_ -= bytes_to_copy; | 303 num_bytes_buffered_ -= bytes_to_copy; |
313 total_bytes_read_ += bytes_to_copy; | 304 total_bytes_read_ += bytes_to_copy; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 frame_arrival_time_map_.insert(updated); | 574 frame_arrival_time_map_.insert(updated); |
584 } | 575 } |
585 } | 576 } |
586 } | 577 } |
587 | 578 |
588 string QuicStreamSequencerBuffer::GapsDebugString() { | 579 string QuicStreamSequencerBuffer::GapsDebugString() { |
589 string current_gaps_string; | 580 string current_gaps_string; |
590 for (const Gap& gap : gaps_) { | 581 for (const Gap& gap : gaps_) { |
591 QuicStreamOffset current_gap_begin = gap.begin_offset; | 582 QuicStreamOffset current_gap_begin = gap.begin_offset; |
592 QuicStreamOffset current_gap_end = gap.end_offset; | 583 QuicStreamOffset current_gap_end = gap.end_offset; |
593 current_gaps_string += RangeDebugString(current_gap_begin, current_gap_end); | 584 current_gaps_string.append( |
| 585 QuicStrCat("[", current_gap_begin, ", ", current_gap_end, ") ")); |
594 } | 586 } |
595 return current_gaps_string; | 587 return current_gaps_string; |
596 } | 588 } |
597 | 589 |
598 string QuicStreamSequencerBuffer::ReceivedFramesDebugString() { | 590 string QuicStreamSequencerBuffer::ReceivedFramesDebugString() { |
599 string current_frames_string; | 591 string current_frames_string; |
600 for (auto it : frame_arrival_time_map_) { | 592 for (auto it : frame_arrival_time_map_) { |
601 QuicStreamOffset current_frame_begin_offset = it.first; | 593 QuicStreamOffset current_frame_begin_offset = it.first; |
602 QuicStreamOffset current_frame_end_offset = | 594 QuicStreamOffset current_frame_end_offset = |
603 it.second.length + current_frame_begin_offset; | 595 it.second.length + current_frame_begin_offset; |
604 current_frames_string = string(StringPrintf( | 596 current_frames_string.append(QuicStrCat( |
605 "%s[%" PRIu64 ", %" PRIu64 ") ", current_frames_string.c_str(), | 597 "[", current_frame_begin_offset, ", ", current_frame_end_offset, |
606 current_frame_begin_offset, current_frame_end_offset)); | 598 ") receiving time ", it.second.timestamp.ToDebuggingValue())); |
607 } | 599 } |
608 return current_frames_string; | 600 return current_frames_string; |
609 } | 601 } |
610 | 602 |
611 } // namespace net | 603 } // namespace net |
OLD | NEW |