|  | // 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. | 
|  |  | 
|  | #ifndef QUICHE_QUIC_CORE_QPACK_QPACK_BLOCKING_MANAGER_H_ | 
|  | #define QUICHE_QUIC_CORE_QPACK_QPACK_BLOCKING_MANAGER_H_ | 
|  |  | 
|  | #include <cstdint> | 
|  | #include <map> | 
|  | #include <set> | 
|  |  | 
|  | #include "absl/container/flat_hash_map.h" | 
|  | #include "quic/core/quic_types.h" | 
|  | #include "quic/platform/api/quic_containers.h" | 
|  | #include "quic/platform/api/quic_export.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | namespace test { | 
|  |  | 
|  | class QpackBlockingManagerPeer; | 
|  |  | 
|  | }  // namespace test | 
|  |  | 
|  | // Class to keep track of blocked streams and blocking dynamic table entries: | 
|  | // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-decoding | 
|  | // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-insertion | 
|  | class QUIC_EXPORT_PRIVATE QpackBlockingManager { | 
|  | public: | 
|  | using IndexSet = std::multiset<uint64_t>; | 
|  |  | 
|  | QpackBlockingManager(); | 
|  |  | 
|  | // Called when a Header Acknowledgement instruction is received on the decoder | 
|  | // stream.  Returns false if there are no outstanding header blocks to be | 
|  | // acknowledged on |stream_id|. | 
|  | bool OnHeaderAcknowledgement(QuicStreamId stream_id); | 
|  |  | 
|  | // Called when a Stream Cancellation instruction is received on the decoder | 
|  | // stream. | 
|  | void OnStreamCancellation(QuicStreamId stream_id); | 
|  |  | 
|  | // Called when an Insert Count Increment instruction is received on the | 
|  | // decoder stream.  Returns true if Known Received Count is successfully | 
|  | // updated.  Returns false on overflow. | 
|  | bool OnInsertCountIncrement(uint64_t increment); | 
|  |  | 
|  | // Called when sending a header block containing references to dynamic table | 
|  | // entries with |indices|.  |indices| must not be empty. | 
|  | void OnHeaderBlockSent(QuicStreamId stream_id, IndexSet indices); | 
|  |  | 
|  | // Returns true if sending blocking references on stream |stream_id| would not | 
|  | // increase the total number of blocked streams above | 
|  | // |maximum_blocked_streams|.  Note that if |stream_id| is already blocked | 
|  | // then it is always allowed to send more blocking references on it. | 
|  | // Behavior is undefined if |maximum_blocked_streams| is smaller than number | 
|  | // of currently blocked streams. | 
|  | bool blocking_allowed_on_stream(QuicStreamId stream_id, | 
|  | uint64_t maximum_blocked_streams) const; | 
|  |  | 
|  | // Returns the index of the blocking entry with the smallest index, | 
|  | // or std::numeric_limits<uint64_t>::max() if there are no blocking entries. | 
|  | uint64_t smallest_blocking_index() const; | 
|  |  | 
|  | // Returns the Known Received Count as defined at | 
|  | // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#known-received-count. | 
|  | uint64_t known_received_count() const { return known_received_count_; } | 
|  |  | 
|  | // Required Insert Count for set of indices. | 
|  | static uint64_t RequiredInsertCount(const IndexSet& indices); | 
|  |  | 
|  | private: | 
|  | friend test::QpackBlockingManagerPeer; | 
|  |  | 
|  | // A stream typically has only one header block, except for the rare cases of | 
|  | // 1xx responses, trailers, or push promises.  Even if there are multiple | 
|  | // header blocks sent on a single stream, they might not be blocked at the | 
|  | // same time.  Use std::list instead of QuicCircularDeque because it has lower | 
|  | // memory footprint when holding few elements. | 
|  | using HeaderBlocksForStream = std::list<IndexSet>; | 
|  | using HeaderBlocks = absl::flat_hash_map<QuicStreamId, HeaderBlocksForStream>; | 
|  |  | 
|  | // Increase or decrease the reference count for each index in |indices|. | 
|  | void IncreaseReferenceCounts(const IndexSet& indices); | 
|  | void DecreaseReferenceCounts(const IndexSet& indices); | 
|  |  | 
|  | // Multiset of indices in each header block for each stream. | 
|  | // Must not contain a stream id with an empty queue. | 
|  | HeaderBlocks header_blocks_; | 
|  |  | 
|  | // Number of references in |header_blocks_| for each entry index. | 
|  | std::map<uint64_t, uint64_t> entry_reference_counts_; | 
|  |  | 
|  | uint64_t known_received_count_; | 
|  | }; | 
|  |  | 
|  | }  // namespace quic | 
|  |  | 
|  | #endif  // QUICHE_QUIC_CORE_QPACK_QPACK_BLOCKING_MANAGER_H_ |