blob: e8e4f879d8bb7928417951adb7538127806ffd7e [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h"
#include <utility>
namespace quic {
QpackBlockingManager::QpackBlockingManager() : known_received_count_(0) {}
bool QpackBlockingManager::OnHeaderAcknowledgement(QuicStreamId stream_id) {
auto it = header_blocks_.find(stream_id);
if (it == header_blocks_.end()) {
return false;
}
DCHECK(!it->second.empty());
const IndexSet& indices = it->second.front();
DCHECK(!indices.empty());
const uint64_t required_index_count = RequiredInsertCount(indices);
if (known_received_count_ < required_index_count) {
known_received_count_ = required_index_count;
}
DecreaseReferenceCounts(indices);
it->second.pop_front();
if (it->second.empty()) {
header_blocks_.erase(it);
}
return true;
}
void QpackBlockingManager::OnStreamCancellation(QuicStreamId stream_id) {
auto it = header_blocks_.find(stream_id);
if (it == header_blocks_.end()) {
return;
}
for (const IndexSet& indices : it->second) {
DecreaseReferenceCounts(indices);
}
header_blocks_.erase(it);
}
void QpackBlockingManager::OnInsertCountIncrement(uint64_t increment) {
known_received_count_ += increment;
}
void QpackBlockingManager::OnHeaderBlockSent(QuicStreamId stream_id,
IndexSet indices) {
DCHECK(!indices.empty());
IncreaseReferenceCounts(indices);
header_blocks_[stream_id].push_back(std::move(indices));
}
uint64_t QpackBlockingManager::blocked_stream_count() const {
uint64_t blocked_stream_count = 0;
for (const auto& header_blocks_for_stream : header_blocks_) {
for (const IndexSet& indices : header_blocks_for_stream.second) {
if (RequiredInsertCount(indices) > known_received_count_) {
++blocked_stream_count;
break;
}
}
}
return blocked_stream_count;
}
uint64_t QpackBlockingManager::smallest_blocking_index() const {
return entry_reference_counts_.empty()
? std::numeric_limits<uint64_t>::max()
: entry_reference_counts_.begin()->first;
}
// static
uint64_t QpackBlockingManager::RequiredInsertCount(const IndexSet& indices) {
return *indices.rbegin() + 1;
}
void QpackBlockingManager::IncreaseReferenceCounts(const IndexSet& indices) {
for (const uint64_t index : indices) {
auto it = entry_reference_counts_.lower_bound(index);
if (it != entry_reference_counts_.end() && it->first == index) {
++it->second;
} else {
entry_reference_counts_.insert(it, {index, 1});
}
}
}
void QpackBlockingManager::DecreaseReferenceCounts(const IndexSet& indices) {
for (const uint64_t index : indices) {
auto it = entry_reference_counts_.find(index);
DCHECK(it != entry_reference_counts_.end());
DCHECK_NE(0u, it->second);
if (it->second == 1) {
entry_reference_counts_.erase(it);
} else {
--it->second;
}
}
}
} // namespace quic