aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/transport
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2016-04-07 07:57:47 -0700
committerGravatar Craig Tiller <ctiller@google.com>2016-04-07 07:57:47 -0700
commit74142a29e942432e17c6bf33e4d7e7d41d5e770f (patch)
treeb8edc8502dca9c5f87b2ab46b0fcb09435b9ef00 /src/core/lib/transport
parent5db5e132934404ae64bcfd34f0e70dd4193daee7 (diff)
parent41d124fe66bd08c3e00a082f282b78ca16eb8903 (diff)
Merge github.com:grpc/grpc into strong-includes
Diffstat (limited to 'src/core/lib/transport')
-rw-r--r--src/core/lib/transport/metadata.c38
-rw-r--r--src/core/lib/transport/metadata.h2
2 files changed, 40 insertions, 0 deletions
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 7de871a9c6..779efbb97d 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>
@@ -80,6 +81,7 @@ gpr_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(gpr_slice input);
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 */
@@ -94,6 +96,8 @@ typedef struct internal_string {
gpr_slice base64_and_huffman;
+ gpr_atm size_in_decoder_table;
+
struct internal_string *bucket_next;
} internal_string;
@@ -414,6 +418,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;
@@ -583,6 +588,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 9641964534..e29e8df2c9 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,