hpack_parser_table.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
22 
23 #include <stdlib.h>
24 
25 #include <algorithm>
26 #include <cstddef>
27 #include <cstring>
28 #include <utility>
29 
30 #include "absl/strings/str_format.h"
31 #include "absl/strings/string_view.h"
32 
33 #include <grpc/support/log.h>
34 
38 
40 
41 namespace grpc_core {
42 
45  if (entries_.size() < max_entries_) {
46  ++num_entries_;
47  return entries_.push_back(std::move(m));
48  }
51  ++num_entries_;
52 }
53 
55  GPR_ASSERT(num_entries_ > 0);
56  size_t index = first_entry_ % max_entries_;
57  ++first_entry_;
58  --num_entries_;
59  return std::move(entries_[index]);
60 }
61 
63  -> const Memento* {
64  if (index >= num_entries_) return nullptr;
65  uint32_t offset = (num_entries_ - 1u - index + first_entry_) % max_entries_;
66  return &entries_[offset];
67 }
68 
70  if (max_entries == max_entries_) return;
71  std::vector<Memento> entries;
72  entries.reserve(num_entries_);
73  for (size_t i = 0; i < num_entries_; i++) {
74  entries.push_back(
75  std::move(entries_[(first_entry_ + i) % entries_.size()]));
76  }
77  first_entry_ = 0;
78  entries_.swap(entries);
79 }
80 
82 
83 HPackTable::~HPackTable() = default;
84 
85 /* Evict one element from the table */
87  auto first_entry = entries_.PopOne();
88  GPR_ASSERT(first_entry.transport_size() <= mem_used_);
89  mem_used_ -= first_entry.transport_size();
90 }
91 
93  if (max_bytes_ == max_bytes) {
94  return;
95  }
97  gpr_log(GPR_INFO, "Update hpack parser max size to %d", max_bytes);
98  }
99  while (mem_used_ > max_bytes) {
100  EvictOne();
101  }
102  max_bytes_ = max_bytes;
103 }
104 
106  if (current_table_bytes_ == bytes) {
107  return GRPC_ERROR_NONE;
108  }
109  if (bytes > max_bytes_) {
111  "Attempt to make hpack table %d bytes when max is %d bytes", bytes,
112  max_bytes_));
113  }
115  gpr_log(GPR_INFO, "Update hpack parser table size to %d", bytes);
116  }
117  while (mem_used_ > bytes) {
118  EvictOne();
119  }
123  entries_.Rebuild(new_cap);
124  return GRPC_ERROR_NONE;
125 }
126 
130  "HPACK max table size reduced to %d but not reflected by hpack "
131  "stream (still at %d)",
133  }
134 
135  // we can't add elements bigger than the max table size
136  if (md.transport_size() > current_table_bytes_) {
137  // HPACK draft 10 section 4.4 states:
138  // If the size of the new entry is less than or equal to the maximum
139  // size, that entry is added to the table. It is not an error to
140  // attempt to add an entry that is larger than the maximum size; an
141  // attempt to add an entry larger than the entire table causes
142  // the table to be emptied of all existing entries, and results in an
143  // empty table.
144  while (entries_.num_entries()) {
145  EvictOne();
146  }
147  return GRPC_ERROR_NONE;
148  }
149 
150  // evict entries to ensure no overflow
151  while (md.transport_size() >
152  static_cast<size_t>(current_table_bytes_) - mem_used_) {
153  EvictOne();
154  }
155 
156  // copy the finalized entry in
157  mem_used_ += md.transport_size();
159  return GRPC_ERROR_NONE;
160 }
161 
162 namespace {
163 struct StaticTableEntry {
164  const char* key;
165  const char* value;
166 };
167 
168 const StaticTableEntry kStaticTable[hpack_constants::kLastStaticEntry] = {
169  {":authority", ""},
170  {":method", "GET"},
171  {":method", "POST"},
172  {":path", "/"},
173  {":path", "/index.html"},
174  {":scheme", "http"},
175  {":scheme", "https"},
176  {":status", "200"},
177  {":status", "204"},
178  {":status", "206"},
179  {":status", "304"},
180  {":status", "400"},
181  {":status", "404"},
182  {":status", "500"},
183  {"accept-charset", ""},
184  {"accept-encoding", "gzip, deflate"},
185  {"accept-language", ""},
186  {"accept-ranges", ""},
187  {"accept", ""},
188  {"access-control-allow-origin", ""},
189  {"age", ""},
190  {"allow", ""},
191  {"authorization", ""},
192  {"cache-control", ""},
193  {"content-disposition", ""},
194  {"content-encoding", ""},
195  {"content-language", ""},
196  {"content-length", ""},
197  {"content-location", ""},
198  {"content-range", ""},
199  {"content-type", ""},
200  {"cookie", ""},
201  {"date", ""},
202  {"etag", ""},
203  {"expect", ""},
204  {"expires", ""},
205  {"from", ""},
206  {"host", ""},
207  {"if-match", ""},
208  {"if-modified-since", ""},
209  {"if-none-match", ""},
210  {"if-range", ""},
211  {"if-unmodified-since", ""},
212  {"last-modified", ""},
213  {"link", ""},
214  {"location", ""},
215  {"max-forwards", ""},
216  {"proxy-authenticate", ""},
217  {"proxy-authorization", ""},
218  {"range", ""},
219  {"referer", ""},
220  {"refresh", ""},
221  {"retry-after", ""},
222  {"server", ""},
223  {"set-cookie", ""},
224  {"strict-transport-security", ""},
225  {"transfer-encoding", ""},
226  {"user-agent", ""},
227  {"vary", ""},
228  {"via", ""},
229  {"www-authenticate", ""},
230 };
231 
232 GPR_ATTRIBUTE_NOINLINE HPackTable::Memento MakeMemento(size_t i) {
233  auto sm = kStaticTable[i];
235  sm.key, Slice::FromStaticString(sm.value),
236  strlen(sm.key) + strlen(sm.value) + hpack_constants::kEntryOverhead,
237  [](absl::string_view, const Slice&) {
238  abort(); // not expecting to see this
239  });
240 }
241 
242 } // namespace
243 
245  static const StaticMementos* const static_mementos = new StaticMementos();
246  return *static_mementos;
247 }
248 
251  memento[i] = MakeMemento(i);
252  }
253 }
254 
255 } // namespace grpc_core
trace.h
slice.h
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
grpc_core::HPackTable::MementoRingBuffer::first_entry_
uint32_t first_entry_
Definition: hpack_parser_table.h:99
grpc_core::HPackTable::MementoRingBuffer::PopOne
Memento PopOne()
Definition: hpack_parser_table.cc:54
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
grpc_core::MetadataMap::Parse
static ParsedMetadata< Derived > Parse(absl::string_view key, Slice value, uint32_t transport_size, MetadataParseErrorFn on_error)
Definition: metadata_batch.h:1142
absl::StrFormat
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:338
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::slice_detail::StaticConstructors< Slice >::FromStaticString
static Slice FromStaticString(const char *s)
Definition: src/core/lib/slice/slice.h:201
grpc_core::HPackTable::MementoRingBuffer::Rebuild
void Rebuild(uint32_t max_entries)
Definition: hpack_parser_table.cc:69
grpc_core::HPackTable::HPackTable
HPackTable()
Definition: hpack_parser_table.cc:81
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
grpc_core::HPackTable::MementoRingBuffer::Lookup
const Memento * Lookup(uint32_t index) const
Definition: hpack_parser_table.cc:62
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
grpc_core::hpack_constants::EntriesForBytes
static constexpr uint32_t EntriesForBytes(uint32_t bytes) noexcept
Definition: hpack_constants.h:32
grpc_core::HPackTable::MementoRingBuffer::entries_
std::vector< Memento > entries_
Definition: hpack_parser_table.h:106
grpc_core::HPackTable::mem_used_
uint32_t mem_used_
Definition: hpack_parser_table.h:118
GRPC_TRACE_FLAG_ENABLED
#define GRPC_TRACE_FLAG_ENABLED(f)
Definition: debug/trace.h:114
grpc_core::HPackTable::current_table_bytes_
uint32_t current_table_bytes_
Definition: hpack_parser_table.h:123
grpc_core::HPackTable::Memento
ParsedMetadata< grpc_metadata_batch > Memento
Definition: hpack_parser_table.h:47
grpc_core::HPackTable::StaticMementos
Definition: hpack_parser_table.h:71
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
grpc_core::HPackTable::MementoRingBuffer::max_entries_
uint32_t max_entries_
Definition: hpack_parser_table.h:104
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
grpc_core::HPackTable::max_bytes_
uint32_t max_bytes_
Definition: hpack_parser_table.h:121
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
grpc_core::HPackTable::Add
grpc_error_handle Add(Memento md) GRPC_MUST_USE_RESULT
Definition: hpack_parser_table.cc:127
grpc_core::HPackTable::EvictOne
void EvictOne()
Definition: hpack_parser_table.cc:86
grpc_core::HPackTable::GetStaticMementos
static const StaticMementos & GetStaticMementos() GPR_ATTRIBUTE_NOINLINE
Definition: hpack_parser_table.cc:244
grpc_core::hpack_constants::kEntryOverhead
static constexpr uint32_t kEntryOverhead
Definition: hpack_constants.h:25
grpc_core::HPackTable::~HPackTable
~HPackTable()
grpc_core::HPackTable::entries_
MementoRingBuffer entries_
Definition: hpack_parser_table.h:125
grpc_core::ParsedMetadata< grpc_metadata_batch >
grpc_core::TraceFlag
Definition: debug/trace.h:63
grpc_core::hpack_constants::kInitialTableEntries
static constexpr uint32_t kInitialTableEntries
Definition: hpack_constants.h:36
grpc_core::hpack_constants::kLastStaticEntry
static constexpr uint32_t kLastStaticEntry
Definition: hpack_constants.h:30
value
const char * value
Definition: hpack_parser_table.cc:165
grpc_core::HPackTable::static_metadata_
const StaticMementos & static_metadata_
Definition: hpack_parser_table.h:127
grpc_core::HPackTable::StaticMementos::StaticMementos
StaticMementos()
Definition: hpack_parser_table.cc:249
grpc_core::HPackTable::MementoRingBuffer::num_entries_
uint32_t num_entries_
Definition: hpack_parser_table.h:101
hpack_parser_table.h
benchmark.md
md
Definition: benchmark.py:86
key
const char * key
Definition: hpack_parser_table.cc:164
bytes
uint8 bytes[10]
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:153
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
GRPC_ERROR_CREATE_FROM_CPP_STRING
#define GRPC_ERROR_CREATE_FROM_CPP_STRING(desc)
Definition: error.h:297
grpc_core::HPackTable::SetCurrentTableSize
grpc_error_handle SetCurrentTableSize(uint32_t bytes)
Definition: hpack_parser_table.cc:105
hpack_constants.h
grpc_core::HPackTable::MementoRingBuffer::num_entries
uint32_t num_entries() const
Definition: hpack_parser_table.h:94
grpc_http_trace
grpc_core::TraceFlag grpc_http_trace
grpc_core::HPackTable::MementoRingBuffer::Put
void Put(Memento m)
Definition: hpack_parser_table.cc:43
grpc_core::HPackTable::SetMaxBytes
void SetMaxBytes(uint32_t max_bytes)
Definition: hpack_parser_table.cc:92
grpc_error
Definition: error_internal.h:42
regress.m
m
Definition: regress/regress.py:25
grpc_core::HPackTable::StaticMementos::memento
Memento memento[hpack_constants::kLastStaticEntry]
Definition: hpack_parser_table.h:73
GPR_ATTRIBUTE_NOINLINE
#define GPR_ATTRIBUTE_NOINLINE
Definition: impl/codegen/port_platform.h:684
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:13