1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_TABLE_H
16 #define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_TABLE_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include <limits>
24 
25 #include "absl/container/inlined_vector.h"
26 
27 #include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
28 
29 namespace grpc_core {
30 
31 // Tracks the values available in the remote HPACK header table, and their
32 // sizes.
33 class HPackEncoderTable {
34  public:
35   using EntrySize = uint16_t;
36 
HPackEncoderTable()37   HPackEncoderTable() : elem_size_(hpack_constants::kInitialTableEntries) {}
38 
MaxEntrySize()39   static constexpr size_t MaxEntrySize() {
40     return std::numeric_limits<EntrySize>::max();
41   }
42 
43   // Reserve space in table for the new element, evict entries if needed.
44   // Return the new index of the element. Return 0 to indicate not adding to
45   // table.
46   uint32_t AllocateIndex(size_t element_size);
47   // Set the maximum table size. Return true if it changed.
48   bool SetMaxSize(uint32_t max_table_size);
49   // Get the current max table size
max_size()50   uint32_t max_size() const { return max_table_size_; }
51   // Get the current table size
test_only_table_size()52   uint32_t test_only_table_size() const { return table_size_; }
53   // Get the number of entries in the table
test_only_table_elems()54   uint32_t test_only_table_elems() const { return table_elems_; }
55 
56   // Convert an element index into a dynamic index
DynamicIndex(uint32_t index)57   uint32_t DynamicIndex(uint32_t index) const {
58     return 1 + hpack_constants::kLastStaticEntry + tail_remote_index_ +
59            table_elems_ - index;
60   }
61   // Check if an element index is convertable to a dynamic index
ConvertableToDynamicIndex(uint32_t index)62   bool ConvertableToDynamicIndex(uint32_t index) const {
63     return index > tail_remote_index_;
64   }
65 
66  private:
67   void EvictOne();
68   void Rebuild(uint32_t capacity);
69 
70   // one before the lowest usable table index
71   uint32_t tail_remote_index_ = 0;
72   uint32_t max_table_size_ = hpack_constants::kInitialTableSize;
73   uint32_t table_elems_ = 0;
74   uint32_t table_size_ = 0;
75   // The size of each element in the HPACK table.
76   absl::InlinedVector<EntrySize, hpack_constants::kInitialTableEntries>
77       elem_size_;
78 };
79 
80 }  // namespace grpc_core
81 
82 #endif  // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_TABLE_H
83