diff options
Diffstat (limited to 'src/core/lib/transport')
23 files changed, 2193 insertions, 1876 deletions
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c index c656d93740..8fc5bf3e9a 100644 --- a/src/core/lib/transport/connectivity_state.c +++ b/src/core/lib/transport/connectivity_state.c @@ -163,7 +163,6 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker, tracker->name, grpc_connectivity_state_name(tracker->current_state), grpc_connectivity_state_name(state), reason, error, error_string); - grpc_error_free_string(error_string); } switch (state) { case GRPC_CHANNEL_INIT: diff --git a/src/core/lib/transport/error_utils.c b/src/core/lib/transport/error_utils.c new file mode 100644 index 0000000000..da77828d9c --- /dev/null +++ b/src/core/lib/transport/error_utils.c @@ -0,0 +1,124 @@ +/* + * + * Copyright 2016, 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. + * + */ + +#include "src/core/lib/transport/error_utils.h" + +#include "src/core/lib/iomgr/error_internal.h" +#include "src/core/lib/transport/status_conversion.h" + +static grpc_error *recursively_find_error_with_field(grpc_error *error, + grpc_error_ints which) { + // If the error itself has a status code, return it. + if (grpc_error_get_int(error, which, NULL)) { + return error; + } + if (grpc_error_is_special(error)) return NULL; + // Otherwise, search through its children. + intptr_t key = 0; + while (true) { + grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); + if (child_error == NULL) break; + grpc_error *result = recursively_find_error_with_field(child_error, which); + if (result != NULL) return result; + } + return NULL; +} + +void grpc_error_get_status(grpc_error *error, gpr_timespec deadline, + grpc_status_code *code, const char **msg, + grpc_http2_error_code *http_error) { + // Start with the parent error and recurse through the tree of children + // until we find the first one that has a status code. + grpc_error *found_error = + recursively_find_error_with_field(error, GRPC_ERROR_INT_GRPC_STATUS); + if (found_error == NULL) { + /// If no grpc-status exists, retry through the tree to find a http2 error + /// code + found_error = + recursively_find_error_with_field(error, GRPC_ERROR_INT_HTTP2_ERROR); + } + + // If we found an error with a status code above, use that; otherwise, + // fall back to using the parent error. + if (found_error == NULL) found_error = error; + + grpc_status_code status = GRPC_STATUS_UNKNOWN; + intptr_t integer; + if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) { + status = (grpc_status_code)integer; + } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, + &integer)) { + status = grpc_http2_error_to_grpc_status((grpc_http2_error_code)integer, + deadline); + } + if (code != NULL) *code = status; + + if (http_error != NULL) { + if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) { + *http_error = (grpc_http2_error_code)integer; + } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, + &integer)) { + *http_error = grpc_status_to_http2_error((grpc_status_code)integer); + } else { + *http_error = found_error == GRPC_ERROR_NONE ? GRPC_HTTP2_NO_ERROR + : GRPC_HTTP2_INTERNAL_ERROR; + } + } + + // If the error has a status message, use it. Otherwise, fall back to + // the error description. + if (msg != NULL) { + *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE); + if (*msg == NULL && error != GRPC_ERROR_NONE) { + *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION); + if (*msg == NULL) *msg = "unknown error"; // Just in case. + } + } + + if (found_error == NULL) found_error = error; +} + +bool grpc_error_has_clear_grpc_status(grpc_error *error) { + if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { + return true; + } + intptr_t key = 0; + while (true) { + grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); + if (child_error == NULL) break; + if (grpc_error_has_clear_grpc_status(child_error)) { + return true; + } + } + return false; +} diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h new file mode 100644 index 0000000000..105338880a --- /dev/null +++ b/src/core/lib/transport/error_utils.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2016, 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_CORE_LIB_TRANSPORT_ERROR_UTILS_H +#define GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H + +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/transport/http2_errors.h" + +/// A utility function to get the status code and message to be returned +/// to the application. If not set in the top-level message, looks +/// through child errors until it finds the first one with these attributes. +/// All attributes are pulled from the same child error. If any of the +/// attributes (code, msg, http_status) are unneeded, they can be passed as +/// NULL. +void grpc_error_get_status(grpc_error *error, gpr_timespec deadline, + grpc_status_code *code, const char **msg, + grpc_http2_error_code *http_status); + +/// A utility function to check whether there is a clear status code that +/// doesn't need to be guessed in \a error. This means that \a error or some +/// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or +/// GRPC_ERROR_CANCELLED +bool grpc_error_has_clear_grpc_status(grpc_error *error); + +#endif /* GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H */ diff --git a/src/core/lib/transport/http2_errors.h b/src/core/lib/transport/http2_errors.h new file mode 100644 index 0000000000..330bc987f6 --- /dev/null +++ b/src/core/lib/transport/http2_errors.h @@ -0,0 +1,56 @@ +/* + * + * 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_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H +#define GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H + +/* error codes for RST_STREAM from http2 draft 14 section 7 */ +typedef enum { + GRPC_HTTP2_NO_ERROR = 0x0, + GRPC_HTTP2_PROTOCOL_ERROR = 0x1, + GRPC_HTTP2_INTERNAL_ERROR = 0x2, + GRPC_HTTP2_FLOW_CONTROL_ERROR = 0x3, + GRPC_HTTP2_SETTINGS_TIMEOUT = 0x4, + GRPC_HTTP2_STREAM_CLOSED = 0x5, + GRPC_HTTP2_FRAME_SIZE_ERROR = 0x6, + GRPC_HTTP2_REFUSED_STREAM = 0x7, + GRPC_HTTP2_CANCEL = 0x8, + GRPC_HTTP2_COMPRESSION_ERROR = 0x9, + GRPC_HTTP2_CONNECT_ERROR = 0xa, + GRPC_HTTP2_ENHANCE_YOUR_CALM = 0xb, + GRPC_HTTP2_INADEQUATE_SECURITY = 0xc, + /* force use of a default clause */ + GRPC_HTTP2__ERROR_DO_NOT_USE = -1 +} grpc_http2_error_code; + +#endif /* GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H */ diff --git a/src/core/lib/transport/mdstr_hash_table.c b/src/core/lib/transport/mdstr_hash_table.c deleted file mode 100644 index 2791bf653b..0000000000 --- a/src/core/lib/transport/mdstr_hash_table.c +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright 2016, 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. -// - -#include "src/core/lib/transport/mdstr_hash_table.h" - -#include <stdbool.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -#include "src/core/lib/transport/metadata.h" - -struct grpc_mdstr_hash_table { - gpr_refcount refs; - size_t size; - grpc_mdstr_hash_table_entry* entries; -}; - -// Helper function for insert and get operations that performs quadratic -// probing (https://en.wikipedia.org/wiki/Quadratic_probing). -static size_t grpc_mdstr_hash_table_find_index( - const grpc_mdstr_hash_table* table, const grpc_mdstr* key, - bool find_empty) { - for (size_t i = 0; i < table->size; ++i) { - const size_t idx = (key->hash + i * i) % table->size; - if (table->entries[idx].key == NULL) return find_empty ? idx : table->size; - if (table->entries[idx].key == key) return idx; - } - return table->size; // Not found. -} - -static void grpc_mdstr_hash_table_add( - grpc_mdstr_hash_table* table, grpc_mdstr* key, void* value, - const grpc_mdstr_hash_table_vtable* vtable) { - GPR_ASSERT(value != NULL); - const size_t idx = - grpc_mdstr_hash_table_find_index(table, key, true /* find_empty */); - GPR_ASSERT(idx != table->size); // Table should never be full. - grpc_mdstr_hash_table_entry* entry = &table->entries[idx]; - entry->key = GRPC_MDSTR_REF(key); - entry->value = vtable->copy_value(value); - entry->vtable = vtable; -} - -grpc_mdstr_hash_table* grpc_mdstr_hash_table_create( - size_t num_entries, grpc_mdstr_hash_table_entry* entries) { - grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table)); - memset(table, 0, sizeof(*table)); - gpr_ref_init(&table->refs, 1); - // Quadratic probing gets best performance when the table is no more - // than half full. - table->size = num_entries * 2; - const size_t entry_size = sizeof(grpc_mdstr_hash_table_entry) * table->size; - table->entries = gpr_malloc(entry_size); - memset(table->entries, 0, entry_size); - for (size_t i = 0; i < num_entries; ++i) { - grpc_mdstr_hash_table_entry* entry = &entries[i]; - grpc_mdstr_hash_table_add(table, entry->key, entry->value, entry->vtable); - } - return table; -} - -grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) { - if (table != NULL) gpr_ref(&table->refs); - return table; -} - -void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx, - grpc_mdstr_hash_table* table) { - if (table != NULL && gpr_unref(&table->refs)) { - for (size_t i = 0; i < table->size; ++i) { - grpc_mdstr_hash_table_entry* entry = &table->entries[i]; - if (entry->key != NULL) { - GRPC_MDSTR_UNREF(exec_ctx, entry->key); - entry->vtable->destroy_value(exec_ctx, entry->value); - } - } - gpr_free(table->entries); - gpr_free(table); - } -} - -void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, - const grpc_mdstr* key) { - const size_t idx = - grpc_mdstr_hash_table_find_index(table, key, false /* find_empty */); - if (idx == table->size) return NULL; // Not found. - return table->entries[idx].value; -} diff --git a/src/core/lib/transport/mdstr_hash_table.h b/src/core/lib/transport/mdstr_hash_table.h deleted file mode 100644 index 57f497ee27..0000000000 --- a/src/core/lib/transport/mdstr_hash_table.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2016, 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_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H -#define GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H - -#include "src/core/lib/transport/metadata.h" - -/** Hash table implementation. - * - * This implementation uses open addressing - * (https://en.wikipedia.org/wiki/Open_addressing) with quadratic - * probing (https://en.wikipedia.org/wiki/Quadratic_probing). - * - * The keys are \a grpc_mdstr objects. The values are arbitrary pointers - * with a common vtable. - * - * Hash tables are intentionally immutable, to avoid the need for locking. - */ - -typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table; - -typedef struct grpc_mdstr_hash_table_vtable { - void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value); - void* (*copy_value)(void* value); -} grpc_mdstr_hash_table_vtable; - -typedef struct grpc_mdstr_hash_table_entry { - grpc_mdstr* key; - void* value; /* Must not be NULL. */ - const grpc_mdstr_hash_table_vtable* vtable; -} grpc_mdstr_hash_table_entry; - -/** Creates a new hash table of containing \a entries, which is an array - of length \a num_entries. - Creates its own copy of all keys and values from \a entries. */ -grpc_mdstr_hash_table* grpc_mdstr_hash_table_create( - size_t num_entries, grpc_mdstr_hash_table_entry* entries); - -grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table); -void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx, - grpc_mdstr_hash_table* table); - -/** Returns the value from \a table associated with \a key. - Returns NULL if \a key is not found. */ -void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, - const grpc_mdstr* key); - -#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */ diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c index 54c39df6a7..489c20cbc8 100644 --- a/src/core/lib/transport/metadata.c +++ b/src/core/lib/transport/metadata.c @@ -48,12 +48,11 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/murmur_hash.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/static_metadata.h" -grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input); - /* There are two kinds of mdelem and mdstr instances. * Static instances are declared in static_metadata.{h,c} and * are initialized by grpc_mdctx_global_init(). @@ -63,9 +62,6 @@ grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input); * used to determine which kind of element a pointer refers to. */ -#define INITIAL_STRTAB_CAPACITY 4 -#define INITIAL_MDTAB_CAPACITY 4 - #ifdef GRPC_METADATA_REFCOUNT_DEBUG #define DEBUG_ARGS , const char *file, int line #define FWD_DEBUG_ARGS , file, line @@ -76,37 +72,20 @@ grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input); #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s)) #endif -#define TABLE_IDX(hash, log2_shards, capacity) \ - (((hash) >> (log2_shards)) % (capacity)) -#define SHARD_IDX(hash, log2_shards) ((hash) & ((1 << (log2_shards)) - 1)) - -typedef void (*destroy_user_data_func)(void *user_data); - -#define SIZE_IN_DECODER_TABLE_NOT_SET -1 -/* Shadow structure for grpc_mdstr for non-static values */ -typedef struct internal_string { - /* must be byte compatible with grpc_mdstr */ - grpc_slice slice; - uint32_t hash; - - /* private only data */ - gpr_atm refcnt; - - uint8_t has_base64_and_huffman_encoded; - grpc_slice_refcount refcount; +#define INITIAL_SHARD_CAPACITY 8 +#define LOG2_SHARD_COUNT 4 +#define SHARD_COUNT ((size_t)(1 << LOG2_SHARD_COUNT)) - grpc_slice base64_and_huffman; +#define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity)) +#define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1)) - gpr_atm size_in_decoder_table; - - struct internal_string *bucket_next; -} internal_string; +typedef void (*destroy_user_data_func)(void *user_data); -/* Shadow structure for grpc_mdelem for non-static elements */ -typedef struct internal_metadata { - /* must be byte compatible with grpc_mdelem */ - internal_string *key; - internal_string *value; +/* Shadow structure for grpc_mdelem_data for interned elements */ +typedef struct interned_metadata { + /* must be byte compatible with grpc_mdelem_data */ + grpc_slice key; + grpc_slice value; /* private only data */ gpr_atm refcnt; @@ -115,19 +94,22 @@ typedef struct internal_metadata { gpr_atm destroy_user_data; gpr_atm user_data; - struct internal_metadata *bucket_next; -} internal_metadata; + struct interned_metadata *bucket_next; +} interned_metadata; -typedef struct strtab_shard { - gpr_mu mu; - internal_string **strs; - size_t count; - size_t capacity; -} strtab_shard; +/* Shadow structure for grpc_mdelem_data for allocated elements */ +typedef struct allocated_metadata { + /* must be byte compatible with grpc_mdelem_data */ + grpc_slice key; + grpc_slice value; + + /* private only data */ + gpr_atm refcnt; +} allocated_metadata; typedef struct mdtab_shard { gpr_mu mu; - internal_metadata **elems; + interned_metadata **elems; size_t count; size_t capacity; /** Estimate of the number of unreferenced mdelems in the hash table. @@ -136,102 +118,26 @@ typedef struct mdtab_shard { gpr_atm free_estimate; } mdtab_shard; -#define LOG2_STRTAB_SHARD_COUNT 5 -#define LOG2_MDTAB_SHARD_COUNT 4 -#define STRTAB_SHARD_COUNT ((size_t)(1 << LOG2_STRTAB_SHARD_COUNT)) -#define MDTAB_SHARD_COUNT ((size_t)(1 << LOG2_MDTAB_SHARD_COUNT)) - -/* hash seed: decided at initialization time */ -static uint32_t g_hash_seed; -static int g_forced_hash_seed = 0; - -/* linearly probed hash tables for static element lookup */ -static grpc_mdstr *g_static_strtab[GRPC_STATIC_MDSTR_COUNT * 2]; -static grpc_mdelem *g_static_mdtab[GRPC_STATIC_MDELEM_COUNT * 2]; -static size_t g_static_strtab_maxprobe; -static size_t g_static_mdtab_maxprobe; - -static strtab_shard g_strtab_shard[STRTAB_SHARD_COUNT]; -static mdtab_shard g_mdtab_shard[MDTAB_SHARD_COUNT]; +static mdtab_shard g_shards[SHARD_COUNT]; static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard); -void grpc_test_only_set_metadata_hash_seed(uint32_t seed) { - g_hash_seed = seed; - g_forced_hash_seed = 1; -} - void grpc_mdctx_global_init(void) { - size_t i, j; - if (!g_forced_hash_seed) { - g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec; - } - g_static_strtab_maxprobe = 0; - g_static_mdtab_maxprobe = 0; - /* build static tables */ - memset(g_static_mdtab, 0, sizeof(g_static_mdtab)); - memset(g_static_strtab, 0, sizeof(g_static_strtab)); - for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { - grpc_mdstr *elem = &grpc_static_mdstr_table[i]; - const char *str = grpc_static_metadata_strings[i]; - uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed); - *(grpc_slice *)&elem->slice = grpc_slice_from_static_string(str); - *(uint32_t *)&elem->hash = hash; - for (j = 0;; j++) { - size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_strtab); - if (g_static_strtab[idx] == NULL) { - g_static_strtab[idx] = &grpc_static_mdstr_table[i]; - break; - } - } - if (j > g_static_strtab_maxprobe) { - g_static_strtab_maxprobe = j; - } - } - for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) { - grpc_mdelem *elem = &grpc_static_mdelem_table[i]; - 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]]; - uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash); - *(grpc_mdstr **)&elem->key = key; - *(grpc_mdstr **)&elem->value = value; - for (j = 0;; j++) { - size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab); - if (g_static_mdtab[idx] == NULL) { - g_static_mdtab[idx] = elem; - break; - } - } - if (j > g_static_mdtab_maxprobe) { - g_static_mdtab_maxprobe = j; - } - } /* initialize shards */ - for (i = 0; i < STRTAB_SHARD_COUNT; i++) { - strtab_shard *shard = &g_strtab_shard[i]; - gpr_mu_init(&shard->mu); - shard->count = 0; - shard->capacity = INITIAL_STRTAB_CAPACITY; - shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity); - memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity); - } - for (i = 0; i < MDTAB_SHARD_COUNT; i++) { - mdtab_shard *shard = &g_mdtab_shard[i]; + for (size_t i = 0; i < SHARD_COUNT; i++) { + mdtab_shard *shard = &g_shards[i]; gpr_mu_init(&shard->mu); shard->count = 0; gpr_atm_no_barrier_store(&shard->free_estimate, 0); - shard->capacity = INITIAL_MDTAB_CAPACITY; + shard->capacity = INITIAL_SHARD_CAPACITY; shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity); memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity); } } void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) { - size_t i; - for (i = 0; i < MDTAB_SHARD_COUNT; i++) { - mdtab_shard *shard = &g_mdtab_shard[i]; + for (size_t i = 0; i < SHARD_COUNT; i++) { + mdtab_shard *shard = &g_shards[i]; gpr_mu_destroy(&shard->mu); gc_mdtab(exec_ctx, shard); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ @@ -244,212 +150,35 @@ void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) { } gpr_free(shard->elems); } - for (i = 0; i < STRTAB_SHARD_COUNT; i++) { - strtab_shard *shard = &g_strtab_shard[i]; - gpr_mu_destroy(&shard->mu); - /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ - if (shard->count != 0) { - gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked", - shard->count); - for (size_t j = 0; j < shard->capacity; j++) { - for (internal_string *s = shard->strs[j]; s; s = s->bucket_next) { - gpr_log(GPR_DEBUG, "LEAKED: %s", - grpc_mdstr_as_c_string((grpc_mdstr *)s)); - } - } - if (grpc_iomgr_abort_on_leaks()) { - abort(); - } - } - gpr_free(shard->strs); - } } -static int is_mdstr_static(grpc_mdstr *s) { - return s >= &grpc_static_mdstr_table[0] && - s < &grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; -} - -static int is_mdelem_static(grpc_mdelem *e) { - return e >= &grpc_static_mdelem_table[0] && - e < &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; +static int is_mdelem_static(grpc_mdelem e) { + return GRPC_MDELEM_DATA(e) >= &grpc_static_mdelem_table[0] && + GRPC_MDELEM_DATA(e) < + &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; } static void ref_md_locked(mdtab_shard *shard, - internal_metadata *md DEBUG_ARGS) { + interned_metadata *md DEBUG_ARGS) { #ifdef GRPC_METADATA_REFCOUNT_DEBUG + char *key_str = grpc_slice_to_c_string(md->key); + char *value_str = grpc_slice_to_c_string(md->value); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), - gpr_atm_no_barrier_load(&md->refcnt) + 1, - grpc_mdstr_as_c_string((grpc_mdstr *)md->key), - grpc_mdstr_as_c_string((grpc_mdstr *)md->value)); + gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); #endif if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) { gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1); } } -static void grow_strtab(strtab_shard *shard) { - size_t capacity = shard->capacity * 2; - size_t i; - internal_string **strtab; - internal_string *s, *next; - - GPR_TIMER_BEGIN("grow_strtab", 0); - - strtab = gpr_malloc(sizeof(internal_string *) * capacity); - memset(strtab, 0, sizeof(internal_string *) * capacity); - - for (i = 0; i < shard->capacity; i++) { - for (s = shard->strs[i]; s; s = next) { - size_t idx = TABLE_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT, capacity); - next = s->bucket_next; - s->bucket_next = strtab[idx]; - strtab[idx] = s; - } - } - - gpr_free(shard->strs); - shard->strs = strtab; - shard->capacity = capacity; - - GPR_TIMER_END("grow_strtab", 0); -} - -static void internal_destroy_string(grpc_exec_ctx *exec_ctx, - strtab_shard *shard, internal_string *is) { - internal_string **prev_next; - internal_string *cur; - GPR_TIMER_BEGIN("internal_destroy_string", 0); - if (is->has_base64_and_huffman_encoded) { - grpc_slice_unref_internal(exec_ctx, is->base64_and_huffman); - } - for (prev_next = &shard->strs[TABLE_IDX(is->hash, LOG2_STRTAB_SHARD_COUNT, - shard->capacity)], - cur = *prev_next; - cur != is; prev_next = &cur->bucket_next, cur = cur->bucket_next) - ; - *prev_next = cur->bucket_next; - shard->count--; - gpr_free(is); - GPR_TIMER_END("internal_destroy_string", 0); -} - -static void slice_ref(void *p) { - internal_string *is = - (internal_string *)((char *)p - offsetof(internal_string, refcount)); - GRPC_MDSTR_REF((grpc_mdstr *)(is)); -} - -static void slice_unref(grpc_exec_ctx *exec_ctx, void *p) { - internal_string *is = - (internal_string *)((char *)p - offsetof(internal_string, refcount)); - GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)(is)); -} - -grpc_mdstr *grpc_mdstr_from_string(const char *str) { - return grpc_mdstr_from_buffer((const uint8_t *)str, strlen(str)); -} - -grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice) { - grpc_mdstr *result = grpc_mdstr_from_buffer(GRPC_SLICE_START_PTR(slice), - GRPC_SLICE_LENGTH(slice)); - grpc_slice_unref_internal(exec_ctx, slice); - return result; -} - -grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) { - uint32_t hash = gpr_murmur_hash3(buf, length, g_hash_seed); - internal_string *s; - strtab_shard *shard = - &g_strtab_shard[SHARD_IDX(hash, LOG2_STRTAB_SHARD_COUNT)]; - size_t i; - size_t idx; - - GPR_TIMER_BEGIN("grpc_mdstr_from_buffer", 0); - - /* search for a static string */ - for (i = 0; i <= g_static_strtab_maxprobe; i++) { - grpc_mdstr *ss; - idx = (hash + i) % GPR_ARRAY_SIZE(g_static_strtab); - ss = g_static_strtab[idx]; - if (ss == NULL) break; - if (ss->hash == hash && GRPC_SLICE_LENGTH(ss->slice) == length && - (length == 0 || - 0 == memcmp(buf, GRPC_SLICE_START_PTR(ss->slice), length))) { - GPR_TIMER_END("grpc_mdstr_from_buffer", 0); - return ss; - } - } - - gpr_mu_lock(&shard->mu); - - /* search for an existing string */ - idx = TABLE_IDX(hash, LOG2_STRTAB_SHARD_COUNT, shard->capacity); - for (s = shard->strs[idx]; s; s = s->bucket_next) { - if (s->hash == hash && GRPC_SLICE_LENGTH(s->slice) == length && - 0 == memcmp(buf, GRPC_SLICE_START_PTR(s->slice), length)) { - if (gpr_atm_full_fetch_add(&s->refcnt, 1) == 0) { - /* If we get here, we've added a ref to something that was about to - * die - drop it immediately. - * The *only* possible path here (given the shard mutex) should be to - * drop from one ref back to zero - assert that with a CAS */ - GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0)); - /* and treat this as if we were never here... sshhh */ - } else { - gpr_mu_unlock(&shard->mu); - GPR_TIMER_END("grpc_mdstr_from_buffer", 0); - return (grpc_mdstr *)s; - } - } - } - - /* not found: create a new string */ - if (length + 1 < GRPC_SLICE_INLINED_SIZE) { - /* string data goes directly into the slice */ - s = gpr_malloc(sizeof(internal_string)); - gpr_atm_rel_store(&s->refcnt, 1); - s->slice.refcount = NULL; - memcpy(s->slice.data.inlined.bytes, buf, length); - s->slice.data.inlined.bytes[length] = 0; - s->slice.data.inlined.length = (uint8_t)length; - } else { - /* string data goes after the internal_string header, and we +1 for null - terminator */ - s = gpr_malloc(sizeof(internal_string) + length + 1); - gpr_atm_rel_store(&s->refcnt, 1); - s->refcount.ref = slice_ref; - s->refcount.unref = slice_unref; - s->slice.refcount = &s->refcount; - s->slice.data.refcounted.bytes = (uint8_t *)(s + 1); - s->slice.data.refcounted.length = length; - memcpy(s->slice.data.refcounted.bytes, buf, length); - /* add a null terminator for cheap c string conversion when desired */ - s->slice.data.refcounted.bytes[length] = 0; - } - s->has_base64_and_huffman_encoded = 0; - s->hash = hash; - s->size_in_decoder_table = SIZE_IN_DECODER_TABLE_NOT_SET; - s->bucket_next = shard->strs[idx]; - shard->strs[idx] = s; - - shard->count++; - - if (shard->count > shard->capacity * 2) { - grow_strtab(shard); - } - - gpr_mu_unlock(&shard->mu); - GPR_TIMER_END("grpc_mdstr_from_buffer", 0); - - return (grpc_mdstr *)s; -} - static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) { size_t i; - internal_metadata **prev_next; - internal_metadata *md, *next; + interned_metadata **prev_next; + interned_metadata *md, *next; gpr_atm num_freed = 0; GPR_TIMER_BEGIN("gc_mdtab", 0); @@ -459,8 +188,8 @@ static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) { void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data); next = md->bucket_next; if (gpr_atm_acq_load(&md->refcnt) == 0) { - GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->key); - GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->value); + grpc_slice_unref_internal(exec_ctx, md->key); + grpc_slice_unref_internal(exec_ctx, md->value); if (md->user_data) { ((destroy_user_data_func)gpr_atm_no_barrier_load( &md->destroy_user_data))(user_data); @@ -481,21 +210,22 @@ static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) { static void grow_mdtab(mdtab_shard *shard) { size_t capacity = shard->capacity * 2; size_t i; - internal_metadata **mdtab; - internal_metadata *md, *next; + interned_metadata **mdtab; + interned_metadata *md, *next; uint32_t hash; GPR_TIMER_BEGIN("grow_mdtab", 0); - mdtab = gpr_malloc(sizeof(internal_metadata *) * capacity); - memset(mdtab, 0, sizeof(internal_metadata *) * capacity); + mdtab = gpr_malloc(sizeof(interned_metadata *) * capacity); + memset(mdtab, 0, sizeof(interned_metadata *) * capacity); for (i = 0; i < shard->capacity; i++) { for (md = shard->elems[i]; md; md = next) { size_t idx; - hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash); + hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), + grpc_slice_hash(md->value)); next = md->bucket_next; - idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, capacity); + idx = TABLE_IDX(hash, capacity); md->bucket_next = mdtab[idx]; mdtab[idx] = md; } @@ -517,62 +247,77 @@ static void rehash_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) { } } -grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx, - grpc_mdstr *mkey, - grpc_mdstr *mvalue) { - internal_string *key = (internal_string *)mkey; - internal_string *value = (internal_string *)mvalue; - uint32_t hash = GRPC_MDSTR_KV_HASH(mkey->hash, mvalue->hash); - internal_metadata *md; - mdtab_shard *shard = &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)]; - size_t i; - size_t idx; +grpc_mdelem grpc_mdelem_create( + grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value, + grpc_mdelem_data *compatible_external_backing_store) { + if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) { + if (compatible_external_backing_store != NULL) { + return GRPC_MAKE_MDELEM(compatible_external_backing_store, + GRPC_MDELEM_STORAGE_EXTERNAL); + } - GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0); + allocated_metadata *allocated = gpr_malloc(sizeof(*allocated)); + allocated->key = grpc_slice_ref_internal(key); + allocated->value = grpc_slice_ref_internal(value); + gpr_atm_rel_store(&allocated->refcnt, 1); +#ifdef GRPC_METADATA_REFCOUNT_DEBUG + char *key_str = grpc_slice_to_c_string(allocated->key); + char *value_str = grpc_slice_to_c_string(allocated->value); + gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%zu: '%s' = '%s'", (void *)allocated, + gpr_atm_no_barrier_load(&allocated->refcnt), key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); +#endif + return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED); + } - if (is_mdstr_static(mkey) && is_mdstr_static(mvalue)) { - for (i = 0; i <= g_static_mdtab_maxprobe; i++) { - grpc_mdelem *smd; - idx = (hash + i) % GPR_ARRAY_SIZE(g_static_mdtab); - smd = g_static_mdtab[idx]; - if (smd == NULL) break; - if (smd->key == mkey && smd->value == mvalue) { - GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0); - return smd; - } + if (GRPC_IS_STATIC_METADATA_STRING(key) && + GRPC_IS_STATIC_METADATA_STRING(value)) { + grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings( + GRPC_STATIC_METADATA_INDEX(key), GRPC_STATIC_METADATA_INDEX(value)); + if (!GRPC_MDISNULL(static_elem)) { + return static_elem; } } + uint32_t hash = + GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value)); + interned_metadata *md; + mdtab_shard *shard = &g_shards[SHARD_IDX(hash)]; + size_t idx; + + GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0); + gpr_mu_lock(&shard->mu); - idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, shard->capacity); + idx = TABLE_IDX(hash, shard->capacity); /* search for an existing pair */ for (md = shard->elems[idx]; md; md = md->bucket_next) { - if (md->key == key && md->value == value) { + if (grpc_slice_eq(key, md->key) && grpc_slice_eq(value, md->value)) { REF_MD_LOCKED(shard, md); - GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)key); - GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)value); gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0); - return (grpc_mdelem *)md; + return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); } } /* not found: create a new pair */ - md = gpr_malloc(sizeof(internal_metadata)); + md = gpr_malloc(sizeof(interned_metadata)); gpr_atm_rel_store(&md->refcnt, 1); - md->key = key; - md->value = value; + md->key = grpc_slice_ref_internal(key); + md->value = grpc_slice_ref_internal(value); md->user_data = 0; md->destroy_user_data = 0; md->bucket_next = shard->elems[idx]; shard->elems[idx] = md; gpr_mu_init(&md->mu_user_data); #ifdef GRPC_METADATA_REFCOUNT_DEBUG + char *key_str = grpc_slice_to_c_string(md->key); + char *value_str = grpc_slice_to_c_string(md->value); gpr_log(GPR_DEBUG, "ELM NEW:%p:%zu: '%s' = '%s'", (void *)md, - gpr_atm_no_barrier_load(&md->refcnt), - grpc_mdstr_as_c_string((grpc_mdstr *)md->key), - grpc_mdstr_as_c_string((grpc_mdstr *)md->value)); + gpr_atm_no_barrier_load(&md->refcnt), key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); #endif shard->count++; @@ -584,29 +329,26 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx, GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0); - return (grpc_mdelem *)md; -} - -grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key, - const char *value) { - return grpc_mdelem_from_metadata_strings( - exec_ctx, grpc_mdstr_from_string(key), grpc_mdstr_from_string(value)); + return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); } -grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, - grpc_slice value) { - return grpc_mdelem_from_metadata_strings( - exec_ctx, grpc_mdstr_from_slice(exec_ctx, key), - grpc_mdstr_from_slice(exec_ctx, value)); +grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, + grpc_slice value) { + grpc_mdelem out = grpc_mdelem_create(exec_ctx, key, value, NULL); + grpc_slice_unref_internal(exec_ctx, key); + grpc_slice_unref_internal(exec_ctx, value); + return out; } -grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx, - const char *key, - const uint8_t *value, - size_t value_length) { - return grpc_mdelem_from_metadata_strings( - exec_ctx, grpc_mdstr_from_string(key), - grpc_mdstr_from_buffer(value, value_length)); +grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx, + grpc_metadata *metadata) { + bool changed = false; + grpc_slice key_slice = + grpc_slice_maybe_static_intern(metadata->key, &changed); + grpc_slice value_slice = + grpc_slice_maybe_static_intern(metadata->value, &changed); + return grpc_mdelem_create(exec_ctx, key_slice, value_slice, + changed ? NULL : (grpc_mdelem_data *)metadata); } static size_t get_base64_encoded_size(size_t raw_length) { @@ -614,160 +356,176 @@ static size_t get_base64_encoded_size(size_t raw_length) { return raw_length / 3 * 4 + tail_xtra[raw_length % 3]; } -size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem) { - size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(elem->key->slice); - size_t value_len = GRPC_SLICE_LENGTH(elem->value->slice); - if (is_mdstr_static(elem->value)) { - if (grpc_is_binary_header( - (const char *)GRPC_SLICE_START_PTR(elem->key->slice), - GRPC_SLICE_LENGTH(elem->key->slice))) { - return overhead_and_key + get_base64_encoded_size(value_len); - } else { - return overhead_and_key + value_len; - } +size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem) { + size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); + size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem)); + if (grpc_is_binary_header(GRPC_MDKEY(elem))) { + return overhead_and_key + get_base64_encoded_size(value_len); } else { - internal_string *is = (internal_string *)elem->value; - gpr_atm current_size = gpr_atm_acq_load(&is->size_in_decoder_table); - if (current_size == SIZE_IN_DECODER_TABLE_NOT_SET) { - if (grpc_is_binary_header( - (const char *)GRPC_SLICE_START_PTR(elem->key->slice), - GRPC_SLICE_LENGTH(elem->key->slice))) { - current_size = (gpr_atm)get_base64_encoded_size(value_len); - } else { - current_size = (gpr_atm)value_len; - } - gpr_atm_rel_store(&is->size_in_decoder_table, current_size); - } - return overhead_and_key + (size_t)current_size; + return overhead_and_key + value_len; } } -grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) { - internal_metadata *md = (internal_metadata *)gmd; - if (is_mdelem_static(gmd)) return gmd; +grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) { + switch (GRPC_MDELEM_STORAGE(gmd)) { + case GRPC_MDELEM_STORAGE_EXTERNAL: + case GRPC_MDELEM_STORAGE_STATIC: + break; + case GRPC_MDELEM_STORAGE_INTERNED: { + interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, - gpr_atm_no_barrier_load(&md->refcnt), - gpr_atm_no_barrier_load(&md->refcnt) + 1, - grpc_mdstr_as_c_string((grpc_mdstr *)md->key), - grpc_mdstr_as_c_string((grpc_mdstr *)md->value)); + char *key_str = grpc_slice_to_c_string(md->key); + char *value_str = grpc_slice_to_c_string(md->value); + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, + gpr_atm_no_barrier_load(&md->refcnt), + gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); #endif - /* we can assume the ref count is >= 1 as the application is calling - this function - meaning that no adjustment to mdtab_free is necessary, - simplifying the logic here to be just an atomic increment */ - /* use C assert to have this removed in opt builds */ - GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1); - gpr_atm_no_barrier_fetch_add(&md->refcnt, 1); - return gmd; -} - -void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *gmd DEBUG_ARGS) { - internal_metadata *md = (internal_metadata *)gmd; - if (!md) return; - if (is_mdelem_static(gmd)) return; + /* we can assume the ref count is >= 1 as the application is calling + this function - meaning that no adjustment to mdtab_free is necessary, + simplifying the logic here to be just an atomic increment */ + /* use C assert to have this removed in opt builds */ + GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1); + gpr_atm_no_barrier_fetch_add(&md->refcnt, 1); + break; + } + case GRPC_MDELEM_STORAGE_ALLOCATED: { + allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, - gpr_atm_no_barrier_load(&md->refcnt), - gpr_atm_no_barrier_load(&md->refcnt) - 1, - grpc_mdstr_as_c_string((grpc_mdstr *)md->key), - grpc_mdstr_as_c_string((grpc_mdstr *)md->value)); + char *key_str = grpc_slice_to_c_string(md->key); + char *value_str = grpc_slice_to_c_string(md->value); + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, + gpr_atm_no_barrier_load(&md->refcnt), + gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); #endif - uint32_t hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash); - const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); - GPR_ASSERT(prev_refcount >= 1); - if (1 == prev_refcount) { - /* once the refcount hits zero, some other thread can come along and - free md at any time: it's unsafe from this point on to access it */ - mdtab_shard *shard = - &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)]; - gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1); + /* we can assume the ref count is >= 1 as the application is calling + this function - meaning that no adjustment to mdtab_free is necessary, + simplifying the logic here to be just an atomic increment */ + /* use C assert to have this removed in opt builds */ + gpr_atm_no_barrier_fetch_add(&md->refcnt, 1); + break; + } } + return gmd; } -const char *grpc_mdstr_as_c_string(const grpc_mdstr *s) { - return (const char *)GRPC_SLICE_START_PTR(s->slice); -} - -size_t grpc_mdstr_length(const grpc_mdstr *s) { return GRPC_MDSTR_LENGTH(s); } - -grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) { - internal_string *s = (internal_string *)gs; - if (is_mdstr_static(gs)) return gs; +void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem gmd DEBUG_ARGS) { + switch (GRPC_MDELEM_STORAGE(gmd)) { + case GRPC_MDELEM_STORAGE_EXTERNAL: + case GRPC_MDELEM_STORAGE_STATIC: + break; + case GRPC_MDELEM_STORAGE_INTERNED: { + interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR REF:%p:%zu->%zu: '%s'", - (void *)s, gpr_atm_no_barrier_load(&s->refcnt), - gpr_atm_no_barrier_load(&s->refcnt) + 1, grpc_mdstr_as_c_string(gs)); + char *key_str = grpc_slice_to_c_string(md->key); + char *value_str = grpc_slice_to_c_string(md->value); + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, + gpr_atm_no_barrier_load(&md->refcnt), + gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); #endif - GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) > 0); - return gs; -} - -void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *gs DEBUG_ARGS) { - internal_string *s = (internal_string *)gs; - if (is_mdstr_static(gs)) return; + uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), + grpc_slice_hash(md->value)); + const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); + GPR_ASSERT(prev_refcount >= 1); + if (1 == prev_refcount) { + /* once the refcount hits zero, some other thread can come along and + free md at any time: it's unsafe from this point on to access it */ + mdtab_shard *shard = &g_shards[SHARD_IDX(hash)]; + gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1); + } + break; + } + case GRPC_MDELEM_STORAGE_ALLOCATED: { + allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd); #ifdef GRPC_METADATA_REFCOUNT_DEBUG - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR UNREF:%p:%zu->%zu: '%s'", - (void *)s, gpr_atm_no_barrier_load(&s->refcnt), - gpr_atm_no_barrier_load(&s->refcnt) - 1, grpc_mdstr_as_c_string(gs)); + char *key_str = grpc_slice_to_c_string(md->key); + char *value_str = grpc_slice_to_c_string(md->value); + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, + gpr_atm_no_barrier_load(&md->refcnt), + gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str); + gpr_free(key_str); + gpr_free(value_str); #endif - if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) { - strtab_shard *shard = - &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)]; - gpr_mu_lock(&shard->mu); - GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt)); - internal_destroy_string(exec_ctx, shard, s); - gpr_mu_unlock(&shard->mu); + const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); + GPR_ASSERT(prev_refcount >= 1); + if (1 == prev_refcount) { + grpc_slice_unref_internal(exec_ctx, md->key); + grpc_slice_unref_internal(exec_ctx, md->value); + gpr_free(md); + } + break; + } } } -void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) { - internal_metadata *im = (internal_metadata *)md; - void *result; - if (is_mdelem_static(md)) { - return (void *)grpc_static_mdelem_user_data[md - grpc_static_mdelem_table]; - } - if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) { - return (void *)gpr_atm_no_barrier_load(&im->user_data); - } else { - return NULL; +void *grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void *)) { + switch (GRPC_MDELEM_STORAGE(md)) { + case GRPC_MDELEM_STORAGE_EXTERNAL: + case GRPC_MDELEM_STORAGE_ALLOCATED: + return NULL; + case GRPC_MDELEM_STORAGE_STATIC: + return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) - + grpc_static_mdelem_table]; + case GRPC_MDELEM_STORAGE_INTERNED: { + interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md); + void *result; + if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) { + return (void *)gpr_atm_no_barrier_load(&im->user_data); + } else { + return NULL; + } + return result; + } } - return result; + GPR_UNREACHABLE_CODE(return NULL); } -void *grpc_mdelem_set_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)) { - /* user data can only be set once */ - gpr_mu_unlock(&im->mu_user_data); - if (destroy_func != NULL) { + switch (GRPC_MDELEM_STORAGE(md)) { + case GRPC_MDELEM_STORAGE_EXTERNAL: + case GRPC_MDELEM_STORAGE_ALLOCATED: destroy_func(user_data); + return NULL; + case GRPC_MDELEM_STORAGE_STATIC: + destroy_func(user_data); + return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) - + grpc_static_mdelem_table]; + case GRPC_MDELEM_STORAGE_INTERNED: { + interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(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)) { + /* user data can only be set once */ + gpr_mu_unlock(&im->mu_user_data); + if (destroy_func != NULL) { + destroy_func(user_data); + } + return (void *)gpr_atm_no_barrier_load(&im->user_data); + } + gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data); + gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func); + gpr_mu_unlock(&im->mu_user_data); + return user_data; } - return (void *)gpr_atm_no_barrier_load(&im->user_data); } - gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data); - gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func); - gpr_mu_unlock(&im->mu_user_data); - return user_data; + GPR_UNREACHABLE_CODE(return NULL); } -grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) { - internal_string *s = (internal_string *)gs; - grpc_slice slice; - strtab_shard *shard = - &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)]; - gpr_mu_lock(&shard->mu); - if (!s->has_base64_and_huffman_encoded) { - s->base64_and_huffman = - grpc_chttp2_base64_encode_and_huffman_compress(s->slice); - s->has_base64_and_huffman_encoded = 1; - } - slice = s->base64_and_huffman; - gpr_mu_unlock(&shard->mu); - return slice; +bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b) { + if (a.payload == b.payload) return true; + if (GRPC_MDELEM_IS_INTERNED(a) && GRPC_MDELEM_IS_INTERNED(b)) return false; + if (GRPC_MDISNULL(a) || GRPC_MDISNULL(b)) return false; + return grpc_slice_eq(GRPC_MDKEY(a), GRPC_MDKEY(b)) && + grpc_slice_eq(GRPC_MDVALUE(a), GRPC_MDVALUE(b)); } diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h index 991eee96f1..f4ba86c854 100644 --- a/src/core/lib/transport/metadata.h +++ b/src/core/lib/transport/metadata.h @@ -34,6 +34,7 @@ #ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_H #define GRPC_CORE_LIB_TRANSPORT_METADATA_H +#include <grpc/grpc.h> #include <grpc/slice.h> #include <grpc/support/useful.h> @@ -74,110 +75,110 @@ extern "C" { declared here - in which case those functions are effectively no-ops. */ /* Forward declarations */ -typedef struct grpc_mdstr grpc_mdstr; typedef struct grpc_mdelem grpc_mdelem; -/* if changing this, make identical changes in internal_string in metadata.c */ -struct grpc_mdstr { - const grpc_slice slice; - const uint32_t hash; +/* if changing this, make identical changes in: + - interned_metadata, allocated_metadata in metadata.c + - grpc_metadata in grpc_types.h */ +typedef struct grpc_mdelem_data { + const grpc_slice key; + const grpc_slice value; /* there is a private part to this in metadata.c */ -}; +} grpc_mdelem_data; + +/* GRPC_MDELEM_STORAGE_* enum values that can be treated as interned always have + this bit set in their integer value */ +#define GRPC_MDELEM_STORAGE_INTERNED_BIT 1 + +typedef enum { + /* memory pointed to by grpc_mdelem::payload is owned by an external system */ + GRPC_MDELEM_STORAGE_EXTERNAL = 0, + /* memory pointed to by grpc_mdelem::payload is interned by the metadata + system */ + GRPC_MDELEM_STORAGE_INTERNED = GRPC_MDELEM_STORAGE_INTERNED_BIT, + /* memory pointed to by grpc_mdelem::payload is allocated by the metadata + system */ + GRPC_MDELEM_STORAGE_ALLOCATED = 2, + /* memory is in the static metadata table */ + GRPC_MDELEM_STORAGE_STATIC = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT, +} grpc_mdelem_data_storage; -/* if changing this, make identical changes in internal_metadata in - metadata.c */ struct grpc_mdelem { - grpc_mdstr *const key; - grpc_mdstr *const value; - /* there is a private part to this in metadata.c */ + /* a grpc_mdelem_data* generally, with the two lower bits signalling memory + ownership as per grpc_mdelem_data_storage */ + uintptr_t payload; }; -void grpc_test_only_set_metadata_hash_seed(uint32_t seed); - -/* Constructors for grpc_mdstr instances; take a variety of data types that - clients may have handy */ -grpc_mdstr *grpc_mdstr_from_string(const char *str); -/* Unrefs the slice. */ -grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice); -grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *str, size_t length); - -/* Returns a borrowed slice from the mdstr with its contents base64 encoded - and huffman compressed */ -grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *str); - -/* Constructors for grpc_mdelem instances; take a variety of data types that - clients may have handy */ -grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx, - grpc_mdstr *key, - grpc_mdstr *value); -grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key, - const char *value); +#define GRPC_MDELEM_DATA(md) \ + ((grpc_mdelem_data *)((md).payload & ~(uintptr_t)3)) +#define GRPC_MDELEM_STORAGE(md) \ + ((grpc_mdelem_data_storage)((md).payload & (uintptr_t)3)) +#define GRPC_MAKE_MDELEM(data, storage) \ + ((grpc_mdelem){((uintptr_t)(data)) | ((uintptr_t)storage)}) +#define GRPC_MDELEM_IS_INTERNED(md) \ + ((grpc_mdelem_data_storage)((md).payload & \ + (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT)) + /* Unrefs the slices. */ -grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, - grpc_slice value); -grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx, - const char *key, - const uint8_t *value, - size_t value_length); +grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, + grpc_slice value); + +/* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata + object as backing storage (so lifetimes should align) */ +grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx, + grpc_metadata *metadata); -size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem); +/* Does not unref the slices; if a new non-interned mdelem is needed, allocates + one if compatible_external_backing_store is NULL, or uses + compatible_external_backing_store if it is non-NULL (in which case it's the + users responsibility to ensure that it outlives usage) */ +grpc_mdelem grpc_mdelem_create( + grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value, + grpc_mdelem_data *compatible_external_backing_store); + +bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b); + +size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem); /* Mutator and accessor for grpc_mdelem user data. The destructor function is used as a type tag and is checked during user_data fetch. */ -void *grpc_mdelem_get_user_data(grpc_mdelem *md, +void *grpc_mdelem_get_user_data(grpc_mdelem md, void (*if_destroy_func)(void *)); -void *grpc_mdelem_set_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); /* Reference counting */ //#define GRPC_METADATA_REFCOUNT_DEBUG #ifdef GRPC_METADATA_REFCOUNT_DEBUG -#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__) -#define GRPC_MDSTR_UNREF(exec_ctx, s) \ - grpc_mdstr_unref((exec_ctx), (s), __FILE__, __LINE__) #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__) #define GRPC_MDELEM_UNREF(exec_ctx, s) \ grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__) -grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line); -void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s, const char *file, - int line); -grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line); -void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md, +grpc_mdelem grpc_mdelem_ref(grpc_mdelem md, const char *file, int line); +void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md, const char *file, int line); #else -#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s)) -#define GRPC_MDSTR_UNREF(exec_ctx, s) grpc_mdstr_unref((exec_ctx), (s)) #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s)) #define GRPC_MDELEM_UNREF(exec_ctx, s) grpc_mdelem_unref((exec_ctx), (s)) -grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s); -void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s); -grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md); -void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md); +grpc_mdelem grpc_mdelem_ref(grpc_mdelem md); +void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md); #endif -/* Recover a char* from a grpc_mdstr. The returned string is null terminated. - Does not promise that the returned string has no embedded nulls however. */ -const char *grpc_mdstr_as_c_string(const grpc_mdstr *s); +#define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key) +#define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value) -#define GRPC_MDSTR_LENGTH(s) (GRPC_SLICE_LENGTH(s->slice)) +#define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL) +#define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL) /* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */ -#define GRPC_MDELEM_LENGTH(e) \ - (GRPC_MDSTR_LENGTH((e)->key) + GRPC_MDSTR_LENGTH((e)->value) + 32) - -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); +#define GRPC_MDELEM_LENGTH(e) \ + (GRPC_SLICE_LENGTH(GRPC_MDKEY((e))) + GRPC_SLICE_LENGTH(GRPC_MDVALUE((e))) + \ + 32) #define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash)) void grpc_mdctx_global_init(void); void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx); -/* Implementation provided by chttp2_transport */ -extern grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)( - grpc_slice input); - #ifdef __cplusplus } #endif diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c index b62ecc3aa6..95b71d33d7 100644 --- a/src/core/lib/transport/metadata_batch.c +++ b/src/core/lib/transport/metadata_batch.c @@ -40,6 +40,8 @@ #include <grpc/support/log.h> #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" static void assert_valid_list(grpc_mdelem_list *list) { #ifndef NDEBUG @@ -51,16 +53,34 @@ static void assert_valid_list(grpc_mdelem_list *list) { GPR_ASSERT(list->tail->next == NULL); GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL)); + size_t verified_count = 0; for (l = list->head; l; l = l->next) { - GPR_ASSERT(l->md); + GPR_ASSERT(!GRPC_MDISNULL(l->md)); GPR_ASSERT((l->prev == NULL) == (l == list->head)); GPR_ASSERT((l->next == NULL) == (l == list->tail)); if (l->next) GPR_ASSERT(l->next->prev == l); if (l->prev) GPR_ASSERT(l->prev->next == l); + verified_count++; } + GPR_ASSERT(list->count == verified_count); #endif /* NDEBUG */ } +static void assert_valid_callouts(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch) { +#ifndef NDEBUG + for (grpc_linked_mdelem *l = batch->list.head; l != NULL; l = l->next) { + grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md)); + grpc_metadata_batch_callouts_index callout_idx = + GRPC_BATCH_INDEX_OF(key_interned); + if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) { + GPR_ASSERT(batch->idx.array[callout_idx] == l); + } + grpc_slice_unref_internal(exec_ctx, key_interned); + } +#endif +} + #ifndef NDEBUG void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) { assert_valid_list(&batch->list); @@ -68,7 +88,7 @@ void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) { #endif /* NDEBUG */ void grpc_metadata_batch_init(grpc_metadata_batch *batch) { - batch->list.head = batch->list.tail = NULL; + memset(batch, 0, sizeof(*batch)); batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); } @@ -80,17 +100,58 @@ void grpc_metadata_batch_destroy(grpc_exec_ctx *exec_ctx, } } -void grpc_metadata_batch_add_head(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem *elem_to_add) { - GPR_ASSERT(elem_to_add); +grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md) { + char *k = grpc_slice_to_c_string(GRPC_MDKEY(md)); + char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md)); + grpc_error *out = grpc_error_set_str( + grpc_error_set_str(src, GRPC_ERROR_STR_KEY, k), GRPC_ERROR_STR_VALUE, v); + gpr_free(k); + gpr_free(v); + return out; +} + +static grpc_error *maybe_link_callout(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) + GRPC_MUST_USE_RESULT; + +static grpc_error *maybe_link_callout(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) { + grpc_metadata_batch_callouts_index idx = + GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); + if (idx == GRPC_BATCH_CALLOUTS_COUNT) { + return GRPC_ERROR_NONE; + } + if (batch->idx.array[idx] == NULL) { + batch->idx.array[idx] = storage; + return GRPC_ERROR_NONE; + } + return grpc_attach_md_to_error( + GRPC_ERROR_CREATE("Unallowed duplicate metadata"), storage->md); +} + +static void maybe_unlink_callout(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) { + grpc_metadata_batch_callouts_index idx = + GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); + if (idx == GRPC_BATCH_CALLOUTS_COUNT) { + return; + } + GPR_ASSERT(batch->idx.array[idx] != NULL); + batch->idx.array[idx] = NULL; +} + +grpc_error *grpc_metadata_batch_add_head(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, + grpc_mdelem elem_to_add) { + GPR_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; - grpc_metadata_batch_link_head(batch, storage); + return grpc_metadata_batch_link_head(exec_ctx, batch, storage); } static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); - GPR_ASSERT(storage->md); + GPR_ASSERT(!GRPC_MDISNULL(storage->md)); storage->prev = NULL; storage->next = list->head; if (list->head != NULL) { @@ -99,25 +160,36 @@ static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { list->tail = storage; } list->head = storage; + list->count++; assert_valid_list(list); } -void grpc_metadata_batch_link_head(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { +grpc_error *grpc_metadata_batch_link_head(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) { + assert_valid_callouts(exec_ctx, batch); + grpc_error *err = maybe_link_callout(batch, storage); + if (err != GRPC_ERROR_NONE) { + assert_valid_callouts(exec_ctx, batch); + return err; + } link_head(&batch->list, storage); + assert_valid_callouts(exec_ctx, batch); + return GRPC_ERROR_NONE; } -void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem *elem_to_add) { - GPR_ASSERT(elem_to_add); +grpc_error *grpc_metadata_batch_add_tail(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, + grpc_mdelem elem_to_add) { + GPR_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; - grpc_metadata_batch_link_tail(batch, storage); + return grpc_metadata_batch_link_tail(exec_ctx, batch, storage); } static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); - GPR_ASSERT(storage->md); + GPR_ASSERT(!GRPC_MDISNULL(storage->md)); storage->prev = list->tail; storage->next = NULL; storage->reserved = NULL; @@ -127,70 +199,82 @@ static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { list->head = storage; } list->tail = storage; + list->count++; assert_valid_list(list); } -void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { +grpc_error *grpc_metadata_batch_link_tail(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) { + assert_valid_callouts(exec_ctx, batch); + grpc_error *err = maybe_link_callout(batch, storage); + if (err != GRPC_ERROR_NONE) { + assert_valid_callouts(exec_ctx, batch); + return err; + } link_tail(&batch->list, storage); + assert_valid_callouts(exec_ctx, batch); + return GRPC_ERROR_NONE; } -void grpc_metadata_batch_move(grpc_metadata_batch *dst, - grpc_metadata_batch *src) { - *dst = *src; - memset(src, 0, sizeof(grpc_metadata_batch)); +static void unlink_storage(grpc_mdelem_list *list, + grpc_linked_mdelem *storage) { + assert_valid_list(list); + if (storage->prev != NULL) { + storage->prev->next = storage->next; + } else { + list->head = storage->next; + } + if (storage->next != NULL) { + storage->next->prev = storage->prev; + } else { + list->tail = storage->prev; + } + list->count--; + assert_valid_list(list); } -void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx, +void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, - grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_mdelem *elem), - void *user_data) { - grpc_linked_mdelem *l; - grpc_linked_mdelem *next; - - GPR_TIMER_BEGIN("grpc_metadata_batch_filter", 0); - - assert_valid_list(&batch->list); - for (l = batch->list.head; l; l = next) { - grpc_mdelem *orig = l->md; - grpc_mdelem *filt = filter(exec_ctx, user_data, orig); - next = l->next; - if (filt == NULL) { - if (l->prev) { - l->prev->next = l->next; - } - if (l->next) { - l->next->prev = l->prev; - } - if (batch->list.head == l) { - batch->list.head = l->next; - } - if (batch->list.tail == l) { - batch->list.tail = l->prev; - } - assert_valid_list(&batch->list); - GRPC_MDELEM_UNREF(exec_ctx, l->md); - } else if (filt != orig) { - GRPC_MDELEM_UNREF(exec_ctx, orig); - l->md = filt; - } - } - assert_valid_list(&batch->list); + grpc_linked_mdelem *storage) { + assert_valid_callouts(exec_ctx, batch); + maybe_unlink_callout(batch, storage); + unlink_storage(&batch->list, storage); + GRPC_MDELEM_UNREF(exec_ctx, storage->md); + assert_valid_callouts(exec_ctx, batch); +} - GPR_TIMER_END("grpc_metadata_batch_filter", 0); +void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx, + grpc_linked_mdelem *storage, + grpc_slice value) { + grpc_mdelem old = storage->md; + grpc_mdelem new = grpc_mdelem_from_slices( + exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(old)), value); + storage->md = new; + GRPC_MDELEM_UNREF(exec_ctx, old); } -static grpc_mdelem *no_metadata_for_you(grpc_exec_ctx *exec_ctx, - void *user_data, grpc_mdelem *elem) { - return NULL; +grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, + grpc_mdelem new) { + grpc_error *error = GRPC_ERROR_NONE; + grpc_mdelem old = storage->md; + if (!grpc_slice_eq(GRPC_MDKEY(new), GRPC_MDKEY(old))) { + maybe_unlink_callout(batch, storage); + storage->md = new; + error = maybe_link_callout(batch, storage); + } else { + storage->md = new; + } + GRPC_MDELEM_UNREF(exec_ctx, old); + return error; } void grpc_metadata_batch_clear(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch) { - batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); - grpc_metadata_batch_filter(exec_ctx, batch, no_metadata_for_you, NULL); + grpc_metadata_batch_destroy(exec_ctx, batch); + grpc_metadata_batch_init(batch); } bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) { @@ -207,3 +291,33 @@ size_t grpc_metadata_batch_size(grpc_metadata_batch *batch) { } return size; } + +static void add_error(grpc_error **composite, grpc_error *error, + const char *composite_error_string) { + if (error == GRPC_ERROR_NONE) return; + if (*composite == GRPC_ERROR_NONE) { + *composite = GRPC_ERROR_CREATE(composite_error_string); + } + *composite = grpc_error_add_child(*composite, error); +} + +grpc_error *grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_metadata_batch_filter_func func, + void *user_data, + const char *composite_error_string) { + grpc_linked_mdelem *l = batch->list.head; + grpc_error *error = GRPC_ERROR_NONE; + while (l) { + grpc_linked_mdelem *next = l->next; + grpc_filtered_mdelem new = func(exec_ctx, user_data, l->md); + add_error(&error, new.error, composite_error_string); + if (GRPC_MDISNULL(new.md)) { + grpc_metadata_batch_remove(exec_ctx, batch, l); + } else if (new.md.payload != l->md.payload) { + grpc_metadata_batch_substitute(exec_ctx, batch, l, new.md); + } + l = next; + } + return error; +} diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index c0bd5174ab..5471539e82 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -41,19 +41,21 @@ #include <grpc/support/port_platform.h> #include <grpc/support/time.h> #include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/static_metadata.h" #ifdef __cplusplus extern "C" { #endif typedef struct grpc_linked_mdelem { - grpc_mdelem *md; + grpc_mdelem md; struct grpc_linked_mdelem *next; struct grpc_linked_mdelem *prev; void *reserved; } grpc_linked_mdelem; typedef struct grpc_mdelem_list { + size_t count; grpc_linked_mdelem *head; grpc_linked_mdelem *tail; } grpc_mdelem_list; @@ -61,6 +63,7 @@ typedef struct grpc_mdelem_list { typedef struct grpc_metadata_batch { /** Metadata elements in this batch */ grpc_mdelem_list list; + grpc_metadata_batch_callouts idx; /** Used to calculate grpc-timeout at the point of sending, or gpr_inf_future if this batch does not need to send a grpc-timeout */ @@ -77,25 +80,37 @@ bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch); /* Returns the transport size of the batch. */ size_t grpc_metadata_batch_size(grpc_metadata_batch *batch); -/** Moves the metadata information from \a src to \a dst. Upon return, \a src is - * zeroed. */ -void grpc_metadata_batch_move(grpc_metadata_batch *dst, - grpc_metadata_batch *src); +/** Remove \a storage from the batch, unreffing the mdelem contained */ +void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage); + +/** Substitute a new mdelem for an old value */ +grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx, + grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, + grpc_mdelem new_value); + +void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx, + grpc_linked_mdelem *storage, + grpc_slice value); /** Add \a storage to the beginning of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ -void grpc_metadata_batch_link_head(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage); +grpc_error *grpc_metadata_batch_link_head( + grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT; /** Add \a storage to the end of \a batch. storage->md is assumed to be valid. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ -void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage); +grpc_error *grpc_metadata_batch_link_tail( + grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT; /** Add \a elem_to_add as the first element in \a batch, using \a storage as backing storage for the linked list element. @@ -103,29 +118,38 @@ void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch, lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ -void grpc_metadata_batch_add_head(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem *elem_to_add); +grpc_error *grpc_metadata_batch_add_head( + grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; /** Add \a elem_to_add as the last element in \a batch, using \a storage as backing storage for the linked list element. \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ -void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem *elem_to_add); - -/** For each element in \a batch, execute \a filter. - The return value from \a filter will be substituted for the - grpc_mdelem passed to \a filter. If \a filter returns NULL, - the element will be moved to the garbage list. */ -void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_mdelem *elem), - void *user_data); +grpc_error *grpc_metadata_batch_add_tail( + grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; + +grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md); + +typedef struct { + grpc_error *error; + grpc_mdelem md; +} grpc_filtered_mdelem; + +#define GRPC_FILTERED_ERROR(error) \ + ((grpc_filtered_mdelem){(error), GRPC_MDNULL}) +#define GRPC_FILTERED_MDELEM(md) ((grpc_filtered_mdelem){GRPC_ERROR_NONE, (md)}) +#define GRPC_FILTERED_REMOVE() \ + ((grpc_filtered_mdelem){GRPC_ERROR_NONE, GRPC_MDNULL}) + +typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)( + grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem elem); +grpc_error *grpc_metadata_batch_filter( + grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, + grpc_metadata_batch_filter_func func, void *user_data, + const char *composite_error_string) GRPC_MUST_USE_RESULT; #ifndef NDEBUG void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd); diff --git a/src/core/lib/transport/method_config.c b/src/core/lib/transport/method_config.c deleted file mode 100644 index 25fb54b37d..0000000000 --- a/src/core/lib/transport/method_config.c +++ /dev/null @@ -1,347 +0,0 @@ -// -// 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. -// - -#include "src/core/lib/transport/method_config.h" - -#include <string.h> - -#include <grpc/impl/codegen/grpc_types.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/time.h> - -#include "src/core/lib/transport/mdstr_hash_table.h" -#include "src/core/lib/transport/metadata.h" - -// -// grpc_method_config -// - -// bool vtable - -static void* bool_copy(void* valuep) { - bool value = *(bool*)valuep; - bool* new_value = gpr_malloc(sizeof(bool)); - *new_value = value; - return new_value; -} - -static int bool_cmp(void* v1, void* v2) { - bool b1 = *(bool*)v1; - bool b2 = *(bool*)v2; - if (!b1 && b2) return -1; - if (b1 && !b2) return 1; - return 0; -} - -static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); } - -static grpc_mdstr_hash_table_vtable bool_vtable = {free_mem, bool_copy, - bool_cmp}; - -// timespec vtable - -static void* timespec_copy(void* valuep) { - gpr_timespec value = *(gpr_timespec*)valuep; - gpr_timespec* new_value = gpr_malloc(sizeof(gpr_timespec)); - *new_value = value; - return new_value; -} - -static int timespec_cmp(void* v1, void* v2) { - return gpr_time_cmp(*(gpr_timespec*)v1, *(gpr_timespec*)v2); -} - -static grpc_mdstr_hash_table_vtable timespec_vtable = {free_mem, timespec_copy, - timespec_cmp}; - -// int32 vtable - -static void* int32_copy(void* valuep) { - int32_t value = *(int32_t*)valuep; - int32_t* new_value = gpr_malloc(sizeof(int32_t)); - *new_value = value; - return new_value; -} - -static int int32_cmp(void* v1, void* v2) { - int32_t i1 = *(int32_t*)v1; - int32_t i2 = *(int32_t*)v2; - if (i1 < i2) return -1; - if (i1 > i2) return 1; - return 0; -} - -static grpc_mdstr_hash_table_vtable int32_vtable = {free_mem, int32_copy, - int32_cmp}; - -// Hash table keys. -#define GRPC_METHOD_CONFIG_WAIT_FOR_READY "grpc.wait_for_ready" // bool -#define GRPC_METHOD_CONFIG_TIMEOUT "grpc.timeout" // gpr_timespec -#define GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES \ - "grpc.max_request_message_bytes" // int32 -#define GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES \ - "grpc.max_response_message_bytes" // int32 - -struct grpc_method_config { - grpc_mdstr_hash_table* table; - grpc_mdstr* wait_for_ready_key; - grpc_mdstr* timeout_key; - grpc_mdstr* max_request_message_bytes_key; - grpc_mdstr* max_response_message_bytes_key; -}; - -grpc_method_config* grpc_method_config_create( - bool* wait_for_ready, gpr_timespec* timeout, - int32_t* max_request_message_bytes, int32_t* max_response_message_bytes) { - grpc_method_config* method_config = gpr_malloc(sizeof(grpc_method_config)); - memset(method_config, 0, sizeof(grpc_method_config)); - method_config->wait_for_ready_key = - grpc_mdstr_from_string(GRPC_METHOD_CONFIG_WAIT_FOR_READY); - method_config->timeout_key = - grpc_mdstr_from_string(GRPC_METHOD_CONFIG_TIMEOUT); - method_config->max_request_message_bytes_key = - grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES); - method_config->max_response_message_bytes_key = - grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES); - grpc_mdstr_hash_table_entry entries[4]; - size_t num_entries = 0; - if (wait_for_ready != NULL) { - entries[num_entries].key = method_config->wait_for_ready_key; - entries[num_entries].value = wait_for_ready; - entries[num_entries].vtable = &bool_vtable; - ++num_entries; - } - if (timeout != NULL) { - entries[num_entries].key = method_config->timeout_key; - entries[num_entries].value = timeout; - entries[num_entries].vtable = ×pec_vtable; - ++num_entries; - } - if (max_request_message_bytes != NULL) { - entries[num_entries].key = method_config->max_request_message_bytes_key; - entries[num_entries].value = max_request_message_bytes; - entries[num_entries].vtable = &int32_vtable; - ++num_entries; - } - if (max_response_message_bytes != NULL) { - entries[num_entries].key = method_config->max_response_message_bytes_key; - entries[num_entries].value = max_response_message_bytes; - entries[num_entries].vtable = &int32_vtable; - ++num_entries; - } - method_config->table = grpc_mdstr_hash_table_create(num_entries, entries); - return method_config; -} - -grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) { - grpc_mdstr_hash_table_ref(method_config->table); - return method_config; -} - -void grpc_method_config_unref(grpc_exec_ctx* exec_ctx, - grpc_method_config* method_config) { - if (grpc_mdstr_hash_table_unref(exec_ctx, method_config->table)) { - GRPC_MDSTR_UNREF(exec_ctx, method_config->wait_for_ready_key); - GRPC_MDSTR_UNREF(exec_ctx, method_config->timeout_key); - GRPC_MDSTR_UNREF(exec_ctx, method_config->max_request_message_bytes_key); - GRPC_MDSTR_UNREF(exec_ctx, method_config->max_response_message_bytes_key); - gpr_free(method_config); - } -} - -int grpc_method_config_cmp(const grpc_method_config* method_config1, - const grpc_method_config* method_config2) { - return grpc_mdstr_hash_table_cmp(method_config1->table, - method_config2->table); -} - -const bool* grpc_method_config_get_wait_for_ready( - const grpc_method_config* method_config) { - return grpc_mdstr_hash_table_get(method_config->table, - method_config->wait_for_ready_key); -} - -const gpr_timespec* grpc_method_config_get_timeout( - const grpc_method_config* method_config) { - return grpc_mdstr_hash_table_get(method_config->table, - method_config->timeout_key); -} - -const int32_t* grpc_method_config_get_max_request_message_bytes( - const grpc_method_config* method_config) { - return grpc_mdstr_hash_table_get( - method_config->table, method_config->max_request_message_bytes_key); -} - -const int32_t* grpc_method_config_get_max_response_message_bytes( - const grpc_method_config* method_config) { - return grpc_mdstr_hash_table_get( - method_config->table, method_config->max_response_message_bytes_key); -} - -// -// grpc_method_config_table -// - -static void method_config_unref(grpc_exec_ctx* exec_ctx, void* valuep) { - grpc_method_config_unref(exec_ctx, valuep); -} - -static void* method_config_ref(void* valuep) { - return grpc_method_config_ref(valuep); -} - -static int method_config_cmp(void* valuep1, void* valuep2) { - return grpc_method_config_cmp(valuep1, valuep2); -} - -static const grpc_mdstr_hash_table_vtable method_config_table_vtable = { - method_config_unref, method_config_ref, method_config_cmp}; - -grpc_method_config_table* grpc_method_config_table_create( - size_t num_entries, grpc_method_config_table_entry* entries) { - grpc_mdstr_hash_table_entry* hash_table_entries = - gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * num_entries); - for (size_t i = 0; i < num_entries; ++i) { - hash_table_entries[i].key = entries[i].method_name; - hash_table_entries[i].value = entries[i].method_config; - hash_table_entries[i].vtable = &method_config_table_vtable; - } - grpc_method_config_table* method_config_table = - grpc_mdstr_hash_table_create(num_entries, hash_table_entries); - gpr_free(hash_table_entries); - return method_config_table; -} - -grpc_method_config_table* grpc_method_config_table_ref( - grpc_method_config_table* table) { - return grpc_mdstr_hash_table_ref(table); -} - -void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx, - grpc_method_config_table* table) { - grpc_mdstr_hash_table_unref(exec_ctx, table); -} - -int grpc_method_config_table_cmp(const grpc_method_config_table* table1, - const grpc_method_config_table* table2) { - return grpc_mdstr_hash_table_cmp(table1, table2); -} - -void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, - const grpc_mdstr_hash_table* table, - const grpc_mdstr* path) { - void* value = grpc_mdstr_hash_table_get(table, path); - // If we didn't find a match for the path, try looking for a wildcard - // entry (i.e., change "/service/method" to "/service/*"). - if (value == NULL) { - const char* path_str = grpc_mdstr_as_c_string(path); - const char* sep = strrchr(path_str, '/') + 1; - const size_t len = (size_t)(sep - path_str); - char* buf = gpr_malloc(len + 2); // '*' and NUL - memcpy(buf, path_str, len); - buf[len] = '*'; - buf[len + 1] = '\0'; - grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf); - gpr_free(buf); - value = grpc_mdstr_hash_table_get(table, wildcard_path); - GRPC_MDSTR_UNREF(exec_ctx, wildcard_path); - } - return value; -} - -static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); } - -static void destroy_arg(grpc_exec_ctx* exec_ctx, void* p) { - grpc_method_config_table_unref(exec_ctx, p); -} - -static int cmp_arg(void* p1, void* p2) { - return grpc_method_config_table_cmp(p1, p2); -} - -static grpc_arg_pointer_vtable arg_vtable = {copy_arg, destroy_arg, cmp_arg}; - -grpc_arg grpc_method_config_table_create_channel_arg( - grpc_method_config_table* table) { - grpc_arg arg; - arg.type = GRPC_ARG_POINTER; - arg.key = GRPC_ARG_SERVICE_CONFIG; - arg.value.pointer.p = table; - arg.value.pointer.vtable = &arg_vtable; - return arg; -} - -// State used by convert_entry() below. -typedef struct conversion_state { - void* (*convert_value)(const grpc_method_config* method_config); - const grpc_mdstr_hash_table_vtable* vtable; - size_t num_entries; - grpc_mdstr_hash_table_entry* entries; -} conversion_state; - -// A function to be passed to grpc_mdstr_hash_table_iterate() to create -// a copy of the entries. -static void convert_entry(const grpc_mdstr_hash_table_entry* entry, - void* user_data) { - conversion_state* state = user_data; - state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key); - state->entries[state->num_entries].value = state->convert_value(entry->value); - state->entries[state->num_entries].vtable = state->vtable; - ++state->num_entries; -} - -grpc_mdstr_hash_table* grpc_method_config_table_convert( - grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table, - void* (*convert_value)(const grpc_method_config* method_config), - const grpc_mdstr_hash_table_vtable* vtable) { - // Create an array of the entries in the table with converted values. - conversion_state state; - state.convert_value = convert_value; - state.vtable = vtable; - state.num_entries = 0; - state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * - grpc_mdstr_hash_table_num_entries(table)); - grpc_mdstr_hash_table_iterate(table, convert_entry, &state); - // Create a new table based on the array we just constructed. - grpc_mdstr_hash_table* new_table = - grpc_mdstr_hash_table_create(state.num_entries, state.entries); - // Clean up the array. - for (size_t i = 0; i < state.num_entries; ++i) { - GRPC_MDSTR_UNREF(exec_ctx, state.entries[i].key); - vtable->destroy_value(exec_ctx, state.entries[i].value); - } - gpr_free(state.entries); - // Return the new table. - return new_table; -} diff --git a/src/core/lib/transport/method_config.h b/src/core/lib/transport/method_config.h deleted file mode 100644 index d17a493fd4..0000000000 --- a/src/core/lib/transport/method_config.h +++ /dev/null @@ -1,139 +0,0 @@ -// -// Copyright 2016, 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_CORE_LIB_TRANSPORT_METHOD_CONFIG_H -#define GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H - -#include <stdbool.h> - -#include <grpc/impl/codegen/gpr_types.h> -#include <grpc/impl/codegen/grpc_types.h> - -#include "src/core/lib/transport/mdstr_hash_table.h" -#include "src/core/lib/transport/metadata.h" - -/// Per-method configuration. -typedef struct grpc_method_config grpc_method_config; - -/// Creates a grpc_method_config with the specified parameters. -/// Any parameter may be NULL to indicate that the value is unset. -/// -/// \a wait_for_ready indicates whether the client should wait until the -/// request deadline for the channel to become ready, even if there is a -/// temporary failure before the deadline while attempting to connect. -/// -/// \a timeout indicates the timeout for calls. -/// -/// \a max_request_message_bytes and \a max_response_message_bytes -/// indicate the maximum sizes of the request (checked when sending) and -/// response (checked when receiving) messages. -grpc_method_config* grpc_method_config_create( - bool* wait_for_ready, gpr_timespec* timeout, - int32_t* max_request_message_bytes, int32_t* max_response_message_bytes); - -grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config); -void grpc_method_config_unref(grpc_exec_ctx* exec_ctx, - grpc_method_config* method_config); - -/// Compares two grpc_method_configs. -/// The sort order is stable but undefined. -int grpc_method_config_cmp(const grpc_method_config* method_config1, - const grpc_method_config* method_config2); - -/// These methods return NULL if the requested field is unset. -/// The caller does NOT take ownership of the result. -const bool* grpc_method_config_get_wait_for_ready( - const grpc_method_config* method_config); -const gpr_timespec* grpc_method_config_get_timeout( - const grpc_method_config* method_config); -const int32_t* grpc_method_config_get_max_request_message_bytes( - const grpc_method_config* method_config); -const int32_t* grpc_method_config_get_max_response_message_bytes( - const grpc_method_config* method_config); - -/// A table of method configs. -typedef grpc_mdstr_hash_table grpc_method_config_table; - -typedef struct grpc_method_config_table_entry { - /// The name is of one of the following forms: - /// service/method -- specifies exact service and method name - /// service/* -- matches all methods for the specified service - grpc_mdstr* method_name; - grpc_method_config* method_config; -} grpc_method_config_table_entry; - -/// Takes new references to all keys and values in \a entries. -grpc_method_config_table* grpc_method_config_table_create( - size_t num_entries, grpc_method_config_table_entry* entries); - -grpc_method_config_table* grpc_method_config_table_ref( - grpc_method_config_table* table); -void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx, - grpc_method_config_table* table); - -/// Compares two grpc_method_config_tables. -/// The sort order is stable but undefined. -int grpc_method_config_table_cmp(const grpc_method_config_table* table1, - const grpc_method_config_table* table2); - -/// Gets the method config for the specified \a path, which should be of -/// the form "/service/method". -/// Returns NULL if the method has no config. -/// Caller does NOT own a reference to the result. -/// -/// Note: This returns a void* instead of a grpc_method_config* so that -/// it can also be used for tables constructed via -/// grpc_method_config_table_convert(). -void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, - const grpc_mdstr_hash_table* table, - const grpc_mdstr* path); - -/// Returns a channel arg containing \a table. -grpc_arg grpc_method_config_table_create_channel_arg( - grpc_method_config_table* table); - -/// Generates a new table from \a table whose values are converted to a -/// new form via the \a convert_value function. The new table will use -/// \a vtable for its values. -/// -/// This is generally used to convert the table's value type from -/// grpc_method_config to a simple struct containing only the parameters -/// relevant to a particular filter, thus avoiding the need for a hash -/// table lookup on the fast path. In that scenario, \a convert_value -/// will return a new instance of the struct containing the values from -/// the grpc_method_config, and \a vtable provides the methods for -/// operating on the struct type. -grpc_mdstr_hash_table* grpc_method_config_table_convert( - grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table, - void* (*convert_value)(const grpc_method_config* method_config), - const grpc_mdstr_hash_table_vtable* vtable); - -#endif /* GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H */ diff --git a/src/core/lib/transport/service_config.c b/src/core/lib/transport/service_config.c index 552d3ec856..12da2a88fe 100644 --- a/src/core/lib/transport/service_config.c +++ b/src/core/lib/transport/service_config.c @@ -39,8 +39,10 @@ #include <grpc/support/string_util.h> #include "src/core/lib/json/json.h" +#include "src/core/lib/slice/slice_hash_table.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" -#include "src/core/lib/transport/mdstr_hash_table.h" // The main purpose of the code here is to parse the service config in // JSON form, which will look like this: @@ -148,8 +150,8 @@ static char* parse_json_method_name(grpc_json* json) { static bool parse_json_method_config( grpc_exec_ctx* exec_ctx, grpc_json* json, void* (*create_value)(const grpc_json* method_config_json), - const grpc_mdstr_hash_table_vtable* vtable, - grpc_mdstr_hash_table_entry* entries, size_t* idx) { + const grpc_slice_hash_table_vtable* vtable, + grpc_slice_hash_table_entry* entries, size_t* idx) { // Construct value. void* method_config = create_value(json); if (method_config == NULL) return false; @@ -170,7 +172,7 @@ static bool parse_json_method_config( if (paths.count == 0) goto done; // No names specified. // Add entry for each path. for (size_t i = 0; i < paths.count; ++i) { - entries[*idx].key = grpc_mdstr_from_string(paths.strs[i]); + entries[*idx].key = grpc_slice_from_copied_string(paths.strs[i]); entries[*idx].value = vtable->copy_value(method_config); entries[*idx].vtable = vtable; ++*idx; @@ -182,15 +184,15 @@ done: return success; } -grpc_mdstr_hash_table* grpc_service_config_create_method_config_table( +grpc_slice_hash_table* grpc_service_config_create_method_config_table( grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config, void* (*create_value)(const grpc_json* method_config_json), - const grpc_mdstr_hash_table_vtable* vtable) { + const grpc_slice_hash_table_vtable* vtable) { const grpc_json* json = service_config->json_tree; // Traverse parsed JSON tree. if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL; size_t num_entries = 0; - grpc_mdstr_hash_table_entry* entries = NULL; + grpc_slice_hash_table_entry* entries = NULL; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key == NULL) return NULL; if (strcmp(field->key, "methodConfig") == 0) { @@ -202,7 +204,7 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table( num_entries += count_names_in_method_config_json(method); } // Populate method config table entries. - entries = gpr_malloc(num_entries * sizeof(grpc_mdstr_hash_table_entry)); + entries = gpr_malloc(num_entries * sizeof(grpc_slice_hash_table_entry)); size_t idx = 0; for (grpc_json* method = field->child; method != NULL; method = method->next) { @@ -215,12 +217,12 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table( } } // Instantiate method config table. - grpc_mdstr_hash_table* method_config_table = NULL; + grpc_slice_hash_table* method_config_table = NULL; if (entries != NULL) { - method_config_table = grpc_mdstr_hash_table_create(num_entries, entries); + method_config_table = grpc_slice_hash_table_create(num_entries, entries); // Clean up. for (size_t i = 0; i < num_entries; ++i) { - GRPC_MDSTR_UNREF(exec_ctx, entries[i].key); + grpc_slice_unref_internal(exec_ctx, entries[i].key); vtable->destroy_value(exec_ctx, entries[i].value); } gpr_free(entries); @@ -229,23 +231,24 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table( } void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, - const grpc_mdstr_hash_table* table, - const grpc_mdstr* path) { - void* value = grpc_mdstr_hash_table_get(table, path); + const grpc_slice_hash_table* table, + grpc_slice path) { + void* value = grpc_slice_hash_table_get(table, path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). if (value == NULL) { - const char* path_str = grpc_mdstr_as_c_string(path); + char* path_str = grpc_slice_to_c_string(path); const char* sep = strrchr(path_str, '/') + 1; const size_t len = (size_t)(sep - path_str); char* buf = gpr_malloc(len + 2); // '*' and NUL memcpy(buf, path_str, len); buf[len] = '*'; buf[len + 1] = '\0'; - grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf); + grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); gpr_free(buf); - value = grpc_mdstr_hash_table_get(table, wildcard_path); - GRPC_MDSTR_UNREF(exec_ctx, wildcard_path); + value = grpc_slice_hash_table_get(table, wildcard_path); + grpc_slice_unref_internal(exec_ctx, wildcard_path); + gpr_free(path_str); } return value; } diff --git a/src/core/lib/transport/service_config.h b/src/core/lib/transport/service_config.h index f0897170fa..cd739a593c 100644 --- a/src/core/lib/transport/service_config.h +++ b/src/core/lib/transport/service_config.h @@ -35,7 +35,7 @@ #include <grpc/impl/codegen/grpc_types.h> #include "src/core/lib/json/json.h" -#include "src/core/lib/transport/mdstr_hash_table.h" +#include "src/core/lib/slice/slice_hash_table.h" typedef struct grpc_service_config grpc_service_config; @@ -53,10 +53,10 @@ const char* grpc_service_config_get_lb_policy_name( /// returned by \a create_value(), based on data parsed from the JSON tree. /// \a vtable provides methods used to manage the values. /// Returns NULL on error. -grpc_mdstr_hash_table* grpc_service_config_create_method_config_table( +grpc_slice_hash_table* grpc_service_config_create_method_config_table( grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config, void* (*create_value)(const grpc_json* method_config_json), - const grpc_mdstr_hash_table_vtable* vtable); + const grpc_slice_hash_table_vtable* vtable); /// A helper function for looking up values in the table returned by /// \a grpc_service_config_create_method_config_table(). @@ -65,7 +65,7 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table( /// Returns NULL if the method has no config. /// Caller does NOT own a reference to the result. void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, - const grpc_mdstr_hash_table* table, - const grpc_mdstr* path); + const grpc_slice_hash_table* table, + grpc_slice path); #endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */ diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c index 8b22592b45..750711befd 100644 --- a/src/core/lib/transport/static_metadata.c +++ b/src/core/lib/transport/static_metadata.c @@ -41,120 +41,770 @@ #include "src/core/lib/transport/static_metadata.h" -grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; +#include "src/core/lib/slice/slice_internal.h" + +static uint8_t g_bytes[] = { + 58, 112, 97, 116, 104, 58, 109, 101, 116, 104, 111, 100, 58, 115, 116, + 97, 116, 117, 115, 58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 58, + 115, 99, 104, 101, 109, 101, 116, 101, 103, 114, 112, 99, 45, 109, 101, + 115, 115, 97, 103, 101, 103, 114, 112, 99, 45, 115, 116, 97, 116, 117, + 115, 103, 114, 112, 99, 45, 112, 97, 121, 108, 111, 97, 100, 45, 98, + 105, 110, 103, 114, 112, 99, 45, 101, 110, 99, 111, 100, 105, 110, 103, + 103, 114, 112, 99, 45, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, + 111, 100, 105, 110, 103, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, + 112, 101, 103, 114, 112, 99, 45, 105, 110, 116, 101, 114, 110, 97, 108, + 45, 101, 110, 99, 111, 100, 105, 110, 103, 45, 114, 101, 113, 117, 101, + 115, 116, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 104, 111, 115, + 116, 108, 98, 45, 116, 111, 107, 101, 110, 108, 98, 45, 99, 111, 115, + 116, 45, 98, 105, 110, 103, 114, 112, 99, 45, 116, 105, 109, 101, 111, + 117, 116, 103, 114, 112, 99, 45, 116, 114, 97, 99, 105, 110, 103, 45, + 98, 105, 110, 103, 114, 112, 99, 45, 115, 116, 97, 116, 115, 45, 98, + 105, 110, 103, 114, 112, 99, 46, 119, 97, 105, 116, 95, 102, 111, 114, + 95, 114, 101, 97, 100, 121, 103, 114, 112, 99, 46, 116, 105, 109, 101, + 111, 117, 116, 103, 114, 112, 99, 46, 109, 97, 120, 95, 114, 101, 113, + 117, 101, 115, 116, 95, 109, 101, 115, 115, 97, 103, 101, 95, 98, 121, + 116, 101, 115, 103, 114, 112, 99, 46, 109, 97, 120, 95, 114, 101, 115, + 112, 111, 110, 115, 101, 95, 109, 101, 115, 115, 97, 103, 101, 95, 98, + 121, 116, 101, 115, 47, 103, 114, 112, 99, 46, 108, 98, 46, 118, 49, + 46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99, 101, 114, 47, 66, + 97, 108, 97, 110, 99, 101, 76, 111, 97, 100, 48, 49, 50, 105, 100, + 101, 110, 116, 105, 116, 121, 103, 122, 105, 112, 100, 101, 102, 108, 97, + 116, 101, 116, 114, 97, 105, 108, 101, 114, 115, 97, 112, 112, 108, 105, + 99, 97, 116, 105, 111, 110, 47, 103, 114, 112, 99, 80, 79, 83, 84, + 50, 48, 48, 52, 48, 52, 104, 116, 116, 112, 104, 116, 116, 112, 115, + 103, 114, 112, 99, 71, 69, 84, 80, 85, 84, 47, 47, 105, 110, 100, + 101, 120, 46, 104, 116, 109, 108, 50, 48, 52, 50, 48, 54, 51, 48, + 52, 52, 48, 48, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, 99, + 104, 97, 114, 115, 101, 116, 97, 99, 99, 101, 112, 116, 45, 101, 110, + 99, 111, 100, 105, 110, 103, 103, 122, 105, 112, 44, 32, 100, 101, 102, + 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, 103, + 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, 103, + 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, 45, + 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, 111, + 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, 117, + 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104, + 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110, + 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111, + 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 99, + 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, + 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99, + 111, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110, + 99, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111, + 111, 107, 105, 101, 100, 97, 116, 101, 101, 116, 97, 103, 101, 120, 112, + 101, 99, 116, 101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 105, + 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100, 105, 102, + 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102, 45, 110, 111, 110, + 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114, 97, 110, 103, 101, + 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105, 101, 100, 45, 115, + 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111, 100, 105, 102, 105, + 101, 100, 108, 105, 110, 107, 108, 111, 99, 97, 116, 105, 111, 110, 109, + 97, 120, 45, 102, 111, 114, 119, 97, 114, 100, 115, 112, 114, 111, 120, + 121, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 112, + 114, 111, 120, 121, 45, 97, 117, 116, 104, 111, 114, 105, 122, 97, 116, + 105, 111, 110, 114, 97, 110, 103, 101, 114, 101, 102, 101, 114, 101, 114, + 114, 101, 102, 114, 101, 115, 104, 114, 101, 116, 114, 121, 45, 97, 102, + 116, 101, 114, 115, 101, 114, 118, 101, 114, 115, 101, 116, 45, 99, 111, + 111, 107, 105, 101, 115, 116, 114, 105, 99, 116, 45, 116, 114, 97, 110, + 115, 112, 111, 114, 116, 45, 115, 101, 99, 117, 114, 105, 116, 121, 116, + 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, 100, 105, 110, + 103, 118, 97, 114, 121, 118, 105, 97, 119, 119, 119, 45, 97, 117, 116, + 104, 101, 110, 116, 105, 99, 97, 116, 101, 105, 100, 101, 110, 116, 105, + 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 105, 100, 101, 110, 116, + 105, 116, 121, 44, 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101, + 44, 103, 122, 105, 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, + 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112}; + +static void static_ref(void *unused) {} +static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {} +static const grpc_slice_refcount_vtable static_sub_vtable = { + static_ref, static_unref, grpc_slice_default_eq_impl, + grpc_slice_default_hash_impl}; +const grpc_slice_refcount_vtable grpc_static_metadata_vtable = { + static_ref, static_unref, grpc_static_slice_eq, grpc_static_slice_hash}; +static grpc_slice_refcount static_sub_refcnt = {&static_sub_vtable, + &static_sub_refcnt}; +grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = { + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, + {&grpc_static_metadata_vtable, &static_sub_refcnt}, +}; + +const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = { + {.refcount = &grpc_static_metadata_refcounts[0], + .data.refcounted = {g_bytes + 0, 5}}, + {.refcount = &grpc_static_metadata_refcounts[1], + .data.refcounted = {g_bytes + 5, 7}}, + {.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[3], + .data.refcounted = {g_bytes + 19, 10}}, + {.refcount = &grpc_static_metadata_refcounts[4], + .data.refcounted = {g_bytes + 29, 7}}, + {.refcount = &grpc_static_metadata_refcounts[5], + .data.refcounted = {g_bytes + 36, 2}}, + {.refcount = &grpc_static_metadata_refcounts[6], + .data.refcounted = {g_bytes + 38, 12}}, + {.refcount = &grpc_static_metadata_refcounts[7], + .data.refcounted = {g_bytes + 50, 11}}, + {.refcount = &grpc_static_metadata_refcounts[8], + .data.refcounted = {g_bytes + 61, 16}}, + {.refcount = &grpc_static_metadata_refcounts[9], + .data.refcounted = {g_bytes + 77, 13}}, + {.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[11], + .data.refcounted = {g_bytes + 110, 12}}, + {.refcount = &grpc_static_metadata_refcounts[12], + .data.refcounted = {g_bytes + 122, 30}}, + {.refcount = &grpc_static_metadata_refcounts[13], + .data.refcounted = {g_bytes + 152, 10}}, + {.refcount = &grpc_static_metadata_refcounts[14], + .data.refcounted = {g_bytes + 162, 4}}, + {.refcount = &grpc_static_metadata_refcounts[15], + .data.refcounted = {g_bytes + 166, 8}}, + {.refcount = &grpc_static_metadata_refcounts[16], + .data.refcounted = {g_bytes + 174, 11}}, + {.refcount = &grpc_static_metadata_refcounts[17], + .data.refcounted = {g_bytes + 185, 12}}, + {.refcount = &grpc_static_metadata_refcounts[18], + .data.refcounted = {g_bytes + 197, 16}}, + {.refcount = &grpc_static_metadata_refcounts[19], + .data.refcounted = {g_bytes + 213, 14}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}, + {.refcount = &grpc_static_metadata_refcounts[21], + .data.refcounted = {g_bytes + 227, 19}}, + {.refcount = &grpc_static_metadata_refcounts[22], + .data.refcounted = {g_bytes + 246, 12}}, + {.refcount = &grpc_static_metadata_refcounts[23], + .data.refcounted = {g_bytes + 258, 30}}, + {.refcount = &grpc_static_metadata_refcounts[24], + .data.refcounted = {g_bytes + 288, 31}}, + {.refcount = &grpc_static_metadata_refcounts[25], + .data.refcounted = {g_bytes + 319, 36}}, + {.refcount = &grpc_static_metadata_refcounts[26], + .data.refcounted = {g_bytes + 355, 1}}, + {.refcount = &grpc_static_metadata_refcounts[27], + .data.refcounted = {g_bytes + 356, 1}}, + {.refcount = &grpc_static_metadata_refcounts[28], + .data.refcounted = {g_bytes + 357, 1}}, + {.refcount = &grpc_static_metadata_refcounts[29], + .data.refcounted = {g_bytes + 358, 8}}, + {.refcount = &grpc_static_metadata_refcounts[30], + .data.refcounted = {g_bytes + 366, 4}}, + {.refcount = &grpc_static_metadata_refcounts[31], + .data.refcounted = {g_bytes + 370, 7}}, + {.refcount = &grpc_static_metadata_refcounts[32], + .data.refcounted = {g_bytes + 377, 8}}, + {.refcount = &grpc_static_metadata_refcounts[33], + .data.refcounted = {g_bytes + 385, 16}}, + {.refcount = &grpc_static_metadata_refcounts[34], + .data.refcounted = {g_bytes + 401, 4}}, + {.refcount = &grpc_static_metadata_refcounts[35], + .data.refcounted = {g_bytes + 405, 3}}, + {.refcount = &grpc_static_metadata_refcounts[36], + .data.refcounted = {g_bytes + 408, 3}}, + {.refcount = &grpc_static_metadata_refcounts[37], + .data.refcounted = {g_bytes + 411, 4}}, + {.refcount = &grpc_static_metadata_refcounts[38], + .data.refcounted = {g_bytes + 415, 5}}, + {.refcount = &grpc_static_metadata_refcounts[39], + .data.refcounted = {g_bytes + 420, 4}}, + {.refcount = &grpc_static_metadata_refcounts[40], + .data.refcounted = {g_bytes + 424, 3}}, + {.refcount = &grpc_static_metadata_refcounts[41], + .data.refcounted = {g_bytes + 427, 3}}, + {.refcount = &grpc_static_metadata_refcounts[42], + .data.refcounted = {g_bytes + 430, 1}}, + {.refcount = &grpc_static_metadata_refcounts[43], + .data.refcounted = {g_bytes + 431, 11}}, + {.refcount = &grpc_static_metadata_refcounts[44], + .data.refcounted = {g_bytes + 442, 3}}, + {.refcount = &grpc_static_metadata_refcounts[45], + .data.refcounted = {g_bytes + 445, 3}}, + {.refcount = &grpc_static_metadata_refcounts[46], + .data.refcounted = {g_bytes + 448, 3}}, + {.refcount = &grpc_static_metadata_refcounts[47], + .data.refcounted = {g_bytes + 451, 3}}, + {.refcount = &grpc_static_metadata_refcounts[48], + .data.refcounted = {g_bytes + 454, 3}}, + {.refcount = &grpc_static_metadata_refcounts[49], + .data.refcounted = {g_bytes + 457, 14}}, + {.refcount = &grpc_static_metadata_refcounts[50], + .data.refcounted = {g_bytes + 471, 15}}, + {.refcount = &grpc_static_metadata_refcounts[51], + .data.refcounted = {g_bytes + 486, 13}}, + {.refcount = &grpc_static_metadata_refcounts[52], + .data.refcounted = {g_bytes + 499, 15}}, + {.refcount = &grpc_static_metadata_refcounts[53], + .data.refcounted = {g_bytes + 514, 13}}, + {.refcount = &grpc_static_metadata_refcounts[54], + .data.refcounted = {g_bytes + 527, 6}}, + {.refcount = &grpc_static_metadata_refcounts[55], + .data.refcounted = {g_bytes + 533, 27}}, + {.refcount = &grpc_static_metadata_refcounts[56], + .data.refcounted = {g_bytes + 560, 3}}, + {.refcount = &grpc_static_metadata_refcounts[57], + .data.refcounted = {g_bytes + 563, 5}}, + {.refcount = &grpc_static_metadata_refcounts[58], + .data.refcounted = {g_bytes + 568, 13}}, + {.refcount = &grpc_static_metadata_refcounts[59], + .data.refcounted = {g_bytes + 581, 13}}, + {.refcount = &grpc_static_metadata_refcounts[60], + .data.refcounted = {g_bytes + 594, 19}}, + {.refcount = &grpc_static_metadata_refcounts[61], + .data.refcounted = {g_bytes + 613, 16}}, + {.refcount = &grpc_static_metadata_refcounts[62], + .data.refcounted = {g_bytes + 629, 16}}, + {.refcount = &grpc_static_metadata_refcounts[63], + .data.refcounted = {g_bytes + 645, 14}}, + {.refcount = &grpc_static_metadata_refcounts[64], + .data.refcounted = {g_bytes + 659, 16}}, + {.refcount = &grpc_static_metadata_refcounts[65], + .data.refcounted = {g_bytes + 675, 13}}, + {.refcount = &grpc_static_metadata_refcounts[66], + .data.refcounted = {g_bytes + 688, 6}}, + {.refcount = &grpc_static_metadata_refcounts[67], + .data.refcounted = {g_bytes + 694, 4}}, + {.refcount = &grpc_static_metadata_refcounts[68], + .data.refcounted = {g_bytes + 698, 4}}, + {.refcount = &grpc_static_metadata_refcounts[69], + .data.refcounted = {g_bytes + 702, 6}}, + {.refcount = &grpc_static_metadata_refcounts[70], + .data.refcounted = {g_bytes + 708, 7}}, + {.refcount = &grpc_static_metadata_refcounts[71], + .data.refcounted = {g_bytes + 715, 4}}, + {.refcount = &grpc_static_metadata_refcounts[72], + .data.refcounted = {g_bytes + 719, 8}}, + {.refcount = &grpc_static_metadata_refcounts[73], + .data.refcounted = {g_bytes + 727, 17}}, + {.refcount = &grpc_static_metadata_refcounts[74], + .data.refcounted = {g_bytes + 744, 13}}, + {.refcount = &grpc_static_metadata_refcounts[75], + .data.refcounted = {g_bytes + 757, 8}}, + {.refcount = &grpc_static_metadata_refcounts[76], + .data.refcounted = {g_bytes + 765, 19}}, + {.refcount = &grpc_static_metadata_refcounts[77], + .data.refcounted = {g_bytes + 784, 13}}, + {.refcount = &grpc_static_metadata_refcounts[78], + .data.refcounted = {g_bytes + 797, 4}}, + {.refcount = &grpc_static_metadata_refcounts[79], + .data.refcounted = {g_bytes + 801, 8}}, + {.refcount = &grpc_static_metadata_refcounts[80], + .data.refcounted = {g_bytes + 809, 12}}, + {.refcount = &grpc_static_metadata_refcounts[81], + .data.refcounted = {g_bytes + 821, 18}}, + {.refcount = &grpc_static_metadata_refcounts[82], + .data.refcounted = {g_bytes + 839, 19}}, + {.refcount = &grpc_static_metadata_refcounts[83], + .data.refcounted = {g_bytes + 858, 5}}, + {.refcount = &grpc_static_metadata_refcounts[84], + .data.refcounted = {g_bytes + 863, 7}}, + {.refcount = &grpc_static_metadata_refcounts[85], + .data.refcounted = {g_bytes + 870, 7}}, + {.refcount = &grpc_static_metadata_refcounts[86], + .data.refcounted = {g_bytes + 877, 11}}, + {.refcount = &grpc_static_metadata_refcounts[87], + .data.refcounted = {g_bytes + 888, 6}}, + {.refcount = &grpc_static_metadata_refcounts[88], + .data.refcounted = {g_bytes + 894, 10}}, + {.refcount = &grpc_static_metadata_refcounts[89], + .data.refcounted = {g_bytes + 904, 25}}, + {.refcount = &grpc_static_metadata_refcounts[90], + .data.refcounted = {g_bytes + 929, 17}}, + {.refcount = &grpc_static_metadata_refcounts[91], + .data.refcounted = {g_bytes + 946, 4}}, + {.refcount = &grpc_static_metadata_refcounts[92], + .data.refcounted = {g_bytes + 950, 3}}, + {.refcount = &grpc_static_metadata_refcounts[93], + .data.refcounted = {g_bytes + 953, 16}}, + {.refcount = &grpc_static_metadata_refcounts[94], + .data.refcounted = {g_bytes + 969, 16}}, + {.refcount = &grpc_static_metadata_refcounts[95], + .data.refcounted = {g_bytes + 985, 13}}, + {.refcount = &grpc_static_metadata_refcounts[96], + .data.refcounted = {g_bytes + 998, 12}}, + {.refcount = &grpc_static_metadata_refcounts[97], + .data.refcounted = {g_bytes + 1010, 21}}, +}; -grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8}; + +static const int8_t elems_r[] = { + 10, 8, -3, 0, 9, 21, -76, 22, 0, 10, -7, 20, 0, 19, 18, 17, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -49, -50, 16, -52, -53, -54, -54, -55, -56, -57, 0, 38, 37, 36, 35, + 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, + 18, 17, 16, 15, 14, 13, 12, 15, 14, 13, 12, 11, 10, 9, 8, 0}; +static uint32_t elems_phash(uint32_t i) { + i -= 42; + uint32_t x = i % 96; + uint32_t y = i / 96; + uint32_t h = x; + if (y < GPR_ARRAY_SIZE(elems_r)) { + uint32_t delta = (uint32_t)elems_r[y]; + h += delta; + } + return h; +} -const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] = - {11, 33, 10, 33, 12, 33, 12, 50, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33, - 19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33, - 28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31, - 40, 32, 40, 49, 40, 54, 40, 55, 40, 56, 40, 57, 41, 31, 41, 49, 41, 54, - 46, 0, 46, 1, 46, 2, 51, 33, 58, 33, 59, 33, 60, 33, 61, 33, 62, 33, - 63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 33, 69, 38, 69, 71, 69, 74, - 70, 82, 70, 83, 72, 33, 73, 33, 75, 33, 76, 33, 77, 33, 78, 33, 79, 39, - 79, 52, 79, 53, 80, 33, 81, 33, 84, 3, 84, 4, 84, 5, 84, 6, 84, 7, - 84, 8, 84, 9, 85, 33, 86, 87, 88, 33, 89, 33, 90, 33, 91, 33, 92, 33}; +static const uint16_t elem_keys[] = { + 1009, 1010, 1011, 240, 241, 242, 243, 244, 138, 139, 42, 43, + 429, 430, 431, 911, 912, 913, 712, 713, 1098, 522, 714, 1294, + 1392, 1490, 1588, 4822, 4920, 4951, 5116, 5214, 5312, 1111, 5410, 5508, + 5606, 5704, 5802, 5900, 5998, 6096, 6194, 6292, 6390, 6488, 6586, 6684, + 6782, 6880, 6978, 7076, 7174, 7272, 7370, 7468, 7566, 7664, 7762, 7860, + 7958, 8056, 8154, 8252, 8350, 1074, 1075, 1076, 1077, 8448, 8546, 8644, + 8742, 8840, 8938, 9036, 9134, 314, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 132, 231, 232, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0}; +static const uint8_t elem_idxs[] = { + 74, 77, 75, 19, 20, 21, 22, 23, 15, 16, 17, 18, 11, 12, 13, + 3, 4, 5, 0, 1, 41, 6, 2, 70, 48, 55, 56, 24, 25, 26, + 27, 28, 29, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 42, 43, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 57, 58, 59, + 60, 61, 62, 63, 64, 76, 78, 79, 80, 65, 66, 67, 68, 69, 71, + 72, 73, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 8, 9, 10}; -const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { - "0", - "1", - "2", - "200", - "204", - "206", - "304", - "400", - "404", - "500", - "accept", - "accept-charset", - "accept-encoding", - "accept-language", - "accept-ranges", - "access-control-allow-origin", - "age", - "allow", - "application/grpc", - ":authority", - "authorization", - "cache-control", - "content-disposition", - "content-encoding", - "content-language", - "content-length", - "content-location", - "content-range", - "content-type", - "cookie", - "date", - "deflate", - "deflate,gzip", - "", - "etag", - "expect", - "expires", - "from", - "GET", - "grpc", - "grpc-accept-encoding", - "grpc-encoding", - "grpc-internal-encoding-request", - "grpc-message", - "grpc-payload-bin", - "grpc-stats-bin", - "grpc-status", - "grpc-timeout", - "grpc-tracing-bin", - "gzip", - "gzip, deflate", - "host", - "http", - "https", - "identity", - "identity,deflate", - "identity,deflate,gzip", - "identity,gzip", - "if-match", - "if-modified-since", - "if-none-match", - "if-range", - "if-unmodified-since", - "last-modified", - "lb-cost-bin", - "lb-token", - "link", - "location", - "max-forwards", - ":method", - ":path", - "POST", - "proxy-authenticate", - "proxy-authorization", - "PUT", - "range", - "referer", - "refresh", - "retry-after", - ":scheme", - "server", - "set-cookie", - "/", - "/index.html", - ":status", - "strict-transport-security", - "te", - "trailers", - "transfer-encoding", - "user-agent", - "vary", - "via", - "www-authenticate"}; +grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) { + if (a == -1 || b == -1) return GRPC_MDNULL; + uint32_t k = (uint32_t)(a * 98 + b); + uint32_t h = elems_phash(k); + return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k + ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]], + GRPC_MDELEM_STORAGE_STATIC) + : GRPC_MDNULL; +} -const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 29, 26, 30, - 28, 32, 27, 31}; +grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { + {{.refcount = &grpc_static_metadata_refcounts[7], + .data.refcounted = {g_bytes + 50, 11}}, + {.refcount = &grpc_static_metadata_refcounts[26], + .data.refcounted = {g_bytes + 355, 1}}}, + {{.refcount = &grpc_static_metadata_refcounts[7], + .data.refcounted = {g_bytes + 50, 11}}, + {.refcount = &grpc_static_metadata_refcounts[27], + .data.refcounted = {g_bytes + 356, 1}}}, + {{.refcount = &grpc_static_metadata_refcounts[7], + .data.refcounted = {g_bytes + 50, 11}}, + {.refcount = &grpc_static_metadata_refcounts[28], + .data.refcounted = {g_bytes + 357, 1}}}, + {{.refcount = &grpc_static_metadata_refcounts[9], + .data.refcounted = {g_bytes + 77, 13}}, + {.refcount = &grpc_static_metadata_refcounts[29], + .data.refcounted = {g_bytes + 358, 8}}}, + {{.refcount = &grpc_static_metadata_refcounts[9], + .data.refcounted = {g_bytes + 77, 13}}, + {.refcount = &grpc_static_metadata_refcounts[30], + .data.refcounted = {g_bytes + 366, 4}}}, + {{.refcount = &grpc_static_metadata_refcounts[9], + .data.refcounted = {g_bytes + 77, 13}}, + {.refcount = &grpc_static_metadata_refcounts[31], + .data.refcounted = {g_bytes + 370, 7}}}, + {{.refcount = &grpc_static_metadata_refcounts[5], + .data.refcounted = {g_bytes + 36, 2}}, + {.refcount = &grpc_static_metadata_refcounts[32], + .data.refcounted = {g_bytes + 377, 8}}}, + {{.refcount = &grpc_static_metadata_refcounts[11], + .data.refcounted = {g_bytes + 110, 12}}, + {.refcount = &grpc_static_metadata_refcounts[33], + .data.refcounted = {g_bytes + 385, 16}}}, + {{.refcount = &grpc_static_metadata_refcounts[1], + .data.refcounted = {g_bytes + 5, 7}}, + {.refcount = &grpc_static_metadata_refcounts[34], + .data.refcounted = {g_bytes + 401, 4}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[35], + .data.refcounted = {g_bytes + 405, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[36], + .data.refcounted = {g_bytes + 408, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[4], + .data.refcounted = {g_bytes + 29, 7}}, + {.refcount = &grpc_static_metadata_refcounts[37], + .data.refcounted = {g_bytes + 411, 4}}}, + {{.refcount = &grpc_static_metadata_refcounts[4], + .data.refcounted = {g_bytes + 29, 7}}, + {.refcount = &grpc_static_metadata_refcounts[38], + .data.refcounted = {g_bytes + 415, 5}}}, + {{.refcount = &grpc_static_metadata_refcounts[4], + .data.refcounted = {g_bytes + 29, 7}}, + {.refcount = &grpc_static_metadata_refcounts[39], + .data.refcounted = {g_bytes + 420, 4}}}, + {{.refcount = &grpc_static_metadata_refcounts[3], + .data.refcounted = {g_bytes + 19, 10}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[1], + .data.refcounted = {g_bytes + 5, 7}}, + {.refcount = &grpc_static_metadata_refcounts[40], + .data.refcounted = {g_bytes + 424, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[1], + .data.refcounted = {g_bytes + 5, 7}}, + {.refcount = &grpc_static_metadata_refcounts[41], + .data.refcounted = {g_bytes + 427, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[0], + .data.refcounted = {g_bytes + 0, 5}}, + {.refcount = &grpc_static_metadata_refcounts[42], + .data.refcounted = {g_bytes + 430, 1}}}, + {{.refcount = &grpc_static_metadata_refcounts[0], + .data.refcounted = {g_bytes + 0, 5}}, + {.refcount = &grpc_static_metadata_refcounts[43], + .data.refcounted = {g_bytes + 431, 11}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[44], + .data.refcounted = {g_bytes + 442, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[45], + .data.refcounted = {g_bytes + 445, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[46], + .data.refcounted = {g_bytes + 448, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[47], + .data.refcounted = {g_bytes + 451, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[2], + .data.refcounted = {g_bytes + 12, 7}}, + {.refcount = &grpc_static_metadata_refcounts[48], + .data.refcounted = {g_bytes + 454, 3}}}, + {{.refcount = &grpc_static_metadata_refcounts[49], + .data.refcounted = {g_bytes + 457, 14}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[50], + .data.refcounted = {g_bytes + 471, 15}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[50], + .data.refcounted = {g_bytes + 471, 15}}, + {.refcount = &grpc_static_metadata_refcounts[51], + .data.refcounted = {g_bytes + 486, 13}}}, + {{.refcount = &grpc_static_metadata_refcounts[52], + .data.refcounted = {g_bytes + 499, 15}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[53], + .data.refcounted = {g_bytes + 514, 13}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[54], + .data.refcounted = {g_bytes + 527, 6}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[55], + .data.refcounted = {g_bytes + 533, 27}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[56], + .data.refcounted = {g_bytes + 560, 3}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[57], + .data.refcounted = {g_bytes + 563, 5}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[58], + .data.refcounted = {g_bytes + 568, 13}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[59], + .data.refcounted = {g_bytes + 581, 13}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[60], + .data.refcounted = {g_bytes + 594, 19}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[61], + .data.refcounted = {g_bytes + 613, 16}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[62], + .data.refcounted = {g_bytes + 629, 16}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[63], + .data.refcounted = {g_bytes + 645, 14}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[64], + .data.refcounted = {g_bytes + 659, 16}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[65], + .data.refcounted = {g_bytes + 675, 13}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[11], + .data.refcounted = {g_bytes + 110, 12}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[66], + .data.refcounted = {g_bytes + 688, 6}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[67], + .data.refcounted = {g_bytes + 694, 4}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[68], + .data.refcounted = {g_bytes + 698, 4}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[69], + .data.refcounted = {g_bytes + 702, 6}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[70], + .data.refcounted = {g_bytes + 708, 7}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[71], + .data.refcounted = {g_bytes + 715, 4}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[14], + .data.refcounted = {g_bytes + 162, 4}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[72], + .data.refcounted = {g_bytes + 719, 8}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[73], + .data.refcounted = {g_bytes + 727, 17}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[74], + .data.refcounted = {g_bytes + 744, 13}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[75], + .data.refcounted = {g_bytes + 757, 8}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[76], + .data.refcounted = {g_bytes + 765, 19}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[77], + .data.refcounted = {g_bytes + 784, 13}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[15], + .data.refcounted = {g_bytes + 166, 8}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[16], + .data.refcounted = {g_bytes + 174, 11}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[78], + .data.refcounted = {g_bytes + 797, 4}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[79], + .data.refcounted = {g_bytes + 801, 8}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[80], + .data.refcounted = {g_bytes + 809, 12}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[81], + .data.refcounted = {g_bytes + 821, 18}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[82], + .data.refcounted = {g_bytes + 839, 19}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[83], + .data.refcounted = {g_bytes + 858, 5}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[84], + .data.refcounted = {g_bytes + 863, 7}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[85], + .data.refcounted = {g_bytes + 870, 7}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[86], + .data.refcounted = {g_bytes + 877, 11}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[87], + .data.refcounted = {g_bytes + 888, 6}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[88], + .data.refcounted = {g_bytes + 894, 10}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[89], + .data.refcounted = {g_bytes + 904, 25}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[90], + .data.refcounted = {g_bytes + 929, 17}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[13], + .data.refcounted = {g_bytes + 152, 10}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[91], + .data.refcounted = {g_bytes + 946, 4}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[92], + .data.refcounted = {g_bytes + 950, 3}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[93], + .data.refcounted = {g_bytes + 953, 16}}, + {.refcount = &grpc_static_metadata_refcounts[20], + .data.refcounted = {g_bytes + 227, 0}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[29], + .data.refcounted = {g_bytes + 358, 8}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[31], + .data.refcounted = {g_bytes + 370, 7}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[94], + .data.refcounted = {g_bytes + 969, 16}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[30], + .data.refcounted = {g_bytes + 366, 4}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[95], + .data.refcounted = {g_bytes + 985, 13}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[96], + .data.refcounted = {g_bytes + 998, 12}}}, + {{.refcount = &grpc_static_metadata_refcounts[10], + .data.refcounted = {g_bytes + 90, 20}}, + {.refcount = &grpc_static_metadata_refcounts[97], + .data.refcounted = {g_bytes + 1010, 21}}}, +}; +const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 74, 75, 76, + 77, 78, 79, 80}; diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h index 28ad6f2961..7649ccd5d2 100644 --- a/src/core/lib/transport/static_metadata.h +++ b/src/core/lib/transport/static_metadata.h @@ -44,375 +44,521 @@ #include "src/core/lib/transport/metadata.h" -#define GRPC_STATIC_MDSTR_COUNT 93 -extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; +#define GRPC_STATIC_MDSTR_COUNT 98 +extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT]; +/* ":path" */ +#define GRPC_MDSTR_PATH (grpc_static_slice_table[0]) +/* ":method" */ +#define GRPC_MDSTR_METHOD (grpc_static_slice_table[1]) +/* ":status" */ +#define GRPC_MDSTR_STATUS (grpc_static_slice_table[2]) +/* ":authority" */ +#define GRPC_MDSTR_AUTHORITY (grpc_static_slice_table[3]) +/* ":scheme" */ +#define GRPC_MDSTR_SCHEME (grpc_static_slice_table[4]) +/* "te" */ +#define GRPC_MDSTR_TE (grpc_static_slice_table[5]) +/* "grpc-message" */ +#define GRPC_MDSTR_GRPC_MESSAGE (grpc_static_slice_table[6]) +/* "grpc-status" */ +#define GRPC_MDSTR_GRPC_STATUS (grpc_static_slice_table[7]) +/* "grpc-payload-bin" */ +#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (grpc_static_slice_table[8]) +/* "grpc-encoding" */ +#define GRPC_MDSTR_GRPC_ENCODING (grpc_static_slice_table[9]) +/* "grpc-accept-encoding" */ +#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (grpc_static_slice_table[10]) +/* "content-type" */ +#define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table[11]) +/* "grpc-internal-encoding-request" */ +#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[12]) +/* "user-agent" */ +#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[13]) +/* "host" */ +#define GRPC_MDSTR_HOST (grpc_static_slice_table[14]) +/* "lb-token" */ +#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[15]) +/* "lb-cost-bin" */ +#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[16]) +/* "grpc-timeout" */ +#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[17]) +/* "grpc-tracing-bin" */ +#define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[18]) +/* "grpc-stats-bin" */ +#define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[19]) +/* "" */ +#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[20]) +/* "grpc.wait_for_ready" */ +#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[21]) +/* "grpc.timeout" */ +#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[22]) +/* "grpc.max_request_message_bytes" */ +#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \ + (grpc_static_slice_table[23]) +/* "grpc.max_response_message_bytes" */ +#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \ + (grpc_static_slice_table[24]) +/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */ +#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \ + (grpc_static_slice_table[25]) /* "0" */ -#define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0]) +#define GRPC_MDSTR_0 (grpc_static_slice_table[26]) /* "1" */ -#define GRPC_MDSTR_1 (&grpc_static_mdstr_table[1]) +#define GRPC_MDSTR_1 (grpc_static_slice_table[27]) /* "2" */ -#define GRPC_MDSTR_2 (&grpc_static_mdstr_table[2]) +#define GRPC_MDSTR_2 (grpc_static_slice_table[28]) +/* "identity" */ +#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[29]) +/* "gzip" */ +#define GRPC_MDSTR_GZIP (grpc_static_slice_table[30]) +/* "deflate" */ +#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[31]) +/* "trailers" */ +#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[32]) +/* "application/grpc" */ +#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[33]) +/* "POST" */ +#define GRPC_MDSTR_POST (grpc_static_slice_table[34]) /* "200" */ -#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[3]) +#define GRPC_MDSTR_200 (grpc_static_slice_table[35]) +/* "404" */ +#define GRPC_MDSTR_404 (grpc_static_slice_table[36]) +/* "http" */ +#define GRPC_MDSTR_HTTP (grpc_static_slice_table[37]) +/* "https" */ +#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[38]) +/* "grpc" */ +#define GRPC_MDSTR_GRPC (grpc_static_slice_table[39]) +/* "GET" */ +#define GRPC_MDSTR_GET (grpc_static_slice_table[40]) +/* "PUT" */ +#define GRPC_MDSTR_PUT (grpc_static_slice_table[41]) +/* "/" */ +#define GRPC_MDSTR_SLASH (grpc_static_slice_table[42]) +/* "/index.html" */ +#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[43]) /* "204" */ -#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[4]) +#define GRPC_MDSTR_204 (grpc_static_slice_table[44]) /* "206" */ -#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[5]) +#define GRPC_MDSTR_206 (grpc_static_slice_table[45]) /* "304" */ -#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[6]) +#define GRPC_MDSTR_304 (grpc_static_slice_table[46]) /* "400" */ -#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[7]) -/* "404" */ -#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[8]) +#define GRPC_MDSTR_400 (grpc_static_slice_table[47]) /* "500" */ -#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[9]) -/* "accept" */ -#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[10]) +#define GRPC_MDSTR_500 (grpc_static_slice_table[48]) /* "accept-charset" */ -#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[11]) +#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[49]) /* "accept-encoding" */ -#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[12]) +#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[50]) +/* "gzip, deflate" */ +#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[51]) /* "accept-language" */ -#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[13]) +#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[52]) /* "accept-ranges" */ -#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[14]) +#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[53]) +/* "accept" */ +#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[54]) /* "access-control-allow-origin" */ -#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[15]) +#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[55]) /* "age" */ -#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[16]) +#define GRPC_MDSTR_AGE (grpc_static_slice_table[56]) /* "allow" */ -#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[19]) +#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[57]) /* "authorization" */ -#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20]) +#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[58]) /* "cache-control" */ -#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21]) +#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[59]) /* "content-disposition" */ -#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22]) +#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[60]) /* "content-encoding" */ -#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23]) +#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[61]) /* "content-language" */ -#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24]) +#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[62]) /* "content-length" */ -#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25]) +#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[63]) /* "content-location" */ -#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26]) +#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[64]) /* "content-range" */ -#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27]) -/* "content-type" */ -#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28]) +#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[65]) /* "cookie" */ -#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29]) +#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[66]) /* "date" */ -#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30]) -/* "deflate" */ -#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31]) -/* "deflate,gzip" */ -#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[32]) -/* "" */ -#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[33]) +#define GRPC_MDSTR_DATE (grpc_static_slice_table[67]) /* "etag" */ -#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[34]) +#define GRPC_MDSTR_ETAG (grpc_static_slice_table[68]) /* "expect" */ -#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[35]) +#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[69]) /* "expires" */ -#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[36]) +#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[70]) /* "from" */ -#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[37]) -/* "GET" */ -#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[38]) -/* "grpc" */ -#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39]) -/* "grpc-accept-encoding" */ -#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40]) -/* "grpc-encoding" */ -#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[41]) -/* "grpc-internal-encoding-request" */ -#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[42]) -/* "grpc-message" */ -#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[43]) -/* "grpc-payload-bin" */ -#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (&grpc_static_mdstr_table[44]) -/* "grpc-stats-bin" */ -#define GRPC_MDSTR_GRPC_STATS_BIN (&grpc_static_mdstr_table[45]) -/* "grpc-status" */ -#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46]) -/* "grpc-timeout" */ -#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47]) -/* "grpc-tracing-bin" */ -#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_mdstr_table[48]) -/* "gzip" */ -#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[49]) -/* "gzip, deflate" */ -#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[50]) -/* "host" */ -#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[51]) -/* "http" */ -#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[52]) -/* "https" */ -#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[53]) -/* "identity" */ -#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[54]) -/* "identity,deflate" */ -#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (&grpc_static_mdstr_table[55]) -/* "identity,deflate,gzip" */ -#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ - (&grpc_static_mdstr_table[56]) -/* "identity,gzip" */ -#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (&grpc_static_mdstr_table[57]) +#define GRPC_MDSTR_FROM (grpc_static_slice_table[71]) /* "if-match" */ -#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[58]) +#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[72]) /* "if-modified-since" */ -#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[59]) +#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[73]) /* "if-none-match" */ -#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[60]) +#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[74]) /* "if-range" */ -#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[61]) +#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[75]) /* "if-unmodified-since" */ -#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[62]) +#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[76]) /* "last-modified" */ -#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[63]) -/* "lb-cost-bin" */ -#define GRPC_MDSTR_LB_COST_BIN (&grpc_static_mdstr_table[64]) -/* "lb-token" */ -#define GRPC_MDSTR_LB_TOKEN (&grpc_static_mdstr_table[65]) +#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[77]) /* "link" */ -#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[66]) +#define GRPC_MDSTR_LINK (grpc_static_slice_table[78]) /* "location" */ -#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[67]) +#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[79]) /* "max-forwards" */ -#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[68]) -/* ":method" */ -#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[69]) -/* ":path" */ -#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[70]) -/* "POST" */ -#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[71]) +#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[80]) /* "proxy-authenticate" */ -#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[72]) +#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[81]) /* "proxy-authorization" */ -#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[73]) -/* "PUT" */ -#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[74]) +#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[82]) /* "range" */ -#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[75]) +#define GRPC_MDSTR_RANGE (grpc_static_slice_table[83]) /* "referer" */ -#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[76]) +#define GRPC_MDSTR_REFERER (grpc_static_slice_table[84]) /* "refresh" */ -#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[77]) +#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[85]) /* "retry-after" */ -#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[78]) -/* ":scheme" */ -#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[79]) +#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[86]) /* "server" */ -#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[80]) +#define GRPC_MDSTR_SERVER (grpc_static_slice_table[87]) /* "set-cookie" */ -#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[81]) -/* "/" */ -#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[82]) -/* "/index.html" */ -#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[83]) -/* ":status" */ -#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[84]) +#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[88]) /* "strict-transport-security" */ -#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[85]) -/* "te" */ -#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[86]) -/* "trailers" */ -#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[87]) +#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[89]) /* "transfer-encoding" */ -#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[88]) -/* "user-agent" */ -#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[89]) +#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[90]) /* "vary" */ -#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[90]) +#define GRPC_MDSTR_VARY (grpc_static_slice_table[91]) /* "via" */ -#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[91]) +#define GRPC_MDSTR_VIA (grpc_static_slice_table[92]) /* "www-authenticate" */ -#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[92]) +#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[93]) +/* "identity,deflate" */ +#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[94]) +/* "identity,gzip" */ +#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[95]) +/* "deflate,gzip" */ +#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[96]) +/* "identity,deflate,gzip" */ +#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ + (grpc_static_slice_table[97]) + +extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable; +extern grpc_slice_refcount + grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT]; +#define GRPC_IS_STATIC_METADATA_STRING(slice) \ + ((slice).refcount != NULL && \ + (slice).refcount->vtable == &grpc_static_metadata_vtable) + +#define GRPC_STATIC_METADATA_INDEX(static_slice) \ + ((int)((static_slice).refcount - grpc_static_metadata_refcounts)) #define GRPC_STATIC_MDELEM_COUNT 81 -extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; +extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; +/* "grpc-status": "0" */ +#define GRPC_MDELEM_GRPC_STATUS_0 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[0], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-status": "1" */ +#define GRPC_MDELEM_GRPC_STATUS_1 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[1], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-status": "2" */ +#define GRPC_MDELEM_GRPC_STATUS_2 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[2], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-encoding": "identity" */ +#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[3], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-encoding": "gzip" */ +#define GRPC_MDELEM_GRPC_ENCODING_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[4], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-encoding": "deflate" */ +#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[5], GRPC_MDELEM_STORAGE_STATIC)) +/* "te": "trailers" */ +#define GRPC_MDELEM_TE_TRAILERS \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[6], GRPC_MDELEM_STORAGE_STATIC)) +/* "content-type": "application/grpc" */ +#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[7], GRPC_MDELEM_STORAGE_STATIC)) +/* ":method": "POST" */ +#define GRPC_MDELEM_METHOD_POST \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[8], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "200" */ +#define GRPC_MDELEM_STATUS_200 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[9], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "404" */ +#define GRPC_MDELEM_STATUS_404 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[10], GRPC_MDELEM_STORAGE_STATIC)) +/* ":scheme": "http" */ +#define GRPC_MDELEM_SCHEME_HTTP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[11], GRPC_MDELEM_STORAGE_STATIC)) +/* ":scheme": "https" */ +#define GRPC_MDELEM_SCHEME_HTTPS \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[12], GRPC_MDELEM_STORAGE_STATIC)) +/* ":scheme": "grpc" */ +#define GRPC_MDELEM_SCHEME_GRPC \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[13], GRPC_MDELEM_STORAGE_STATIC)) +/* ":authority": "" */ +#define GRPC_MDELEM_AUTHORITY_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[14], GRPC_MDELEM_STORAGE_STATIC)) +/* ":method": "GET" */ +#define GRPC_MDELEM_METHOD_GET \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[15], GRPC_MDELEM_STORAGE_STATIC)) +/* ":method": "PUT" */ +#define GRPC_MDELEM_METHOD_PUT \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[16], GRPC_MDELEM_STORAGE_STATIC)) +/* ":path": "/" */ +#define GRPC_MDELEM_PATH_SLASH \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[17], GRPC_MDELEM_STORAGE_STATIC)) +/* ":path": "/index.html" */ +#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[18], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "204" */ +#define GRPC_MDELEM_STATUS_204 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[19], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "206" */ +#define GRPC_MDELEM_STATUS_206 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[20], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "304" */ +#define GRPC_MDELEM_STATUS_304 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[21], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "400" */ +#define GRPC_MDELEM_STATUS_400 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[22], GRPC_MDELEM_STORAGE_STATIC)) +/* ":status": "500" */ +#define GRPC_MDELEM_STATUS_500 \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[23], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-charset": "" */ -#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY (&grpc_static_mdelem_table[0]) -/* "accept": "" */ -#define GRPC_MDELEM_ACCEPT_EMPTY (&grpc_static_mdelem_table[1]) +#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[24], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-encoding": "" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY (&grpc_static_mdelem_table[2]) +#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[25], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-encoding": "gzip, deflate" */ #define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \ - (&grpc_static_mdelem_table[3]) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[26], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-language": "" */ -#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[4]) +#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[27], GRPC_MDELEM_STORAGE_STATIC)) /* "accept-ranges": "" */ -#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY (&grpc_static_mdelem_table[5]) +#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[28], GRPC_MDELEM_STORAGE_STATIC)) +/* "accept": "" */ +#define GRPC_MDELEM_ACCEPT_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[29], GRPC_MDELEM_STORAGE_STATIC)) /* "access-control-allow-origin": "" */ #define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \ - (&grpc_static_mdelem_table[6]) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[30], GRPC_MDELEM_STORAGE_STATIC)) /* "age": "" */ -#define GRPC_MDELEM_AGE_EMPTY (&grpc_static_mdelem_table[7]) +#define GRPC_MDELEM_AGE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[31], GRPC_MDELEM_STORAGE_STATIC)) /* "allow": "" */ -#define GRPC_MDELEM_ALLOW_EMPTY (&grpc_static_mdelem_table[8]) -/* ":authority": "" */ -#define GRPC_MDELEM_AUTHORITY_EMPTY (&grpc_static_mdelem_table[9]) +#define GRPC_MDELEM_ALLOW_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[32], GRPC_MDELEM_STORAGE_STATIC)) /* "authorization": "" */ -#define GRPC_MDELEM_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[10]) +#define GRPC_MDELEM_AUTHORIZATION_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[33], GRPC_MDELEM_STORAGE_STATIC)) /* "cache-control": "" */ -#define GRPC_MDELEM_CACHE_CONTROL_EMPTY (&grpc_static_mdelem_table[11]) +#define GRPC_MDELEM_CACHE_CONTROL_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[34], GRPC_MDELEM_STORAGE_STATIC)) /* "content-disposition": "" */ -#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY (&grpc_static_mdelem_table[12]) +#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC)) /* "content-encoding": "" */ -#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY (&grpc_static_mdelem_table[13]) +#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC)) /* "content-language": "" */ -#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[14]) +#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC)) /* "content-length": "" */ -#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY (&grpc_static_mdelem_table[15]) +#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC)) /* "content-location": "" */ -#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY (&grpc_static_mdelem_table[16]) +#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC)) /* "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]) +#define GRPC_MDELEM_CONTENT_RANGE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC)) /* "content-type": "" */ -#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (&grpc_static_mdelem_table[19]) +#define GRPC_MDELEM_CONTENT_TYPE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC)) /* "cookie": "" */ -#define GRPC_MDELEM_COOKIE_EMPTY (&grpc_static_mdelem_table[20]) +#define GRPC_MDELEM_COOKIE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC)) /* "date": "" */ -#define GRPC_MDELEM_DATE_EMPTY (&grpc_static_mdelem_table[21]) +#define GRPC_MDELEM_DATE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC)) /* "etag": "" */ -#define GRPC_MDELEM_ETAG_EMPTY (&grpc_static_mdelem_table[22]) +#define GRPC_MDELEM_ETAG_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC)) /* "expect": "" */ -#define GRPC_MDELEM_EXPECT_EMPTY (&grpc_static_mdelem_table[23]) +#define GRPC_MDELEM_EXPECT_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC)) /* "expires": "" */ -#define GRPC_MDELEM_EXPIRES_EMPTY (&grpc_static_mdelem_table[24]) +#define GRPC_MDELEM_EXPIRES_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC)) /* "from": "" */ -#define GRPC_MDELEM_FROM_EMPTY (&grpc_static_mdelem_table[25]) -/* "grpc-accept-encoding": "deflate" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE (&grpc_static_mdelem_table[26]) -/* "grpc-accept-encoding": "deflate,gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \ - (&grpc_static_mdelem_table[27]) -/* "grpc-accept-encoding": "gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP (&grpc_static_mdelem_table[28]) -/* "grpc-accept-encoding": "identity" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \ - (&grpc_static_mdelem_table[29]) -/* "grpc-accept-encoding": "identity,deflate" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \ - (&grpc_static_mdelem_table[30]) -/* "grpc-accept-encoding": "identity,deflate,gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ - (&grpc_static_mdelem_table[31]) -/* "grpc-accept-encoding": "identity,gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ - (&grpc_static_mdelem_table[32]) -/* "grpc-encoding": "deflate" */ -#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE (&grpc_static_mdelem_table[33]) -/* "grpc-encoding": "gzip" */ -#define GRPC_MDELEM_GRPC_ENCODING_GZIP (&grpc_static_mdelem_table[34]) -/* "grpc-encoding": "identity" */ -#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY (&grpc_static_mdelem_table[35]) -/* "grpc-status": "0" */ -#define GRPC_MDELEM_GRPC_STATUS_0 (&grpc_static_mdelem_table[36]) -/* "grpc-status": "1" */ -#define GRPC_MDELEM_GRPC_STATUS_1 (&grpc_static_mdelem_table[37]) -/* "grpc-status": "2" */ -#define GRPC_MDELEM_GRPC_STATUS_2 (&grpc_static_mdelem_table[38]) +#define GRPC_MDELEM_FROM_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC)) /* "host": "" */ -#define GRPC_MDELEM_HOST_EMPTY (&grpc_static_mdelem_table[39]) +#define GRPC_MDELEM_HOST_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC)) /* "if-match": "" */ -#define GRPC_MDELEM_IF_MATCH_EMPTY (&grpc_static_mdelem_table[40]) +#define GRPC_MDELEM_IF_MATCH_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC)) /* "if-modified-since": "" */ -#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[41]) +#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC)) /* "if-none-match": "" */ -#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (&grpc_static_mdelem_table[42]) +#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC)) /* "if-range": "" */ -#define GRPC_MDELEM_IF_RANGE_EMPTY (&grpc_static_mdelem_table[43]) +#define GRPC_MDELEM_IF_RANGE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC)) /* "if-unmodified-since": "" */ -#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[44]) +#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC)) /* "last-modified": "" */ -#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45]) -/* "lb-cost-bin": "" */ -#define GRPC_MDELEM_LB_COST_BIN_EMPTY (&grpc_static_mdelem_table[46]) +#define GRPC_MDELEM_LAST_MODIFIED_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC)) /* "lb-token": "" */ -#define GRPC_MDELEM_LB_TOKEN_EMPTY (&grpc_static_mdelem_table[47]) +#define GRPC_MDELEM_LB_TOKEN_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC)) +/* "lb-cost-bin": "" */ +#define GRPC_MDELEM_LB_COST_BIN_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC)) /* "link": "" */ -#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[48]) +#define GRPC_MDELEM_LINK_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC)) /* "location": "" */ -#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[49]) +#define GRPC_MDELEM_LOCATION_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC)) /* "max-forwards": "" */ -#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[50]) -/* ":method": "GET" */ -#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[51]) -/* ":method": "POST" */ -#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[52]) -/* ":method": "PUT" */ -#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[53]) -/* ":path": "/" */ -#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[54]) -/* ":path": "/index.html" */ -#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[55]) +#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC)) /* "proxy-authenticate": "" */ -#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[56]) +#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC)) /* "proxy-authorization": "" */ -#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[57]) +#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC)) /* "range": "" */ -#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[58]) +#define GRPC_MDELEM_RANGE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC)) /* "referer": "" */ -#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[59]) +#define GRPC_MDELEM_REFERER_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC)) /* "refresh": "" */ -#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[60]) +#define GRPC_MDELEM_REFRESH_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC)) /* "retry-after": "" */ -#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[61]) -/* ":scheme": "grpc" */ -#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[62]) -/* ":scheme": "http" */ -#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[63]) -/* ":scheme": "https" */ -#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[64]) +#define GRPC_MDELEM_RETRY_AFTER_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC)) /* "server": "" */ -#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[65]) +#define GRPC_MDELEM_SERVER_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC)) /* "set-cookie": "" */ -#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[66]) -/* ":status": "200" */ -#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[67]) -/* ":status": "204" */ -#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[68]) -/* ":status": "206" */ -#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[69]) -/* ":status": "304" */ -#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[70]) -/* ":status": "400" */ -#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[71]) -/* ":status": "404" */ -#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[72]) -/* ":status": "500" */ -#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[73]) +#define GRPC_MDELEM_SET_COOKIE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC)) /* "strict-transport-security": "" */ #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ - (&grpc_static_mdelem_table[74]) -/* "te": "trailers" */ -#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[75]) + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC)) /* "transfer-encoding": "" */ -#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[76]) +#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC)) /* "user-agent": "" */ -#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[77]) +#define GRPC_MDELEM_USER_AGENT_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC)) /* "vary": "" */ -#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[78]) +#define GRPC_MDELEM_VARY_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC)) /* "via": "" */ -#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[79]) +#define GRPC_MDELEM_VIA_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC)) /* "www-authenticate": "" */ -#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[80]) +#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "identity" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "deflate" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "identity,deflate" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "gzip" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "identity,gzip" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "deflate,gzip" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC)) +/* "grpc-accept-encoding": "identity,deflate,gzip" */ +#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ + (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[80], GRPC_MDELEM_STORAGE_STATIC)) + +grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b); +typedef enum { + GRPC_BATCH_PATH, + GRPC_BATCH_METHOD, + GRPC_BATCH_STATUS, + GRPC_BATCH_AUTHORITY, + GRPC_BATCH_SCHEME, + GRPC_BATCH_TE, + GRPC_BATCH_GRPC_MESSAGE, + GRPC_BATCH_GRPC_STATUS, + GRPC_BATCH_GRPC_PAYLOAD_BIN, + GRPC_BATCH_GRPC_ENCODING, + GRPC_BATCH_GRPC_ACCEPT_ENCODING, + GRPC_BATCH_CONTENT_TYPE, + GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST, + GRPC_BATCH_USER_AGENT, + GRPC_BATCH_HOST, + GRPC_BATCH_LB_TOKEN, + GRPC_BATCH_LB_COST_BIN, + GRPC_BATCH_CALLOUTS_COUNT +} grpc_metadata_batch_callouts_index; + +typedef union { + struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT]; + struct { + struct grpc_linked_mdelem *path; + struct grpc_linked_mdelem *method; + struct grpc_linked_mdelem *status; + struct grpc_linked_mdelem *authority; + struct grpc_linked_mdelem *scheme; + struct grpc_linked_mdelem *te; + struct grpc_linked_mdelem *grpc_message; + struct grpc_linked_mdelem *grpc_status; + struct grpc_linked_mdelem *grpc_payload_bin; + struct grpc_linked_mdelem *grpc_encoding; + struct grpc_linked_mdelem *grpc_accept_encoding; + struct grpc_linked_mdelem *content_type; + struct grpc_linked_mdelem *grpc_internal_encoding_request; + struct grpc_linked_mdelem *user_agent; + struct grpc_linked_mdelem *host; + struct grpc_linked_mdelem *lb_token; + struct grpc_linked_mdelem *lb_cost_bin; + } named; +} grpc_metadata_batch_callouts; + +#define GRPC_BATCH_INDEX_OF(slice) \ + (GRPC_IS_STATIC_METADATA_STRING((slice)) \ + ? (grpc_metadata_batch_callouts_index)GPR_CLAMP( \ + GRPC_STATIC_METADATA_INDEX((slice)), 0, \ + GRPC_BATCH_CALLOUTS_COUNT) \ + : GRPC_BATCH_CALLOUTS_COUNT) -extern const uint8_t - grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2]; -extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT]; extern const uint8_t grpc_static_accept_encoding_metadata[8]; -#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \ - (&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]]) +#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \ + (GRPC_MAKE_MDELEM( \ + &grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], \ + GRPC_MDELEM_STORAGE_STATIC)) #endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */ diff --git a/src/core/lib/transport/status_conversion.c b/src/core/lib/transport/status_conversion.c new file mode 100644 index 0000000000..af0ac89db7 --- /dev/null +++ b/src/core/lib/transport/status_conversion.c @@ -0,0 +1,113 @@ +/* + * + * 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. + * + */ + +#include "src/core/lib/transport/status_conversion.h" + +int grpc_status_to_http2_error(grpc_status_code status) { + switch (status) { + case GRPC_STATUS_OK: + return GRPC_HTTP2_NO_ERROR; + case GRPC_STATUS_CANCELLED: + return GRPC_HTTP2_CANCEL; + case GRPC_STATUS_DEADLINE_EXCEEDED: + return GRPC_HTTP2_CANCEL; + case GRPC_STATUS_RESOURCE_EXHAUSTED: + return GRPC_HTTP2_ENHANCE_YOUR_CALM; + case GRPC_STATUS_PERMISSION_DENIED: + return GRPC_HTTP2_INADEQUATE_SECURITY; + case GRPC_STATUS_UNAVAILABLE: + return GRPC_HTTP2_REFUSED_STREAM; + default: + return GRPC_HTTP2_INTERNAL_ERROR; + } +} + +grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error, + gpr_timespec deadline) { + switch (error) { + case GRPC_HTTP2_NO_ERROR: + /* should never be received */ + return GRPC_STATUS_INTERNAL; + case GRPC_HTTP2_CANCEL: + /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been + * exceeded */ + return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0 + ? GRPC_STATUS_DEADLINE_EXCEEDED + : GRPC_STATUS_CANCELLED; + case GRPC_HTTP2_ENHANCE_YOUR_CALM: + return GRPC_STATUS_RESOURCE_EXHAUSTED; + case GRPC_HTTP2_INADEQUATE_SECURITY: + return GRPC_STATUS_PERMISSION_DENIED; + case GRPC_HTTP2_REFUSED_STREAM: + return GRPC_STATUS_UNAVAILABLE; + default: + return GRPC_STATUS_INTERNAL; + } +} + +grpc_status_code grpc_http2_status_to_grpc_status(int status) { + switch (status) { + /* these HTTP2 status codes are called out explicitly in status.proto */ + case 200: + return GRPC_STATUS_OK; + case 400: + return GRPC_STATUS_INVALID_ARGUMENT; + case 401: + return GRPC_STATUS_UNAUTHENTICATED; + case 403: + return GRPC_STATUS_PERMISSION_DENIED; + case 404: + return GRPC_STATUS_NOT_FOUND; + case 409: + return GRPC_STATUS_ABORTED; + case 412: + return GRPC_STATUS_FAILED_PRECONDITION; + case 429: + return GRPC_STATUS_RESOURCE_EXHAUSTED; + case 499: + return GRPC_STATUS_CANCELLED; + case 500: + return GRPC_STATUS_UNKNOWN; + case 501: + return GRPC_STATUS_UNIMPLEMENTED; + case 503: + return GRPC_STATUS_UNAVAILABLE; + case 504: + return GRPC_STATUS_DEADLINE_EXCEEDED; + /* everything else is unknown */ + default: + return GRPC_STATUS_UNKNOWN; + } +} + +int grpc_status_to_http2_status(grpc_status_code status) { return 200; } diff --git a/src/core/lib/transport/status_conversion.h b/src/core/lib/transport/status_conversion.h new file mode 100644 index 0000000000..e6a23a606b --- /dev/null +++ b/src/core/lib/transport/status_conversion.h @@ -0,0 +1,49 @@ +/* + * + * 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_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H +#define GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H + +#include <grpc/grpc.h> +#include "src/core/lib/transport/http2_errors.h" + +/* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */ +grpc_http2_error_code grpc_status_to_http2_error(grpc_status_code status); +grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error, + gpr_timespec deadline); + +/* Conversion of HTTP status codes (:status) to grpc status codes */ +grpc_status_code grpc_http2_status_to_grpc_status(int status); +int grpc_status_to_http2_status(grpc_status_code status); + +#endif /* GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H */ diff --git a/src/core/lib/transport/timeout_encoding.c b/src/core/lib/transport/timeout_encoding.c index b58ebbd0a8..0d4d7e5a7e 100644 --- a/src/core/lib/transport/timeout_encoding.c +++ b/src/core/lib/transport/timeout_encoding.c @@ -131,20 +131,21 @@ void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer) { } } -static int is_all_whitespace(const char *p) { - while (*p == ' ') p++; - return *p == 0; +static int is_all_whitespace(const char *p, const char *end) { + while (p != end && *p == ' ') p++; + return p == end; } -int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout) { +int grpc_http2_decode_timeout(grpc_slice text, gpr_timespec *timeout) { int32_t x = 0; - const uint8_t *p = (const uint8_t *)buffer; + const uint8_t *p = GRPC_SLICE_START_PTR(text); + const uint8_t *end = GRPC_SLICE_END_PTR(text); int have_digit = 0; /* skip whitespace */ - for (; *p == ' '; p++) + for (; p != end && *p == ' '; p++) ; /* decode numeric part */ - for (; *p >= '0' && *p <= '9'; p++) { + for (; p != end && *p >= '0' && *p <= '9'; p++) { int32_t digit = (int32_t)(*p - (uint8_t)'0'); have_digit = 1; /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */ @@ -158,8 +159,9 @@ int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout) { } if (!have_digit) return 0; /* skip whitespace */ - for (; *p == ' '; p++) + for (; p != end && *p == ' '; p++) ; + if (p == end) return 0; /* decode unit specifier */ switch (*p) { case 'n': @@ -184,5 +186,5 @@ int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout) { return 0; } p++; - return is_all_whitespace((const char *)p); + return is_all_whitespace((const char *)p, (const char *)end); } diff --git a/src/core/lib/transport/timeout_encoding.h b/src/core/lib/transport/timeout_encoding.h index 92f02f6ecd..4c8025d800 100644 --- a/src/core/lib/transport/timeout_encoding.h +++ b/src/core/lib/transport/timeout_encoding.h @@ -34,7 +34,9 @@ #ifndef GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H #define GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H +#include <grpc/slice.h> #include <grpc/support/time.h> + #include "src/core/lib/support/string.h" #define GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1) @@ -42,6 +44,6 @@ /* Encode/decode timeouts to the GRPC over HTTP/2 format; encoding may round up arbitrarily */ void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer); -int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout); +int grpc_http2_decode_timeout(grpc_slice text, gpr_timespec *timeout); #endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */ diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 055edbb39f..004e748f25 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -40,6 +40,7 @@ #include <grpc/support/log.h> #include <grpc/support/sync.h> +#include "src/core/lib/iomgr/executor.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" @@ -69,6 +70,16 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount) { #endif if (gpr_unref(&refcount->refs)) { + if (exec_ctx->flags & GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP) { + /* Ick. + The thread we're running on MAY be owned (indirectly) by a call-stack. + If that's the case, destroying the call-stack MAY try to destroy the + thread, which is a tangled mess that we just don't want to ever have to + cope with. + Throw this over to the executor (on a core-owned thread) and process it + there. */ + refcount->destroy.scheduler = grpc_executor_scheduler; + } grpc_closure_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE); } } @@ -173,93 +184,7 @@ void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx, grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready, GRPC_ERROR_REF(error)); grpc_closure_sched(exec_ctx, op->on_complete, error); -} - -typedef struct { - grpc_error *error; - grpc_closure *then_call; - grpc_closure closure; -} close_message_data; - -static void free_message(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - close_message_data *cmd = p; - GRPC_ERROR_UNREF(cmd->error); - if (cmd->then_call != NULL) { - cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, error); - } - gpr_free(cmd); -} - -static void add_error(grpc_transport_stream_op *op, grpc_error **which, - grpc_error *error) { - close_message_data *cmd; - cmd = gpr_malloc(sizeof(*cmd)); - cmd->error = error; - cmd->then_call = op->on_complete; - grpc_closure_init(&cmd->closure, free_message, cmd, - grpc_schedule_on_exec_ctx); - op->on_complete = &cmd->closure; - *which = error; -} - -void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op, - grpc_status_code status) { - GPR_ASSERT(status != GRPC_STATUS_OK); - if (op->cancel_error == GRPC_ERROR_NONE) { - op->cancel_error = grpc_error_set_int(GRPC_ERROR_CANCELLED, - GRPC_ERROR_INT_GRPC_STATUS, status); - op->close_error = GRPC_ERROR_NONE; - } -} - -void grpc_transport_stream_op_add_cancellation_with_message( - grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op, - grpc_status_code status, grpc_slice *optional_message) { - GPR_ASSERT(status != GRPC_STATUS_OK); - if (op->cancel_error != GRPC_ERROR_NONE) { - if (optional_message) { - grpc_slice_unref_internal(exec_ctx, *optional_message); - } - return; - } - grpc_error *error; - if (optional_message != NULL) { - char *msg = grpc_dump_slice(*optional_message, GPR_DUMP_ASCII); - error = grpc_error_set_str(GRPC_ERROR_CREATE(msg), - GRPC_ERROR_STR_GRPC_MESSAGE, msg); - gpr_free(msg); - grpc_slice_unref_internal(exec_ctx, *optional_message); - } else { - error = GRPC_ERROR_CREATE("Call cancelled"); - } - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); - add_error(op, &op->cancel_error, error); -} - -void grpc_transport_stream_op_add_close(grpc_exec_ctx *exec_ctx, - grpc_transport_stream_op *op, - grpc_status_code status, - grpc_slice *optional_message) { - GPR_ASSERT(status != GRPC_STATUS_OK); - if (op->cancel_error != GRPC_ERROR_NONE || - op->close_error != GRPC_ERROR_NONE) { - if (optional_message) { - grpc_slice_unref_internal(exec_ctx, *optional_message); - } - return; - } - grpc_error *error; - if (optional_message != NULL) { - char *msg = grpc_dump_slice(*optional_message, GPR_DUMP_ASCII); - error = grpc_error_set_str(GRPC_ERROR_CREATE(msg), - GRPC_ERROR_STR_GRPC_MESSAGE, msg); - gpr_free(msg); - grpc_slice_unref_internal(exec_ctx, *optional_message); - } else { - error = GRPC_ERROR_CREATE("Call force closed"); - } - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); - add_error(op, &op->close_error, error); + GRPC_ERROR_UNREF(op->cancel_error); } typedef struct { diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index d1281830aa..9a0abe1ca4 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -150,13 +150,18 @@ typedef struct grpc_transport_stream_op { /** Collect any stats into provided buffer, zero internal stat counters */ grpc_transport_stream_stats *collect_stats; - /** If != GRPC_ERROR_NONE, cancel this stream */ + /** If != GRPC_ERROR_NONE, forcefully close this stream. + The HTTP2 semantics should be: + - server side: if cancel_error has GRPC_ERROR_INT_GRPC_STATUS, and + trailing metadata has not been sent, send trailing metadata with status + and message from cancel_error (use grpc_error_get_status) followed by + a RST_STREAM with error=GRPC_CHTTP2_NO_ERROR to force a full close + - at all other times: use grpc_error_get_status to get a status code, and + convert to a HTTP2 error code using + grpc_chttp2_grpc_status_to_http2_error. Send a RST_STREAM with this + error. */ grpc_error *cancel_error; - /** If != GRPC_ERROR_NONE, send grpc-status, grpc-message, and close this - stream for both reading and writing */ - grpc_error *close_error; - /* Indexes correspond to grpc_context_index enum values */ grpc_call_context_element *context; @@ -176,13 +181,8 @@ typedef struct grpc_transport_op { grpc_connectivity_state *connectivity_state; /** should the transport be disconnected */ grpc_error *disconnect_with_error; - /** should we send a goaway? - after a goaway is sent, once there are no more active calls on - the transport, the transport should disconnect */ - bool send_goaway; /** what should the goaway contain? */ - grpc_status_code goaway_status; - grpc_slice *goaway_message; + grpc_error *goaway_error; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its @@ -245,18 +245,6 @@ void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op, grpc_error *error); -void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op, - grpc_status_code status); - -void grpc_transport_stream_op_add_cancellation_with_message( - grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op, - grpc_status_code status, grpc_slice *optional_message); - -void grpc_transport_stream_op_add_close(grpc_exec_ctx *exec_ctx, - grpc_transport_stream_op *op, - grpc_status_code status, - grpc_slice *optional_message); - char *grpc_transport_stream_op_string(grpc_transport_stream_op *op); char *grpc_transport_op_string(grpc_transport_op *op); diff --git a/src/core/lib/transport/transport_op_string.c b/src/core/lib/transport/transport_op_string.c index 58d6ad508e..28360e3784 100644 --- a/src/core/lib/transport/transport_op_string.c +++ b/src/core/lib/transport/transport_op_string.c @@ -47,14 +47,14 @@ /* These routines are here to facilitate debugging - they produce string representations of various transport data structures */ -static void put_metadata(gpr_strvec *b, grpc_mdelem *md) { +static void put_metadata(gpr_strvec *b, grpc_mdelem md) { gpr_strvec_add(b, gpr_strdup("key=")); gpr_strvec_add( - b, grpc_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII)); + b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII)); gpr_strvec_add(b, gpr_strdup(" value=")); gpr_strvec_add( - b, grpc_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII)); + b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII)); } static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) { @@ -121,15 +121,7 @@ char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) { gpr_strvec_add(&b, gpr_strdup(" ")); const char *msg = grpc_error_string(op->cancel_error); gpr_asprintf(&tmp, "CANCEL:%s", msg); - grpc_error_free_string(msg); - gpr_strvec_add(&b, tmp); - } - if (op->close_error != GRPC_ERROR_NONE) { - gpr_strvec_add(&b, gpr_strdup(" ")); - const char *msg = grpc_error_string(op->close_error); - gpr_asprintf(&tmp, "CLOSE:%s", msg); - grpc_error_free_string(msg); gpr_strvec_add(&b, tmp); } @@ -168,18 +160,14 @@ char *grpc_transport_op_string(grpc_transport_op *op) { const char *err = grpc_error_string(op->disconnect_with_error); gpr_asprintf(&tmp, "DISCONNECT:%s", err); gpr_strvec_add(&b, tmp); - grpc_error_free_string(err); } - if (op->send_goaway) { + if (op->goaway_error) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; - char *msg = op->goaway_message == NULL - ? "null" - : grpc_dump_slice(*op->goaway_message, - GPR_DUMP_ASCII | GPR_DUMP_HEX); - gpr_asprintf(&tmp, "SEND_GOAWAY:status=%d:msg=%s", op->goaway_status, msg); - if (op->goaway_message != NULL) gpr_free(msg); + const char *msg = grpc_error_string(op->goaway_error); + gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg); + gpr_strvec_add(&b, tmp); } |