diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c index 8e2264a6029..7f7dfa5b554 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c @@ -187,9 +187,23 @@ static void evict_entry(grpc_chttp2_hpack_compressor *c) { c->table_elems--; } +static bool is_interned(grpc_mdelem elem) { + switch (GRPC_MDELEM_STORAGE(elem)) { + case GRPC_MDELEM_STORAGE_ALLOCATED: + case GRPC_MDELEM_STORAGE_EXTERNAL: + return false; + case GRPC_MDELEM_STORAGE_INTERNED: + case GRPC_MDELEM_STORAGE_STATIC: + return true; + } + GPR_UNREACHABLE_CODE(return false); +} + /* add an element to the decoder table */ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_mdelem elem) { + GPR_ASSERT(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); @@ -384,13 +398,6 @@ static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) { /* encode an mdelem */ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_mdelem elem, framer_state *st) { - 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); - size_t decoder_space_usage; - uint32_t indices_key; - int should_add_elem; - 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; @@ -400,6 +407,22 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, "Reserved header (colon-prefixed) happening after regular ones."); } + if (!is_interned(elem)) { + emit_lithdr_noidx_v(c, 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; + + 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); + inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems); /* is this elem currently in the decoders table? */ diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c index 91bedcf7f0a..a1ff528d720 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.c +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c @@ -671,6 +671,8 @@ static const uint8_t inverse_base64[256] = { static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_mdelem md, int add_to_table) { if (add_to_table) { + GPR_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED || + GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC); grpc_error *err = grpc_chttp2_hptbl_add(exec_ctx, &p->table, md); if (err != GRPC_ERROR_NONE) return err; } @@ -683,8 +685,14 @@ static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, } static grpc_slice take_string(grpc_chttp2_hpack_parser *p, - grpc_chttp2_hpack_parser_string *str) { - grpc_slice s = grpc_slice_from_copied_buffer(str->str, str->length); + grpc_chttp2_hpack_parser_string *str, + bool intern) { + grpc_slice s; + if (intern) { + s = grpc_slice_intern(grpc_slice_from_static_buffer(str->str, str->length)); + } else { + s = grpc_slice_from_copied_buffer(str->str, str->length); + } str->length = 0; return s; } @@ -819,7 +827,7 @@ static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx, grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), - take_string(p, &p->value)), + take_string(p, &p->value, true)), 1); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); @@ -830,10 +838,11 @@ static grpc_error *finish_lithdr_incidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { - grpc_error *err = on_hdr( - exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key), - take_string(p, &p->value)), - 1); + grpc_error *err = + on_hdr(exec_ctx, p, + grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key, true), + take_string(p, &p->value, true)), + 1); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } @@ -888,7 +897,7 @@ static grpc_error *finish_lithdr_notidx(grpc_exec_ctx *exec_ctx, grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), - take_string(p, &p->value)), + take_string(p, &p->value, false)), 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); @@ -899,10 +908,11 @@ static grpc_error *finish_lithdr_notidx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { - grpc_error *err = on_hdr( - exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key), - take_string(p, &p->value)), - 0); + grpc_error *err = + on_hdr(exec_ctx, p, + grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key, false), + take_string(p, &p->value, false)), + 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); } @@ -957,7 +967,7 @@ static grpc_error *finish_lithdr_nvridx(grpc_exec_ctx *exec_ctx, grpc_error *err = on_hdr( exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), - take_string(p, &p->value)), + take_string(p, &p->value, false)), 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); @@ -968,10 +978,11 @@ static grpc_error *finish_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { - grpc_error *err = on_hdr( - exec_ctx, p, grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key), - take_string(p, &p->value)), - 0); + grpc_error *err = + on_hdr(exec_ctx, p, + grpc_mdelem_from_slices(exec_ctx, take_string(p, &p->key, false), + take_string(p, &p->value, false)), + 0); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); return parse_begin(exec_ctx, p, cur, end); }