| // 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 "quiche/quic/core/quic_types.h" |
| #include "quiche/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 quiche::QuicheCircularDeque 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_ |