diff options
author | Hope Casey-Allen <hcaseyal@google.com> | 2018-09-06 11:56:12 -0700 |
---|---|---|
committer | Hope Casey-Allen <hcaseyal@google.com> | 2018-09-06 11:59:37 -0700 |
commit | 8a8ed0e7115a4c21fbdd40968d688faaba379f2c (patch) | |
tree | aa6364d65022640331b9b01c2e43450d72364814 /src/core/lib/transport | |
parent | 6e7e29aaae698d03dab71715c1913a5f813337ef (diff) |
WIP. Handling error conditions such as duplicate metadata, metadata size limit, and default count. Clang tidy.
Diffstat (limited to 'src/core/lib/transport')
-rw-r--r-- | src/core/lib/transport/metadata.cc | 65 | ||||
-rw-r--r-- | src/core/lib/transport/metadata.h | 9 | ||||
-rw-r--r-- | src/core/lib/transport/metadata_batch.cc | 188 | ||||
-rw-r--r-- | src/core/lib/transport/metadata_batch.h | 25 |
4 files changed, 186 insertions, 101 deletions
diff --git a/src/core/lib/transport/metadata.cc b/src/core/lib/transport/metadata.cc index 793a1fcd53..d10194a2fe 100644 --- a/src/core/lib/transport/metadata.cc +++ b/src/core/lib/transport/metadata.cc @@ -69,71 +69,6 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_metadata(false, "metadata"); #define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity)) #define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1)) -static_hpack_table_metadata_info static_hpack_table_metadata[] = { - {0, 0, 0}, // NOT USED - {GRPC_MDELEM_AUTHORITY_EMPTY_INDEX, 10 + 32, 3}, - {GRPC_MDELEM_METHOD_GET_INDEX, 10 + 32, 1}, - {GRPC_MDELEM_METHOD_POST_INDEX, 11 + 32, 1}, - {GRPC_MDELEM_PATH_SLASH_INDEX, 6 + 32, 0}, - {GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML_INDEX, 16 + 32, 0}, - {GRPC_MDELEM_SCHEME_HTTP_INDEX, 11 + 32, 4}, - {GRPC_MDELEM_SCHEME_HTTPS_INDEX, 12 + 32, 4}, - {GRPC_MDELEM_STATUS_200_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_STATUS_204_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_STATUS_206_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_STATUS_304_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_STATUS_400_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_STATUS_404_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_STATUS_500_INDEX, 10 + 32, 2}, - {GRPC_MDELEM_ACCEPT_CHARSET_EMPTY_INDEX, 14 + 32, 24}, // Not a callout - {GRPC_MDELEM_ACCEPT_ENCODING_GZIP_DEFLATE_INDEX, 28 + 32, 16}, - {GRPC_MDELEM_MDELEM_ACCEPT_LANGUAGE_EMPTY_INDEX, 15 + 32, 24}, // Not a callout - {GRPC_MDELEM_MDELEM_ACCEPT_RANGES_EMPTY_INDEX, 13 + 32, 24}, // Not a callout - {GRPC_MDELEM_ACCEPT_EMPTY_INDEX, 6 + 32, 24}, // Not a callout - {GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY_INDEX, 27 + 32, 24}, // Not a callout - {GRPC_MDELEM_AGE_EMPTY_INDEX, 3 + 32, 24}, // Not a callout - {GRPC_MDELEM_ALLOW_EMPTY_INDEX, 5 + 32, 24}, // Not a callout - {GRPC_MDELEM_AUTHORIZATION_EMPTY_INDEX, 13 + 32, 24}, // Not a callout - {GRPC_MDELEM_CACHE_CONTROL_EMPTY_INDEX, 13 + 32, 24}, // Not a callout - {GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY_INDEX, 19 + 32, 24}, // Not a callout - {GRPC_MDELEM_CONTENT_ENCODING_EMPTY_INDEX, 16 + 32, 15}, - {GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY_INDEX, 16 + 32, 24}, // Not a callout - {GRPC_MDELEM_CONTENT_LENGTH_EMPTY_INDEX, 14 + 32, 24}, // Not a callout - {GRPC_MDELEM_CONTENT_LOCATION_EMPTY_INDEX, 16 + 32, 24}, // Not a callout - {GRPC_MDELEM_CONTENT_RANGE_EMPTY_INDEX, 13 + 32, 24}, // Not a callout - {GRPC_MDELEM_CONTENT_TYPE_EMPTY_INDEX, 12 + 32, 15}, - {GRPC_MDELEM_COOKIE_EMPTY_INDEX, 6 + 32, 24}, // Not a callout - {GRPC_MDELEM_DATE_EMPTY_INDEX, 4 + 32, 24}, // Not a callout - {GRPC_MDELEM_ETAG_EMPTY_INDEX, 4 + 32, 24}, // Not a callout - {GRPC_MDELEM_EXPECT_EMPTY_INDEX, 6 + 32, 24}, // Not a callout - {GRPC_MDELEM_EXPIRES_EMPTY_INDEX, 7 + 32, 24}, // Not a callout - {GRPC_MDELEM_FROM_EMPTY_INDEX, 4 + 32, 24}, // Not a callout - {GRPC_MDELEM_HOST_EMPTY_INDEX, 4 + 32, 20}, - {GRPC_MDELEM_IF_MATCH_EMPTY_INDEX, 8 + 32, 24}, // Not a callout - {GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY_INDEX, 17 + 32, 24}, // Not a callout - {GRPC_MDELEM_IF_NONE_MATCH_EMPTY_INDEX, 13 + 32, 24}, // Not a callout - {GRPC_MDELEM_IF_RANGE_EMPTY_INDEX, 8 + 32, 24}, // Not a callout - {GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY_INDEX, 19 + 32, 24}, // Not a callout - {GRPC_MDELEM_LAST_MODIFIED_EMPTY_INDEX, 13 + 32, 24}, // Not a callout - {GRPC_MDELEM_LINK_EMPTY_INDEX, 4 + 32, 24}, // Not a callout - {GRPC_MDELEM_LOCATION_EMPTY_INDEX, 8 + 32, 24}, // Not a callout - {GRPC_MDELEM_MAX_FORWARDS_EMPTY_INDEX, 12 + 32, 24}, // Not a callout - {GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY_INDEX, 18 + 32, 24}, // Not a callout - {GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY_INDEX, 19 + 32, 24}, // Not a callout - {GRPC_MDELEM_RANGE_EMPTY_INDEX, 5 + 32, 24}, // Not a callout - {GRPC_MDELEM_REFERER_EMPTY_INDEX, 7 + 32, 24}, // Not a callout - {GRPC_MDELEM_REFRESH_EMPTY_INDEX, 7 + 32, 24}, // Not a callout - {GRPC_MDELEM_RETRY_AFTER_EMPTY_INDEX, 11 + 32, 24}, // Not a callout - {GRPC_MDELEM_SERVER_EMPTY_INDEX, 6 + 32, 24}, // Not a callout - {GRPC_MDELEM_SET_COOKIE_EMPTY_INDEX, 10 + 32, 24}, // Not a callout - {GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY_INDEX, 25 + 32, 24}, // Not a callout - {GRPC_MDELEM_TRANSFER_ENCODING_EMPTY_INDEX, 17 + 32, 24}, // Not a callout - {GRPC_MDELEM_USER_AGENT_EMPTY_INDEX, 10 + 32, 19}, - {GRPC_MDELEM_VARY_EMPTY_INDEX, 4 + 32, 24}, // Not a callout - {GRPC_MDELEM_VIA_EMPTY_INDEX, 3 + 32, 24}, // Not a callout - {GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY_INDEX, 16 + 32, 24}, // Not a callout - }; - typedef void (*destroy_user_data_func)(void* user_data); /* Shadow structure for grpc_mdelem_data for interned elements */ diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h index 998d2fc64a..74c6672fd2 100644 --- a/src/core/lib/transport/metadata.h +++ b/src/core/lib/transport/metadata.h @@ -348,15 +348,6 @@ void grpc_mdctx_global_shutdown(); /* {"www-authenticate", ""} */ #define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY_INDEX 61 -/* Static hpack table metadata info */ -typedef struct static_hpack_table_metadata_info { - uint8_t index; // Index in the static hpack table - uint8_t size; // Size of the metadata per RFC-7540 section 6.5.2., including 32 bytes of padding - uint8_t callouts_index; // For duplicate metadata detection. If GRPC_BATCH_CALLOUTS_COUNT, then the metadata is not one of the callouts. -} static_hpack_table_metadata_info; - -extern static_hpack_table_metadata_info static_hpack_table_metadata[]; - /* Forward declarations */ typedef struct grpc_mdelem grpc_mdelem; #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */ diff --git a/src/core/lib/transport/metadata_batch.cc b/src/core/lib/transport/metadata_batch.cc index 6cad7c9028..604ace5751 100644 --- a/src/core/lib/transport/metadata_batch.cc +++ b/src/core/lib/transport/metadata_batch.cc @@ -25,11 +25,103 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/string_util.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_hpack_table_metadata_info static_hpack_table_metadata[] = { + {0, 0, GRPC_BATCH_CALLOUTS_COUNT}, // NOT USED + {GRPC_MDELEM_AUTHORITY_EMPTY_INDEX, 10 + 32, GRPC_BATCH_AUTHORITY}, + {GRPC_MDELEM_METHOD_GET_INDEX, 10 + 32, GRPC_BATCH_METHOD}, + {GRPC_MDELEM_METHOD_POST_INDEX, 11 + 32, GRPC_BATCH_METHOD}, + {GRPC_MDELEM_PATH_SLASH_INDEX, 6 + 32, GRPC_BATCH_PATH}, + {GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML_INDEX, 16 + 32, GRPC_BATCH_PATH}, + {GRPC_MDELEM_SCHEME_HTTP_INDEX, 11 + 32, GRPC_BATCH_SCHEME}, + {GRPC_MDELEM_SCHEME_HTTPS_INDEX, 12 + 32, GRPC_BATCH_SCHEME}, + {GRPC_MDELEM_STATUS_200_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_STATUS_204_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_STATUS_206_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_STATUS_304_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_STATUS_400_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_STATUS_404_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_STATUS_500_INDEX, 10 + 32, GRPC_BATCH_STATUS}, + {GRPC_MDELEM_ACCEPT_CHARSET_EMPTY_INDEX, 14 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_ACCEPT_ENCODING_GZIP_DEFLATE_INDEX, 28 + 32, + GRPC_BATCH_ACCEPT_ENCODING}, + {GRPC_MDELEM_MDELEM_ACCEPT_LANGUAGE_EMPTY_INDEX, 15 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_MDELEM_ACCEPT_RANGES_EMPTY_INDEX, 13 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_ACCEPT_EMPTY_INDEX, 6 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY_INDEX, 27 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_AGE_EMPTY_INDEX, 3 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_ALLOW_EMPTY_INDEX, 5 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_AUTHORIZATION_EMPTY_INDEX, 13 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CACHE_CONTROL_EMPTY_INDEX, 13 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY_INDEX, 19 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CONTENT_ENCODING_EMPTY_INDEX, 16 + 32, + GRPC_BATCH_CONTENT_ENCODING}, + {GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY_INDEX, 16 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CONTENT_LENGTH_EMPTY_INDEX, 14 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CONTENT_LOCATION_EMPTY_INDEX, 16 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CONTENT_RANGE_EMPTY_INDEX, 13 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_CONTENT_TYPE_EMPTY_INDEX, 12 + 32, GRPC_BATCH_CONTENT_TYPE}, + {GRPC_MDELEM_COOKIE_EMPTY_INDEX, 6 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_DATE_EMPTY_INDEX, 4 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_ETAG_EMPTY_INDEX, 4 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_EXPECT_EMPTY_INDEX, 6 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_EXPIRES_EMPTY_INDEX, 7 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_FROM_EMPTY_INDEX, 4 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_HOST_EMPTY_INDEX, 4 + 32, GRPC_BATCH_HOST}, + {GRPC_MDELEM_IF_MATCH_EMPTY_INDEX, 8 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY_INDEX, 17 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_IF_NONE_MATCH_EMPTY_INDEX, 13 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_IF_RANGE_EMPTY_INDEX, 8 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY_INDEX, 19 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_LAST_MODIFIED_EMPTY_INDEX, 13 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_LINK_EMPTY_INDEX, 4 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_LOCATION_EMPTY_INDEX, 8 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_MAX_FORWARDS_EMPTY_INDEX, 12 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY_INDEX, 18 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY_INDEX, 19 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_RANGE_EMPTY_INDEX, 5 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_REFERER_EMPTY_INDEX, 7 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_REFRESH_EMPTY_INDEX, 7 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_RETRY_AFTER_EMPTY_INDEX, 11 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_SERVER_EMPTY_INDEX, 6 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_COOKIE_EMPTY_INDEX, 10 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY_INDEX, 25 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_TRANSFER_ENCODING_EMPTY_INDEX, 17 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_USER_AGENT_EMPTY_INDEX, 10 + 32, GRPC_BATCH_USER_AGENT}, + {GRPC_MDELEM_VARY_EMPTY_INDEX, 4 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_VIA_EMPTY_INDEX, 3 + 32, GRPC_BATCH_CALLOUTS_COUNT}, + {GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY_INDEX, 16 + 32, + GRPC_BATCH_CALLOUTS_COUNT}, +}; + +/* This is a faster check for seeing if a mdelem index is used or not. To verify + that the index value is valid, use 'is_valid_mdelem_index' */ +static bool is_mdelem_index_used(uint8_t index); + +static void set_mdelem_index_unused(uint8_t* index); + +static grpc_metadata_batch_callouts_index get_callouts_index( + grpc_linked_mdelem* storage); + static void assert_valid_list(grpc_mdelem_list* list) { #ifndef NDEBUG grpc_linked_mdelem* l; @@ -56,13 +148,21 @@ static void assert_valid_list(grpc_mdelem_list* list) { static void assert_valid_callouts(grpc_metadata_batch* batch) { #ifndef NDEBUG for (grpc_linked_mdelem* l = batch->list.head; l != nullptr; 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_metadata_batch_callouts_index callout_idx; + if (is_mdelem_index_used(l->md_index)) { + GPR_ASSERT(is_valid_mdelem_index(l->md_index)); + callout_idx = get_callouts_index(l->md_index); + if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) { + GPR_ASSERT(batch->idx.array[callout_idx] == l); + } + } else { + grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md)); + 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(key_interned); } - grpc_slice_unref_internal(key_interned); } #endif } @@ -81,7 +181,9 @@ void grpc_metadata_batch_init(grpc_metadata_batch* batch) { void grpc_metadata_batch_destroy(grpc_metadata_batch* batch) { grpc_linked_mdelem* l; for (l = batch->list.head; l; l = l->next) { - GRPC_MDELEM_UNREF(l->md); + if (!is_mdelem_index_used(l->md_index)) { + GRPC_MDELEM_UNREF(l->md); + } } } @@ -93,14 +195,22 @@ grpc_error* grpc_attach_md_to_error(grpc_error* src, grpc_mdelem md) { return out; } +static grpc_metadata_batch_callouts_index get_callouts_index( + grpc_linked_mdelem* storage) { + if (is_mdelem_index_used(storage->md_index)) { + return static_hpack_table_metadata[storage->md_index].callouts_index; + } else { + return GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); + } +} + 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)); + grpc_metadata_batch_callouts_index idx = get_callouts_index(storage); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return GRPC_ERROR_NONE; } @@ -109,15 +219,27 @@ static grpc_error* maybe_link_callout(grpc_metadata_batch* batch, batch->idx.array[idx] = storage; return GRPC_ERROR_NONE; } - return grpc_attach_md_to_error( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"), - storage->md); + + grpc_error* err; + if (is_mdelem_index_used(storage->md_index)) { + char* message; + gpr_asprintf(&message, + "Unallowed duplicate metadata with static hpack table index " + "%d and callouts index %d", + storage->md_index, idx); + err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(message); + gpr_free(message); + } else { + err = grpc_attach_md_to_error( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"), + storage->md); + } + return err; } 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)); + grpc_metadata_batch_callouts_index idx = get_callouts_index(storage); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { return; } @@ -126,11 +248,18 @@ static void maybe_unlink_callout(grpc_metadata_batch* batch, batch->idx.array[idx] = nullptr; } -bool is_valid_mdelem_index(int64_t index) { +bool is_valid_mdelem_index(uint8_t index) { return index >= MIN_STATIC_HPACK_TABLE_IDX && index <= MAX_STATIC_HPACK_TABLE_IDX; } +bool is_mdelem_index_used(uint8_t index) { return index != 0; } + +void set_mdelem_index_unused(uint8_t* index) { + GPR_ASSERT(index != nullptr); + *index = 0; +} + grpc_error* grpc_metadata_batch_add_head(grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_mdelem elem_to_add) { @@ -141,7 +270,7 @@ grpc_error* grpc_metadata_batch_add_head(grpc_metadata_batch* batch, grpc_error* grpc_metadata_batch_add_head_index(grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - int64_t index_to_add) { + uint8_t index_to_add) { GPR_ASSERT(is_valid_mdelem_index(index_to_add)); storage->md_index = index_to_add; return grpc_metadata_batch_link_head(batch, storage); @@ -186,7 +315,7 @@ grpc_error* grpc_metadata_batch_add_tail(grpc_metadata_batch* batch, grpc_error* grpc_metadata_batch_add_tail_index(grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - int64_t index_to_add) { + uint8_t index_to_add) { GPR_ASSERT(is_valid_mdelem_index(index_to_add)); storage->md_index = index_to_add; return grpc_metadata_batch_link_tail(batch, storage); @@ -244,12 +373,15 @@ void grpc_metadata_batch_remove(grpc_metadata_batch* batch, assert_valid_callouts(batch); maybe_unlink_callout(batch, storage); unlink_storage(&batch->list, storage); - GRPC_MDELEM_UNREF(storage->md); + if (!is_mdelem_index_used(storage->md_index)) { + GRPC_MDELEM_UNREF(storage->md); + } assert_valid_callouts(batch); } void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, grpc_slice value) { + set_mdelem_index_unused(&storage->md_index); grpc_mdelem old_mdelem = storage->md; grpc_mdelem new_mdelem = grpc_mdelem_from_slices( grpc_slice_ref_internal(GRPC_MDKEY(old_mdelem)), value); @@ -263,18 +395,26 @@ grpc_error* grpc_metadata_batch_substitute(grpc_metadata_batch* batch, assert_valid_callouts(batch); grpc_error* error = GRPC_ERROR_NONE; grpc_mdelem old_mdelem = storage->md; - if (!grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) { + bool is_index_used = is_mdelem_index_used(storage->md_index); + if (is_index_used || + !grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) { maybe_unlink_callout(batch, storage); storage->md = new_mdelem; + set_mdelem_index_unused(&storage->md_index); error = maybe_link_callout(batch, storage); if (error != GRPC_ERROR_NONE) { unlink_storage(&batch->list, storage); - GRPC_MDELEM_UNREF(storage->md); + if (!is_index_used) { + GRPC_MDELEM_UNREF(storage->md); + } } } else { storage->md = new_mdelem; } - GRPC_MDELEM_UNREF(old_mdelem); + + if (!is_index_used) { + GRPC_MDELEM_UNREF(old_mdelem); + } assert_valid_callouts(batch); return error; } @@ -293,7 +433,11 @@ size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) { size_t size = 0; for (grpc_linked_mdelem* elem = batch->list.head; elem != nullptr; elem = elem->next) { - size += GRPC_MDELEM_LENGTH(elem->md); + if (!is_mdelem_index_used(elem->md_index)) { + size += GRPC_MDELEM_LENGTH(elem->md); + } else { // Mdelem is represented by static hpack table index + size += static_hpack_table_metadata[elem->md_index].size; + } } return size; } diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index f1c199489f..25f9d0c14c 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -32,13 +32,13 @@ /** Each grpc_linked_mdelem refers to a particular metadata element by either: 1) grpc_mdelem md - 2) int64_t md_index + 2) uint8_t md_index md_index is an optional optimization. It can only be used for metadata in the hpack static table and is equivalent to the metadata's index in the table. If a metadata elem is not contained in the hpack static table, then md must be used instead. */ typedef struct grpc_linked_mdelem { - int64_t md_index; // If -1, not used. Else, use this field instead of md. + uint8_t md_index; // If 0, not used. Else, use this field instead of md. grpc_mdelem md; // If md_index is 0, use this field instead of md_index. struct grpc_linked_mdelem* next; struct grpc_linked_mdelem* prev; @@ -115,7 +115,7 @@ grpc_error* grpc_metadata_batch_add_head( be a valid static hpack table index */ grpc_error* grpc_metadata_batch_add_head_index( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - int64_t index_to_add) GRPC_MUST_USE_RESULT; + uint8_t index_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. @@ -132,11 +132,26 @@ grpc_error* grpc_metadata_batch_add_tail( be a valid static hpack table index */ grpc_error* grpc_metadata_batch_add_head_index( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - int64_t index_to_add) GRPC_MUST_USE_RESULT; + uint8_t index_to_add) GRPC_MUST_USE_RESULT; grpc_error* grpc_attach_md_to_error(grpc_error* src, grpc_mdelem md); -bool is_valid_mdelem_index(int64_t index); +/** Returns if the index is a valid static hpack table index, and thus if the + grpc_linked_mdelem stores the index rather than the actual grpc_mdelem **/ +bool is_valid_mdelem_index(uint8_t index); + +/* Static hpack table metadata info */ +typedef struct static_hpack_table_metadata_info { + uint8_t index; // Index in the static hpack table + uint8_t size; // Size of the metadata per RFC-7540 section 6.5.2., including + // 32 bytes of padding + grpc_metadata_batch_callouts_index + callouts_index; // For duplicate metadata detection. If + // GRPC_BATCH_CALLOUTS_COUNT, then the metadata is not + // one of the callouts. +} static_hpack_table_metadata_info; + +extern static_hpack_table_metadata_info static_hpack_table_metadata[]; typedef struct { grpc_error* error; |