blob: 04d824fa96990b7a652aef1fc03a5e6542108689 [file] [log] [blame]
bncbdf981f2019-07-30 17:21:14 -07001// Copyright (c) 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h"
6
7#include <utility>
8
9namespace quic {
10
11QpackBlockingManager::QpackBlockingManager() : known_received_count_(0) {}
12
13bool QpackBlockingManager::OnHeaderAcknowledgement(QuicStreamId stream_id) {
14 auto it = header_blocks_.find(stream_id);
15 if (it == header_blocks_.end()) {
16 return false;
17 }
18
19 DCHECK(!it->second.empty());
20
21 const IndexSet& indices = it->second.front();
22 DCHECK(!indices.empty());
23
24 const uint64_t required_index_count = RequiredInsertCount(indices);
25 if (known_received_count_ < required_index_count) {
bnc6b2cf772019-08-13 05:19:21 -070026 IncreaseKnownReceivedCountTo(required_index_count);
bncbdf981f2019-07-30 17:21:14 -070027 }
28
29 DecreaseReferenceCounts(indices);
30
31 it->second.pop_front();
32 if (it->second.empty()) {
33 header_blocks_.erase(it);
34 }
35
36 return true;
37}
38
39void QpackBlockingManager::OnStreamCancellation(QuicStreamId stream_id) {
40 auto it = header_blocks_.find(stream_id);
41 if (it == header_blocks_.end()) {
42 return;
43 }
44
45 for (const IndexSet& indices : it->second) {
46 DecreaseReferenceCounts(indices);
47 }
48
49 header_blocks_.erase(it);
50}
51
52void QpackBlockingManager::OnInsertCountIncrement(uint64_t increment) {
bnc6b2cf772019-08-13 05:19:21 -070053 IncreaseKnownReceivedCountTo(known_received_count_ + increment);
bncbdf981f2019-07-30 17:21:14 -070054}
55
56void QpackBlockingManager::OnHeaderBlockSent(QuicStreamId stream_id,
57 IndexSet indices) {
58 DCHECK(!indices.empty());
59
60 IncreaseReferenceCounts(indices);
61 header_blocks_[stream_id].push_back(std::move(indices));
62}
63
bnc6b2cf772019-08-13 05:19:21 -070064void QpackBlockingManager::OnReferenceSentOnEncoderStream(
65 uint64_t inserted_index,
66 uint64_t referred_index) {
67 auto result = unacked_encoder_stream_references_.insert(
68 {inserted_index, referred_index});
69 // Each dynamic table entry can refer to at most one |referred_index|.
70 DCHECK(result.second);
71 IncreaseReferenceCounts({referred_index});
72}
73
bncbdf981f2019-07-30 17:21:14 -070074uint64_t QpackBlockingManager::blocked_stream_count() const {
75 uint64_t blocked_stream_count = 0;
76 for (const auto& header_blocks_for_stream : header_blocks_) {
77 for (const IndexSet& indices : header_blocks_for_stream.second) {
78 if (RequiredInsertCount(indices) > known_received_count_) {
79 ++blocked_stream_count;
80 break;
81 }
82 }
83 }
84
85 return blocked_stream_count;
86}
87
88uint64_t QpackBlockingManager::smallest_blocking_index() const {
89 return entry_reference_counts_.empty()
90 ? std::numeric_limits<uint64_t>::max()
91 : entry_reference_counts_.begin()->first;
92}
93
94// static
95uint64_t QpackBlockingManager::RequiredInsertCount(const IndexSet& indices) {
96 return *indices.rbegin() + 1;
97}
98
bnc6b2cf772019-08-13 05:19:21 -070099void QpackBlockingManager::IncreaseKnownReceivedCountTo(
100 uint64_t new_known_received_count) {
101 DCHECK_GT(new_known_received_count, known_received_count_);
102
103 known_received_count_ = new_known_received_count;
104
105 // Remove referred indices with key less than new Known Received Count from
106 // |unacked_encoder_stream_references_| and |entry_reference_counts_|.
107 IndexSet acknowledged_references;
108 auto it = unacked_encoder_stream_references_.begin();
109 while (it != unacked_encoder_stream_references_.end() &&
110 it->first < known_received_count_) {
111 acknowledged_references.insert(it->second);
112 ++it;
113 }
114 unacked_encoder_stream_references_.erase(
115 unacked_encoder_stream_references_.begin(), it);
116 DecreaseReferenceCounts(acknowledged_references);
117}
118
bncbdf981f2019-07-30 17:21:14 -0700119void QpackBlockingManager::IncreaseReferenceCounts(const IndexSet& indices) {
120 for (const uint64_t index : indices) {
121 auto it = entry_reference_counts_.lower_bound(index);
122 if (it != entry_reference_counts_.end() && it->first == index) {
123 ++it->second;
124 } else {
125 entry_reference_counts_.insert(it, {index, 1});
126 }
127 }
128}
129
130void QpackBlockingManager::DecreaseReferenceCounts(const IndexSet& indices) {
131 for (const uint64_t index : indices) {
132 auto it = entry_reference_counts_.find(index);
133 DCHECK(it != entry_reference_counts_.end());
134 DCHECK_NE(0u, it->second);
135
136 if (it->second == 1) {
137 entry_reference_counts_.erase(it);
138 } else {
139 --it->second;
140 }
141 }
142}
143
144} // namespace quic