|
|
|
@ -33,6 +33,7 @@ |
|
|
|
|
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" |
|
|
|
|
#include "src/core/ext/transport/chttp2/transport/hpack_table.h" |
|
|
|
|
#include "src/core/ext/transport/chttp2/transport/varint.h" |
|
|
|
|
#include "src/core/lib/debug/stats.h" |
|
|
|
|
#include "src/core/lib/slice/slice_internal.h" |
|
|
|
|
#include "src/core/lib/slice/slice_string_helpers.h" |
|
|
|
|
#include "src/core/lib/transport/metadata.h" |
|
|
|
@ -271,8 +272,10 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index, |
|
|
|
|
static void emit_indexed(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_chttp2_hpack_compressor *c, uint32_t elem_index, |
|
|
|
|
framer_state *st) { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_INDEXED(exec_ctx); |
|
|
|
|
uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1); |
|
|
|
|
GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len), |
|
|
|
|
len); |
|
|
|
@ -284,15 +287,18 @@ typedef struct { |
|
|
|
|
bool insert_null_before_wire_value; |
|
|
|
|
} wire_value; |
|
|
|
|
|
|
|
|
|
static wire_value get_wire_value(grpc_mdelem elem, bool true_binary_enabled) { |
|
|
|
|
static wire_value get_wire_value(grpc_exec_ctx *exec_ctx, grpc_mdelem elem, |
|
|
|
|
bool true_binary_enabled) { |
|
|
|
|
wire_value wire_val; |
|
|
|
|
if (grpc_is_binary_header(GRPC_MDKEY(elem))) { |
|
|
|
|
if (true_binary_enabled) { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_BINARY(exec_ctx); |
|
|
|
|
wire_val.huffman_prefix = 0x00; |
|
|
|
|
wire_val.insert_null_before_wire_value = true; |
|
|
|
|
wire_val.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_BINARY_BASE64(exec_ctx); |
|
|
|
|
wire_val.huffman_prefix = 0x80; |
|
|
|
|
wire_val.insert_null_before_wire_value = false; |
|
|
|
|
wire_val.data = |
|
|
|
@ -300,6 +306,7 @@ static wire_value get_wire_value(grpc_mdelem elem, bool true_binary_enabled) { |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
/* TODO(ctiller): opportunistically compress non-binary headers */ |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(exec_ctx); |
|
|
|
|
wire_val.huffman_prefix = 0x00; |
|
|
|
|
wire_val.insert_null_before_wire_value = false; |
|
|
|
|
wire_val.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)); |
|
|
|
@ -316,11 +323,14 @@ static void add_wire_value(framer_state *st, wire_value v) { |
|
|
|
|
add_header_data(st, v.data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c, |
|
|
|
|
static void emit_lithdr_incidx(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_chttp2_hpack_compressor *c, |
|
|
|
|
uint32_t key_index, grpc_mdelem elem, |
|
|
|
|
framer_state *st) { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX(exec_ctx); |
|
|
|
|
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2); |
|
|
|
|
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); |
|
|
|
|
wire_value value = |
|
|
|
|
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata); |
|
|
|
|
size_t len_val = wire_value_length(value); |
|
|
|
|
uint32_t len_val_len; |
|
|
|
|
GPR_ASSERT(len_val <= UINT32_MAX); |
|
|
|
@ -332,11 +342,14 @@ 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_exec_ctx *exec_ctx, |
|
|
|
|
grpc_chttp2_hpack_compressor *c, |
|
|
|
|
uint32_t key_index, grpc_mdelem elem, |
|
|
|
|
framer_state *st) { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX(exec_ctx); |
|
|
|
|
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4); |
|
|
|
|
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); |
|
|
|
|
wire_value value = |
|
|
|
|
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata); |
|
|
|
|
size_t len_val = wire_value_length(value); |
|
|
|
|
uint32_t len_val_len; |
|
|
|
|
GPR_ASSERT(len_val <= UINT32_MAX); |
|
|
|
@ -348,10 +361,13 @@ 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, |
|
|
|
|
static void emit_lithdr_incidx_v(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_chttp2_hpack_compressor *c, |
|
|
|
|
grpc_mdelem elem, framer_state *st) { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V(exec_ctx); |
|
|
|
|
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); |
|
|
|
|
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); |
|
|
|
|
wire_value value = |
|
|
|
|
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata); |
|
|
|
|
uint32_t len_val = (uint32_t)wire_value_length(value); |
|
|
|
|
uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); |
|
|
|
|
uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); |
|
|
|
@ -366,10 +382,13 @@ 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, |
|
|
|
|
static void emit_lithdr_noidx_v(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_chttp2_hpack_compressor *c, |
|
|
|
|
grpc_mdelem elem, framer_state *st) { |
|
|
|
|
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(exec_ctx); |
|
|
|
|
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); |
|
|
|
|
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); |
|
|
|
|
wire_value value = |
|
|
|
|
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata); |
|
|
|
|
uint32_t len_val = (uint32_t)wire_value_length(value); |
|
|
|
|
uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); |
|
|
|
|
uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); |
|
|
|
@ -422,7 +441,7 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, |
|
|
|
|
gpr_free(v); |
|
|
|
|
} |
|
|
|
|
if (!GRPC_MDELEM_IS_INTERNED(elem)) { |
|
|
|
|
emit_lithdr_noidx_v(c, elem, st); |
|
|
|
|
emit_lithdr_noidx_v(exec_ctx, c, elem, st); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -444,16 +463,16 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, |
|
|
|
|
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); |
|
|
|
|
emit_indexed(exec_ctx, 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); |
|
|
|
|
emit_indexed(exec_ctx, c, |
|
|
|
|
dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), st); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -471,11 +490,11 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, |
|
|
|
|
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); |
|
|
|
|
emit_lithdr_incidx(exec_ctx, c, dynidx(c, indices_key), elem, st); |
|
|
|
|
add_elem(exec_ctx, c, elem); |
|
|
|
|
return; |
|
|
|
|
} else { |
|
|
|
|
emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); |
|
|
|
|
emit_lithdr_noidx(exec_ctx, c, dynidx(c, indices_key), elem, st); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
GPR_UNREACHABLE_CODE(return ); |
|
|
|
@ -487,11 +506,11 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, |
|
|
|
|
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); |
|
|
|
|
emit_lithdr_incidx(exec_ctx, c, dynidx(c, indices_key), elem, st); |
|
|
|
|
add_elem(exec_ctx, c, elem); |
|
|
|
|
return; |
|
|
|
|
} else { |
|
|
|
|
emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); |
|
|
|
|
emit_lithdr_noidx(exec_ctx, c, dynidx(c, indices_key), elem, st); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
GPR_UNREACHABLE_CODE(return ); |
|
|
|
@ -500,11 +519,11 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, |
|
|
|
|
/* no elem, key in the table... fall back to literal emission */ |
|
|
|
|
|
|
|
|
|
if (should_add_elem) { |
|
|
|
|
emit_lithdr_incidx_v(c, elem, st); |
|
|
|
|
emit_lithdr_incidx_v(exec_ctx, c, elem, st); |
|
|
|
|
add_elem(exec_ctx, c, elem); |
|
|
|
|
return; |
|
|
|
|
} else { |
|
|
|
|
emit_lithdr_noidx_v(c, elem, st); |
|
|
|
|
emit_lithdr_noidx_v(exec_ctx, c, elem, st); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
GPR_UNREACHABLE_CODE(return ); |
|
|
|
|