#include <limits>
#include "base/logging.h"
+#include "base/metrics/sparse_histogram.h"
#include "net/quic/reliable_quic_stream.h"
using std::min;
QuicStreamSequencer::QuicStreamSequencer(ReliableQuicStream* quic_stream)
: stream_(quic_stream),
num_bytes_consumed_(0),
- max_frame_memory_(numeric_limits<size_t>::max()),
close_offset_(numeric_limits<QuicStreamOffset>::max()),
blocked_(false),
- num_bytes_buffered_(0) {
-}
-
-QuicStreamSequencer::QuicStreamSequencer(size_t max_frame_memory,
- ReliableQuicStream* quic_stream)
- : stream_(quic_stream),
- num_bytes_consumed_(0),
- max_frame_memory_(max_frame_memory),
- close_offset_(numeric_limits<QuicStreamOffset>::max()),
- blocked_(false),
- num_bytes_buffered_(0) {
- if (max_frame_memory < kMaxPacketSize) {
- LOG(DFATAL) << "Setting max frame memory to " << max_frame_memory
- << ". Some frames will be impossible to handle.";
- }
+ num_bytes_buffered_(0),
+ num_frames_received_(0),
+ num_duplicate_frames_received_(0) {
}
QuicStreamSequencer::~QuicStreamSequencer() {
}
-bool QuicStreamSequencer::WillAcceptStreamFrame(
- const QuicStreamFrame& frame) const {
- size_t data_len = frame.data.TotalBufferSize();
- if (data_len > max_frame_memory_) {
- LOG(DFATAL) << "data_len: " << data_len << " > max_frame_memory_: "
- << max_frame_memory_;
- return false;
- }
-
- if (IsDuplicate(frame)) {
- return true;
- }
- QuicStreamOffset byte_offset = frame.offset;
- if (data_len > max_frame_memory_) {
- // We're never going to buffer this frame and we can't pass it up.
- // The stream might only consume part of it and we'd need a partial ack.
- //
- // Ideally this should never happen, as we check that
- // max_frame_memory_ > kMaxPacketSize and lower levels should reject
- // frames larger than that.
- return false;
- }
- if (byte_offset + data_len - num_bytes_consumed_ > max_frame_memory_) {
- // We can buffer this but not right now. Toss it.
- // It might be worth trying an experiment where we try best-effort buffering
- return false;
- }
- return true;
-}
-
bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
- if (!WillAcceptStreamFrame(frame)) {
- // This should not happen, as WillAcceptFrame should be called before
- // OnStreamFrame. Error handling should be done by the caller.
- return false;
- }
+ ++num_frames_received_;
if (IsDuplicate(frame)) {
+ ++num_duplicate_frames_received_;
// Silently ignore duplicates.
return true;
}
data.iovec()[i].iov_len);
}
num_bytes_consumed_ += bytes_consumed;
+ stream_->AddBytesConsumed(bytes_consumed);
+ stream_->MaybeSendWindowUpdate();
+
if (MaybeCloseStream()) {
return true;
}
byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len)));
byte_offset += iov.iov_len;
num_bytes_buffered_ += iov.iov_len;
+ stream_->AddBytesBuffered(iov.iov_len);
}
return true;
}
return num_bytes_consumed_ - initial_bytes_consumed;
}
-void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) {
- DCHECK(!blocked_);
- size_t end_offset = num_bytes_consumed_ + num_bytes_consumed;
- while (!frames_.empty() && end_offset != num_bytes_consumed_) {
- FrameMap::iterator it = frames_.begin();
- if (it->first != num_bytes_consumed_) {
- LOG(DFATAL) << "Invalid argument to MarkConsumed. "
- << " num_bytes_consumed_: " << num_bytes_consumed_
- << " end_offset: " << end_offset
- << " offset: " << it->first
- << " length: " << it->second.length();
- stream_->Reset(QUIC_ERROR_PROCESSING_STREAM);
- return;
- }
-
- if (it->first + it->second.length() <= end_offset) {
- num_bytes_consumed_ += it->second.length();
- num_bytes_buffered_ -= it->second.length();
- // This chunk is entirely consumed.
- frames_.erase(it);
- continue;
- }
-
- // Partially consume this frame.
- size_t delta = end_offset - it->first;
- RecordBytesConsumed(delta);
- frames_.insert(make_pair(end_offset, it->second.substr(delta)));
- frames_.erase(it);
- break;
- }
-}
-
bool QuicStreamSequencer::HasBytesToRead() const {
FrameMap::const_iterator it = frames_.begin();
void QuicStreamSequencer::RecordBytesConsumed(size_t bytes_consumed) {
num_bytes_consumed_ += bytes_consumed;
num_bytes_buffered_ -= bytes_consumed;
+
+ stream_->AddBytesConsumed(bytes_consumed);
+ stream_->RemoveBytesBuffered(bytes_consumed);
+ stream_->MaybeSendWindowUpdate();
}
} // namespace net