aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext
diff options
context:
space:
mode:
authorGravatar Yash Tibrewal <yashkt@google.com>2018-09-21 16:50:49 -0700
committerGravatar Yash Tibrewal <yashkt@google.com>2018-09-21 16:50:49 -0700
commit4c1243478c591438194403d907b8d6971792144a (patch)
tree6cfb70370e60ac3be687713e468890e99fc61007 /src/core/ext
parentcd1992bc04f01279be9e00226633fa5984713cd6 (diff)
parenta6d8972a07a70e359b0e7c543a0fea8256af549c (diff)
Merge branch 'master' into statuscaution
Diffstat (limited to 'src/core/ext')
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.cc17
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_mapping.cc39
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_mapping.h38
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_table.cc29
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_table.h9
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.cc133
6 files changed, 208 insertions, 57 deletions
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
index 0eaf63f133..920d52770f 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
@@ -525,7 +525,7 @@ static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
/* should this elem be in the table? */
size_t decoder_space_usage =
- grpc_mdelem_get_size_in_hpack_table(elem, st->use_true_binary_metadata);
+ grpc_chttp2_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)] >=
@@ -688,11 +688,22 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
emit_advertise_table_size_change(c, &st);
}
for (size_t i = 0; i < extra_headers_size; ++i) {
- hpack_enc(c, *extra_headers[i], &st);
+ grpc_mdelem md = *extra_headers[i];
+ uint8_t static_index = grpc_chttp2_get_static_hpack_table_index(md);
+ if (static_index) {
+ emit_indexed(c, static_index, &st);
+ } else {
+ hpack_enc(c, md, &st);
+ }
}
grpc_metadata_batch_assert_ok(metadata);
for (grpc_linked_mdelem* l = metadata->list.head; l; l = l->next) {
- hpack_enc(c, l->md, &st);
+ uint8_t static_index = grpc_chttp2_get_static_hpack_table_index(l->md);
+ if (static_index) {
+ emit_indexed(c, static_index, &st);
+ } else {
+ hpack_enc(c, l->md, &st);
+ }
}
grpc_millis deadline = metadata->deadline;
if (deadline != GRPC_MILLIS_INF_FUTURE) {
diff --git a/src/core/ext/transport/chttp2/transport/hpack_mapping.cc b/src/core/ext/transport/chttp2/transport/hpack_mapping.cc
new file mode 100644
index 0000000000..fd529f0fd4
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_mapping.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * WARNING: Auto-generated code.
+ *
+ * To make changes to this file, change
+ * tools/codegen/core/gen_static_metadata.py, and then re-run it.
+ *
+ * This file contains the mapping from the index of each metadata element in the
+ * grpc static metadata table to the index of that element in the hpack static
+ * metadata table. If the element is not contained in the static hpack table,
+ * then the returned index is 0.
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/transport/chttp2/transport/hpack_mapping.h"
+
+const uint8_t grpc_hpack_static_mdelem_indices[GRPC_STATIC_MDELEM_COUNT] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 13, 6, 7, 0, 1, 2, 0, 4,
+ 5, 9, 10, 11, 12, 14, 15, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 0, 0, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
diff --git a/src/core/ext/transport/chttp2/transport/hpack_mapping.h b/src/core/ext/transport/chttp2/transport/hpack_mapping.h
new file mode 100644
index 0000000000..ebcd65bd9f
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/hpack_mapping.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * WARNING: Auto-generated code.
+ *
+ * To make changes to this file, change
+ * tools/codegen/core/gen_static_metadata.py, and then re-run it.
+ *
+ * This file contains the mapping from the index of each metadata element in the
+ * grpc static metadata table to the index of that element in the hpack static
+ * metadata table. If the element is not contained in the static hpack table,
+ * then the returned index is 0.
+ */
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_MAPPING_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_MAPPING_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/transport/static_metadata.h"
+
+extern const uint8_t grpc_hpack_static_mdelem_indices[GRPC_STATIC_MDELEM_COUNT];
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_MAPPING_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.cc b/src/core/ext/transport/chttp2/transport/hpack_table.cc
index 7929258356..117679ab75 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.cc
@@ -27,8 +27,10 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include "src/core/ext/transport/chttp2/transport/hpack_mapping.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gpr/murmur_hash.h"
+#include "src/core/lib/transport/static_metadata.h"
extern grpc_core::TraceFlag grpc_http_trace;
@@ -366,3 +368,30 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
return r;
}
+
+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_chttp2_get_size_in_hpack_table(grpc_mdelem elem,
+ bool use_true_binary_metadata) {
+ size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
+ size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem));
+ if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
+ return overhead_and_key + (use_true_binary_metadata
+ ? value_len + 1
+ : get_base64_encoded_size(value_len));
+ } else {
+ return overhead_and_key + value_len;
+ }
+}
+
+uint8_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md) {
+ if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
+ return grpc_hpack_static_mdelem_indices[GRPC_MDELEM_DATA(md) -
+ grpc_static_mdelem_table];
+ } else {
+ return 0;
+ }
+}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.h b/src/core/ext/transport/chttp2/transport/hpack_table.h
index 98026a4ba4..a0ffc6fab7 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.h
@@ -83,6 +83,15 @@ grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl* tbl,
/* add a table entry to the index */
grpc_error* grpc_chttp2_hptbl_add(grpc_chttp2_hptbl* tbl,
grpc_mdelem md) GRPC_MUST_USE_RESULT;
+
+size_t grpc_chttp2_get_size_in_hpack_table(grpc_mdelem elem,
+ bool use_true_binary_metadata);
+
+/* Returns the static hpack table index that corresponds to /a elem. Returns 0
+ if /a elem is not statically stored or if it is not in the static hpack
+ table */
+uint8_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md);
+
/* Find a key/value pair in the table... returns the index in the table of the
most similar entry, or 0 if the value was not found */
typedef struct {
diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc
index 1e491d2ef8..8e9aa613a6 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.cc
+++ b/src/core/ext/transport/chttp2/transport/parsing.cc
@@ -409,67 +409,81 @@ static void on_initial_header(void* tp, grpc_mdelem md) {
gpr_free(value);
}
- if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
- !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
- /* TODO(ctiller): check for a status like " 0" */
- s->seen_error = true;
- }
+ if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
+ // We don't use grpc_mdelem_eq here to avoid executing additional
+ // instructions. The reasoning is if the payload is not equal, we already
+ // know that the metadata elements are not equal because the md is
+ // confirmed to be static. If we had used grpc_mdelem_eq here, then if the
+ // payloads are not equal, grpc_mdelem_eq executes more instructions to
+ // determine if they're equal or not.
+ if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload ||
+ md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) {
+ s->seen_error = true;
+ }
+ } else {
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+ !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
+ /* TODO(ctiller): check for a status like " 0" */
+ s->seen_error = true;
+ }
- if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
- grpc_millis* cached_timeout =
- static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
- grpc_millis timeout;
- if (cached_timeout != nullptr) {
- timeout = *cached_timeout;
- } else {
- if (GPR_UNLIKELY(
- !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
- char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
- gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
- gpr_free(val);
- timeout = GRPC_MILLIS_INF_FUTURE;
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
+ grpc_millis* cached_timeout = static_cast<grpc_millis*>(
+ grpc_mdelem_get_user_data(md, free_timeout));
+ grpc_millis timeout;
+ if (cached_timeout != nullptr) {
+ timeout = *cached_timeout;
+ } else {
+ if (GPR_UNLIKELY(
+ !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
+ char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+ gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
+ gpr_free(val);
+ timeout = GRPC_MILLIS_INF_FUTURE;
+ }
+ if (GRPC_MDELEM_IS_INTERNED(md)) {
+ /* store the result */
+ cached_timeout =
+ static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
+ *cached_timeout = timeout;
+ grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+ }
}
- if (GRPC_MDELEM_IS_INTERNED(md)) {
- /* store the result */
- cached_timeout =
- static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
- *cached_timeout = timeout;
- grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+ if (timeout != GRPC_MILLIS_INF_FUTURE) {
+ grpc_chttp2_incoming_metadata_buffer_set_deadline(
+ &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
}
+ GRPC_MDELEM_UNREF(md);
+ return;
}
- if (timeout != GRPC_MILLIS_INF_FUTURE) {
- grpc_chttp2_incoming_metadata_buffer_set_deadline(
- &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
- }
+ }
+
+ const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
+ const size_t metadata_size_limit =
+ t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
+ if (new_size > metadata_size_limit) {
+ gpr_log(GPR_DEBUG,
+ "received initial metadata size exceeds limit (%" PRIuPTR
+ " vs. %" PRIuPTR ")",
+ new_size, metadata_size_limit);
+ grpc_chttp2_cancel_stream(
+ t, s,
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "received initial metadata size exceeds limit"),
+ GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_RESOURCE_EXHAUSTED));
+ grpc_chttp2_parsing_become_skip_parser(t);
+ s->seen_error = true;
GRPC_MDELEM_UNREF(md);
} else {
- const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
- const size_t metadata_size_limit =
- t->settings[GRPC_ACKED_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
- if (new_size > metadata_size_limit) {
- gpr_log(GPR_DEBUG,
- "received initial metadata size exceeds limit (%" PRIuPTR
- " vs. %" PRIuPTR ")",
- new_size, metadata_size_limit);
- grpc_chttp2_cancel_stream(
- t, s,
- grpc_error_set_int(
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "received initial metadata size exceeds limit"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
+ grpc_error* error =
+ grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
+ if (error != GRPC_ERROR_NONE) {
+ grpc_chttp2_cancel_stream(t, s, error);
grpc_chttp2_parsing_become_skip_parser(t);
s->seen_error = true;
GRPC_MDELEM_UNREF(md);
- } else {
- grpc_error* error =
- grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
- if (error != GRPC_ERROR_NONE) {
- grpc_chttp2_cancel_stream(t, s, error);
- grpc_chttp2_parsing_become_skip_parser(t);
- s->seen_error = true;
- GRPC_MDELEM_UNREF(md);
- }
}
}
}
@@ -491,8 +505,19 @@ static void on_trailing_header(void* tp, grpc_mdelem md) {
gpr_free(value);
}
- if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
- !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
+ if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
+ // We don't use grpc_mdelem_eq here to avoid executing additional
+ // instructions. The reasoning is if the payload is not equal, we already
+ // know that the metadata elements are not equal because the md is
+ // confirmed to be static. If we had used grpc_mdelem_eq here, then if the
+ // payloads are not equal, grpc_mdelem_eq executes more instructions to
+ // determine if they're equal or not.
+ if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload ||
+ md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) {
+ s->seen_error = true;
+ }
+ } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+ !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
/* TODO(ctiller): check for a status like " 0" */
s->seen_error = true;
}