aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ext/transport/chttp2/transport/hpack_encoder.cc')
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.cc329
1 files changed, 187 insertions, 142 deletions
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
index 60cd8d9400..e225a0244a 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
@@ -70,15 +70,15 @@ typedef struct {
uint8_t seen_regular_header;
/* output stream id */
uint32_t stream_id;
- grpc_slice_buffer *output;
- grpc_transport_one_way_stats *stats;
+ grpc_slice_buffer* output;
+ grpc_transport_one_way_stats* stats;
/* maximum size of a frame */
size_t max_frame_size;
bool use_true_binary_metadata;
} framer_state;
/* fills p (which is expected to be 9 bytes long) with a data frame header */
-static void fill_header(uint8_t *p, uint8_t type, uint32_t id, size_t len,
+static void fill_header(uint8_t* p, uint8_t type, uint32_t id, size_t len,
uint8_t flags) {
GPR_ASSERT(len < 16777316);
*p++ = (uint8_t)(len >> 16);
@@ -93,7 +93,7 @@ static void fill_header(uint8_t *p, uint8_t type, uint32_t id, size_t len,
}
/* finish a frame - fill in the previously reserved header */
-static void finish_frame(framer_state *st, int is_header_boundary,
+static void finish_frame(framer_state* st, int is_header_boundary,
int is_last_in_stream) {
uint8_t type = 0xff;
type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
@@ -109,7 +109,7 @@ static void finish_frame(framer_state *st, int is_header_boundary,
/* begin a new frame: reserve off header space, remember how many bytes we'd
output before beginning */
-static void begin_frame(framer_state *st) {
+static void begin_frame(framer_state* st) {
st->header_idx =
grpc_slice_buffer_add_indexed(st->output, GRPC_SLICE_MALLOC(9));
st->output_length_at_start_of_frame = st->output->length;
@@ -118,7 +118,7 @@ static void begin_frame(framer_state *st) {
/* make sure that the current frame is of the type desired, and has sufficient
space to add at least about_to_add bytes -- finishes the current frame if
needed */
-static void ensure_space(framer_state *st, size_t need_bytes) {
+static void ensure_space(framer_state* st, size_t need_bytes) {
if (st->output->length - st->output_length_at_start_of_frame + need_bytes <=
st->max_frame_size) {
return;
@@ -128,7 +128,7 @@ static void ensure_space(framer_state *st, size_t need_bytes) {
}
/* increment a filter count, halve all counts if one element reaches max */
-static void inc_filter(uint8_t idx, uint32_t *sum, uint8_t *elems) {
+static void inc_filter(uint8_t idx, uint32_t* sum, uint8_t* elems) {
elems[idx]++;
if (elems[idx] < 255) {
(*sum)++;
@@ -142,7 +142,7 @@ static void inc_filter(uint8_t idx, uint32_t *sum, uint8_t *elems) {
}
}
-static void add_header_data(framer_state *st, grpc_slice slice) {
+static void add_header_data(framer_state* st, grpc_slice slice) {
size_t len = GRPC_SLICE_LENGTH(slice);
size_t remaining;
if (len == 0) return;
@@ -160,13 +160,13 @@ static void add_header_data(framer_state *st, grpc_slice slice) {
}
}
-static uint8_t *add_tiny_header_data(framer_state *st, size_t len) {
+static uint8_t* add_tiny_header_data(framer_state* st, size_t len) {
ensure_space(st, len);
st->stats->header_bytes += len;
return grpc_slice_buffer_tiny_add(st->output, len);
}
-static void evict_entry(grpc_chttp2_hpack_compressor *c) {
+static void evict_entry(grpc_chttp2_hpack_compressor* c) {
c->tail_remote_index++;
GPR_ASSERT(c->tail_remote_index > 0);
GPR_ASSERT(c->table_size >=
@@ -178,23 +178,19 @@ static void evict_entry(grpc_chttp2_hpack_compressor *c) {
c->table_elems--;
}
-/* add an element to the decoder table */
-static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem) {
- GPR_ASSERT(GRPC_MDELEM_IS_INTERNED(elem));
-
- uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
- uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
- uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
+// Reserve space in table for the new element, evict entries if needed.
+// Return the new index of the element. Return 0 to indicate not adding to
+// table.
+static uint32_t prepare_space_for_new_elem(grpc_chttp2_hpack_compressor* c,
+ size_t elem_size) {
uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
- size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
-
GPR_ASSERT(elem_size < 65536);
if (elem_size > c->max_table_size) {
while (c->table_size > 0) {
evict_entry(c);
}
- return;
+ return 0;
}
/* Reserve space for this element in the remote table: if this overflows
@@ -208,37 +204,24 @@ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem) {
c->table_size = (uint16_t)(c->table_size + elem_size);
c->table_elems++;
- /* Store this element into {entries,indices}_elem */
- if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) {
- /* already there: update with new index */
- c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
- } else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)],
- elem)) {
- /* already there (cuckoo): update with new index */
- c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
- } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) {
- /* not there, but a free element: add */
- c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
- c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
- } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) {
- /* not there (cuckoo), but a free element: add */
- c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
- c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
- } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] <
- c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) {
- /* not there: replace oldest */
- GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_2(elem_hash)]);
- c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
- c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
- } else {
- /* not there: replace oldest */
- GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_3(elem_hash)]);
- c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
- c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+ return new_index;
+}
+
+/* dummy function */
+static void add_nothing(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
+ size_t elem_size) {}
+
+// Add a key to the dynamic table. Both key and value will be added to table at
+// the decoder.
+static void add_key_with_index(grpc_chttp2_hpack_compressor* c,
+ grpc_mdelem elem, uint32_t new_index) {
+ if (new_index == 0) {
+ return;
}
- /* do exactly the same for the key (so we can find by that again too) */
+ uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
+ /* Store the key into {entries,indices}_keys */
if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
GRPC_MDKEY(elem))) {
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
@@ -269,8 +252,64 @@ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem) {
}
}
-static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
- framer_state *st) {
+/* add an element to the decoder table */
+static void add_elem_with_index(grpc_chttp2_hpack_compressor* c,
+ grpc_mdelem elem, uint32_t new_index) {
+ if (new_index == 0) {
+ return;
+ }
+ GPR_ASSERT(GRPC_MDELEM_IS_INTERNED(elem));
+
+ uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
+ uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
+ uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
+
+ /* Store this element into {entries,indices}_elem */
+ if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) {
+ /* already there: update with new index */
+ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+ } else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)],
+ elem)) {
+ /* already there (cuckoo): update with new index */
+ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+ } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) {
+ /* not there, but a free element: add */
+ c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
+ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+ } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) {
+ /* not there (cuckoo), but a free element: add */
+ c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
+ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+ } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] <
+ c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) {
+ /* not there: replace oldest */
+ GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_2(elem_hash)]);
+ c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
+ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+ } else {
+ /* not there: replace oldest */
+ GRPC_MDELEM_UNREF(c->entries_elems[HASH_FRAGMENT_3(elem_hash)]);
+ c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
+ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+ }
+
+ add_key_with_index(c, elem, new_index);
+}
+
+static void add_elem(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
+ size_t elem_size) {
+ uint32_t new_index = prepare_space_for_new_elem(c, elem_size);
+ add_elem_with_index(c, elem, new_index);
+}
+
+static void add_key(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
+ size_t elem_size) {
+ uint32_t new_index = prepare_space_for_new_elem(c, elem_size);
+ add_key_with_index(c, elem, new_index);
+}
+
+static void emit_indexed(grpc_chttp2_hpack_compressor* c, uint32_t elem_index,
+ framer_state* st) {
GRPC_STATS_INC_HPACK_SEND_INDEXED();
uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1);
GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len),
@@ -313,14 +352,14 @@ static size_t wire_value_length(wire_value v) {
return GPR_SLICE_LENGTH(v.data) + v.insert_null_before_wire_value;
}
-static void add_wire_value(framer_state *st, wire_value v) {
+static void add_wire_value(framer_state* st, wire_value v) {
if (v.insert_null_before_wire_value) *add_tiny_header_data(st, 1) = 0;
add_header_data(st, v.data);
}
-static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
+static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor* c,
uint32_t key_index, grpc_mdelem elem,
- framer_state *st) {
+ framer_state* st) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX();
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
wire_value value = get_wire_value(elem, st->use_true_binary_metadata);
@@ -335,9 +374,9 @@ static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value);
}
-static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
+static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor* c,
uint32_t key_index, grpc_mdelem elem,
- framer_state *st) {
+ framer_state* st) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX();
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
wire_value value = get_wire_value(elem, st->use_true_binary_metadata);
@@ -352,8 +391,10 @@ static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value);
}
-static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
- grpc_mdelem elem, framer_state *st) {
+static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor* c,
+ uint32_t unused_index, grpc_mdelem elem,
+ framer_state* st) {
+ GPR_ASSERT(unused_index == 0);
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V();
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
@@ -372,8 +413,10 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value);
}
-static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
- grpc_mdelem elem, framer_state *st) {
+static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor* c,
+ uint32_t unused_index, grpc_mdelem elem,
+ framer_state* st) {
+ GPR_ASSERT(unused_index == 0);
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V();
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
@@ -392,22 +435,22 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value);
}
-static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
- framer_state *st) {
+static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor* c,
+ framer_state* st) {
uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3);
GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20,
add_tiny_header_data(st, len), len);
c->advertise_table_size_change = 0;
}
-static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) {
+static uint32_t dynidx(grpc_chttp2_hpack_compressor* c, uint32_t elem_index) {
return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index +
c->table_elems - elem_index;
}
/* encode an mdelem */
-static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem,
- framer_state *st) {
+static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
+ framer_state* st) {
GPR_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0);
if (GRPC_SLICE_START_PTR(GRPC_MDKEY(elem))[0] != ':') { /* regular header */
st->seen_regular_header = 1;
@@ -417,9 +460,14 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem,
"Reserved header (colon-prefixed) happening after regular ones.");
}
- if (GRPC_TRACER_ON(grpc_http_trace) && !GRPC_MDELEM_IS_INTERNED(elem)) {
- char *k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
- char *v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
+ if (GRPC_TRACER_ON(grpc_http_trace)) {
+ char* k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
+ char* v = NULL;
+ if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
+ v = grpc_dump_slice(GRPC_MDVALUE(elem), GPR_DUMP_HEX);
+ } else {
+ v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
+ }
gpr_log(
GPR_DEBUG,
"Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
@@ -429,64 +477,69 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem,
gpr_free(k);
gpr_free(v);
}
- if (!GRPC_MDELEM_IS_INTERNED(elem)) {
- emit_lithdr_noidx_v(c, elem, st);
+
+ bool elem_interned = GRPC_MDELEM_IS_INTERNED(elem);
+ bool key_interned = elem_interned || grpc_slice_is_interned(GRPC_MDKEY(elem));
+
+ // Key is not interned, emit literals.
+ if (!key_interned) {
+ emit_lithdr_noidx_v(c, 0, elem, st);
return;
}
- uint32_t key_hash;
- uint32_t value_hash;
- uint32_t elem_hash;
- size_t decoder_space_usage;
- uint32_t indices_key;
- int should_add_elem;
+ uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
+ uint32_t elem_hash = 0;
- key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
- value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
- elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
+ if (elem_interned) {
+ uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
+ elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
- inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems);
+ inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum,
+ c->filter_elems);
- /* is this elem currently in the decoders table? */
+ /* is this elem currently in the decoders table? */
- if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
- c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
- /* HIT: complete element (first cuckoo hash) */
- emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
- st);
- return;
- }
+ if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
+ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
+ /* HIT: complete element (first cuckoo hash) */
+ emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
+ st);
+ return;
+ }
- if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
- c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
- /* HIT: complete element (second cuckoo hash) */
- emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
- st);
- return;
+ if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
+ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
+ /* HIT: complete element (second cuckoo hash) */
+ emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
+ st);
+ return;
+ }
}
+ uint32_t indices_key;
+
/* should this elem be in the table? */
- decoder_space_usage = grpc_mdelem_get_size_in_hpack_table(elem);
- should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
- c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
- c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
+ size_t decoder_space_usage =
+ grpc_mdelem_get_size_in_hpack_table(elem, st->use_true_binary_metadata);
+ bool should_add_elem = elem_interned &&
+ decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
+ c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
+ c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
+ void (*maybe_add)(grpc_chttp2_hpack_compressor*, grpc_mdelem, size_t) =
+ should_add_elem ? add_elem : add_nothing;
+ void (*emit)(grpc_chttp2_hpack_compressor*, uint32_t, grpc_mdelem,
+ framer_state*) =
+ should_add_elem ? emit_lithdr_incidx : emit_lithdr_noidx;
/* no hits for the elem... maybe there's a key? */
-
indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
GRPC_MDKEY(elem)) &&
indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */
- if (should_add_elem) {
- emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
- add_elem(c, elem);
- return;
- } else {
- emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
- return;
- }
- GPR_UNREACHABLE_CODE(return );
+ emit(c, dynidx(c, indices_key), elem, st);
+ maybe_add(c, elem, decoder_space_usage);
+ return;
}
indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
@@ -494,35 +547,27 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem elem,
GRPC_MDKEY(elem)) &&
indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */
- if (should_add_elem) {
- emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st);
- add_elem(c, elem);
- return;
- } else {
- emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st);
- return;
- }
- GPR_UNREACHABLE_CODE(return );
+ emit(c, dynidx(c, indices_key), elem, st);
+ maybe_add(c, elem, decoder_space_usage);
+ return;
}
/* no elem, key in the table... fall back to literal emission */
-
- if (should_add_elem) {
- emit_lithdr_incidx_v(c, elem, st);
- add_elem(c, elem);
- return;
- } else {
- emit_lithdr_noidx_v(c, elem, st);
- return;
- }
- GPR_UNREACHABLE_CODE(return );
+ bool should_add_key =
+ !elem_interned && decoder_space_usage < MAX_DECODER_SPACE_USAGE;
+ emit = (should_add_elem || should_add_key) ? emit_lithdr_incidx_v
+ : emit_lithdr_noidx_v;
+ maybe_add =
+ should_add_elem ? add_elem : (should_add_key ? add_key : add_nothing);
+ emit(c, 0, elem, st);
+ maybe_add(c, elem, decoder_space_usage);
}
#define STRLEN_LIT(x) (sizeof(x) - 1)
#define TIMEOUT_KEY "grpc-timeout"
-static void deadline_enc(grpc_chttp2_hpack_compressor *c, grpc_millis deadline,
- framer_state *st) {
+static void deadline_enc(grpc_chttp2_hpack_compressor* c, grpc_millis deadline,
+ framer_state* st) {
char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
grpc_mdelem mdelem;
grpc_http2_encode_timeout(deadline - grpc_exec_ctx_now(), timeout_str);
@@ -534,14 +579,14 @@ static void deadline_enc(grpc_chttp2_hpack_compressor *c, grpc_millis deadline,
static uint32_t elems_for_bytes(uint32_t bytes) { return (bytes + 31) / 32; }
-void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) {
+void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor* c) {
memset(c, 0, sizeof(*c));
c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
c->cap_table_elems = elems_for_bytes(c->max_table_size);
c->max_table_elems = c->cap_table_elems;
c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
c->table_elem_size =
- (uint16_t *)gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
+ (uint16_t*)gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
memset(c->table_elem_size, 0,
sizeof(*c->table_elem_size) * c->cap_table_elems);
for (size_t i = 0; i < GPR_ARRAY_SIZE(c->entries_keys); i++) {
@@ -549,7 +594,7 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) {
}
}
-void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
+void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor* c) {
int i;
for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
if (c->entries_keys[i].refcount != &terminal_slice_refcount) {
@@ -561,15 +606,15 @@ void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
}
void grpc_chttp2_hpack_compressor_set_max_usable_size(
- grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) {
+ grpc_chttp2_hpack_compressor* c, uint32_t max_table_size) {
c->max_usable_size = max_table_size;
grpc_chttp2_hpack_compressor_set_max_table_size(
c, GPR_MIN(c->max_table_size, max_table_size));
}
-static void rebuild_elems(grpc_chttp2_hpack_compressor *c, uint32_t new_cap) {
- uint16_t *table_elem_size =
- (uint16_t *)gpr_malloc(sizeof(*table_elem_size) * new_cap);
+static void rebuild_elems(grpc_chttp2_hpack_compressor* c, uint32_t new_cap) {
+ uint16_t* table_elem_size =
+ (uint16_t*)gpr_malloc(sizeof(*table_elem_size) * new_cap);
uint32_t i;
memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap);
@@ -587,7 +632,7 @@ static void rebuild_elems(grpc_chttp2_hpack_compressor *c, uint32_t new_cap) {
}
void grpc_chttp2_hpack_compressor_set_max_table_size(
- grpc_chttp2_hpack_compressor *c, uint32_t max_table_size) {
+ grpc_chttp2_hpack_compressor* c, uint32_t max_table_size) {
max_table_size = GPR_MIN(max_table_size, c->max_usable_size);
if (max_table_size == c->max_table_size) {
return;
@@ -611,12 +656,12 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
}
}
-void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
- grpc_mdelem **extra_headers,
+void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
+ grpc_mdelem** extra_headers,
size_t extra_headers_size,
- grpc_metadata_batch *metadata,
- const grpc_encode_header_options *options,
- grpc_slice_buffer *outbuf) {
+ grpc_metadata_batch* metadata,
+ const grpc_encode_header_options* options,
+ grpc_slice_buffer* outbuf) {
GPR_ASSERT(options->stream_id != 0);
framer_state st;
@@ -640,7 +685,7 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
hpack_enc(c, *extra_headers[i], &st);
}
grpc_metadata_batch_assert_ok(metadata);
- for (grpc_linked_mdelem *l = metadata->list.head; l; l = l->next) {
+ for (grpc_linked_mdelem* l = metadata->list.head; l; l = l->next) {
hpack_enc(c, l->md, &st);
}
grpc_millis deadline = metadata->deadline;