| 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 | 14 |
| 14 using base::StringPrintf; | 15 using base::StringPrintf; |
| 15 using std::string; | 16 using std::string; |
| 16 | 17 |
| 17 namespace net { | 18 namespace net { |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 // 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 |
| 21 // 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 |
| 22 // arrives. | 23 // arrives. |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 188 } |
| 188 | 189 |
| 189 if (reduce_sequencer_buffer_memory_life_time_ && blocks_ == nullptr) { | 190 if (reduce_sequencer_buffer_memory_life_time_ && blocks_ == nullptr) { |
| 190 blocks_.reset(new BufferBlock*[blocks_count_]()); | 191 blocks_.reset(new BufferBlock*[blocks_count_]()); |
| 191 for (size_t i = 0; i < blocks_count_; ++i) { | 192 for (size_t i = 0; i < blocks_count_; ++i) { |
| 192 blocks_[i] = nullptr; | 193 blocks_[i] = nullptr; |
| 193 } | 194 } |
| 194 } | 195 } |
| 195 | 196 |
| 196 if (write_block_num >= blocks_count_) { | 197 if (write_block_num >= blocks_count_) { |
| 197 *error_details = StringPrintf( | 198 *error_details = QuicStrCat( |
| 198 "QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds." | 199 "QuicStreamSequencerBuffer error: OnStreamData() exceed array bounds." |
| 199 "write offset = %" PRIu64 " write_block_num = %" PRIuS | 200 "write offset = ", |
| 200 " blocks_count_ = %" PRIuS, | 201 offset, " write_block_num = ", write_block_num, " blocks_count_ = ", |
| 201 offset, write_block_num, blocks_count_); | 202 blocks_count_); |
| 202 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 203 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
| 203 } | 204 } |
| 204 if (blocks_ == nullptr) { | 205 if (blocks_ == nullptr) { |
| 205 *error_details = | 206 *error_details = |
| 206 "QuicStreamSequencerBuffer error: OnStreamData() blocks_ is null"; | 207 "QuicStreamSequencerBuffer error: OnStreamData() blocks_ is null"; |
| 207 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 208 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
| 208 } | 209 } |
| 209 if (blocks_[write_block_num] == nullptr) { | 210 if (blocks_[write_block_num] == nullptr) { |
| 210 // TODO(danzh): Investigate if using a freelist would improve performance. | 211 // TODO(danzh): Investigate if using a freelist would improve performance. |
| 211 // Same as RetireBlock(). | 212 // Same as RetireBlock(). |
| 212 blocks_[write_block_num] = new BufferBlock(); | 213 blocks_[write_block_num] = new BufferBlock(); |
| 213 } | 214 } |
| 214 | 215 |
| 215 const size_t bytes_to_copy = | 216 const size_t bytes_to_copy = |
| 216 std::min<size_t>(bytes_avail, source_remaining); | 217 std::min<size_t>(bytes_avail, source_remaining); |
| 217 char* dest = blocks_[write_block_num]->buffer + write_block_offset; | 218 char* dest = blocks_[write_block_num]->buffer + write_block_offset; |
| 218 DVLOG(1) << "Write at offset: " << offset << " length: " << bytes_to_copy; | 219 DVLOG(1) << "Write at offset: " << offset << " length: " << bytes_to_copy; |
| 219 | 220 |
| 220 if (dest == nullptr || source == nullptr) { | 221 if (dest == nullptr || source == nullptr) { |
| 221 *error_details = StringPrintf( | 222 *error_details = QuicStrCat( |
| 222 "QuicStreamSequencerBuffer error: OnStreamData()" | 223 "QuicStreamSequencerBuffer error: OnStreamData()" |
| 223 " dest == nullptr: %s" | 224 " dest == nullptr: ", |
| 224 " source == nullptr: %s" | 225 (dest == nullptr), " source == nullptr: ", (source == nullptr), |
| 225 " Writing at offset %" PRIu64 | 226 " Writing at offset ", offset, " Gaps: ", GapsDebugString(), |
| 226 " Gaps: %s" | 227 " Remaining frames: ", ReceivedFramesDebugString(), |
| 227 " Remaining frames: %s" | 228 " total_bytes_read_ = ", total_bytes_read_); |
| 228 " total_bytes_read_ = %" PRIu64, | |
| 229 (dest == nullptr ? "true" : "false"), | |
| 230 (source == nullptr ? "true" : "false"), offset, | |
| 231 GapsDebugString().c_str(), ReceivedFramesDebugString().c_str(), | |
| 232 total_bytes_read_); | |
| 233 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 229 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
| 234 } | 230 } |
| 235 memcpy(dest, source, bytes_to_copy); | 231 memcpy(dest, source, bytes_to_copy); |
| 236 source += bytes_to_copy; | 232 source += bytes_to_copy; |
| 237 source_remaining -= bytes_to_copy; | 233 source_remaining -= bytes_to_copy; |
| 238 offset += bytes_to_copy; | 234 offset += bytes_to_copy; |
| 239 total_written += bytes_to_copy; | 235 total_written += bytes_to_copy; |
| 240 } | 236 } |
| 241 | 237 |
| 242 DCHECK_GT(total_written, 0u); | 238 DCHECK_GT(total_written, 0u); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 while (dest_remaining > 0 && ReadableBytes() > 0) { | 289 while (dest_remaining > 0 && ReadableBytes() > 0) { |
| 294 size_t block_idx = NextBlockToRead(); | 290 size_t block_idx = NextBlockToRead(); |
| 295 size_t start_offset_in_block = ReadOffset(); | 291 size_t start_offset_in_block = ReadOffset(); |
| 296 size_t block_capacity = GetBlockCapacity(block_idx); | 292 size_t block_capacity = GetBlockCapacity(block_idx); |
| 297 size_t bytes_available_in_block = std::min<size_t>( | 293 size_t bytes_available_in_block = std::min<size_t>( |
| 298 ReadableBytes(), block_capacity - start_offset_in_block); | 294 ReadableBytes(), block_capacity - start_offset_in_block); |
| 299 size_t bytes_to_copy = | 295 size_t bytes_to_copy = |
| 300 std::min<size_t>(bytes_available_in_block, dest_remaining); | 296 std::min<size_t>(bytes_available_in_block, dest_remaining); |
| 301 DCHECK_GT(bytes_to_copy, 0UL); | 297 DCHECK_GT(bytes_to_copy, 0UL); |
| 302 if (blocks_[block_idx] == nullptr || dest == nullptr) { | 298 if (blocks_[block_idx] == nullptr || dest == nullptr) { |
| 303 *error_details = StringPrintf( | 299 *error_details = QuicStrCat( |
| 304 "QuicStreamSequencerBuffer error:" | 300 "QuicStreamSequencerBuffer error:" |
| 305 " Readv() dest == nullptr: %s" | 301 " Readv() dest == nullptr: ", |
| 306 " blocks_[%" PRIuS "] == nullptr: %s", | 302 (dest == nullptr), " blocks_[", block_idx, "] == nullptr: ", |
| 307 (dest == nullptr ? "true" : "false"), block_idx, | 303 (blocks_[block_idx] == nullptr), " Gaps: ", GapsDebugString(), |
| 308 (blocks_[block_idx] == nullptr ? "true" : "false")); | 304 " Remaining frames: ", ReceivedFramesDebugString(), |
| 305 " total_bytes_read_ = ", total_bytes_read_); |
| 309 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 306 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
| 310 } | 307 } |
| 311 memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, | 308 memcpy(dest, blocks_[block_idx]->buffer + start_offset_in_block, |
| 312 bytes_to_copy); | 309 bytes_to_copy); |
| 313 dest += bytes_to_copy; | 310 dest += bytes_to_copy; |
| 314 dest_remaining -= bytes_to_copy; | 311 dest_remaining -= bytes_to_copy; |
| 315 num_bytes_buffered_ -= bytes_to_copy; | 312 num_bytes_buffered_ -= bytes_to_copy; |
| 316 total_bytes_read_ += bytes_to_copy; | 313 total_bytes_read_ += bytes_to_copy; |
| 317 *bytes_read += bytes_to_copy; | 314 *bytes_read += bytes_to_copy; |
| 318 | 315 |
| 319 // Retire the block if all the data is read out and no other data is | 316 // Retire the block if all the data is read out and no other data is |
| 320 // stored in this block. | 317 // stored in this block. |
| 321 // In case of failing to retire a block which is ready to retire, return | 318 // In case of failing to retire a block which is ready to retire, return |
| 322 // immediately. | 319 // immediately. |
| 323 if (bytes_to_copy == bytes_available_in_block) { | 320 if (bytes_to_copy == bytes_available_in_block) { |
| 324 bool retire_successfully = RetireBlockIfEmpty(block_idx); | 321 bool retire_successfully = RetireBlockIfEmpty(block_idx); |
| 325 if (!retire_successfully) { | 322 if (!retire_successfully) { |
| 326 *error_details = StringPrintf( | 323 *error_details = QuicStrCat( |
| 327 "QuicStreamSequencerBuffer error: fail to retire block %" PRIuS | 324 "QuicStreamSequencerBuffer error: fail to retire block ", |
| 328 " as the block is already released + total_bytes_read_ = %" PRIu64 | 325 block_idx, |
| 329 " Gaps: %s", | 326 " as the block is already released, total_bytes_read_ = ", |
| 330 block_idx, total_bytes_read_, GapsDebugString().c_str()); | 327 total_bytes_read_, " Gaps: ", GapsDebugString()); |
| 331 return QUIC_STREAM_SEQUENCER_INVALID_STATE; | 328 return QUIC_STREAM_SEQUENCER_INVALID_STATE; |
| 332 } | 329 } |
| 333 } | 330 } |
| 334 } | 331 } |
| 335 } | 332 } |
| 336 | 333 |
| 337 if (*bytes_read > 0) { | 334 if (*bytes_read > 0) { |
| 338 UpdateFrameArrivalMap(total_bytes_read_); | 335 UpdateFrameArrivalMap(total_bytes_read_); |
| 339 } | 336 } |
| 340 return QUIC_NO_ERROR; | 337 return QUIC_NO_ERROR; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 QuicStreamOffset current_frame_end_offset = | 602 QuicStreamOffset current_frame_end_offset = |
| 606 it.second.length + current_frame_begin_offset; | 603 it.second.length + current_frame_begin_offset; |
| 607 current_frames_string = string(StringPrintf( | 604 current_frames_string = string(StringPrintf( |
| 608 "%s[%" PRIu64 ", %" PRIu64 ") ", current_frames_string.c_str(), | 605 "%s[%" PRIu64 ", %" PRIu64 ") ", current_frames_string.c_str(), |
| 609 current_frame_begin_offset, current_frame_end_offset)); | 606 current_frame_begin_offset, current_frame_end_offset)); |
| 610 } | 607 } |
| 611 return current_frames_string; | 608 return current_frames_string; |
| 612 } | 609 } |
| 613 | 610 |
| 614 } // namespace net | 611 } // namespace net |
| OLD | NEW |