From ebdef9d674b33e7bd117e2a4a2da7762c35bbdfc Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 19 Nov 2015 17:09:49 -0800 Subject: [PATCH] Remove metadata context from the channel stack --- BUILD | 3 + build.yaml | 1 + gRPC.podspec | 2 + src/core/channel/client_channel.c | 3 +- src/core/channel/client_uchannel.c | 6 +- src/core/channel/client_uchannel.h | 3 +- src/core/channel/compress_filter.c | 62 +--- src/core/channel/http_client_filter.c | 150 +++------- src/core/channel/http_server_filter.c | 104 ++----- src/core/channel/subchannel_call_holder.c | 15 +- src/core/channel/subchannel_call_holder.h | 4 +- src/core/client_config/subchannel.c | 34 +-- src/core/client_config/subchannel.h | 7 +- src/core/compression/algorithm.c | 50 +++- src/core/compression/algorithm_metadata.h | 53 ++++ src/core/surface/call.c | 47 ++- src/core/surface/channel.c | 141 ++++----- src/core/surface/channel.h | 6 - src/core/surface/lame_client.c | 12 +- src/core/surface/server.c | 13 +- src/core/transport/metadata.c | 97 +++++- src/core/transport/metadata.h | 21 ++ src/core/transport/static_metadata.c | 23 +- src/core/transport/static_metadata.h | 275 ++++++++++-------- test/core/channel/channel_stack_test.c | 4 +- test/core/end2end/fixtures/h2_uchannel.c | 4 +- .../core/transport/chttp2/hpack_parser_test.c | 1 + test/core/transport/metadata_test.c | 6 +- tools/codegen/core/gen_static_metadata.py | 7 + tools/doxygen/Doxyfile.core.internal | 1 + tools/run_tests/run_tests.py | 4 +- tools/run_tests/sources_and_headers.json | 4 + vsprojects/vcxproj/grpc/grpc.vcxproj | 1 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj | 1 + .../grpc_unsecure.vcxproj.filters | 3 + 36 files changed, 621 insertions(+), 550 deletions(-) create mode 100644 src/core/compression/algorithm_metadata.h diff --git a/BUILD b/BUILD index 9f378ae990d..091669917be 100644 --- a/BUILD +++ b/BUILD @@ -178,6 +178,7 @@ cc_library( "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h", "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h", "src/core/client_config/uri_parser.h", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.h", "src/core/debug/trace.h", "src/core/httpcli/format_request.h", @@ -470,6 +471,7 @@ cc_library( "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h", "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h", "src/core/client_config/uri_parser.h", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.h", "src/core/debug/trace.h", "src/core/httpcli/format_request.h", @@ -1269,6 +1271,7 @@ objc_library( "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h", "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h", "src/core/client_config/uri_parser.h", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.h", "src/core/debug/trace.h", "src/core/httpcli/format_request.h", diff --git a/build.yaml b/build.yaml index 63d47ed84d9..d157ace2f76 100644 --- a/build.yaml +++ b/build.yaml @@ -134,6 +134,7 @@ filegroups: - src/core/client_config/subchannel_factory_decorators/add_channel_arg.h - src/core/client_config/subchannel_factory_decorators/merge_channel_args.h - src/core/client_config/uri_parser.h + - src/core/compression/algorithm_metadata.h - src/core/compression/message_compress.h - src/core/debug/trace.h - src/core/httpcli/format_request.h diff --git a/gRPC.podspec b/gRPC.podspec index 1e248f58fdb..ac80ee02a9a 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -182,6 +182,7 @@ Pod::Spec.new do |s| 'src/core/client_config/subchannel_factory_decorators/add_channel_arg.h', 'src/core/client_config/subchannel_factory_decorators/merge_channel_args.h', 'src/core/client_config/uri_parser.h', + 'src/core/compression/algorithm_metadata.h', 'src/core/compression/message_compress.h', 'src/core/debug/trace.h', 'src/core/httpcli/format_request.h', @@ -480,6 +481,7 @@ Pod::Spec.new do |s| 'src/core/client_config/subchannel_factory_decorators/add_channel_arg.h', 'src/core/client_config/subchannel_factory_decorators/merge_channel_args.h', 'src/core/client_config/uri_parser.h', + 'src/core/compression/algorithm_metadata.h', 'src/core/compression/message_compress.h', 'src/core/debug/trace.h', 'src/core/httpcli/format_request.h', diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index 020138bf157..1abcd3b9cc8 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -364,7 +364,8 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp, /* Constructor for call_data */ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_call_element_args *args) { - grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem); + grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem, + args->metadata_context); } /* Destructor for call_data */ diff --git a/src/core/channel/client_uchannel.c b/src/core/channel/client_uchannel.c index cf5e3bf482c..3276635625d 100644 --- a/src/core/channel/client_uchannel.c +++ b/src/core/channel/client_uchannel.c @@ -140,7 +140,7 @@ static int cuc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg, static void cuc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_call_element_args *args) { grpc_subchannel_call_holder_init(elem->call_data, cuc_pick_subchannel, - elem->channel_data); + elem->channel_data, args->metadata_context); } /* Destructor for call_data */ @@ -244,11 +244,11 @@ void grpc_client_uchannel_del_interested_party(grpc_exec_ctx *exec_ctx, } grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel, - grpc_channel_args *args) { + grpc_channel_args *args, + grpc_mdctx *mdctx) { grpc_channel *channel = NULL; #define MAX_FILTERS 3 const grpc_channel_filter *filters[MAX_FILTERS]; - grpc_mdctx *mdctx = grpc_subchannel_get_mdctx(subchannel); grpc_channel *master = grpc_subchannel_get_master(subchannel); char *target = grpc_channel_get_target(master); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; diff --git a/src/core/channel/client_uchannel.h b/src/core/channel/client_uchannel.h index dfe6695ae3e..54fbea964c1 100644 --- a/src/core/channel/client_uchannel.h +++ b/src/core/channel/client_uchannel.h @@ -62,7 +62,8 @@ void grpc_client_uchannel_del_interested_party(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset); grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel, - grpc_channel_args *args); + grpc_channel_args *args, + grpc_mdctx *mdctx); void grpc_client_uchannel_set_subchannel(grpc_channel *uchannel, grpc_subchannel *subchannel); diff --git a/src/core/channel/compress_filter.c b/src/core/channel/compress_filter.c index 62219f5aa72..25d6e51281b 100644 --- a/src/core/channel/compress_filter.c +++ b/src/core/channel/compress_filter.c @@ -42,6 +42,7 @@ #include "src/core/channel/compress_filter.h" #include "src/core/channel/channel_args.h" #include "src/core/profiling/timers.h" +#include "src/core/compression/algorithm_metadata.h" #include "src/core/compression/message_compress.h" #include "src/core/support/string.h" #include "src/core/transport/static_metadata.h" @@ -65,6 +66,8 @@ typedef struct call_data { grpc_closure *post_send; grpc_closure send_done; grpc_closure got_slice; + + grpc_mdctx *mdctx; } call_data; typedef struct channel_data { @@ -72,6 +75,8 @@ typedef struct channel_data { grpc_compression_algorithm default_compression_algorithm; /** Compression options for the channel */ grpc_compression_options compression_options; + /** Supported compression algorithms */ + gpr_uint32 supported_compression_algorithms; } channel_data; /** For each \a md element from the incoming metadata, filter out the entry for @@ -82,7 +87,7 @@ static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; - if (md->key == GRPC_MDSTR_GRPC_ENCODING) { + if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) { const char *md_c_str = grpc_mdstr_as_c_string(md->value); if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str), &calld->compression_algorithm)) { @@ -138,14 +143,13 @@ static void process_send_initial_metadata( /* hint compression algorithm */ grpc_metadata_batch_add_tail( initial_metadata, &calld->compression_algorithm_storage, - GRPC_MDELEM_REF( - channeld - ->mdelem_compression_algorithms[calld->compression_algorithm])); + grpc_compression_encoding_mdelem(calld->compression_algorithm)); /* convey supported compression algorithms */ grpc_metadata_batch_add_tail( initial_metadata, &calld->accept_encoding_storage, - GRPC_MDELEM_REF(channeld->mdelem_accept_encoding)); + GRPC_MDELEM_REF(grpc_accept_encoding_mdelem_from_compression_algorithms( + calld->mdctx, channeld->supported_compression_algorithms))); } static void continue_send_message(grpc_exec_ctx *exec_ctx, @@ -239,6 +243,7 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, /* initialize members */ gpr_slice_buffer_init(&calld->slices); calld->has_compression_algorithm = 0; + calld->mdctx = args->metadata_context; grpc_closure_init(&calld->got_slice, got_slice, elem); grpc_closure_init(&calld->send_done, send_done, elem); } @@ -257,10 +262,6 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element_args *args) { channel_data *channeld = elem->channel_data; grpc_compression_algorithm algo_idx; - const char *supported_algorithms_names[GRPC_COMPRESS_ALGORITHMS_COUNT - 1]; - size_t supported_algorithms_idx = 0; - char *accept_encoding_str; - size_t accept_encoding_str_len; grpc_compression_options_init(&channeld->compression_options); channeld->compression_options.enabled_algorithms_bitset = @@ -275,61 +276,22 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx, channeld->compression_options.default_compression_algorithm = channeld->default_compression_algorithm; - channeld->mdstr_request_compression_algorithm_key = grpc_mdstr_from_string( - args->metadata_context, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY); - - channeld->mdstr_outgoing_compression_algorithm_key = - grpc_mdstr_from_string(args->metadata_context, "grpc-encoding"); - - channeld->mdstr_compression_capabilities_key = - grpc_mdstr_from_string(args->metadata_context, "grpc-accept-encoding"); - + channeld->supported_compression_algorithms = 0; for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { - char *algorithm_name; /* skip disabled algorithms */ if (grpc_compression_options_is_algorithm_enabled( &channeld->compression_options, algo_idx) == 0) { continue; } - GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorithm_name) != 0); - channeld->mdelem_compression_algorithms[algo_idx] = - grpc_mdelem_from_metadata_strings( - args->metadata_context, - GRPC_MDSTR_REF(channeld->mdstr_outgoing_compression_algorithm_key), - grpc_mdstr_from_string(args->metadata_context, algorithm_name)); - if (algo_idx > 0) { - supported_algorithms_names[supported_algorithms_idx++] = algorithm_name; - } + channeld->supported_compression_algorithms |= 1u << algo_idx; } - /* TODO(dgq): gpr_strjoin_sep could be made to work with statically allocated - * arrays, as to avoid the heap allocs */ - accept_encoding_str = - gpr_strjoin_sep(supported_algorithms_names, supported_algorithms_idx, ",", - &accept_encoding_str_len); - - channeld->mdelem_accept_encoding = grpc_mdelem_from_metadata_strings( - args->metadata_context, - GRPC_MDSTR_REF(channeld->mdstr_compression_capabilities_key), - grpc_mdstr_from_string(args->metadata_context, accept_encoding_str)); - gpr_free(accept_encoding_str); - GPR_ASSERT(!args->is_last); } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { - channel_data *channeld = elem->channel_data; - grpc_compression_algorithm algo_idx; - - GRPC_MDSTR_UNREF(channeld->mdstr_request_compression_algorithm_key); - GRPC_MDSTR_UNREF(channeld->mdstr_outgoing_compression_algorithm_key); - GRPC_MDSTR_UNREF(channeld->mdstr_compression_capabilities_key); - for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { - GRPC_MDELEM_UNREF(channeld->mdelem_compression_algorithms[algo_idx]); - } - GRPC_MDELEM_UNREF(channeld->mdelem_accept_encoding); } const grpc_channel_filter grpc_compress_filter = { diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c index 3a0f68f30fc..ec7791656fa 100644 --- a/src/core/channel/http_client_filter.c +++ b/src/core/channel/http_client_filter.c @@ -37,6 +37,7 @@ #include #include "src/core/support/string.h" #include "src/core/profiling/timers.h" +#include "src/core/transport/static_metadata.h" typedef struct call_data { grpc_linked_mdelem method; @@ -54,17 +55,11 @@ typedef struct call_data { up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure hc_on_recv; + + grpc_mdctx *mdctx; } call_data; -typedef struct channel_data { - grpc_mdelem *te_trailers; - grpc_mdelem *method; - grpc_mdelem *scheme; - grpc_mdelem *content_type; - grpc_mdelem *status; - /** complete user agent mdelem */ - grpc_mdelem *user_agent; -} channel_data; +typedef struct channel_data { grpc_mdelem *static_scheme; } channel_data; typedef struct { grpc_call_element *elem; @@ -73,14 +68,12 @@ typedef struct { static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) { client_recv_filter_args *a = user_data; - grpc_call_element *elem = a->elem; - channel_data *channeld = elem->channel_data; - if (md == channeld->status) { + if (md == GRPC_MDELEM_STATUS_200) { return NULL; - } else if (md->key == channeld->status->key) { - grpc_call_element_send_cancel(a->exec_ctx, elem); + } else if (md->key == GRPC_MDSTR_STATUS) { + grpc_call_element_send_cancel(a->exec_ctx, a->elem); return NULL; - } else if (md->key == channeld->content_type->key) { + } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { return NULL; } return md; @@ -98,14 +91,12 @@ static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, int success) { } static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) { - grpc_call_element *elem = user_data; - channel_data *channeld = elem->channel_data; /* eat the things we'd like to set ourselves */ - if (md->key == channeld->method->key) return NULL; - if (md->key == channeld->scheme->key) return NULL; - if (md->key == channeld->te_trailers->key) return NULL; - if (md->key == channeld->content_type->key) return NULL; - if (md->key == channeld->user_agent->key) return NULL; + if (md->key == GRPC_MDSTR_METHOD) return NULL; + if (md->key == GRPC_MDSTR_SCHEME) return NULL; + if (md->key == GRPC_MDSTR_TE) return NULL; + if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL; + if (md->key == GRPC_MDSTR_USER_AGENT) return NULL; return md; } @@ -120,16 +111,18 @@ static void hc_mutate_op(grpc_call_element *elem, /* Send : prefixed headers, which have to be before any application layer headers. */ grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method, - GRPC_MDELEM_REF(channeld->method)); + GRPC_MDELEM_METHOD_POST); grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme, - GRPC_MDELEM_REF(channeld->scheme)); + channeld->static_scheme); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers, - GRPC_MDELEM_REF(channeld->te_trailers)); - grpc_metadata_batch_add_tail(op->send_initial_metadata, - &calld->content_type, - GRPC_MDELEM_REF(channeld->content_type)); - grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent, - GRPC_MDELEM_REF(channeld->user_agent)); + GRPC_MDELEM_TE_TRAILERS); + grpc_metadata_batch_add_tail( + op->send_initial_metadata, &calld->content_type, + GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); + grpc_metadata_batch_add_tail( + op->send_initial_metadata, &calld->user_agent, + GRPC_MDELEM_REF(grpc_mdelem_from_cache(calld->mdctx, + GRPC_MDELEM_CACHED_USER_AGENT))); } if (op->recv_initial_metadata != NULL) { @@ -155,6 +148,7 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_call_element_args *args) { call_data *calld = elem->call_data; calld->on_done_recv = NULL; + calld->mdctx = args->metadata_context; grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem); } @@ -162,109 +156,39 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {} -static const char *scheme_from_args(const grpc_channel_args *args) { +static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) { unsigned i; + size_t j; + grpc_mdelem *valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP, + GRPC_MDELEM_SCHEME_HTTPS}; if (args != NULL) { for (i = 0; i < args->num_args; ++i) { if (args->args[i].type == GRPC_ARG_STRING && strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) { - return args->args[i].value.string; + for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) { + if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value), + args->args[i].value.string)) { + return valid_schemes[j]; + } + } } } } - return "http"; -} - -static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx, - const grpc_channel_args *args) { - gpr_strvec v; - size_t i; - int is_first = 1; - char *tmp; - grpc_mdstr *result; - - gpr_strvec_init(&v); - - for (i = 0; args && i < args->num_args; i++) { - if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) { - if (args->args[i].type != GRPC_ARG_STRING) { - gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", - GRPC_ARG_PRIMARY_USER_AGENT_STRING); - } else { - if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); - is_first = 0; - gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string)); - } - } - } - - gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ", - grpc_version_string(), GPR_PLATFORM_STRING); - is_first = 0; - gpr_strvec_add(&v, tmp); - - for (i = 0; args && i < args->num_args; i++) { - if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) { - if (args->args[i].type != GRPC_ARG_STRING) { - gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", - GRPC_ARG_SECONDARY_USER_AGENT_STRING); - } else { - if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); - is_first = 0; - gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string)); - } - } - } - - tmp = gpr_strvec_flatten(&v, NULL); - gpr_strvec_destroy(&v); - result = grpc_mdstr_from_string(mdctx, tmp); - gpr_free(tmp); - - return result; + return GRPC_MDELEM_SCHEME_HTTP; } /* Constructor for channel_data */ static void init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { - /* grab pointers to our data from the channel element */ - channel_data *channeld = elem->channel_data; - - /* The first and the last filters tend to be implemented differently to - handle the case that there's no 'next' filter to call on the up or down - path */ + channel_data *chand = elem->channel_data; GPR_ASSERT(!args->is_last); - - /* initialize members */ - channeld->te_trailers = - grpc_mdelem_from_strings(args->metadata_context, "te", "trailers"); - channeld->method = - grpc_mdelem_from_strings(args->metadata_context, ":method", "POST"); - channeld->scheme = grpc_mdelem_from_strings( - args->metadata_context, ":scheme", scheme_from_args(args->channel_args)); - channeld->content_type = grpc_mdelem_from_strings( - args->metadata_context, "content-type", "application/grpc"); - channeld->status = - grpc_mdelem_from_strings(args->metadata_context, ":status", "200"); - channeld->user_agent = grpc_mdelem_from_metadata_strings( - args->metadata_context, - grpc_mdstr_from_string(args->metadata_context, "user-agent"), - user_agent_from_args(args->metadata_context, args->channel_args)); + chand->static_scheme = scheme_from_args(args->channel_args); } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { - /* grab pointers to our data from the channel element */ - channel_data *channeld = elem->channel_data; - - GRPC_MDELEM_UNREF(channeld->te_trailers); - GRPC_MDELEM_UNREF(channeld->method); - GRPC_MDELEM_UNREF(channeld->scheme); - GRPC_MDELEM_UNREF(channeld->content_type); - GRPC_MDELEM_UNREF(channeld->status); - GRPC_MDELEM_UNREF(channeld->user_agent); } const grpc_channel_filter grpc_http_client_filter = { diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 2adfe2bb61d..c9db9470e06 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -37,6 +37,7 @@ #include #include #include "src/core/profiling/timers.h" +#include "src/core/transport/static_metadata.h" typedef struct call_data { gpr_uint8 seen_path; @@ -55,24 +56,10 @@ typedef struct call_data { up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure hs_on_recv; + grpc_mdctx *mdctx; } call_data; -typedef struct channel_data { - grpc_mdelem *te_trailers; - grpc_mdelem *method_post; - grpc_mdelem *http_scheme; - grpc_mdelem *https_scheme; - /* TODO(klempner): Remove this once we stop using it */ - grpc_mdelem *grpc_scheme; - grpc_mdelem *content_type; - grpc_mdelem *status_ok; - grpc_mdelem *status_not_found; - grpc_mdstr *path_key; - grpc_mdstr *authority_key; - grpc_mdstr *host_key; - - grpc_mdctx *mdctx; -} channel_data; +typedef struct channel_data { gpr_uint8 unused; } channel_data; typedef struct { grpc_call_element *elem; @@ -82,25 +69,24 @@ typedef struct { static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) { server_filter_args *a = user_data; grpc_call_element *elem = a->elem; - channel_data *channeld = elem->channel_data; call_data *calld = elem->call_data; /* Check if it is one of the headers we care about. */ - if (md == channeld->te_trailers || md == channeld->method_post || - md == channeld->http_scheme || md == channeld->https_scheme || - md == channeld->grpc_scheme || md == channeld->content_type) { + if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST || + md == GRPC_MDELEM_SCHEME_HTTP || md == GRPC_MDELEM_SCHEME_HTTPS || + md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { /* swallow it */ - if (md == channeld->method_post) { + if (md == GRPC_MDELEM_METHOD_POST) { calld->seen_post = 1; - } else if (md->key == channeld->http_scheme->key) { + } else if (md->key == GRPC_MDSTR_SCHEME) { calld->seen_scheme = 1; - } else if (md == channeld->te_trailers) { + } else if (md == GRPC_MDELEM_TE_TRAILERS) { calld->seen_te_trailers = 1; } /* TODO(klempner): Track that we've seen all the headers we should require */ return NULL; - } else if (md->key == channeld->content_type->key) { + } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { if (strncmp(grpc_mdstr_as_c_string(md->value), "application/grpc+", 17) == 0) { /* Although the C implementation doesn't (currently) generate them, @@ -112,12 +98,11 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ gpr_log(GPR_INFO, "Unexpected content-type %s", - channeld->content_type->key); + grpc_mdstr_as_c_string(md->value)); } return NULL; - } else if (md->key == channeld->te_trailers->key || - md->key == channeld->method_post->key || - md->key == channeld->http_scheme->key) { + } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD || + md->key == GRPC_MDSTR_SCHEME) { gpr_log(GPR_ERROR, "Invalid %s: header: '%s'", grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)); /* swallow it and error everything out. */ @@ -125,22 +110,21 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) { on the wire here. */ grpc_call_element_send_cancel(a->exec_ctx, elem); return NULL; - } else if (md->key == channeld->path_key) { + } else if (md->key == GRPC_MDSTR_PATH) { if (calld->seen_path) { gpr_log(GPR_ERROR, "Received :path twice"); return NULL; } calld->seen_path = 1; return md; - } else if (md->key == channeld->authority_key) { + } else if (md->key == GRPC_MDSTR_AUTHORITY) { calld->seen_authority = 1; return md; - } else if (md->key == channeld->host_key) { + } else if (md->key == GRPC_MDSTR_HOST) { /* translate host to :authority since :authority may be omitted */ grpc_mdelem *authority = grpc_mdelem_from_metadata_strings( - channeld->mdctx, GRPC_MDSTR_REF(channeld->authority_key), - GRPC_MDSTR_REF(md->value)); + calld->mdctx, GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value)); GRPC_MDELEM_UNREF(md); calld->seen_authority = 1; return authority; @@ -191,15 +175,14 @@ static void hs_mutate_op(grpc_call_element *elem, grpc_transport_stream_op *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; - channel_data *channeld = elem->channel_data; if (op->send_initial_metadata != NULL && !calld->sent_status) { calld->sent_status = 1; grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status, - GRPC_MDELEM_REF(channeld->status_ok)); - grpc_metadata_batch_add_tail(op->send_initial_metadata, - &calld->content_type, - GRPC_MDELEM_REF(channeld->content_type)); + GRPC_MDELEM_STATUS_200); + grpc_metadata_batch_add_tail( + op->send_initial_metadata, &calld->content_type, + GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); } if (op->recv_initial_metadata) { @@ -228,6 +211,7 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, /* initialize members */ memset(calld, 0, sizeof(*calld)); grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem); + calld->mdctx = args->metadata_context; } /* Destructor for call_data */ @@ -238,56 +222,12 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, static void init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { - /* grab pointers to our data from the channel element */ - channel_data *channeld = elem->channel_data; - - /* The first and the last filters tend to be implemented differently to - handle the case that there's no 'next' filter to call on the up or down - path */ GPR_ASSERT(!args->is_last); - - /* initialize members */ - channeld->te_trailers = - grpc_mdelem_from_strings(args->metadata_context, "te", "trailers"); - channeld->status_ok = - grpc_mdelem_from_strings(args->metadata_context, ":status", "200"); - channeld->status_not_found = - grpc_mdelem_from_strings(args->metadata_context, ":status", "404"); - channeld->method_post = - grpc_mdelem_from_strings(args->metadata_context, ":method", "POST"); - channeld->http_scheme = - grpc_mdelem_from_strings(args->metadata_context, ":scheme", "http"); - channeld->https_scheme = - grpc_mdelem_from_strings(args->metadata_context, ":scheme", "https"); - channeld->grpc_scheme = - grpc_mdelem_from_strings(args->metadata_context, ":scheme", "grpc"); - channeld->path_key = grpc_mdstr_from_string(args->metadata_context, ":path"); - channeld->authority_key = - grpc_mdstr_from_string(args->metadata_context, ":authority"); - channeld->host_key = grpc_mdstr_from_string(args->metadata_context, "host"); - channeld->content_type = grpc_mdelem_from_strings( - args->metadata_context, "content-type", "application/grpc"); - - channeld->mdctx = args->metadata_context; } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { - /* grab pointers to our data from the channel element */ - channel_data *channeld = elem->channel_data; - - GRPC_MDELEM_UNREF(channeld->te_trailers); - GRPC_MDELEM_UNREF(channeld->status_ok); - GRPC_MDELEM_UNREF(channeld->status_not_found); - GRPC_MDELEM_UNREF(channeld->method_post); - GRPC_MDELEM_UNREF(channeld->http_scheme); - GRPC_MDELEM_UNREF(channeld->https_scheme); - GRPC_MDELEM_UNREF(channeld->grpc_scheme); - GRPC_MDELEM_UNREF(channeld->content_type); - GRPC_MDSTR_UNREF(channeld->path_key); - GRPC_MDSTR_UNREF(channeld->authority_key); - GRPC_MDSTR_UNREF(channeld->host_key); } const grpc_channel_filter grpc_http_server_filter = { diff --git a/src/core/channel/subchannel_call_holder.c b/src/core/channel/subchannel_call_holder.c index 72517145191..c5340e0eaf8 100644 --- a/src/core/channel/subchannel_call_holder.c +++ b/src/core/channel/subchannel_call_holder.c @@ -58,7 +58,7 @@ static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, void grpc_subchannel_call_holder_init( grpc_subchannel_call_holder *holder, grpc_subchannel_call_holder_pick_subchannel pick_subchannel, - void *pick_subchannel_arg) { + void *pick_subchannel_arg, grpc_mdctx *mdctx) { gpr_atm_rel_store(&holder->subchannel_call, 0); holder->pick_subchannel = pick_subchannel; holder->pick_subchannel_arg = pick_subchannel_arg; @@ -68,6 +68,7 @@ void grpc_subchannel_call_holder_init( holder->waiting_ops_count = 0; holder->waiting_ops_capacity = 0; holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; + holder->mdctx = mdctx; } void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx, @@ -156,9 +157,9 @@ retry: holder->subchannel != NULL) { holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_CREATING_CALL; grpc_closure_init(&holder->next_step, call_ready, holder); - if (grpc_subchannel_create_call(exec_ctx, holder->subchannel, - holder->pollset, &holder->subchannel_call, - &holder->next_step)) { + if (grpc_subchannel_create_call( + exec_ctx, holder->subchannel, holder->pollset, holder->mdctx, + &holder->subchannel_call, &holder->next_step)) { /* got one immediately - continue the op (and any waiting ops) */ holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; retry_waiting_locked(exec_ctx, holder); @@ -184,9 +185,9 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, int success) { fail_locked(exec_ctx, holder); } else { grpc_closure_init(&holder->next_step, call_ready, holder); - if (grpc_subchannel_create_call(exec_ctx, holder->subchannel, - holder->pollset, &holder->subchannel_call, - &holder->next_step)) { + if (grpc_subchannel_create_call( + exec_ctx, holder->subchannel, holder->pollset, holder->mdctx, + &holder->subchannel_call, &holder->next_step)) { holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; /* got one immediately - continue the op (and any waiting ops) */ retry_waiting_locked(exec_ctx, holder); diff --git a/src/core/channel/subchannel_call_holder.h b/src/core/channel/subchannel_call_holder.h index bda051c5660..a770be257c1 100644 --- a/src/core/channel/subchannel_call_holder.h +++ b/src/core/channel/subchannel_call_holder.h @@ -68,6 +68,8 @@ typedef struct grpc_subchannel_call_holder { grpc_subchannel_call_holder_pick_subchannel pick_subchannel; void *pick_subchannel_arg; + grpc_mdctx *mdctx; + gpr_mu mu; grpc_subchannel_call_holder_creation_phase creation_phase; @@ -84,7 +86,7 @@ typedef struct grpc_subchannel_call_holder { void grpc_subchannel_call_holder_init( grpc_subchannel_call_holder *holder, grpc_subchannel_call_holder_pick_subchannel pick_subchannel, - void *pick_subchannel_arg); + void *pick_subchannel_arg, grpc_mdctx *mdctx); void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder); diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c index b15a9033af8..5f906a82fb1 100644 --- a/src/core/client_config/subchannel.c +++ b/src/core/client_config/subchannel.c @@ -73,6 +73,7 @@ typedef struct waiting_for_connect { grpc_pollset *pollset; gpr_atm *target; grpc_subchannel *subchannel; + grpc_mdctx *mdctx; grpc_closure continuation; } waiting_for_connect; @@ -87,8 +88,6 @@ struct grpc_subchannel { /** address to connect to */ struct sockaddr *addr; size_t addr_len; - /** metadata context */ - grpc_mdctx *mdctx; /** master channel - the grpc_channel instance that ultimately owns this channel_data via its channel stack. We occasionally use this to bump the refcount on the master channel @@ -147,8 +146,8 @@ struct grpc_subchannel_call { (((grpc_subchannel_call *)(callstack)) - 1) static grpc_subchannel_call *create_call(grpc_exec_ctx *exec_ctx, - connection *con, - grpc_pollset *pollset); + connection *con, grpc_pollset *pollset, + grpc_mdctx *mdctx); static void connectivity_state_changed_locked(grpc_exec_ctx *exec_ctx, grpc_subchannel *c, const char *reason); @@ -267,7 +266,6 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { gpr_free((void *)c->filters); grpc_channel_args_destroy(c->args); gpr_free(c->addr); - grpc_mdctx_unref(c->mdctx); grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker); grpc_connector_unref(exec_ctx, c->connector); gpr_free(c); @@ -306,11 +304,9 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector, memcpy(c->addr, args->addr, args->addr_len); c->addr_len = args->addr_len; c->args = grpc_channel_args_copy(args->args); - c->mdctx = args->mdctx; c->master = args->master; c->pollset_set = grpc_client_channel_get_connecting_pollset_set(parent_elem); c->random = random_seed(); - grpc_mdctx_ref(c->mdctx); grpc_closure_init(&c->connected, subchannel_connected, c); grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, "subchannel"); @@ -398,8 +394,9 @@ static void continue_creating_call(grpc_exec_ctx *exec_ctx, void *arg, int call_creation_finished_ok; waiting_for_connect *w4c = arg; grpc_subchannel_del_interested_party(exec_ctx, w4c->subchannel, w4c->pollset); - call_creation_finished_ok = grpc_subchannel_create_call( - exec_ctx, w4c->subchannel, w4c->pollset, w4c->target, w4c->notify); + call_creation_finished_ok = + grpc_subchannel_create_call(exec_ctx, w4c->subchannel, w4c->pollset, + w4c->mdctx, w4c->target, w4c->notify); GPR_ASSERT(call_creation_finished_ok == 1); w4c->notify->cb(exec_ctx, w4c->notify->cb_arg, iomgr_success); GRPC_SUBCHANNEL_UNREF(exec_ctx, w4c->subchannel, "waiting_for_connect"); @@ -407,8 +404,8 @@ static void continue_creating_call(grpc_exec_ctx *exec_ctx, void *arg, } int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx, grpc_subchannel *c, - grpc_pollset *pollset, gpr_atm *target, - grpc_closure *notify) { + grpc_pollset *pollset, grpc_mdctx *mdctx, + gpr_atm *target, grpc_closure *notify) { connection *con; grpc_subchannel_call *call; GPR_TIMER_BEGIN("grpc_subchannel_create_call", 0); @@ -418,7 +415,7 @@ int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx, grpc_subchannel *c, CONNECTION_REF_LOCKED(con, "call"); gpr_mu_unlock(&c->mu); - call = create_call(exec_ctx, con, pollset); + call = create_call(exec_ctx, con, pollset, mdctx); if (!gpr_atm_rel_cas(target, 0, (gpr_atm)(gpr_uintptr)call)) { GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "failed to set"); } @@ -431,6 +428,7 @@ int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx, grpc_subchannel *c, w4c->pollset = pollset; w4c->target = target; w4c->subchannel = c; + w4c->mdctx = mdctx; /* released when clearing w4c */ SUBCHANNEL_REF_LOCKED(c, "waiting_for_connect"); grpc_closure_init(&w4c->continuation, continue_creating_call, w4c); @@ -624,7 +622,7 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { con->refs = 0; con->subchannel = c; grpc_channel_stack_init(exec_ctx, filters, num_filters, c->master, c->args, - c->mdctx, stk); + stk); grpc_connected_channel_bind_transport(stk, c->connecting_result.transport); gpr_free((void *)c->connecting_result.filters); memset(&c->connecting_result, 0, sizeof(c->connecting_result)); @@ -858,23 +856,19 @@ void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx, } static grpc_subchannel_call *create_call(grpc_exec_ctx *exec_ctx, - connection *con, - grpc_pollset *pollset) { + connection *con, grpc_pollset *pollset, + grpc_mdctx *mdctx) { grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); grpc_subchannel_call *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call); call->connection = con; grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call, - NULL, NULL, callstk); + NULL, NULL, mdctx, callstk); grpc_call_stack_set_pollset(exec_ctx, callstk, pollset); return call; } -grpc_mdctx *grpc_subchannel_get_mdctx(grpc_subchannel *subchannel) { - return subchannel->mdctx; -} - grpc_channel *grpc_subchannel_get_master(grpc_subchannel *subchannel) { return subchannel->master; } diff --git a/src/core/client_config/subchannel.h b/src/core/client_config/subchannel.h index 381b7689b89..02ff25eb21d 100644 --- a/src/core/client_config/subchannel.h +++ b/src/core/client_config/subchannel.h @@ -84,8 +84,8 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, * asynchronously, invoking the \a notify callback upon completion. */ int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx, grpc_subchannel *subchannel, - grpc_pollset *pollset, gpr_atm *target, - grpc_closure *notify); + grpc_pollset *pollset, grpc_mdctx *mdctx, + gpr_atm *target, grpc_closure *notify); /** cancel \a call in the waiting state. */ void grpc_subchannel_cancel_create_call(grpc_exec_ctx *exec_ctx, @@ -157,9 +157,6 @@ struct grpc_subchannel_args { grpc_subchannel *grpc_subchannel_create(grpc_connector *connector, grpc_subchannel_args *args); -/** Return the metadata context associated with the subchannel */ -grpc_mdctx *grpc_subchannel_get_mdctx(grpc_subchannel *subchannel); - /** Return the master channel associated with the subchannel */ grpc_channel *grpc_subchannel_get_master(grpc_subchannel *subchannel); diff --git a/src/core/compression/algorithm.c b/src/core/compression/algorithm.c index fd95a3c8912..73d91fa8ea5 100644 --- a/src/core/compression/algorithm.c +++ b/src/core/compression/algorithm.c @@ -37,7 +37,9 @@ #include #include +#include "src/core/compression/algorithm_metadata.h" #include "src/core/surface/api_trace.h" +#include "src/core/transport/static_metadata.h" int grpc_compression_algorithm_parse(const char *name, size_t name_length, grpc_compression_algorithm *algorithm) { @@ -72,17 +74,55 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, switch (algorithm) { case GRPC_COMPRESS_NONE: *name = "identity"; - break; + return 1; case GRPC_COMPRESS_DEFLATE: *name = "deflate"; - break; + return 1; case GRPC_COMPRESS_GZIP: *name = "gzip"; - break; - default: + return 1; + case GRPC_COMPRESS_ALGORITHMS_COUNT: return 0; } - return 1; + return 0; +} + +grpc_compression_algorithm grpc_compression_algorithm_from_mdstr( + grpc_mdstr *str) { + if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE; + if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE; + if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP; + return GRPC_COMPRESS_ALGORITHMS_COUNT; +} + +grpc_mdstr *grpc_compression_algorithm_mdstr( + grpc_compression_algorithm algorithm) { + switch (algorithm) { + case GRPC_COMPRESS_NONE: + return GRPC_MDSTR_IDENTITY; + case GRPC_COMPRESS_DEFLATE: + return GRPC_MDSTR_DEFLATE; + case GRPC_COMPRESS_GZIP: + return GRPC_MDSTR_GZIP; + case GRPC_COMPRESS_ALGORITHMS_COUNT: + return NULL; + } + return NULL; +} + +grpc_mdelem *grpc_compression_encoding_mdelem( + grpc_compression_algorithm algorithm) { + switch (algorithm) { + case GRPC_COMPRESS_NONE: + return GRPC_MDELEM_GRPC_ENCODING_IDENTITY; + case GRPC_COMPRESS_DEFLATE: + return GRPC_MDELEM_GRPC_ENCODING_DEFLATE; + case GRPC_COMPRESS_GZIP: + return GRPC_MDELEM_GRPC_ENCODING_GZIP; + case GRPC_COMPRESS_ALGORITHMS_COUNT: + return NULL; + } + return NULL; } /* TODO(dgq): Add the ability to specify parameters to the individual diff --git a/src/core/compression/algorithm_metadata.h b/src/core/compression/algorithm_metadata.h new file mode 100644 index 00000000000..882633c3074 --- /dev/null +++ b/src/core/compression/algorithm_metadata.h @@ -0,0 +1,53 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_CORE_COMPRESSION_ALGORITHM_METADATA_H +#define GRPC_INTERNAL_CORE_COMPRESSION_ALGORITHM_METADATA_H + +#include +#include "src/core/transport/metadata.h" + +/** Return compression algorithm based metadata value */ +grpc_mdstr *grpc_compression_algorithm_mdstr( + grpc_compression_algorithm algorithm); + +/** Return compression algorithm based metadata element (grpc-encoding: xxx) */ +grpc_mdelem *grpc_compression_encoding_mdelem( + grpc_compression_algorithm algorithm); + +/** Find compression algorithm based on passed in mdstr - returns + * GRPC_COMPRESS_ALGORITHM_COUNT on failure */ +grpc_compression_algorithm grpc_compression_algorithm_from_mdstr( + grpc_mdstr *str); + +#endif /* GRPC_INTERNAL_CORE_COMPRESSION_ALGORITHM_METADATA_H */ diff --git a/src/core/surface/call.c b/src/core/surface/call.c index aa435d44d38..de0afb93b30 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -43,6 +43,7 @@ #include #include "src/core/channel/channel_stack.h" +#include "src/core/compression/algorithm_metadata.h" #include "src/core/iomgr/timer.h" #include "src/core/profiling/timers.h" #include "src/core/support/string.h" @@ -50,6 +51,7 @@ #include "src/core/surface/call.h" #include "src/core/surface/channel.h" #include "src/core/surface/completion_queue.h" +#include "src/core/transport/static_metadata.h" /** The maximum number of concurrent batches possible. Based upon the maximum number of individually queueable ops in the batch @@ -271,6 +273,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call, /* initial refcount dropped by grpc_call_destroy */ grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call, call->context, server_transport_data, + grpc_channel_get_metadata_context(channel), CALL_STACK_FROM_CALL(call)); if (cq != NULL) { GRPC_CQ_INTERNAL_REF(cq, "bind"); @@ -788,8 +791,12 @@ static void destroy_status(void *ignored) {} static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; - void *user_data = grpc_mdelem_get_user_data(md, destroy_status); - if (user_data) { + void *user_data; + if (md == GRPC_MDELEM_GRPC_STATUS_0) return 0; + if (md == GRPC_MDELEM_GRPC_STATUS_1) return 1; + if (md == GRPC_MDELEM_GRPC_STATUS_2) return 2; + user_data = grpc_mdelem_get_user_data(md, destroy_status); + if (user_data != NULL) { status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), @@ -803,38 +810,23 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { return status; } -/* just as for status above, we need to offset: metadata userdata can't hold a - * zero (null), which in this case is used to signal no compression */ -#define COMPRESS_OFFSET 1 -static void destroy_compression(void *ignored) {} - static gpr_uint32 decode_compression(grpc_mdelem *md) { - grpc_compression_algorithm algorithm; - void *user_data = grpc_mdelem_get_user_data(md, destroy_compression); - if (user_data) { - algorithm = - ((grpc_compression_algorithm)(gpr_intptr)user_data) - COMPRESS_OFFSET; - } else { + grpc_compression_algorithm algorithm = + grpc_compression_algorithm_from_mdstr(md->value); + if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) { const char *md_c_str = grpc_mdstr_as_c_string(md->value); - if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str), - &algorithm)) { - gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str); - assert(0); - } - grpc_mdelem_set_user_data( - md, destroy_compression, - (void *)(gpr_intptr)(algorithm + COMPRESS_OFFSET)); + gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str); } return algorithm; } static grpc_mdelem *recv_common_filter(grpc_call *call, grpc_mdelem *elem) { - if (elem->key == grpc_channel_get_status_string(call->channel)) { + if (elem->key == GRPC_MDSTR_GRPC_STATUS) { GPR_TIMER_BEGIN("status", 0); set_status_code(call, STATUS_FROM_WIRE, decode_status(elem)); GPR_TIMER_END("status", 0); return NULL; - } else if (elem->key == grpc_channel_get_message_string(call->channel)) { + } else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) { GPR_TIMER_BEGIN("status-details", 0); set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(elem->value)); GPR_TIMER_END("status-details", 0); @@ -867,14 +859,12 @@ static grpc_mdelem *recv_initial_filter(void *callp, grpc_mdelem *elem) { elem = recv_common_filter(call, elem); if (elem == NULL) { return NULL; - } else if (elem->key == - grpc_channel_get_compression_algorithm_string(call->channel)) { + } else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) { GPR_TIMER_BEGIN("compression_algorithm", 0); set_compression_algorithm(call, decode_compression(elem)); GPR_TIMER_END("compression_algorithm", 0); return NULL; - } else if (elem->key == grpc_channel_get_encodings_accepted_by_peer_string( - call->channel)) { + } else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) { GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0); set_encodings_accepted_by_peer(call, elem); GPR_TIMER_END("encodings_accepted_by_peer", 0); @@ -1240,8 +1230,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->channel, op->data.send_status_from_server.status); if (op->data.send_status_from_server.status_details != NULL) { call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings( - call->metadata_context, - GRPC_MDSTR_REF(grpc_channel_get_message_string(call->channel)), + call->metadata_context, GRPC_MDSTR_GRPC_MESSAGE, grpc_mdstr_from_string( call->metadata_context, op->data.send_status_from_server.status_details)); diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index a9a5f828f27..0ca877a394a 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -46,6 +46,7 @@ #include "src/core/surface/api_trace.h" #include "src/core/surface/call.h" #include "src/core/surface/init.h" +#include "src/core/transport/static_metadata.h" /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS. * Avoids needing to take a metadata context lock for sending status @@ -65,16 +66,7 @@ struct grpc_channel { gpr_refcount refs; gpr_uint32 max_message_length; grpc_mdctx *metadata_context; - /** mdstr for the grpc-status key */ - grpc_mdstr *grpc_status_string; - grpc_mdstr *grpc_compression_algorithm_string; - grpc_mdstr *grpc_encodings_accepted_by_peer_string; - grpc_mdstr *grpc_message_string; - grpc_mdstr *path_string; - grpc_mdstr *authority_string; grpc_mdelem *default_authority; - /** mdelem for grpc-status: 0 thru grpc-status: 2 */ - grpc_mdelem *grpc_status_elem[NUM_CACHED_STATUS_ELEMS]; gpr_mu registered_call_mu; registered_call *registered_calls; @@ -90,6 +82,55 @@ struct grpc_channel { /* the protobuf library will (by default) start warning at 100megs */ #define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024) +static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx, + const grpc_channel_args *args) { + gpr_strvec v; + size_t i; + int is_first = 1; + char *tmp; + grpc_mdstr *result; + + gpr_strvec_init(&v); + + for (i = 0; args && i < args->num_args; i++) { + if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) { + if (args->args[i].type != GRPC_ARG_STRING) { + gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", + GRPC_ARG_PRIMARY_USER_AGENT_STRING); + } else { + if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); + is_first = 0; + gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string)); + } + } + } + + gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ", + grpc_version_string(), GPR_PLATFORM_STRING); + is_first = 0; + gpr_strvec_add(&v, tmp); + + for (i = 0; args && i < args->num_args; i++) { + if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) { + if (args->args[i].type != GRPC_ARG_STRING) { + gpr_log(GPR_ERROR, "Channel argument '%s' should be a string", + GRPC_ARG_SECONDARY_USER_AGENT_STRING); + } else { + if (!is_first) gpr_strvec_add(&v, gpr_strdup(" ")); + is_first = 0; + gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string)); + } + } + } + + tmp = gpr_strvec_flatten(&v, NULL); + gpr_strvec_destroy(&v); + result = grpc_mdstr_from_string(mdctx, tmp); + gpr_free(tmp); + + return result; +} + grpc_channel *grpc_channel_create_from_filters( grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_filter **filters, size_t num_filters, @@ -105,24 +146,16 @@ grpc_channel *grpc_channel_create_from_filters( /* decremented by grpc_channel_destroy */ gpr_ref_init(&channel->refs, 1); channel->metadata_context = mdctx; - channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status"); - channel->grpc_compression_algorithm_string = - grpc_mdstr_from_string(mdctx, "grpc-encoding"); - channel->grpc_encodings_accepted_by_peer_string = - grpc_mdstr_from_string(mdctx, "grpc-accept-encoding"); - channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message"); - for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { - char buf[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa((long)i, buf); - channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings( - mdctx, GRPC_MDSTR_REF(channel->grpc_status_string), - grpc_mdstr_from_string(mdctx, buf)); - } - channel->path_string = grpc_mdstr_from_string(mdctx, ":path"); - channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority"); gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; + if (is_client) { + grpc_mdctx_set_mdelem_cache( + mdctx, GRPC_MDELEM_CACHED_USER_AGENT, + grpc_mdelem_from_metadata_strings(mdctx, GRPC_MDSTR_USER_AGENT, + user_agent_from_args(mdctx, args))); + } + channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH; if (args) { for (i = 0; i < args->num_args; i++) { @@ -178,7 +211,6 @@ grpc_channel *grpc_channel_create_from_filters( } grpc_channel_stack_init(exec_ctx, filters, num_filters, channel, args, - channel->metadata_context, CHANNEL_STACK_FROM_CHANNEL(channel)); return channel; @@ -228,11 +260,10 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel, return grpc_channel_create_call_internal( channel, parent_call, propagation_mask, cq, grpc_mdelem_from_metadata_strings( - channel->metadata_context, GRPC_MDSTR_REF(channel->path_string), + channel->metadata_context, GRPC_MDSTR_PATH, grpc_mdstr_from_string(channel->metadata_context, method)), host ? grpc_mdelem_from_metadata_strings( - channel->metadata_context, - GRPC_MDSTR_REF(channel->authority_string), + channel->metadata_context, GRPC_MDSTR_AUTHORITY, grpc_mdstr_from_string(channel->metadata_context, host)) : NULL, deadline); @@ -246,12 +277,11 @@ void *grpc_channel_register_call(grpc_channel *channel, const char *method, 4, (channel, method, host, reserved)); GPR_ASSERT(!reserved); rc->path = grpc_mdelem_from_metadata_strings( - channel->metadata_context, GRPC_MDSTR_REF(channel->path_string), + channel->metadata_context, GRPC_MDSTR_PATH, grpc_mdstr_from_string(channel->metadata_context, method)); rc->authority = host ? grpc_mdelem_from_metadata_strings( - channel->metadata_context, - GRPC_MDSTR_REF(channel->authority_string), + channel->metadata_context, GRPC_MDSTR_AUTHORITY, grpc_mdstr_from_string(channel->metadata_context, host)) : NULL; gpr_mu_lock(&channel->registered_call_mu); @@ -293,17 +323,7 @@ void grpc_channel_internal_ref(grpc_channel *c) { } static void destroy_channel(grpc_exec_ctx *exec_ctx, grpc_channel *channel) { - size_t i; grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel)); - for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { - GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]); - } - GRPC_MDSTR_UNREF(channel->grpc_status_string); - GRPC_MDSTR_UNREF(channel->grpc_compression_algorithm_string); - GRPC_MDSTR_UNREF(channel->grpc_encodings_accepted_by_peer_string); - GRPC_MDSTR_UNREF(channel->grpc_message_string); - GRPC_MDSTR_UNREF(channel->path_string); - GRPC_MDSTR_UNREF(channel->authority_string); while (channel->registered_calls) { registered_call *rc = channel->registered_calls; channel->registered_calls = rc->next; @@ -316,6 +336,7 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, grpc_channel *channel) { if (channel->default_authority != NULL) { GRPC_MDELEM_UNREF(channel->default_authority); } + grpc_mdctx_drop_caches(channel->metadata_context); grpc_mdctx_unref(channel->metadata_context); gpr_mu_destroy(&channel->registered_call_mu); gpr_free(channel->target); @@ -359,34 +380,20 @@ grpc_mdctx *grpc_channel_get_metadata_context(grpc_channel *channel) { return channel->metadata_context; } -grpc_mdstr *grpc_channel_get_status_string(grpc_channel *channel) { - return channel->grpc_status_string; -} - -grpc_mdstr *grpc_channel_get_compression_algorithm_string( - grpc_channel *channel) { - return channel->grpc_compression_algorithm_string; -} - -grpc_mdstr *grpc_channel_get_encodings_accepted_by_peer_string( - grpc_channel *channel) { - return channel->grpc_encodings_accepted_by_peer_string; -} - grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) { - if (i >= 0 && i < NUM_CACHED_STATUS_ELEMS) { - return GRPC_MDELEM_REF(channel->grpc_status_elem[i]); - } else { - char tmp[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(i, tmp); - return grpc_mdelem_from_metadata_strings( - channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string), - grpc_mdstr_from_string(channel->metadata_context, tmp)); + char tmp[GPR_LTOA_MIN_BUFSIZE]; + switch (i) { + case 0: + return GRPC_MDELEM_GRPC_STATUS_0; + case 1: + return GRPC_MDELEM_GRPC_STATUS_1; + case 2: + return GRPC_MDELEM_GRPC_STATUS_2; } -} - -grpc_mdstr *grpc_channel_get_message_string(grpc_channel *channel) { - return channel->grpc_message_string; + gpr_ltoa(i, tmp); + return grpc_mdelem_from_metadata_strings( + channel->metadata_context, GRPC_MDSTR_GRPC_STATUS, + grpc_mdstr_from_string(channel->metadata_context, tmp)); } gpr_uint32 grpc_channel_get_max_message_length(grpc_channel *channel) { diff --git a/src/core/surface/channel.h b/src/core/surface/channel.h index e5030d52d2f..8bafce4216a 100644 --- a/src/core/surface/channel.h +++ b/src/core/surface/channel.h @@ -54,12 +54,6 @@ grpc_mdctx *grpc_channel_get_metadata_context(grpc_channel *channel); The returned elem is owned by the caller. */ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int status_code); -grpc_mdstr *grpc_channel_get_status_string(grpc_channel *channel); -grpc_mdstr *grpc_channel_get_compression_algorithm_string( - grpc_channel *channel); -grpc_mdstr *grpc_channel_get_encodings_accepted_by_peer_string( - grpc_channel *channel); -grpc_mdstr *grpc_channel_get_message_string(grpc_channel *channel); gpr_uint32 grpc_channel_get_max_message_length(grpc_channel *channel); #ifdef GRPC_CHANNEL_REF_COUNT_DEBUG diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index fc458a603d3..96ad012addb 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -46,10 +46,10 @@ typedef struct { grpc_linked_mdelem status; grpc_linked_mdelem details; + grpc_mdctx *mdctx; } call_data; typedef struct { - grpc_mdctx *mdctx; grpc_channel *master; grpc_status_code error_code; const char *error_message; @@ -60,8 +60,8 @@ static void fill_metadata(grpc_call_element *elem, grpc_metadata_batch *mdb) { channel_data *chand = elem->channel_data; char tmp[GPR_LTOA_MIN_BUFSIZE]; gpr_ltoa(chand->error_code, tmp); - calld->status.md = grpc_mdelem_from_strings(chand->mdctx, "grpc-status", tmp); - calld->details.md = grpc_mdelem_from_strings(chand->mdctx, "grpc-message", + calld->status.md = grpc_mdelem_from_strings(calld->mdctx, "grpc-status", tmp); + calld->details.md = grpc_mdelem_from_strings(calld->mdctx, "grpc-message", chand->error_message); calld->status.prev = calld->details.next = NULL; calld->status.next = &calld->details; @@ -104,7 +104,10 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx, } static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) {} + grpc_call_element_args *args) { + call_data *calld = elem->call_data; + calld->mdctx = args->metadata_context; +} static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {} @@ -115,7 +118,6 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx, channel_data *chand = elem->channel_data; GPR_ASSERT(args->is_first); GPR_ASSERT(args->is_last); - chand->mdctx = args->metadata_context; chand->master = args->master; } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index e9f380083f8..d33c4218770 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -54,6 +54,7 @@ #include "src/core/surface/completion_queue.h" #include "src/core/surface/init.h" #include "src/core/transport/metadata.h" +#include "src/core/transport/static_metadata.h" typedef struct listener { void *arg; @@ -108,8 +109,6 @@ struct channel_data { grpc_server *server; grpc_connectivity_state connectivity_state; grpc_channel *channel; - grpc_mdstr *path_key; - grpc_mdstr *authority_key; /* linked list of all channels on a server */ channel_data *next; channel_data *prev; @@ -558,12 +557,11 @@ static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) { grpc_call_element *elem = user_data; - channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; - if (md->key == chand->path_key) { + if (md->key == GRPC_MDSTR_PATH) { calld->path = GRPC_MDSTR_REF(md->value); return NULL; - } else if (md->key == chand->authority_key) { + } else if (md->key == GRPC_MDSTR_AUTHORITY) { calld->host = GRPC_MDSTR_REF(md->value); return NULL; } @@ -718,9 +716,6 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx, GPR_ASSERT(!args->is_last); chand->server = NULL; chand->channel = NULL; - chand->path_key = grpc_mdstr_from_string(args->metadata_context, ":path"); - chand->authority_key = - grpc_mdstr_from_string(args->metadata_context, ":authority"); chand->next = chand->prev = chand; chand->registered_methods = NULL; chand->connectivity_state = GRPC_CHANNEL_IDLE; @@ -750,8 +745,6 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, chand->next = chand->prev = chand; maybe_finish_shutdown(exec_ctx, chand->server); gpr_mu_unlock(&chand->server->mu_global); - GRPC_MDSTR_UNREF(chand->path_key); - GRPC_MDSTR_UNREF(chand->authority_key); server_unref(exec_ctx, chand->server); } } diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index fa941a73c6d..cbec63c8686 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -37,12 +37,15 @@ #include #include +#include #include #include #include +#include #include #include "src/core/profiling/timers.h" #include "src/core/support/murmur_hash.h" +#include "src/core/support/string.h" #include "src/core/transport/chttp2/bin_encoder.h" #include "src/core/transport/static_metadata.h" @@ -157,6 +160,11 @@ struct grpc_mdctx { size_t mdtab_count; size_t mdtab_free; size_t mdtab_capacity; + + /* cache slots */ + gpr_atm cache_slots[GRPC_MDELEM_CACHE_SLOT_COUNT]; + /* compression algorithm mdelems: one per algorithm bitmask */ + gpr_atm compression_algorithm_mdelem[1 << GRPC_COMPRESS_ALGORITHMS_COUNT]; }; static void internal_string_ref(internal_string *s DEBUG_ARGS); @@ -175,8 +183,10 @@ void grpc_mdctx_global_init(void) { } for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) { grpc_mdelem *elem = &grpc_static_mdelem_table[i]; - grpc_mdstr *key = &grpc_static_mdstr_table[2 * i + 0]; - grpc_mdstr *value = &grpc_static_mdstr_table[2 * i + 1]; + grpc_mdstr *key = + &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]]; + grpc_mdstr *value = + &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]]; *(grpc_mdstr **)&elem->key = key; *(grpc_mdstr **)&elem->value = value; } @@ -304,6 +314,42 @@ grpc_mdctx *grpc_mdctx_create(void) { (gpr_uint32)gpr_now(GPR_CLOCK_REALTIME).tv_nsec); } +static void drop_cached_elem(gpr_atm *slot) { + gpr_atm value = gpr_atm_no_barrier_load(slot); + gpr_atm_rel_store(slot, 0); + GRPC_MDELEM_UNREF((grpc_mdelem *)value); +} + +void grpc_mdctx_drop_caches(grpc_mdctx *ctx) { + size_t i; + for (i = 0; i < GRPC_MDELEM_CACHE_SLOT_COUNT; i++) { + drop_cached_elem(&ctx->cache_slots[i]); + } + for (i = 0; i < GPR_ARRAY_SIZE(ctx->compression_algorithm_mdelem); i++) { + drop_cached_elem(&ctx->compression_algorithm_mdelem[i]); + } +} + +static void set_cache(gpr_atm *slot, grpc_mdelem *elem) { + if (!gpr_atm_rel_cas(slot, 0, (gpr_atm)elem)) { + GRPC_MDELEM_UNREF(elem); + } +} + +void grpc_mdctx_set_mdelem_cache(grpc_mdctx *ctx, grpc_mdelem_cache_slot slot, + grpc_mdelem *elem) { + set_cache(&ctx->cache_slots[slot], elem); +} + +static grpc_mdelem *get_cache(gpr_atm *slot) { + return (grpc_mdelem *)gpr_atm_acq_load(slot); +} + +grpc_mdelem *grpc_mdelem_from_cache(grpc_mdctx *ctx, + grpc_mdelem_cache_slot slot) { + return get_cache(&ctx->cache_slots[slot]); +} + static void discard_metadata(grpc_mdctx *ctx) { size_t i; internal_metadata *next, *cur; @@ -780,6 +826,7 @@ void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) { void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *), void *user_data) { internal_metadata *im = (internal_metadata *)md; + GPR_ASSERT(!is_mdelem_static(md)); GPR_ASSERT((user_data == NULL) == (destroy_func == NULL)); gpr_mu_lock(&im->mu_user_data); if (gpr_atm_no_barrier_load(&im->destroy_user_data)) { @@ -838,6 +885,52 @@ int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s) { return conforms_to(s, legal_header_bits); } +static grpc_mdelem *make_accept_encoding_mdelem_for_compression_algorithms( + grpc_mdctx *mdctx, gpr_uint32 algorithms) { + gpr_strvec sv; + int i; + char *str; + grpc_mdelem *out; + + gpr_strvec_init(&sv); + for (i = 0; algorithms != 0; i++, algorithms >>= 1) { + if (algorithms & 1) { + char *name; + GPR_ASSERT(grpc_compression_algorithm_name((grpc_compression_algorithm)i, + &name)); + if (sv.count) { + gpr_strvec_add(&sv, gpr_strdup(",")); + } + gpr_strvec_add(&sv, gpr_strdup(name)); + } + } + str = gpr_strvec_flatten(&sv, NULL); + out = + grpc_mdelem_from_metadata_strings(mdctx, GRPC_MDSTR_GRPC_ACCEPT_ENCODING, + grpc_mdstr_from_string(mdctx, str)); + gpr_strvec_destroy(&sv); + gpr_free(str); + return out; +} + +grpc_mdelem *grpc_accept_encoding_mdelem_from_compression_algorithms( + grpc_mdctx *ctx, gpr_uint32 algorithms) { + grpc_mdelem *ret; + gpr_atm *slot; + GPR_ASSERT(algorithms < GPR_ARRAY_SIZE(ctx->compression_algorithm_mdelem)); + + slot = &ctx->compression_algorithm_mdelem[algorithms]; + ret = get_cache(slot); + if (ret == NULL) { + set_cache(slot, make_accept_encoding_mdelem_for_compression_algorithms( + ctx, algorithms)); + ret = get_cache(slot); + GPR_ASSERT(ret != NULL); + } + + return ret; +} + int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s) { /* TODO(ctiller): consider caching this */ return grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(s->slice), diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h index 7d70883fa48..0f12a7392c7 100644 --- a/src/core/transport/metadata.h +++ b/src/core/transport/metadata.h @@ -93,6 +93,8 @@ grpc_mdctx *grpc_mdctx_create_with_seed(gpr_uint32 seed); void grpc_mdctx_ref(grpc_mdctx *mdctx); void grpc_mdctx_unref(grpc_mdctx *mdctx); +void grpc_mdctx_drop_caches(grpc_mdctx *mdctx); + /* Test only accessors to internal state - only for testing this code - do not rely on it outside of metadata_test.c */ size_t grpc_mdctx_get_mdtab_capacity_test_only(grpc_mdctx *mdctx); @@ -161,6 +163,25 @@ int grpc_mdstr_is_legal_header(grpc_mdstr *s); int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s); int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s); +/* Gross layering hack (that we seem to need): + * metadata context keeps a cache of algorithm bitset to + * 'accept-encoding: algorithm1,algorithm2' in order to accelerate sending + * compression metadata */ +grpc_mdelem *grpc_accept_encoding_mdelem_from_compression_algorithms( + grpc_mdctx *ctx, gpr_uint32 algorithm_mask); + +/* Cache-slots + * A metadata context can cache (on behalf of its owner) some small set of + * metadata elements. */ +typedef enum { + GRPC_MDELEM_CACHED_USER_AGENT = 0, + GRPC_MDELEM_CACHE_SLOT_COUNT +} grpc_mdelem_cache_slot; +void grpc_mdctx_set_mdelem_cache(grpc_mdctx *ctx, grpc_mdelem_cache_slot slot, + grpc_mdelem *elem); +grpc_mdelem *grpc_mdelem_from_cache(grpc_mdctx *ctx, + grpc_mdelem_cache_slot slot); + #define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash)) void grpc_mdctx_global_init(void); diff --git a/src/core/transport/static_metadata.c b/src/core/transport/static_metadata.c index f359ce5c209..fb7c5006e11 100644 --- a/src/core/transport/static_metadata.c +++ b/src/core/transport/static_metadata.c @@ -47,18 +47,21 @@ grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; -const gpr_uint8 grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * - 2] = { - 9, 29, 8, 29, 10, 29, 10, 42, 11, 29, 12, 29, 13, 29, 14, 29, 15, 29, 16, - 29, 17, 29, 18, 29, 19, 29, 20, 29, 21, 29, 22, 29, 23, 29, 24, 29, 25, 29, - 26, 29, 27, 29, 30, 29, 31, 29, 32, 29, 33, 29, 39, 0, 43, 29, 47, 29, 48, - 29, 49, 29, 50, 29, 51, 29, 52, 29, 53, 29, 54, 29, 55, 29, 56, 34, 56, 58, - 57, 68, 57, 69, 59, 29, 60, 29, 61, 29, 62, 29, 63, 29, 64, 29, 65, 35, 65, - 44, 65, 45, 66, 29, 67, 29, 70, 1, 70, 2, 70, 3, 70, 4, 70, 5, 70, 6, - 70, 7, 71, 29, 72, 73, 74, 29, 75, 29, 76, 29, 77, 29, 78, 29}; +const gpr_uint8 + grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] = { + 11, 32, 10, 32, 12, 32, 12, 46, 13, 32, 14, 32, 15, 32, 16, 32, 17, 32, + 19, 32, 20, 32, 21, 32, 22, 32, 23, 32, 24, 32, 25, 32, 26, 32, 27, 32, + 28, 18, 28, 32, 29, 32, 30, 32, 33, 32, 34, 32, 35, 32, 36, 32, 40, 31, + 40, 45, 40, 50, 43, 0, 43, 1, 43, 2, 47, 32, 51, 32, 52, 32, 53, 32, + 54, 32, 55, 32, 56, 32, 57, 32, 58, 32, 59, 32, 60, 37, 60, 62, 61, 72, + 61, 73, 63, 32, 64, 32, 65, 32, 66, 32, 67, 32, 68, 32, 69, 38, 69, 48, + 69, 49, 70, 32, 71, 32, 74, 3, 74, 4, 74, 5, 74, 6, 74, 7, 74, 8, + 74, 9, 75, 32, 76, 77, 78, 32, 79, 32, 80, 32, 81, 32, 82, 32}; const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "0", + "1", + "2", "200", "204", "206", @@ -74,6 +77,7 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "access-control-allow-origin", "age", "allow", + "application/grpc", ":authority", "authorization", "cache-control", @@ -96,6 +100,7 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "grpc", "grpc-accept-encoding", "grpc-encoding", + "grpc-internal-encoding-request", "grpc-message", "grpc-status", "grpc-timeout", diff --git a/src/core/transport/static_metadata.h b/src/core/transport/static_metadata.h index 4a7bee1da8b..671801636b8 100644 --- a/src/core/transport/static_metadata.h +++ b/src/core/transport/static_metadata.h @@ -46,168 +46,176 @@ #include "src/core/transport/metadata.h" -#define GRPC_STATIC_MDSTR_COUNT 79 +#define GRPC_STATIC_MDSTR_COUNT 83 extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; /* "0" */ #define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0]) +/* "1" */ +#define GRPC_MDSTR_1 (&grpc_static_mdstr_table[1]) +/* "2" */ +#define GRPC_MDSTR_2 (&grpc_static_mdstr_table[2]) /* "200" */ -#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[1]) +#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[3]) /* "204" */ -#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[2]) +#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[4]) /* "206" */ -#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[3]) +#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[5]) /* "304" */ -#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[4]) +#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[6]) /* "400" */ -#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[5]) +#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[7]) /* "404" */ -#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[6]) +#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[8]) /* "500" */ -#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[7]) +#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[9]) /* "accept" */ -#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[8]) +#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[10]) /* "accept-charset" */ -#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[9]) +#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[11]) /* "accept-encoding" */ -#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[10]) +#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[12]) /* "accept-language" */ -#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[11]) +#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[13]) /* "accept-ranges" */ -#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[12]) +#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[14]) /* "access-control-allow-origin" */ -#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[13]) +#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[15]) /* "age" */ -#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[14]) +#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[16]) /* "allow" */ -#define GRPC_MDSTR_ALLOW (&grpc_static_mdstr_table[15]) +#define GRPC_MDSTR_ALLOW (&grpc_static_mdstr_table[17]) +/* "application/grpc" */ +#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (&grpc_static_mdstr_table[18]) /* ":authority" */ -#define GRPC_MDSTR_AUTHORITY (&grpc_static_mdstr_table[16]) +#define GRPC_MDSTR_AUTHORITY (&grpc_static_mdstr_table[19]) /* "authorization" */ -#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[17]) +#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20]) /* "cache-control" */ -#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[18]) +#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21]) /* "content-disposition" */ -#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[19]) +#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22]) /* "content-encoding" */ -#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[20]) +#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23]) /* "content-language" */ -#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[21]) +#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24]) /* "content-length" */ -#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[22]) +#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25]) /* "content-location" */ -#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[23]) +#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26]) /* "content-range" */ -#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[24]) +#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27]) /* "content-type" */ -#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[25]) +#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28]) /* "cookie" */ -#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[26]) +#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29]) /* "date" */ -#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[27]) +#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30]) /* "deflate" */ -#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[28]) +#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31]) /* "" */ -#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[29]) +#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[32]) /* "etag" */ -#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[30]) +#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[33]) /* "expect" */ -#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[31]) +#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[34]) /* "expires" */ -#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[32]) +#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[35]) /* "from" */ -#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[33]) +#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[36]) /* "GET" */ -#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[34]) +#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[37]) /* "grpc" */ -#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[35]) +#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[38]) /* "grpc-accept-encoding" */ -#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[36]) +#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[39]) /* "grpc-encoding" */ -#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[37]) +#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[40]) +/* "grpc-internal-encoding-request" */ +#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[41]) /* "grpc-message" */ -#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[38]) +#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[42]) /* "grpc-status" */ -#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[39]) +#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[43]) /* "grpc-timeout" */ -#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[40]) +#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[44]) /* "gzip" */ -#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[41]) +#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[45]) /* "gzip, deflate" */ -#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[42]) +#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[46]) /* "host" */ -#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[43]) +#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[47]) /* "http" */ -#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[44]) +#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[48]) /* "https" */ -#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[45]) +#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[49]) /* "identity" */ -#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[46]) +#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[50]) /* "if-match" */ -#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[47]) +#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[51]) /* "if-modified-since" */ -#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[48]) +#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[52]) /* "if-none-match" */ -#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[49]) +#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[53]) /* "if-range" */ -#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[50]) +#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[54]) /* "if-unmodified-since" */ -#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[51]) +#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[55]) /* "last-modified" */ -#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[52]) +#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[56]) /* "link" */ -#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[53]) +#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[57]) /* "location" */ -#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[54]) +#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[58]) /* "max-forwards" */ -#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[55]) +#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[59]) /* ":method" */ -#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[56]) +#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[60]) /* ":path" */ -#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[57]) +#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[61]) /* "POST" */ -#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[58]) +#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[62]) /* "proxy-authenticate" */ -#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[59]) +#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[63]) /* "proxy-authorization" */ -#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[60]) +#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[64]) /* "range" */ -#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[61]) +#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[65]) /* "referer" */ -#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[62]) +#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[66]) /* "refresh" */ -#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[63]) +#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[67]) /* "retry-after" */ -#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[64]) +#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[68]) /* ":scheme" */ -#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[65]) +#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[69]) /* "server" */ -#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[66]) +#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[70]) /* "set-cookie" */ -#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[67]) +#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[71]) /* "/" */ -#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[68]) +#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[72]) /* "/index.html" */ -#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[69]) +#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[73]) /* ":status" */ -#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[70]) +#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[74]) /* "strict-transport-security" */ -#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[71]) +#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[75]) /* "te" */ -#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[72]) +#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[76]) /* "trailers" */ -#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[73]) +#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[77]) /* "transfer-encoding" */ -#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[74]) +#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[78]) /* "user-agent" */ -#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[75]) +#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[79]) /* "vary" */ -#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[76]) +#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[80]) /* "via" */ -#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[77]) +#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[81]) /* "www-authenticate" */ -#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[78]) +#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[82]) -#define GRPC_STATIC_MDELEM_COUNT 65 +#define GRPC_STATIC_MDELEM_COUNT 71 extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; /* "accept-charset": "" */ #define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY (&grpc_static_mdelem_table[0]) @@ -247,101 +255,114 @@ extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; #define GRPC_MDELEM_CONTENT_LOCATION_EMPTY (&grpc_static_mdelem_table[16]) /* "content-range": "" */ #define GRPC_MDELEM_CONTENT_RANGE_EMPTY (&grpc_static_mdelem_table[17]) +/* "content-type": "application/grpc" */ +#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \ + (&grpc_static_mdelem_table[18]) /* "content-type": "" */ -#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (&grpc_static_mdelem_table[18]) +#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (&grpc_static_mdelem_table[19]) /* "cookie": "" */ -#define GRPC_MDELEM_COOKIE_EMPTY (&grpc_static_mdelem_table[19]) +#define GRPC_MDELEM_COOKIE_EMPTY (&grpc_static_mdelem_table[20]) /* "date": "" */ -#define GRPC_MDELEM_DATE_EMPTY (&grpc_static_mdelem_table[20]) +#define GRPC_MDELEM_DATE_EMPTY (&grpc_static_mdelem_table[21]) /* "etag": "" */ -#define GRPC_MDELEM_ETAG_EMPTY (&grpc_static_mdelem_table[21]) +#define GRPC_MDELEM_ETAG_EMPTY (&grpc_static_mdelem_table[22]) /* "expect": "" */ -#define GRPC_MDELEM_EXPECT_EMPTY (&grpc_static_mdelem_table[22]) +#define GRPC_MDELEM_EXPECT_EMPTY (&grpc_static_mdelem_table[23]) /* "expires": "" */ -#define GRPC_MDELEM_EXPIRES_EMPTY (&grpc_static_mdelem_table[23]) +#define GRPC_MDELEM_EXPIRES_EMPTY (&grpc_static_mdelem_table[24]) /* "from": "" */ -#define GRPC_MDELEM_FROM_EMPTY (&grpc_static_mdelem_table[24]) +#define GRPC_MDELEM_FROM_EMPTY (&grpc_static_mdelem_table[25]) +/* "grpc-encoding": "deflate" */ +#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE (&grpc_static_mdelem_table[26]) +/* "grpc-encoding": "gzip" */ +#define GRPC_MDELEM_GRPC_ENCODING_GZIP (&grpc_static_mdelem_table[27]) +/* "grpc-encoding": "identity" */ +#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY (&grpc_static_mdelem_table[28]) /* "grpc-status": "0" */ -#define GRPC_MDELEM_GRPC_STATUS_0 (&grpc_static_mdelem_table[25]) +#define GRPC_MDELEM_GRPC_STATUS_0 (&grpc_static_mdelem_table[29]) +/* "grpc-status": "1" */ +#define GRPC_MDELEM_GRPC_STATUS_1 (&grpc_static_mdelem_table[30]) +/* "grpc-status": "2" */ +#define GRPC_MDELEM_GRPC_STATUS_2 (&grpc_static_mdelem_table[31]) /* "host": "" */ -#define GRPC_MDELEM_HOST_EMPTY (&grpc_static_mdelem_table[26]) +#define GRPC_MDELEM_HOST_EMPTY (&grpc_static_mdelem_table[32]) /* "if-match": "" */ -#define GRPC_MDELEM_IF_MATCH_EMPTY (&grpc_static_mdelem_table[27]) +#define GRPC_MDELEM_IF_MATCH_EMPTY (&grpc_static_mdelem_table[33]) /* "if-modified-since": "" */ -#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[28]) +#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[34]) /* "if-none-match": "" */ -#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (&grpc_static_mdelem_table[29]) +#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (&grpc_static_mdelem_table[35]) /* "if-range": "" */ -#define GRPC_MDELEM_IF_RANGE_EMPTY (&grpc_static_mdelem_table[30]) +#define GRPC_MDELEM_IF_RANGE_EMPTY (&grpc_static_mdelem_table[36]) /* "if-unmodified-since": "" */ -#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[31]) +#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[37]) /* "last-modified": "" */ -#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[32]) +#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[38]) /* "link": "" */ -#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[33]) +#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[39]) /* "location": "" */ -#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[34]) +#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[40]) /* "max-forwards": "" */ -#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[35]) +#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[41]) /* ":method": "GET" */ -#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[36]) +#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[42]) /* ":method": "POST" */ -#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[37]) +#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[43]) /* ":path": "/" */ -#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[38]) +#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[44]) /* ":path": "/index.html" */ -#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[39]) +#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[45]) /* "proxy-authenticate": "" */ -#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[40]) +#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[46]) /* "proxy-authorization": "" */ -#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[41]) +#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[47]) /* "range": "" */ -#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[42]) +#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[48]) /* "referer": "" */ -#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[43]) +#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[49]) /* "refresh": "" */ -#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[44]) +#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[50]) /* "retry-after": "" */ -#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[45]) +#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[51]) /* ":scheme": "grpc" */ -#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[46]) +#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[52]) /* ":scheme": "http" */ -#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[47]) +#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[53]) /* ":scheme": "https" */ -#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[48]) +#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[54]) /* "server": "" */ -#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[49]) +#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[55]) /* "set-cookie": "" */ -#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[50]) +#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[56]) /* ":status": "200" */ -#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[51]) +#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[57]) /* ":status": "204" */ -#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[52]) +#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[58]) /* ":status": "206" */ -#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[53]) +#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[59]) /* ":status": "304" */ -#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[54]) +#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[60]) /* ":status": "400" */ -#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[55]) +#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[61]) /* ":status": "404" */ -#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[56]) +#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[62]) /* ":status": "500" */ -#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[57]) +#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[63]) /* "strict-transport-security": "" */ #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ - (&grpc_static_mdelem_table[58]) + (&grpc_static_mdelem_table[64]) /* "te": "trailers" */ -#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[59]) +#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[65]) /* "transfer-encoding": "" */ -#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[60]) +#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[66]) /* "user-agent": "" */ -#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[61]) +#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[67]) /* "vary": "" */ -#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[62]) +#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[68]) /* "via": "" */ -#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[63]) +#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[69]) /* "www-authenticate": "" */ -#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[64]) +#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[70]) const gpr_uint8 grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2]; const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT]; diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c index 08550b4934e..2a05c608bb2 100644 --- a/test/core/channel/channel_stack_test.c +++ b/test/core/channel/channel_stack_test.c @@ -109,7 +109,7 @@ static void test_create_channel_stack(void) { channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); grpc_channel_stack_init(&exec_ctx, &filters, 1, NULL, &chan_args, - metadata_context, channel_stack); + channel_stack); GPR_ASSERT(channel_stack->count == 1); channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_data = (int *)channel_elem->channel_data; @@ -117,7 +117,7 @@ static void test_create_channel_stack(void) { call_stack = gpr_malloc(channel_stack->call_stack_size); grpc_call_stack_init(&exec_ctx, channel_stack, 0, NULL, NULL, NULL, NULL, - call_stack); + metadata_context, call_stack); GPR_ASSERT(call_stack->count == 1); call_elem = grpc_call_stack_element(call_stack, 0); GPR_ASSERT(call_elem->filter == channel_elem->filter); diff --git a/test/core/end2end/fixtures/h2_uchannel.c b/test/core/end2end/fixtures/h2_uchannel.c index d1f9d38b82b..5fed175f9d5 100644 --- a/test/core/end2end/fixtures/h2_uchannel.c +++ b/test/core/end2end/fixtures/h2_uchannel.c @@ -263,7 +263,9 @@ static void chttp2_init_client_micro_fullstack(grpc_end2end_test_fixture *f, /* here sniffed_subchannel should be ready to use */ GPR_ASSERT(conn_state == GRPC_CHANNEL_IDLE); GPR_ASSERT(ffd->sniffed_subchannel != NULL); - f->client = grpc_client_uchannel_create(ffd->sniffed_subchannel, client_args); + f->client = grpc_client_uchannel_create( + ffd->sniffed_subchannel, client_args, + grpc_channel_get_metadata_context(ffd->master_channel)); grpc_client_uchannel_set_subchannel(f->client, ffd->sniffed_subchannel); gpr_log(GPR_INFO, "CHANNEL WRAPPING SUBCHANNEL: %p(%p)", f->client, ffd->sniffed_subchannel); diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c index 4e52b0e4668..a790b461b68 100644 --- a/test/core/transport/chttp2/hpack_parser_test.c +++ b/test/core/transport/chttp2/hpack_parser_test.c @@ -35,6 +35,7 @@ #include +#include #include #include #include diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c index fc9c93a7742..875ab3d77b4 100644 --- a/test/core/transport/metadata_test.c +++ b/test/core/transport/metadata_test.c @@ -35,11 +35,13 @@ #include -#include "src/core/support/string.h" -#include "src/core/transport/chttp2/bin_encoder.h" +#include #include #include #include + +#include "src/core/support/string.h" +#include "src/core/transport/chttp2/bin_encoder.h" #include "test/core/util/test_config.h" #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x) diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py index 0e84a73ea59..d52e3290233 100755 --- a/tools/codegen/core/gen_static_metadata.py +++ b/tools/codegen/core/gen_static_metadata.py @@ -41,6 +41,7 @@ import sys CONFIG = [ 'grpc-timeout', + 'grpc-internal-encoding-request', ':path', 'grpc-encoding', 'grpc-accept-encoding', @@ -54,7 +55,13 @@ CONFIG = [ 'identity', '', ('grpc-status', '0'), + ('grpc-status', '1'), + ('grpc-status', '2'), + ('grpc-encoding', 'identity'), + ('grpc-encoding', 'gzip'), + ('grpc-encoding', 'deflate'), ('te', 'trailers'), + ('content-type', 'application/grpc'), (':method', 'POST'), (':status', '200'), (':status', '404'), diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index fbabae42382..da65d0024e1 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -809,6 +809,7 @@ src/core/client_config/subchannel_factory.h \ src/core/client_config/subchannel_factory_decorators/add_channel_arg.h \ src/core/client_config/subchannel_factory_decorators/merge_channel_args.h \ src/core/client_config/uri_parser.h \ +src/core/compression/algorithm_metadata.h \ src/core/compression/message_compress.h \ src/core/debug/trace.h \ src/core/httpcli/format_request.h \ diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index aa433372632..7fd7cff8d61 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -485,10 +485,10 @@ _CONFIGS = { 'msan': SimpleConfig('msan', timeout_multiplier=1.5), 'ubsan': SimpleConfig('ubsan'), 'asan': SimpleConfig('asan', timeout_multiplier=1.5, environ={ - 'ASAN_OPTIONS': 'detect_leaks=1:color=always:suppressions=tools/tsan_suppressions.txt', + 'ASAN_OPTIONS': 'detect_leaks=1:color=always', 'LSAN_OPTIONS': 'report_objects=1'}), 'asan-noleaks': SimpleConfig('asan', environ={ - 'ASAN_OPTIONS': 'detect_leaks=0:color=always:suppressions=tools/tsan_suppressions.txt'}), + 'ASAN_OPTIONS': 'detect_leaks=0:color=always'}), 'gcov': SimpleConfig('gcov'), 'memcheck': ValgrindConfig('valgrind', 'memcheck', ['--leak-check=full']), 'helgrind': ValgrindConfig('dbg', 'helgrind') diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 485fe870d0a..cd9f630adf0 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -14032,6 +14032,7 @@ "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h", "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h", "src/core/client_config/uri_parser.h", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.h", "src/core/debug/trace.h", "src/core/httpcli/format_request.h", @@ -14207,6 +14208,7 @@ "src/core/client_config/uri_parser.c", "src/core/client_config/uri_parser.h", "src/core/compression/algorithm.c", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.c", "src/core/compression/message_compress.h", "src/core/debug/trace.c", @@ -14547,6 +14549,7 @@ "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h", "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h", "src/core/client_config/uri_parser.h", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.h", "src/core/debug/trace.h", "src/core/httpcli/format_request.h", @@ -14708,6 +14711,7 @@ "src/core/client_config/uri_parser.c", "src/core/client_config/uri_parser.h", "src/core/compression/algorithm.c", + "src/core/compression/algorithm_metadata.h", "src/core/compression/message_compress.c", "src/core/compression/message_compress.h", "src/core/debug/trace.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 2345f8569e3..1311bfb6caf 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -295,6 +295,7 @@ + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 16d7d8aaed4..b20bd914864 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -602,6 +602,9 @@ src\core\client_config + + src\core\compression + src\core\compression diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index efc99fee73c..dba01c85df6 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -274,6 +274,7 @@ + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 2eb7849bec5..cf12c96f135 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -500,6 +500,9 @@ src\core\client_config + + src\core\compression + src\core\compression