diff options
author | Nicolas Noble <nicolasnoble@users.noreply.github.com> | 2016-04-06 16:40:49 -0700 |
---|---|---|
committer | Nicolas Noble <nicolasnoble@users.noreply.github.com> | 2016-04-06 16:40:49 -0700 |
commit | 41d124fe66bd08c3e00a082f282b78ca16eb8903 (patch) | |
tree | daaebb170ab610b94754ea6e9539630430b985e3 /src/core/lib/transport | |
parent | 2879aa1b1db9a72299c62cb9e9f2aa74e3e3e762 (diff) | |
parent | 39afce836de1fb6e49c0eefc5ed77a4d44f1837a (diff) |
Merge pull request #6029 from yang-g/hpack_table
Use base64 encoded length for decoder table size calculation of binary headers
Diffstat (limited to 'src/core/lib/transport')
-rw-r--r-- | src/core/lib/transport/metadata.c | 38 | ||||
-rw-r--r-- | src/core/lib/transport/metadata.h | 2 |
2 files changed, 40 insertions, 0 deletions
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c index d037c61d72..5d9e7e74c1 100644 --- a/src/core/lib/transport/metadata.c +++ b/src/core/lib/transport/metadata.c @@ -38,6 +38,7 @@ #include <string.h> #include <grpc/compression.h> +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/atm.h> #include <grpc/support/log.h> @@ -79,6 +80,7 @@ typedef void (*destroy_user_data_func)(void *user_data); +#define SIZE_IN_DECODER_TABLE_NOT_SET -1 /* Shadow structure for grpc_mdstr for non-static values */ typedef struct internal_string { /* must be byte compatible with grpc_mdstr */ @@ -93,6 +95,8 @@ typedef struct internal_string { gpr_slice base64_and_huffman; + gpr_atm size_in_decoder_table; + struct internal_string *bucket_next; } internal_string; @@ -413,6 +417,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) { } s->has_base64_and_huffman_encoded = 0; s->hash = hash; + s->size_in_decoder_table = SIZE_IN_DECODER_TABLE_NOT_SET; s->bucket_next = shard->strs[idx]; shard->strs[idx] = s; @@ -582,6 +587,39 @@ grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key, grpc_mdstr_from_string(key), grpc_mdstr_from_buffer(value, value_length)); } +static size_t get_base64_encoded_size(size_t raw_length) { + static const uint8_t tail_xtra[3] = {0, 2, 3}; + return raw_length / 3 * 4 + tail_xtra[raw_length % 3]; +} + +size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem) { + size_t overhead_and_key = 32 + GPR_SLICE_LENGTH(elem->key->slice); + size_t value_len = GPR_SLICE_LENGTH(elem->value->slice); + if (is_mdstr_static(elem->value)) { + if (grpc_is_binary_header( + (const char *)GPR_SLICE_START_PTR(elem->key->slice), + GPR_SLICE_LENGTH(elem->key->slice))) { + return overhead_and_key + get_base64_encoded_size(value_len); + } else { + return overhead_and_key + value_len; + } + } else { + internal_string *is = (internal_string *)elem->value; + gpr_atm current_size = gpr_atm_acq_load(&is->size_in_decoder_table); + if (current_size == SIZE_IN_DECODER_TABLE_NOT_SET) { + if (grpc_is_binary_header( + (const char *)GPR_SLICE_START_PTR(elem->key->slice), + GPR_SLICE_LENGTH(elem->key->slice))) { + current_size = (gpr_atm)get_base64_encoded_size(value_len); + } else { + current_size = (gpr_atm)value_len; + } + gpr_atm_rel_store(&is->size_in_decoder_table, current_size); + } + return overhead_and_key + (size_t)current_size; + } +} + grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) { internal_metadata *md = (internal_metadata *)gmd; if (is_mdelem_static(gmd)) return gmd; diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h index 6a02437fdf..8630b0e0e8 100644 --- a/src/core/lib/transport/metadata.h +++ b/src/core/lib/transport/metadata.h @@ -110,6 +110,8 @@ grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key, const uint8_t *value, size_t value_length); +size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem); + /* Mutator and accessor for grpc_mdelem user data. The destructor function is used as a type tag and is checked during user_data fetch. */ void *grpc_mdelem_get_user_data(grpc_mdelem *md, |