Move content-type, colon prefixed metadata to new system (#28204)

* Eliminate most of grpc_message metadata handling

* Eliminate most of host metadata handling

* Remove more callouts without fixing code

* fiiixes

* typo

* Automated change: Fix sanity tests

* try-shrink

* Automated change: Fix sanity tests

* size tweaks

* less tricks

* deunique

* commonize

* commonize

* Automated change: Fix sanity tests

* size tuning, fixes

* Automated change: Fix sanity tests

* fix

* size tuning, fixes

* remove constexpr

* fix

* reuse code

* fix

* tweak code

* more tweaks

* tell no lies

* fixes

* fixes

* Automated change: Fix sanity tests

* fix

* fix

* fix

* fix

* fix?

* fix binder

* fix

* fix

* fixes

* Automated change: Fix sanity tests

* fix

* initial refactoring

* optimize status encoding

* Automated change: Fix sanity tests

* Automated change: Fix sanity tests

* content-type

* Automated change: Fix sanity tests

* clang-format

* fix

* Move colon prefixed metadata

* Automated change: Fix sanity tests

* Automated change: Fix sanity tests

* try to fix windows failure

* try and scale sizes better

* ambiguity fix?

* wip metadatavalueasslice

* Fix status code for resource exhaustion

* Revert "Revert "Move a bunch of slice typed metadata to new system (#28107)" (#28208)"

This reverts commit 7717587063.

* fix test

* Automated change: Fix sanity tests

* Automated change: Fix sanity tests

* slice helper

* x

* noinline

* try and scale sizes better

* Automated change: Fix sanity tests

* fixes

* fix

* fix

* fixes

* fix build

* fix overflow

* progress

* Automated change: Fix sanity tests

* fix

* fix

* fix

* Automated change: Fix sanity tests

* fix

* fix

* fix

* compressor for path/authority

* Automated change: Fix sanity tests

* legalize

* status-enc

* fmt

* fix

* fix

* fix

* fix

* fix/opt

* fix

* fix

* fix

* fix

* Automated change: Fix sanity tests

* remove arg

* review feedback

* fix

* Small improvement in memory usage and performance

* Automated change: Fix sanity tests

* fix crash in alts

* review feedback

* fixes

* fixes

* fixes

* Automated change: Fix sanity tests

* speedup

* fix

* fix

* add comment

* add comment

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/28103/head
Craig Tiller 3 years ago committed by GitHub
parent a9a14a461b
commit 0deb64d1f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/core/ext/filters/client_channel/client_channel.cc
  2. 9
      src/core/ext/filters/client_channel/health/health_check_client.cc
  3. 1
      src/core/ext/filters/client_channel/health/health_check_client.h
  4. 2
      src/core/ext/filters/client_channel/retry_filter.cc
  5. 170
      src/core/ext/filters/http/client/http_client_filter.cc
  6. 31
      src/core/ext/filters/http/client_authority_filter.cc
  7. 184
      src/core/ext/filters/http/server/http_server_filter.cc
  8. 65
      src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
  9. 3
      src/core/ext/filters/load_reporting/server_load_reporting_filter.h
  10. 32
      src/core/ext/transport/binder/transport/binder_transport.cc
  11. 179
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  12. 83
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  13. 21
      src/core/ext/transport/chttp2/transport/hpack_parser.cc
  14. 8
      src/core/ext/transport/chttp2/transport/hpack_parser_table.h
  15. 36
      src/core/ext/transport/chttp2/transport/writing.cc
  16. 75
      src/core/ext/transport/cronet/transport/cronet_transport.cc
  17. 12
      src/core/ext/xds/xds_server_config_fetcher.cc
  18. 28
      src/core/lib/security/authorization/evaluate_args.cc
  19. 39
      src/core/lib/security/transport/client_auth_filter.cc
  20. 5
      src/core/lib/slice/slice.h
  21. 330
      src/core/lib/slice/static_slice.cc
  22. 135
      src/core/lib/slice/static_slice.h
  23. 52
      src/core/lib/surface/call.cc
  24. 6
      src/core/lib/surface/call.h
  25. 61
      src/core/lib/surface/channel.cc
  26. 4
      src/core/lib/surface/channel.h
  27. 30
      src/core/lib/surface/server.cc
  28. 4
      src/core/lib/surface/server.h
  29. 265
      src/core/lib/transport/metadata_batch.h
  30. 62
      src/core/lib/transport/parsed_metadata.h
  31. 617
      src/core/lib/transport/static_metadata.cc
  32. 49
      src/core/lib/transport/static_metadata.h
  33. 2
      src/core/tsi/alts/handshaker/alts_handshaker_client.cc
  34. 3
      src/cpp/ext/filters/census/client_filter.cc
  35. 9
      src/cpp/ext/filters/census/context.h
  36. 2
      src/cpp/ext/filters/census/open_census_call_tracer.h
  37. 15
      src/cpp/ext/filters/census/server_filter.cc
  38. 3
      src/cpp/ext/filters/census/server_filter.h
  39. 14
      test/core/end2end/fuzzers/hpack.dictionary
  40. 7
      test/core/end2end/tests/filter_status_code.cc
  41. 9
      test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc
  42. 9
      test/core/end2end/tests/retry_server_pushback_delay.cc
  43. 57
      test/core/transport/binder/binder_transport_test.cc
  44. 33
      test/core/transport/chttp2/hpack_parser_test.cc
  45. 12
      test/core/transport/parsed_metadata_test.cc
  46. 6
      test/core/util/evaluate_args_test_util.h
  47. 281
      test/cpp/microbenchmarks/bm_chttp2_hpack.cc
  48. 34
      test/cpp/microbenchmarks/bm_chttp2_transport.cc
  49. 4
      test/cpp/microbenchmarks/representative_server_initial_metadata.headers
  50. 3
      test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
  51. 9
      tools/codegen/core/gen_static_metadata.py

@ -2433,11 +2433,8 @@ class ClientChannel::LoadBalancedCall::Metadata
class Encoder { class Encoder {
public: public:
void Encode(grpc_mdelem md) { void Encode(grpc_mdelem md) {
auto key = StringViewFromSlice(GRPC_MDKEY(md)); out_.emplace_back(std::string(StringViewFromSlice(GRPC_MDKEY(md))),
if (key != ":path") { std::string(StringViewFromSlice(GRPC_MDVALUE(md))));
out_.emplace_back(std::string(key),
std::string(StringViewFromSlice(GRPC_MDVALUE(md))));
}
} }
template <class Which> template <class Which>
@ -2448,6 +2445,7 @@ class ClientChannel::LoadBalancedCall::Metadata
} }
void Encode(GrpcTimeoutMetadata, grpc_millis) {} void Encode(GrpcTimeoutMetadata, grpc_millis) {}
void Encode(HttpPathMetadata, const Slice&) {}
std::vector<std::pair<std::string, std::string>> Take() { std::vector<std::pair<std::string, std::string>> Take() {
return std::move(out_); return std::move(out_);

@ -326,12 +326,9 @@ void HealthCheckClient::CallState::StartCall() {
batch_.on_complete = GRPC_CLOSURE_INIT(&on_complete_, OnComplete, this, batch_.on_complete = GRPC_CLOSURE_INIT(&on_complete_, OnComplete, this,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
// Add send_initial_metadata op. // Add send_initial_metadata op.
error = grpc_metadata_batch_add_head( send_initial_metadata_.Set(
&send_initial_metadata_, &path_metadata_storage_, HttpPathMetadata(),
grpc_mdelem_from_slices( Slice(GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH));
GRPC_MDSTR_PATH,
GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH),
GRPC_BATCH_PATH);
GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(error == GRPC_ERROR_NONE);
payload_.send_initial_metadata.send_initial_metadata = payload_.send_initial_metadata.send_initial_metadata =
&send_initial_metadata_; &send_initial_metadata_;

@ -111,7 +111,6 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
// send_initial_metadata // send_initial_metadata
grpc_metadata_batch send_initial_metadata_; grpc_metadata_batch send_initial_metadata_;
grpc_linked_mdelem path_metadata_storage_;
// send_message // send_message
ManualConstructor<SliceBufferByteStream> send_message_; ManualConstructor<SliceBufferByteStream> send_message_;

@ -1544,7 +1544,7 @@ void GetCallStatus(grpc_millis deadline, grpc_metadata_batch* md_batch,
*is_lb_drop = true; *is_lb_drop = true;
} }
} else { } else {
*status = md_batch->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN); *status = *md_batch->get(GrpcStatusMetadata());
*server_pushback_ms = md_batch->get(GrpcRetryPushbackMsMetadata()); *server_pushback_ms = md_batch->get(GrpcRetryPushbackMsMetadata());
} }
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);

@ -75,10 +75,6 @@ struct call_data {
~call_data() { GRPC_ERROR_UNREF(recv_initial_metadata_error); } ~call_data() { GRPC_ERROR_UNREF(recv_initial_metadata_error); }
grpc_core::CallCombiner* call_combiner; grpc_core::CallCombiner* call_combiner;
// State for handling send_initial_metadata ops.
grpc_linked_mdelem method;
grpc_linked_mdelem scheme;
grpc_linked_mdelem content_type;
// State for handling recv_initial_metadata ops. // State for handling recv_initial_metadata ops.
grpc_metadata_batch* recv_initial_metadata; grpc_metadata_batch* recv_initial_metadata;
grpc_error_handle recv_initial_metadata_error = GRPC_ERROR_NONE; grpc_error_handle recv_initial_metadata_error = GRPC_ERROR_NONE;
@ -102,7 +98,7 @@ struct call_data {
}; };
struct channel_data { struct channel_data {
grpc_mdelem static_scheme; grpc_core::HttpSchemeMetadata::ValueType static_scheme;
grpc_core::Slice user_agent; grpc_core::Slice user_agent;
size_t max_payload_size_for_get; size_t max_payload_size_for_get;
}; };
@ -110,32 +106,27 @@ struct channel_data {
static grpc_error_handle client_filter_incoming_metadata( static grpc_error_handle client_filter_incoming_metadata(
grpc_metadata_batch* b) { grpc_metadata_batch* b) {
if (b->legacy_index()->named.status != nullptr) { if (auto* status = b->get_pointer(grpc_core::HttpStatusMetadata())) {
/* If both gRPC status and HTTP status are provided in the response, we /* If both gRPC status and HTTP status are provided in the response, we
* should prefer the gRPC status code, as mentioned in * should prefer the gRPC status code, as mentioned in
* https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. * https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md.
*/ */
const grpc_status_code* grpc_status = const grpc_status_code* grpc_status =
b->get_pointer(grpc_core::GrpcStatusMetadata()); b->get_pointer(grpc_core::GrpcStatusMetadata());
if (grpc_status != nullptr || if (grpc_status != nullptr || *status == 200) {
grpc_mdelem_static_value_eq(b->legacy_index()->named.status->md, b->Remove(grpc_core::HttpStatusMetadata());
GRPC_MDELEM_STATUS_200)) {
b->Remove(GRPC_BATCH_STATUS);
} else { } else {
char* val = grpc_dump_slice(
GRPC_MDVALUE(b->legacy_index()->named.status->md), GPR_DUMP_ASCII);
std::string msg = std::string msg =
absl::StrCat("Received http2 header with status: ", val); absl::StrCat("Received http2 header with status: ", *status);
grpc_error_handle e = grpc_error_set_str( grpc_error_handle e = grpc_error_set_str(
grpc_error_set_int( grpc_error_set_int(
grpc_error_set_str( grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Received http2 :status header with non-200 OK status"), "Received http2 :status header with non-200 OK status"),
GRPC_ERROR_STR_VALUE, val), GRPC_ERROR_STR_VALUE, std::to_string(*status)),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_ERROR_INT_GRPC_STATUS,
grpc_http2_status_to_grpc_status(atoi(val))), grpc_http2_status_to_grpc_status(*status)),
GRPC_ERROR_STR_GRPC_MESSAGE, msg); GRPC_ERROR_STR_GRPC_MESSAGE, msg);
gpr_free(val);
return e; return e;
} }
} }
@ -146,38 +137,7 @@ static grpc_error_handle client_filter_incoming_metadata(
grpc_core::PermissivePercentDecodeSlice(std::move(*grpc_message)); grpc_core::PermissivePercentDecodeSlice(std::move(*grpc_message));
} }
if (b->legacy_index()->named.content_type != nullptr) { b->Remove(grpc_core::ContentTypeMetadata());
if (!grpc_mdelem_static_value_eq(
b->legacy_index()->named.content_type->md,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
if (grpc_slice_buf_start_eq(
GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) &&
(GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->legacy_index()
->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
'+' ||
GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->legacy_index()
->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
as +proto or +json, or at least stashing them if we see them. */
/* TODO(klempner): Should we be surfacing this to application code? */
} else {
/* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */
char* val = grpc_dump_slice(
GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
gpr_free(val);
}
}
b->Remove(GRPC_BATCH_CONTENT_TYPE);
}
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -308,53 +268,41 @@ static char* slice_buffer_to_string(grpc_slice_buffer* slice_buffer) {
// Modifies the path entry in the batch's send_initial_metadata to // Modifies the path entry in the batch's send_initial_metadata to
// append the base64-encoded query for a GET request. // append the base64-encoded query for a GET request.
static grpc_error_handle update_path_for_get( static void update_path_for_get(grpc_call_element* elem,
grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { grpc_transport_stream_op_batch* batch) {
grpc_metadata_batch* b =
batch->payload->send_initial_metadata.send_initial_metadata;
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
grpc_slice path_slice = const grpc_core::Slice& path_slice =
GRPC_MDVALUE(batch->payload->send_initial_metadata.send_initial_metadata *b->get_pointer(grpc_core::HttpPathMetadata());
->legacy_index()
->named.path->md);
/* sum up individual component's lengths and allocate enough memory to /* sum up individual component's lengths and allocate enough memory to
* hold combined path+query */ * hold combined path+query */
size_t estimated_len = GRPC_SLICE_LENGTH(path_slice); size_t estimated_len = path_slice.size();
estimated_len++; /* for the '?' */ estimated_len++; /* for the '?' */
estimated_len += grpc_base64_estimate_encoded_size( estimated_len += grpc_base64_estimate_encoded_size(
batch->payload->send_message.send_message->length(), batch->payload->send_message.send_message->length(),
false /* multi_line */); false /* multi_line */);
grpc_core::UnmanagedMemorySlice path_with_query_slice(estimated_len); grpc_core::MutableSlice path_with_query_slice =
grpc_core::MutableSlice::CreateUninitialized(estimated_len);
/* memcopy individual pieces into this slice */ /* memcopy individual pieces into this slice */
char* write_ptr = uint8_t* write_ptr = path_with_query_slice.begin();
reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_with_query_slice); const uint8_t* original_path = path_slice.data();
char* original_path = memcpy(write_ptr, original_path, path_slice.size());
reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_slice); write_ptr += path_slice.size();
memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice));
write_ptr += GRPC_SLICE_LENGTH(path_slice);
*write_ptr++ = '?'; *write_ptr++ = '?';
char* payload_bytes = char* payload_bytes =
slice_buffer_to_string(calld->send_message_cache->cache_buffer()); slice_buffer_to_string(calld->send_message_cache->cache_buffer());
grpc_base64_encode_core(write_ptr, payload_bytes, grpc_base64_encode_core(reinterpret_cast<char*>(write_ptr), payload_bytes,
batch->payload->send_message.send_message->length(), batch->payload->send_message.send_message->length(),
true /* url_safe */, false /* multi_line */); true /* url_safe */, false /* multi_line */);
gpr_free(payload_bytes); gpr_free(payload_bytes);
/* remove trailing unused memory and add trailing 0 to terminate string */ char* t = reinterpret_cast<char*>(path_with_query_slice.begin()) +
char* t = path_slice.size();
reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_with_query_slice) +
GRPC_SLICE_LENGTH(path_slice);
/* safe to use strlen since base64_encode will always add '\0' */ /* safe to use strlen since base64_encode will always add '\0' */
path_with_query_slice = grpc_slice_sub_no_ref(
path_with_query_slice, 0, GRPC_SLICE_LENGTH(path_slice) + strlen(t));
/* substitute previous path with the new path+query */ /* substitute previous path with the new path+query */
grpc_mdelem mdelem_path_and_query = b->Set(grpc_core::HttpPathMetadata(),
grpc_mdelem_from_slices(GRPC_MDSTR_PATH, path_with_query_slice); grpc_core::Slice(path_with_query_slice.TakeSubSlice(
grpc_metadata_batch* b = 0, path_slice.size() + strlen(t))));
batch->payload->send_initial_metadata.send_initial_metadata;
return b->Substitute(b->legacy_index()->named.path, mdelem_path_and_query);
}
static void remove_if_present(grpc_metadata_batch* batch,
grpc_metadata_batch_callouts_index idx) {
batch->Remove(idx);
} }
static void http_client_start_transport_stream_op_batch( static void http_client_start_transport_stream_op_batch(
@ -390,7 +338,8 @@ static void http_client_start_transport_stream_op_batch(
// cacheable, and the operation contains both initial metadata and send // cacheable, and the operation contains both initial metadata and send
// message, and the payload is below the size threshold, and all the data // message, and the payload is below the size threshold, and all the data
// for this request is immediately available. // for this request is immediately available.
grpc_mdelem method = GRPC_MDELEM_METHOD_POST; grpc_core::HttpMethodMetadata::ValueType method =
grpc_core::HttpMethodMetadata::kPost;
if (batch->send_message && if (batch->send_message &&
(batch->payload->send_initial_metadata.send_initial_metadata_flags & (batch->payload->send_initial_metadata.send_initial_metadata_flags &
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) && GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) &&
@ -410,9 +359,8 @@ static void http_client_start_transport_stream_op_batch(
// If all the data has been read, then we can use GET. // If all the data has been read, then we can use GET.
if (calld->send_message_bytes_read == if (calld->send_message_bytes_read ==
calld->send_message_caching_stream->length()) { calld->send_message_caching_stream->length()) {
method = GRPC_MDELEM_METHOD_GET; method = grpc_core::HttpMethodMetadata::kGet;
error = update_path_for_get(elem, batch); update_path_for_get(elem, batch);
if (error != GRPC_ERROR_NONE) goto done;
batch->send_message = false; batch->send_message = false;
calld->send_message_caching_stream->Orphan(); calld->send_message_caching_stream->Orphan();
} else { } else {
@ -427,36 +375,20 @@ static void http_client_start_transport_stream_op_batch(
} else if (batch->payload->send_initial_metadata } else if (batch->payload->send_initial_metadata
.send_initial_metadata_flags & .send_initial_metadata_flags &
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) {
method = GRPC_MDELEM_METHOD_PUT; method = grpc_core::HttpMethodMetadata::kPut;
} }
remove_if_present(
batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_METHOD);
remove_if_present(
batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_SCHEME);
remove_if_present(
batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_CONTENT_TYPE);
/* Send : prefixed headers, which have to be before any application /* Send : prefixed headers, which have to be before any application
layer headers. */ layer headers. */
error = grpc_metadata_batch_add_head( batch->payload->send_initial_metadata.send_initial_metadata->Set(
batch->payload->send_initial_metadata.send_initial_metadata, grpc_core::HttpMethodMetadata(), method);
&calld->method, method, GRPC_BATCH_METHOD); batch->payload->send_initial_metadata.send_initial_metadata->Set(
if (error != GRPC_ERROR_NONE) goto done; grpc_core::HttpSchemeMetadata(), channeld->static_scheme);
error = grpc_metadata_batch_add_head(
batch->payload->send_initial_metadata.send_initial_metadata,
&calld->scheme, channeld->static_scheme, GRPC_BATCH_SCHEME);
if (error != GRPC_ERROR_NONE) goto done;
batch->payload->send_initial_metadata.send_initial_metadata->Set( batch->payload->send_initial_metadata.send_initial_metadata->Set(
grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers); grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
error = grpc_metadata_batch_add_tail( batch->payload->send_initial_metadata.send_initial_metadata->Set(
batch->payload->send_initial_metadata.send_initial_metadata, grpc_core::ContentTypeMetadata(),
&calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC, grpc_core::ContentTypeMetadata::kApplicationGrpc);
GRPC_BATCH_CONTENT_TYPE);
if (error != GRPC_ERROR_NONE) goto done;
batch->payload->send_initial_metadata.send_initial_metadata->Set( batch->payload->send_initial_metadata.send_initial_metadata->Set(
grpc_core::UserAgentMetadata(), channeld->user_agent.Ref()); grpc_core::UserAgentMetadata(), channeld->user_agent.Ref());
} }
@ -485,25 +417,21 @@ static void http_client_destroy_call_elem(
calld->~call_data(); calld->~call_data();
} }
static grpc_mdelem scheme_from_args(const grpc_channel_args* args) { static grpc_core::HttpSchemeMetadata::ValueType scheme_from_args(
unsigned i; const grpc_channel_args* args) {
size_t j;
grpc_mdelem valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
GRPC_MDELEM_SCHEME_HTTPS};
if (args != nullptr) { if (args != nullptr) {
for (i = 0; i < args->num_args; ++i) { for (size_t i = 0; i < args->num_args; ++i) {
if (args->args[i].type == GRPC_ARG_STRING && if (args->args[i].type == GRPC_ARG_STRING &&
strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) { 0 == strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME)) {
for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) { grpc_core::HttpSchemeMetadata::ValueType scheme =
if (0 == grpc_slice_str_cmp(GRPC_MDVALUE(valid_schemes[j]), grpc_core::HttpSchemeMetadata::Parse(
args->args[i].value.string)) { args->args[i].value.string,
return valid_schemes[j]; [](absl::string_view, const grpc_core::Slice&) {});
} if (scheme != grpc_core::HttpSchemeMetadata::kInvalid) return scheme;
}
} }
} }
} }
return GRPC_MDELEM_SCHEME_HTTP; return grpc_core::HttpSchemeMetadata::kHttp;
} }
static size_t max_payload_size_from_args(const grpc_channel_args* args) { static size_t max_payload_size_from_args(const grpc_channel_args* args) {

@ -41,34 +41,23 @@
namespace { namespace {
struct call_data { struct call_data {
grpc_linked_mdelem authority_storage;
grpc_core::CallCombiner* call_combiner; grpc_core::CallCombiner* call_combiner;
}; };
struct channel_data { struct channel_data {
grpc_core::ManagedMemorySlice default_authority; grpc_core::Slice default_authority;
grpc_mdelem default_authority_mdelem;
}; };
void client_authority_start_transport_stream_op_batch( void client_authority_start_transport_stream_op_batch(
grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
// Handle send_initial_metadata. // Handle send_initial_metadata.
// If the initial metadata doesn't already contain :authority, add it. // If the initial metadata doesn't already contain :authority, add it.
if (batch->send_initial_metadata && if (batch->send_initial_metadata &&
batch->payload->send_initial_metadata.send_initial_metadata batch->payload->send_initial_metadata.send_initial_metadata->get_pointer(
->legacy_index() grpc_core::HttpAuthorityMetadata()) == nullptr) {
->named.authority == nullptr) { batch->payload->send_initial_metadata.send_initial_metadata->Set(
grpc_error_handle error = grpc_metadata_batch_add_head( grpc_core::HttpAuthorityMetadata(), chand->default_authority.Ref());
batch->payload->send_initial_metadata.send_initial_metadata,
&calld->authority_storage,
GRPC_MDELEM_REF(chand->default_authority_mdelem), GRPC_BATCH_AUTHORITY);
if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure(batch, error,
calld->call_combiner);
return;
}
} }
// Pass control down the stack. // Pass control down the stack.
grpc_call_next_op(elem, batch); grpc_call_next_op(elem, batch);
@ -90,7 +79,7 @@ void client_authority_destroy_call_elem(
/* Constructor for channel_data */ /* Constructor for channel_data */
grpc_error_handle client_authority_init_channel_elem( grpc_error_handle client_authority_init_channel_elem(
grpc_channel_element* elem, grpc_channel_element_args* args) { grpc_channel_element* elem, grpc_channel_element_args* args) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = new (elem->channel_data) channel_data;
const grpc_arg* default_authority_arg = const grpc_arg* default_authority_arg =
grpc_channel_args_find(args->channel_args, GRPC_ARG_DEFAULT_AUTHORITY); grpc_channel_args_find(args->channel_args, GRPC_ARG_DEFAULT_AUTHORITY);
if (default_authority_arg == nullptr) { if (default_authority_arg == nullptr) {
@ -105,18 +94,14 @@ grpc_error_handle client_authority_init_channel_elem(
"GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string"); "GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string");
} }
chand->default_authority = chand->default_authority =
grpc_core::ManagedMemorySlice(default_authority_str); grpc_core::Slice::FromCopiedString(default_authority_str);
chand->default_authority_mdelem = grpc_mdelem_create(
GRPC_MDSTR_AUTHORITY, chand->default_authority, nullptr);
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
/* Destructor for channel data */ /* Destructor for channel data */
void client_authority_destroy_channel_elem(grpc_channel_element* elem) { void client_authority_destroy_channel_elem(grpc_channel_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data); static_cast<channel_data*>(elem->channel_data)->~channel_data();
grpc_slice_unref_internal(chand->default_authority);
GRPC_MDELEM_UNREF(chand->default_authority_mdelem);
} }
} // namespace } // namespace

@ -34,9 +34,6 @@
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#define EXPECTED_CONTENT_TYPE "application/grpc"
#define EXPECTED_CONTENT_TYPE_LENGTH (sizeof(EXPECTED_CONTENT_TYPE) - 1)
static void hs_recv_initial_metadata_ready(void* user_data, static void hs_recv_initial_metadata_ready(void* user_data,
grpc_error_handle err); grpc_error_handle err);
static void hs_recv_trailing_metadata_ready(void* user_data, static void hs_recv_trailing_metadata_ready(void* user_data,
@ -67,10 +64,6 @@ struct call_data {
grpc_core::CallCombiner* call_combiner; grpc_core::CallCombiner* call_combiner;
// Outgoing headers to add to send_initial_metadata.
grpc_linked_mdelem status;
grpc_linked_mdelem content_type;
// If we see the recv_message contents in the GET query string, we // If we see the recv_message contents in the GET query string, we
// store it here. // store it here.
grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> read_stream; grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> read_stream;
@ -121,63 +114,37 @@ static void hs_add_error(const char* error_name, grpc_error_handle* cumulative,
*cumulative = grpc_error_add_child(*cumulative, new_err); *cumulative = grpc_error_add_child(*cumulative, new_err);
} }
// Metadata equality within this filter leverages the fact that the sender was
// likely using the gRPC chttp2 transport, in which case the encoder would emit
// indexed values, in which case the local hpack parser would intern the
// relevant metadata, allowing a simple pointer comparison.
//
// That said, if the header was transmitted sans indexing/encoding, we still
// need to do the right thing.
//
// Assumptions:
// 1) The keys for a and b_static must match
// 2) b_static must be a statically allocated metadata object.
// 3) It is assumed that the remote end is indexing, but not necessary.
// TODO(arjunroy): Revisit this method when grpc_mdelem is strongly typed.
static bool md_strict_equal(grpc_mdelem a, grpc_mdelem b_static) {
// Hpack encoder on the remote side should emit indexed values, in which case
// hpack parser on this end should pick up interned values, in which case the
// pointer comparison alone is enough.
//
if (GPR_LIKELY(GRPC_MDELEM_IS_INTERNED(a))) {
return a.payload == b_static.payload;
} else {
return grpc_slice_eq_static_interned(GRPC_MDVALUE(a),
GRPC_MDVALUE(b_static));
}
}
static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
grpc_metadata_batch* b) { grpc_metadata_batch* b) {
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
grpc_error_handle error = GRPC_ERROR_NONE; grpc_error_handle error = GRPC_ERROR_NONE;
static const char* error_name = "Failed processing incoming headers"; static const char* error_name = "Failed processing incoming headers";
if (b->legacy_index()->named.method != nullptr) { auto method = b->Take(grpc_core::HttpMethodMetadata());
if (md_strict_equal(b->legacy_index()->named.method->md, if (method.has_value()) {
GRPC_MDELEM_METHOD_POST)) { switch (*method) {
*calld->recv_initial_metadata_flags &= case grpc_core::HttpMethodMetadata::kPost:
~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | *calld->recv_initial_metadata_flags &=
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); ~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST |
} else if (md_strict_equal(b->legacy_index()->named.method->md, GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
GRPC_MDELEM_METHOD_PUT)) { break;
*calld->recv_initial_metadata_flags &= case grpc_core::HttpMethodMetadata::kPut:
~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; *calld->recv_initial_metadata_flags &=
*calld->recv_initial_metadata_flags |= ~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST;
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; *calld->recv_initial_metadata_flags |=
} else if (md_strict_equal(b->legacy_index()->named.method->md, GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
GRPC_MDELEM_METHOD_GET)) { break;
*calld->recv_initial_metadata_flags |= case grpc_core::HttpMethodMetadata::kGet:
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; *calld->recv_initial_metadata_flags |=
*calld->recv_initial_metadata_flags &= GRPC_INITIAL_METADATA_CACHEABLE_REQUEST;
~GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; *calld->recv_initial_metadata_flags &=
} else { ~GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
hs_add_error(error_name, &error, break;
grpc_attach_md_to_error( case grpc_core::HttpMethodMetadata::kInvalid:
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), hs_add_error(error_name, &error,
b->legacy_index()->named.method->md)); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad method header"));
break;
} }
b->Remove(GRPC_BATCH_METHOD);
} else { } else {
hs_add_error(error_name, &error, hs_add_error(error_name, &error,
grpc_error_set_str( grpc_error_set_str(
@ -198,19 +165,12 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad te header")); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad te header"));
} }
if (b->legacy_index()->named.scheme != nullptr) { auto scheme = b->Take(grpc_core::HttpSchemeMetadata());
if (!md_strict_equal(b->legacy_index()->named.scheme->md, if (scheme.has_value()) {
GRPC_MDELEM_SCHEME_HTTP) && if (*scheme == grpc_core::HttpSchemeMetadata::kInvalid) {
!md_strict_equal(b->legacy_index()->named.scheme->md,
GRPC_MDELEM_SCHEME_HTTPS) &&
!grpc_mdelem_static_value_eq(b->legacy_index()->named.scheme->md,
GRPC_MDELEM_SCHEME_GRPC)) {
hs_add_error(error_name, &error, hs_add_error(error_name, &error,
grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad :scheme header"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
b->legacy_index()->named.scheme->md));
} }
b->Remove(GRPC_BATCH_SCHEME);
} else { } else {
hs_add_error(error_name, &error, hs_add_error(error_name, &error,
grpc_error_set_str( grpc_error_set_str(
@ -218,40 +178,10 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
GRPC_ERROR_STR_KEY, ":scheme")); GRPC_ERROR_STR_KEY, ":scheme"));
} }
if (b->legacy_index()->named.content_type != nullptr) { b->Remove(grpc_core::ContentTypeMetadata());
if (!grpc_mdelem_static_value_eq(
b->legacy_index()->named.content_type->md,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
if (grpc_slice_buf_start_eq(
GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) &&
(GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->legacy_index()
->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
'+' ||
GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->legacy_index()
->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
as +proto or +json, or at least stashing them if we see them. */
/* TODO(klempner): Should we be surfacing this to application code? */
} else {
/* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */
char* val = grpc_dump_slice(
GRPC_MDVALUE(b->legacy_index()->named.content_type->md),
GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
gpr_free(val);
}
}
b->Remove(GRPC_BATCH_CONTENT_TYPE);
}
if (b->legacy_index()->named.path == nullptr) { grpc_core::Slice* path_slice = b->get_pointer(grpc_core::HttpPathMetadata());
if (path_slice == nullptr) {
hs_add_error(error_name, &error, hs_add_error(error_name, &error,
grpc_error_set_str( grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
@ -260,25 +190,18 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) {
/* We have a cacheable request made with GET verb. The path contains the /* We have a cacheable request made with GET verb. The path contains the
* query parameter which is base64 encoded request payload. */ * query parameter which is base64 encoded request payload. */
const char k_query_separator = '?'; static const char kQuerySeparator = '?';
grpc_slice path_slice = GRPC_MDVALUE(b->legacy_index()->named.path->md);
uint8_t* path_ptr = GRPC_SLICE_START_PTR(path_slice);
size_t path_length = GRPC_SLICE_LENGTH(path_slice);
/* offset of the character '?' */ /* offset of the character '?' */
size_t offset = 0; auto it =
for (offset = 0; offset < path_length && *path_ptr != k_query_separator; std::find(path_slice->begin(), path_slice->end(), kQuerySeparator);
path_ptr++, offset++) { if (it != path_slice->end()) {
} const auto query_start = it - path_slice->begin() + 1;
if (offset < path_length) { auto query_slice = path_slice->RefSubSlice(
grpc_slice query_slice = query_start, path_slice->size() - query_start);
grpc_slice_sub(path_slice, offset + 1, path_length);
/* substitute path metadata with just the path (not query) */ /* substitute path metadata with just the path (not query) */
grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices( auto path_without_query = path_slice->TakeSubSlice(0, query_start - 1);
GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset)); *path_slice = std::move(path_without_query);
(void)b->Substitute(b->legacy_index()->named.path,
mdelem_path_without_query);
/* decode payload from query and add to the slice buffer to be returned */ /* decode payload from query and add to the slice buffer to be returned */
const int k_url_safe = 1; const int k_url_safe = 1;
@ -287,25 +210,24 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem,
grpc_slice_buffer_add( grpc_slice_buffer_add(
&read_slice_buffer, &read_slice_buffer,
grpc_base64_decode_with_len( grpc_base64_decode_with_len(
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(query_slice), reinterpret_cast<const char*>(query_slice.begin()),
GRPC_SLICE_LENGTH(query_slice), k_url_safe)); query_slice.size(), k_url_safe));
calld->read_stream.Init(&read_slice_buffer, 0); calld->read_stream.Init(&read_slice_buffer, 0);
grpc_slice_buffer_destroy_internal(&read_slice_buffer); grpc_slice_buffer_destroy_internal(&read_slice_buffer);
calld->have_read_stream = true; calld->have_read_stream = true;
grpc_slice_unref_internal(query_slice);
} else { } else {
gpr_log(GPR_ERROR, "GET request without QUERY"); gpr_log(GPR_ERROR, "GET request without QUERY");
} }
} }
if (b->legacy_index()->named.authority == nullptr) { if (b->get_pointer(grpc_core::HttpAuthorityMetadata()) == nullptr) {
absl::optional<grpc_core::Slice> host = b->Take(grpc_core::HostMetadata()); absl::optional<grpc_core::Slice> host = b->Take(grpc_core::HostMetadata());
if (host.has_value()) { if (host.has_value()) {
b->Append(":authority", std::move(*host)); b->Set(grpc_core::HttpAuthorityMetadata(), std::move(*host));
} }
} }
if (b->legacy_index()->named.authority == nullptr) { if (b->get_pointer(grpc_core::HttpAuthorityMetadata()) == nullptr) {
hs_add_error(error_name, &error, hs_add_error(error_name, &error,
grpc_error_set_str( grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
@ -410,17 +332,11 @@ static grpc_error_handle hs_mutate_op(grpc_call_element* elem,
if (op->send_initial_metadata) { if (op->send_initial_metadata) {
grpc_error_handle error = GRPC_ERROR_NONE; grpc_error_handle error = GRPC_ERROR_NONE;
static const char* error_name = "Failed sending initial metadata"; static const char* error_name = "Failed sending initial metadata";
hs_add_error( op->payload->send_initial_metadata.send_initial_metadata->Set(
error_name, &error, grpc_core::HttpStatusMetadata(), 200);
grpc_metadata_batch_add_head( op->payload->send_initial_metadata.send_initial_metadata->Set(
op->payload->send_initial_metadata.send_initial_metadata, grpc_core::ContentTypeMetadata(),
&calld->status, GRPC_MDELEM_STATUS_200, GRPC_BATCH_STATUS)); grpc_core::ContentTypeMetadata::kApplicationGrpc);
hs_add_error(error_name, &error,
grpc_metadata_batch_add_tail(
op->payload->send_initial_metadata.send_initial_metadata,
&calld->content_type,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
GRPC_BATCH_CONTENT_TYPE));
hs_add_error(error_name, &error, hs_add_error(error_name, &error,
hs_filter_outgoing_metadata( hs_filter_outgoing_metadata(
op->payload->send_initial_metadata.send_initial_metadata)); op->payload->send_initial_metadata.send_initial_metadata));

@ -24,6 +24,7 @@
#include <string> #include <string>
#include "absl/strings/ascii.h"
#include "absl/strings/str_format.h" #include "absl/strings/str_format.h"
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
@ -93,14 +94,13 @@ void ServerLoadReportingCallData::Destroy(
{{::grpc::load_reporter::TagKeyToken(), {{::grpc::load_reporter::TagKeyToken(),
{client_ip_and_lr_token_, client_ip_and_lr_token_len_}}, {client_ip_and_lr_token_, client_ip_and_lr_token_len_}},
{::grpc::load_reporter::TagKeyHost(), {::grpc::load_reporter::TagKeyHost(),
{target_host_, target_host_len_}}, {target_host_.data(), target_host_.length()}},
{::grpc::load_reporter::TagKeyUserId(), {::grpc::load_reporter::TagKeyUserId(),
{chand->peer_identity(), chand->peer_identity_len()}}, {chand->peer_identity(), chand->peer_identity_len()}},
{::grpc::load_reporter::TagKeyStatus(), {::grpc::load_reporter::TagKeyStatus(),
GetStatusTagForStatus(final_info->final_status)}}); GetStatusTagForStatus(final_info->final_status)}});
gpr_free(client_ip_and_lr_token_); gpr_free(client_ip_and_lr_token_);
} }
gpr_free(target_host_);
grpc_slice_unref_internal(service_method_); grpc_slice_unref_internal(service_method_);
} }
@ -205,35 +205,6 @@ void ServerLoadReportingCallData::StoreClientIpAndLrToken(const char* lr_token,
client_ip_and_lr_token_len_); client_ip_and_lr_token_len_);
} }
grpc_filtered_mdelem ServerLoadReportingCallData::RecvInitialMetadataFilter(
void* user_data, grpc_mdelem md) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
ServerLoadReportingCallData* calld =
reinterpret_cast<ServerLoadReportingCallData*>(elem->call_data);
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) {
calld->service_method_ = grpc_slice_ref_internal(GRPC_MDVALUE(md));
} else if (calld->target_host_ == nullptr &&
grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) {
grpc_slice target_host_slice = GRPC_MDVALUE(md);
calld->target_host_len_ = GRPC_SLICE_LENGTH(target_host_slice);
calld->target_host_ =
reinterpret_cast<char*>(gpr_zalloc(calld->target_host_len_));
for (size_t i = 0; i < calld->target_host_len_; ++i) {
calld->target_host_[i] = static_cast<char>(
tolower(GRPC_SLICE_START_PTR(target_host_slice)[i]));
}
} else if (grpc_slice_str_cmp(GRPC_MDKEY(md),
grpc_core::kGrpcLbLbTokenMetadataKey) == 0) {
if (calld->client_ip_and_lr_token_ == nullptr) {
calld->StoreClientIpAndLrToken(
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(GRPC_MDVALUE(md)),
GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)));
}
return GRPC_FILTERED_REMOVE();
}
return GRPC_FILTERED_MDELEM(md);
}
void ServerLoadReportingCallData::RecvInitialMetadataReady( void ServerLoadReportingCallData::RecvInitialMetadataReady(
void* arg, grpc_error_handle err) { void* arg, grpc_error_handle err) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(arg); grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(arg);
@ -242,11 +213,29 @@ void ServerLoadReportingCallData::RecvInitialMetadataReady(
ServerLoadReportingChannelData* chand = ServerLoadReportingChannelData* chand =
reinterpret_cast<ServerLoadReportingChannelData*>(elem->channel_data); reinterpret_cast<ServerLoadReportingChannelData*>(elem->channel_data);
if (err == GRPC_ERROR_NONE) { if (err == GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR( if (const grpc_core::Slice* path =
"server_load_reporting_filter", calld->recv_initial_metadata_->get_pointer(
grpc_metadata_batch_filter(calld->recv_initial_metadata_, grpc_core::HttpPathMetadata())) {
RecvInitialMetadataFilter, elem, calld->service_method_ = path->Ref().TakeCSlice();
"recv_initial_metadata filtering error")); }
if (const grpc_core::Slice* authority =
calld->recv_initial_metadata_->get_pointer(
grpc_core::HttpAuthorityMetadata())) {
calld->target_host_ = absl::AsciiStrToLower(authority->as_string_view());
}
std::string buffer;
auto lb_token = calld->recv_initial_metadata_->GetValue(
grpc_core::kGrpcLbLbTokenMetadataKey, &buffer);
if (lb_token.has_value()) {
if (calld->client_ip_and_lr_token_ == nullptr) {
calld->StoreClientIpAndLrToken(lb_token->data(), lb_token->size());
}
auto old = calld->recv_initial_metadata_->Remove(
grpc_core::Slice::FromCopiedString(
grpc_core::kGrpcLbLbTokenMetadataKey)
.c_slice());
if (old.has_value()) grpc_slice_unref_internal(*old);
}
// If the LB token was not found in the recv_initial_metadata, only the // If the LB token was not found in the recv_initial_metadata, only the
// client IP part will be recorded (with an empty LB token). // client IP part will be recorded (with an empty LB token).
if (calld->client_ip_and_lr_token_ == nullptr) { if (calld->client_ip_and_lr_token_ == nullptr) {
@ -257,7 +246,7 @@ void ServerLoadReportingCallData::RecvInitialMetadataReady(
{{::grpc::load_reporter::TagKeyToken(), {{::grpc::load_reporter::TagKeyToken(),
{calld->client_ip_and_lr_token_, calld->client_ip_and_lr_token_len_}}, {calld->client_ip_and_lr_token_, calld->client_ip_and_lr_token_len_}},
{::grpc::load_reporter::TagKeyHost(), {::grpc::load_reporter::TagKeyHost(),
{calld->target_host_, calld->target_host_len_}}, {calld->target_host_.data(), calld->target_host_.length()}},
{::grpc::load_reporter::TagKeyUserId(), {::grpc::load_reporter::TagKeyUserId(),
{chand->peer_identity(), chand->peer_identity_len()}}}); {chand->peer_identity(), chand->peer_identity_len()}}});
} }
@ -303,7 +292,7 @@ grpc_filtered_mdelem ServerLoadReportingCallData::SendTrailingMetadataFilter(
{{::grpc::load_reporter::TagKeyToken(), {{::grpc::load_reporter::TagKeyToken(),
{calld->client_ip_and_lr_token_, calld->client_ip_and_lr_token_len_}}, {calld->client_ip_and_lr_token_, calld->client_ip_and_lr_token_len_}},
{::grpc::load_reporter::TagKeyHost(), {::grpc::load_reporter::TagKeyHost(),
{calld->target_host_, calld->target_host_len_}}, {calld->target_host_.data(), calld->target_host_.length()}},
{::grpc::load_reporter::TagKeyUserId(), {::grpc::load_reporter::TagKeyUserId(),
{chand->peer_identity(), chand->peer_identity_len()}}, {chand->peer_identity(), chand->peer_identity_len()}},
{::grpc::load_reporter::TagKeyMetricName(), {::grpc::load_reporter::TagKeyMetricName(),

@ -106,8 +106,7 @@ class ServerLoadReportingCallData : public CallData {
// different from the actual backend in the case of, for example, // different from the actual backend in the case of, for example,
// load-balanced targets. We store a copy of the metadata slice in order to // load-balanced targets. We store a copy of the metadata slice in order to
// lowercase it. */ // lowercase it. */
char* target_host_; std::string target_host_;
size_t target_host_len_;
// The client IP address (including a length prefix) and the load reporting // The client IP address (including a length prefix) and the load reporting
// token. // token.

@ -123,7 +123,13 @@ static void AssignMetadata(grpc_metadata_batch* mb,
const grpc_binder::Metadata& md) { const grpc_binder::Metadata& md) {
mb->Clear(); mb->Clear();
for (auto& p : md) { for (auto& p : md) {
mb->Append(p.first, grpc_core::Slice::FromCopiedString(p.second)); mb->Append(p.first, grpc_core::Slice::FromCopiedString(p.second),
[&](absl::string_view error, const grpc_core::Slice& value) {
gpr_log(GPR_DEBUG, "Failed to parse metadata: %s",
absl::StrCat("key=", p.first, " error=", error,
" value=", value.as_string_view())
.c_str());
});
} }
} }
@ -326,18 +332,18 @@ class MetadataEncoder {
absl::string_view value = grpc_core::StringViewFromSlice(GRPC_MDVALUE(md)); absl::string_view value = grpc_core::StringViewFromSlice(GRPC_MDVALUE(md));
gpr_log(GPR_INFO, "send metadata key-value %s", gpr_log(GPR_INFO, "send metadata key-value %s",
absl::StrCat(key, " ", value).c_str()); absl::StrCat(key, " ", value).c_str());
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { init_md_->emplace_back(std::string(key), std::string(value));
// TODO(b/192208403): Figure out if it is correct to simply drop '/' }
// prefix and treat it as rpc method name
GPR_ASSERT(value[0] == '/'); void Encode(grpc_core::HttpPathMetadata, const grpc_core::Slice& value) {
std::string path = std::string(value).substr(1); // TODO(b/192208403): Figure out if it is correct to simply drop '/'
// prefix and treat it as rpc method name
// Only client send method ref. GPR_ASSERT(value[0] == '/');
GPR_ASSERT(is_client_); std::string path = std::string(value.as_string_view().substr(1));
tx_->SetMethodRef(path);
} else { // Only client send method ref.
init_md_->emplace_back(std::string(key), std::string(value)); GPR_ASSERT(is_client_);
} tx_->SetMethodRef(path);
} }
void Encode(grpc_core::GrpcStatusMetadata, grpc_status_code status) { void Encode(grpc_core::GrpcStatusMetadata, grpc_status_code status) {

@ -23,6 +23,8 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "hpack_constants.h"
/* This is here for grpc_is_binary_header /* This is here for grpc_is_binary_header
* TODO(murgatroid99): Remove this * TODO(murgatroid99): Remove this
*/ */
@ -395,6 +397,30 @@ void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyNotIdx(
Add(emit.data()); Add(emit.data());
} }
void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyIncIdx(
const grpc_slice& key_slice, const grpc_slice& value_slice) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V();
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
StringKey key(key_slice);
key.WritePrefix(0x40, AddTiny(key.prefix_length()));
Add(grpc_slice_ref_internal(key.key()));
BinaryStringValue emit(value_slice, use_true_binary_metadata_);
emit.WritePrefix(AddTiny(emit.prefix_length()));
Add(emit.data());
}
void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyNotIdx(
uint32_t key_index, const grpc_slice& value_slice) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX();
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED();
BinaryStringValue emit(value_slice, use_true_binary_metadata_);
VarintWriter<4> key(key_index);
uint8_t* data = AddTiny(key.length() + emit.prefix_length());
key.Write(0x00, data);
emit.WritePrefix(data + key.length());
Add(emit.data());
}
void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyNotIdx( void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyNotIdx(
const grpc_slice& key_slice, const grpc_slice& value_slice) { const grpc_slice& key_slice, const grpc_slice& value_slice) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(); GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V();
@ -525,6 +551,54 @@ void HPackCompressor::Framer::EncodeDynamic(grpc_mdelem elem) {
} }
} }
void HPackCompressor::SliceIndex::EmitTo(const grpc_slice& key,
const Slice& value, Framer* framer) {
auto& table = framer->compressor_->table_;
using It = std::vector<ValueIndex>::iterator;
It prev = values_.end();
uint32_t transport_length =
GRPC_SLICE_LENGTH(key) + value.length() + hpack_constants::kEntryOverhead;
// Linear scan through previous values to see if we find the value.
for (It it = values_.begin(); it != values_.end(); ++it) {
if (value == it->value) {
// Got a hit... is it still in the decode table?
if (table.ConvertableToDynamicIndex(it->index)) {
// Yes, emit the index and proceed to cleanup.
framer->EmitIndexed(table.DynamicIndex(it->index));
} else {
// Not current, emit a new literal and update the index.
it->index = table.AllocateIndex(transport_length);
framer->EmitLitHdrWithNonBinaryStringKeyIncIdx(key, value.c_slice());
}
// Bubble this entry up if we can - ensures that the most used values end
// up towards the start of the array.
if (prev != values_.end()) std::swap(*prev, *it);
// If there are entries at the end of the array, and those entries are no
// longer in the table, remove them.
while (!values_.empty() &&
!table.ConvertableToDynamicIndex(values_.back().index)) {
values_.pop_back();
}
// All done, early out.
return;
}
prev = it;
}
// No hit, emit a new literal and add it to the index.
uint32_t index = table.AllocateIndex(transport_length);
framer->EmitLitHdrWithNonBinaryStringKeyIncIdx(key, value.c_slice());
values_.emplace_back(value.Ref(), index);
}
void HPackCompressor::Framer::Encode(HttpPathMetadata, const Slice& value) {
compressor_->path_index_.EmitTo(GRPC_MDSTR_PATH, value, this);
}
void HPackCompressor::Framer::Encode(HttpAuthorityMetadata,
const Slice& value) {
compressor_->authority_index_.EmitTo(GRPC_MDSTR_AUTHORITY, value, this);
}
void HPackCompressor::Framer::Encode(TeMetadata, TeMetadata::ValueType value) { void HPackCompressor::Framer::Encode(TeMetadata, TeMetadata::ValueType value) {
GPR_ASSERT(value == TeMetadata::ValueType::kTrailers); GPR_ASSERT(value == TeMetadata::ValueType::kTrailers);
EncodeAlwaysIndexed( EncodeAlwaysIndexed(
@ -532,6 +606,97 @@ void HPackCompressor::Framer::Encode(TeMetadata, TeMetadata::ValueType value) {
2 /* te */ + 8 /* trailers */ + hpack_constants::kEntryOverhead); 2 /* te */ + 8 /* trailers */ + hpack_constants::kEntryOverhead);
} }
void HPackCompressor::Framer::Encode(ContentTypeMetadata,
ContentTypeMetadata::ValueType value) {
GPR_ASSERT(value == ContentTypeMetadata::ValueType::kApplicationGrpc);
EncodeAlwaysIndexed(
&compressor_->content_type_index_, GRPC_MDSTR_CONTENT_TYPE,
StaticSlice::FromStaticString("application/grpc").c_slice(),
12 /* content-type */ + 16 /* application/grpc */ +
hpack_constants::kEntryOverhead);
}
void HPackCompressor::Framer::Encode(HttpSchemeMetadata,
HttpSchemeMetadata::ValueType value) {
switch (value) {
case HttpSchemeMetadata::ValueType::kHttp:
EmitIndexed(6); // :scheme: http
break;
case HttpSchemeMetadata::ValueType::kHttps:
EmitIndexed(7); // :scheme: https
break;
case HttpSchemeMetadata::ValueType::kInvalid:
GPR_ASSERT(false);
break;
}
}
void HPackCompressor::Framer::Encode(GrpcTraceBinMetadata, const Slice& slice) {
EncodeIndexedKeyWithBinaryValue(&compressor_->grpc_trace_bin_index_,
"grpc-trace-bin", slice.c_slice());
}
void HPackCompressor::Framer::Encode(GrpcTagsBinMetadata, const Slice& slice) {
EncodeIndexedKeyWithBinaryValue(&compressor_->grpc_tags_bin_index_,
"grpc-tags-bin", slice.c_slice());
}
void HPackCompressor::Framer::Encode(HttpStatusMetadata, uint32_t status) {
if (status == 200) {
EmitIndexed(8); // :status: 200
return;
}
uint8_t index = 0;
switch (status) {
case 204:
index = 9; // :status: 204
break;
case 206:
index = 10; // :status: 206
break;
case 304:
index = 11; // :status: 304
break;
case 400:
index = 12; // :status: 400
break;
case 404:
index = 13; // :status: 404
break;
case 500:
index = 14; // :status: 500
break;
}
if (GPR_LIKELY(index != 0)) {
EmitIndexed(index);
} else {
char buffer[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(status, buffer);
EmitLitHdrWithNonBinaryStringKeyIncIdx(
GRPC_MDSTR_STATUS, Slice::FromCopiedString(buffer).c_slice());
}
}
void HPackCompressor::Framer::Encode(HttpMethodMetadata,
HttpMethodMetadata::ValueType method) {
switch (method) {
case HttpMethodMetadata::ValueType::kGet:
EmitIndexed(2); // :method: GET
break;
case HttpMethodMetadata::ValueType::kPost:
EmitIndexed(3); // :method: POST
break;
case HttpMethodMetadata::ValueType::kPut:
EmitLitHdrWithNonBinaryStringKeyNotIdx(
StaticSlice::FromStaticString(":method").c_slice(),
StaticSlice::FromStaticString("PUT").c_slice());
break;
case HttpMethodMetadata::ValueType::kInvalid:
GPR_ASSERT(false);
break;
}
}
void HPackCompressor::Framer::EncodeAlwaysIndexed(uint32_t* index, void HPackCompressor::Framer::EncodeAlwaysIndexed(uint32_t* index,
const grpc_slice& key, const grpc_slice& key,
const grpc_slice& value, const grpc_slice& value,
@ -544,6 +709,20 @@ void HPackCompressor::Framer::EncodeAlwaysIndexed(uint32_t* index,
} }
} }
void HPackCompressor::Framer::EncodeIndexedKeyWithBinaryValue(
uint32_t* index, absl::string_view key, const grpc_slice& value) {
if (compressor_->table_.ConvertableToDynamicIndex(*index)) {
EmitLitHdrWithBinaryStringKeyNotIdx(
compressor_->table_.DynamicIndex(*index), value);
} else {
*index = compressor_->table_.AllocateIndex(key.length() +
GRPC_SLICE_LENGTH(value) +
hpack_constants::kEntryOverhead);
EmitLitHdrWithBinaryStringKeyIncIdx(
StaticSlice::FromStaticString(key).c_slice(), value);
}
}
void HPackCompressor::Framer::Encode(GrpcTimeoutMetadata, void HPackCompressor::Framer::Encode(GrpcTimeoutMetadata,
grpc_millis deadline) { grpc_millis deadline) {
char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <cstdint>
#include <grpc/slice.h> #include <grpc/slice.h>
#include <grpc/slice_buffer.h> #include <grpc/slice_buffer.h>
@ -36,48 +38,9 @@ extern grpc_core::TraceFlag grpc_http_trace;
namespace grpc_core { namespace grpc_core {
// Wrapper to take an array of mdelems and make them encodable
class MetadataArray {
public:
MetadataArray(grpc_mdelem** elems, size_t count)
: elems_(elems), count_(count) {}
template <typename Encoder>
void Encode(Encoder* encoder) const {
for (size_t i = 0; i < count_; i++) {
encoder->Encode(*elems_[i]);
}
}
private:
grpc_mdelem** elems_;
size_t count_;
};
namespace metadata_detail {
template <typename A, typename B>
class ConcatMetadata {
public:
ConcatMetadata(const A& a, const B& b) : a_(a), b_(b) {}
template <typename Encoder>
void Encode(Encoder* encoder) const {
a_.Encode(encoder);
b_.Encode(encoder);
}
private:
const A& a_;
const B& b_;
};
} // namespace metadata_detail
template <typename A, typename B>
metadata_detail::ConcatMetadata<A, B> ConcatMetadata(const A& a, const B& b) {
return metadata_detail::ConcatMetadata<A, B>(a, b);
}
class HPackCompressor { class HPackCompressor {
class SliceIndex;
public: public:
HPackCompressor() = default; HPackCompressor() = default;
~HPackCompressor() = default; ~HPackCompressor() = default;
@ -117,10 +80,18 @@ class HPackCompressor {
Framer& operator=(const Framer&) = delete; Framer& operator=(const Framer&) = delete;
void Encode(grpc_mdelem md); void Encode(grpc_mdelem md);
void Encode(HttpPathMetadata, const Slice& value);
void Encode(HttpAuthorityMetadata, const Slice& value);
void Encode(HttpStatusMetadata, uint32_t status);
void Encode(GrpcTimeoutMetadata, grpc_millis deadline); void Encode(GrpcTimeoutMetadata, grpc_millis deadline);
void Encode(TeMetadata, TeMetadata::ValueType value); void Encode(TeMetadata, TeMetadata::ValueType value);
void Encode(ContentTypeMetadata, ContentTypeMetadata::ValueType value);
void Encode(HttpSchemeMetadata, HttpSchemeMetadata::ValueType value);
void Encode(HttpMethodMetadata, HttpMethodMetadata::ValueType method);
void Encode(UserAgentMetadata, const Slice& slice); void Encode(UserAgentMetadata, const Slice& slice);
void Encode(GrpcStatusMetadata, grpc_status_code status); void Encode(GrpcStatusMetadata, grpc_status_code status);
void Encode(GrpcTagsBinMetadata, const Slice& slice);
void Encode(GrpcTraceBinMetadata, const Slice& slice);
void Encode(GrpcMessageMetadata, const Slice& slice) { void Encode(GrpcMessageMetadata, const Slice& slice) {
if (slice.empty()) return; if (slice.empty()) return;
EmitLitHdrWithNonBinaryStringKeyNotIdx( EmitLitHdrWithNonBinaryStringKeyNotIdx(
@ -142,6 +113,8 @@ class HPackCompressor {
} }
private: private:
friend class SliceIndex;
struct FramePrefix { struct FramePrefix {
// index (in output_) of the header for the frame // index (in output_) of the header for the frame
size_t header_idx; size_t header_idx;
@ -164,8 +137,12 @@ class HPackCompressor {
void EmitLitHdrWithStringKeyIncIdx(grpc_mdelem elem); void EmitLitHdrWithStringKeyIncIdx(grpc_mdelem elem);
void EmitLitHdrWithNonBinaryStringKeyIncIdx(const grpc_slice& key_slice, void EmitLitHdrWithNonBinaryStringKeyIncIdx(const grpc_slice& key_slice,
const grpc_slice& value_slice); const grpc_slice& value_slice);
void EmitLitHdrWithBinaryStringKeyIncIdx(const grpc_slice& key_slice,
const grpc_slice& value_slice);
void EmitLitHdrWithBinaryStringKeyNotIdx(const grpc_slice& key_slice, void EmitLitHdrWithBinaryStringKeyNotIdx(const grpc_slice& key_slice,
const grpc_slice& value_slice); const grpc_slice& value_slice);
void EmitLitHdrWithBinaryStringKeyNotIdx(uint32_t key_index,
const grpc_slice& value_slice);
void EmitLitHdrWithNonBinaryStringKeyNotIdx(const grpc_slice& key_slice, void EmitLitHdrWithNonBinaryStringKeyNotIdx(const grpc_slice& key_slice,
const grpc_slice& value_slice); const grpc_slice& value_slice);
void EmitLitHdrWithStringKeyNotIdx(grpc_mdelem elem); void EmitLitHdrWithStringKeyNotIdx(grpc_mdelem elem);
@ -173,6 +150,8 @@ class HPackCompressor {
void EncodeAlwaysIndexed(uint32_t* index, const grpc_slice& key, void EncodeAlwaysIndexed(uint32_t* index, const grpc_slice& key,
const grpc_slice& value, const grpc_slice& value,
uint32_t transport_length); uint32_t transport_length);
void EncodeIndexedKeyWithBinaryValue(uint32_t* index, absl::string_view key,
const grpc_slice& value);
size_t CurrentFrameSize() const; size_t CurrentFrameSize() const;
void Add(grpc_slice slice); void Add(grpc_slice slice);
@ -295,18 +274,40 @@ class HPackCompressor {
uint32_t hash_; uint32_t hash_;
}; };
class SliceIndex {
public:
void EmitTo(const grpc_slice& key, const Slice& value, Framer* framer);
private:
struct ValueIndex {
ValueIndex(Slice value, uint32_t index)
: value(std::move(value)), index(index) {}
Slice value;
uint32_t index;
};
std::vector<ValueIndex> values_;
};
// entry tables for keys & elems: these tables track values that have been // entry tables for keys & elems: these tables track values that have been
// seen and *may* be in the decompressor table // seen and *may* be in the decompressor table
HPackEncoderIndex<KeyElem, kNumFilterValues> elem_index_; HPackEncoderIndex<KeyElem, kNumFilterValues> elem_index_;
HPackEncoderIndex<KeySliceRef, kNumFilterValues> key_index_; HPackEncoderIndex<KeySliceRef, kNumFilterValues> key_index_;
// Index into table_ for the te:trailers metadata element // Index into table_ for the te:trailers metadata element
uint32_t te_index_ = 0; uint32_t te_index_ = 0;
// Index into table_ for the content-type metadata element
uint32_t content_type_index_ = 0;
// Index into table_ for the user-agent metadata element // Index into table_ for the user-agent metadata element
uint32_t user_agent_index_ = 0; uint32_t user_agent_index_ = 0;
// Cached grpc-status values // Cached grpc-status values
uint32_t cached_grpc_status_[kNumCachedGrpcStatusValues] = {}; uint32_t cached_grpc_status_[kNumCachedGrpcStatusValues] = {};
// Index of something that was sent with grpc-tags-bin
uint32_t grpc_tags_bin_index_ = 0;
// Index of something that was sent with grpc-trace-bin
uint32_t grpc_trace_bin_index_ = 0;
// The user-agent string referred to by user_agent_index_ // The user-agent string referred to by user_agent_index_
Slice user_agent_; Slice user_agent_;
SliceIndex path_index_;
SliceIndex authority_index_;
}; };
} // namespace grpc_core } // namespace grpc_core

@ -1129,8 +1129,11 @@ class HPackParser::Parser {
auto value_slice = value->Take<TakeValueType>(); auto value_slice = value->Take<TakeValueType>();
const auto transport_size = key_string.size() + value_slice.size() + const auto transport_size = key_string.size() + value_slice.size() +
hpack_constants::kEntryOverhead; hpack_constants::kEntryOverhead;
return grpc_metadata_batch::Parse(key->string_view(), return grpc_metadata_batch::Parse(
std::move(value_slice), transport_size); key->string_view(), std::move(value_slice), transport_size,
[key_string](absl::string_view error, const Slice& value) {
ReportMetadataParseError(key_string, error, value.as_string_view());
});
} }
// Parse an index encoded key and a string encoded value // Parse an index encoded key and a string encoded value
@ -1143,7 +1146,11 @@ class HPackParser::Parser {
} }
auto value = ParseValueString(elem->is_binary_header()); auto value = ParseValueString(elem->is_binary_header());
if (GPR_UNLIKELY(!value.has_value())) return {}; if (GPR_UNLIKELY(!value.has_value())) return {};
return elem->WithNewValue(value->Take<TakeValueType>()); return elem->WithNewValue(value->Take<TakeValueType>(),
[=](absl::string_view error, const Slice& value) {
ReportMetadataParseError(
elem->key(), error, value.as_string_view());
});
} }
// Parse a varint index encoded key and a string encoded value // Parse a varint index encoded key and a string encoded value
@ -1230,6 +1237,14 @@ class HPackParser::Parser {
false); false);
} }
static void ReportMetadataParseError(absl::string_view key,
absl::string_view error,
absl::string_view value) {
gpr_log(
GPR_ERROR, "Error parsing metadata: %s",
absl::StrCat("error=", error, " key=", key, " value=", value).c_str());
}
Input* const input_; Input* const input_;
grpc_metadata_batch* const metadata_buffer_; grpc_metadata_batch* const metadata_buffer_;
HPackTable* const table_; HPackTable* const table_;

@ -71,7 +71,13 @@ class HPackTable {
struct StaticMementos { struct StaticMementos {
StaticMementos() { StaticMementos() {
for (uint32_t i = 0; i < hpack_constants::kLastStaticEntry; i++) { for (uint32_t i = 0; i < hpack_constants::kLastStaticEntry; i++) {
memento[i] = Memento(g_static_mdelem_manifested[i]); const grpc_mdelem_data& sm = g_static_mdelem_table[i].data();
memento[i] = grpc_metadata_batch::Parse(
StringViewFromSlice(sm.key),
Slice(grpc_slice_ref_internal(sm.value)),
GRPC_SLICE_LENGTH(sm.key) + GRPC_SLICE_LENGTH(sm.value) +
hpack_constants::kEntryOverhead,
[](absl::string_view, const Slice&) {});
} }
} }
Memento memento[hpack_constants::kLastStaticEntry]; Memento memento[hpack_constants::kLastStaticEntry];

@ -570,6 +570,14 @@ class StreamWriteContext {
grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, 0, true, grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, 0, true,
&s_->stats.outgoing, &t_->outbuf); &s_->stats.outgoing, &t_->outbuf);
} else { } else {
if (send_status_.has_value()) {
s_->send_trailing_metadata->Set(grpc_core::HttpStatusMetadata(),
*send_status_);
}
if (send_content_type_.has_value()) {
s_->send_trailing_metadata->Set(grpc_core::ContentTypeMetadata(),
*send_content_type_);
}
t_->hpack_compressor.EncodeHeaders( t_->hpack_compressor.EncodeHeaders(
grpc_core::HPackCompressor::EncodeHeaderOptions{ grpc_core::HPackCompressor::EncodeHeaderOptions{
s_->id, true, s_->id, true,
@ -580,12 +588,7 @@ class StreamWriteContext {
t_->settings[GRPC_PEER_SETTINGS] t_->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
&s_->stats.outgoing}, &s_->stats.outgoing},
grpc_core::ConcatMetadata( *s_->send_trailing_metadata, &t_->outbuf);
grpc_core::MetadataArray(
extra_headers_for_trailing_metadata_,
num_extra_headers_for_trailing_metadata_),
*s_->send_trailing_metadata),
&t_->outbuf);
} }
write_context_->IncTrailingMetadataWrites(); write_context_->IncTrailingMetadataWrites();
grpc_chttp2_reset_ping_clock(t_); grpc_chttp2_reset_ping_clock(t_);
@ -605,18 +608,10 @@ class StreamWriteContext {
gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)")); gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
// When sending Trailers-Only, we need to move the :status and // When sending Trailers-Only, we need to move the :status and
// content-type headers to the trailers. // content-type headers to the trailers.
if (s_->send_initial_metadata->legacy_index()->named.status != nullptr) { send_status_ =
extra_headers_for_trailing_metadata_ s_->send_initial_metadata->get(grpc_core::HttpStatusMetadata());
[num_extra_headers_for_trailing_metadata_++] = send_content_type_ =
&s_->send_initial_metadata->legacy_index()->named.status->md; s_->send_initial_metadata->get(grpc_core::ContentTypeMetadata());
}
if (s_->send_initial_metadata->legacy_index()->named.content_type !=
nullptr) {
extra_headers_for_trailing_metadata_
[num_extra_headers_for_trailing_metadata_++] =
&s_->send_initial_metadata->legacy_index()
->named.content_type->md;
}
} }
void SentLastFrame() { void SentLastFrame() {
@ -641,8 +636,9 @@ class StreamWriteContext {
grpc_chttp2_transport* const t_; grpc_chttp2_transport* const t_;
grpc_chttp2_stream* const s_; grpc_chttp2_stream* const s_;
bool stream_became_writable_ = false; bool stream_became_writable_ = false;
grpc_mdelem* extra_headers_for_trailing_metadata_[2]; absl::optional<uint32_t> send_status_;
size_t num_extra_headers_for_trailing_metadata_ = 0; absl::optional<grpc_core::ContentTypeMetadata::ValueType> send_content_type_ =
{};
}; };
} // namespace } // namespace

@ -417,7 +417,14 @@ static void convert_cronet_array_to_metadata(
value = grpc_slice_intern( value = grpc_slice_intern(
grpc_slice_from_static_string(header_array->headers[i].value)); grpc_slice_from_static_string(header_array->headers[i].value));
} }
mds->Append(header_array->headers[i].key, grpc_core::Slice(value)); mds->Append(header_array->headers[i].key, grpc_core::Slice(value),
[&](absl::string_view error, const grpc_core::Slice& value) {
gpr_log(GPR_DEBUG, "Failed to parse metadata: %s",
absl::StrCat("key=", header_array->headers[i].key,
" error=", error,
" value=", value.as_string_view())
.c_str());
});
} }
} }
@ -723,6 +730,38 @@ class CronetMetadataEncoder {
GRPC_MDELEM_UNREF(mdelem); GRPC_MDELEM_UNREF(mdelem);
} }
void Encode(grpc_core::HttpSchemeMetadata,
grpc_core::HttpSchemeMetadata::ValueType) {
/* Cronet populates these fields on its own */
}
void Encode(grpc_core::HttpAuthorityMetadata,
const grpc_core::HttpAuthorityMetadata::ValueType&) {
/* Cronet populates these fields on its own */
}
void Encode(grpc_core::HttpMethodMetadata,
grpc_core::HttpMethodMetadata::ValueType method) {
switch (method) {
case grpc_core::HttpMethodMetadata::kPost:
*method_ = "POST";
break;
case grpc_core::HttpMethodMetadata::kPut:
*method_ = "PUT";
break;
case grpc_core::HttpMethodMetadata::kGet:
*method_ = "GET";
break;
case grpc_core::HttpMethodMetadata::kInvalid:
abort();
}
}
void Encode(grpc_core::HttpPathMetadata,
const grpc_core::HttpPathMetadata::ValueType& path) {
/* Create URL by appending :path value to the hostname */
*url_ = absl::StrCat("https://", host_, path.as_string_view());
}
void Encode(grpc_mdelem mdelem) { void Encode(grpc_mdelem mdelem) {
char* key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem)); char* key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem));
char* value; char* value;
@ -733,32 +772,6 @@ class CronetMetadataEncoder {
} else { } else {
value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem)); value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem));
} }
if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_SCHEME) ||
grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem),
GRPC_MDSTR_AUTHORITY)) {
/* Cronet populates these fields on its own */
gpr_free(key);
gpr_free(value);
return;
}
if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_METHOD)) {
if (grpc_slice_eq_static_interned(GRPC_MDVALUE(mdelem), GRPC_MDSTR_PUT)) {
*method_ = "PUT";
} else {
/* POST method in default*/
*method_ = "POST";
}
gpr_free(key);
gpr_free(value);
return;
}
if (grpc_slice_eq_static_interned(GRPC_MDKEY(mdelem), GRPC_MDSTR_PATH)) {
/* Create URL by appending :path value to the hostname */
*url_ = absl::StrCat("https://", host_, value);
gpr_free(key);
gpr_free(value);
return;
}
CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value); CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value);
GPR_ASSERT(count_ < capacity_); GPR_ASSERT(count_ < capacity_);
headers_[count_].key = key; headers_[count_].key = key;
@ -801,13 +814,7 @@ static void parse_grpc_header(const uint8_t* data, int* length,
} }
static bool header_has_authority(const grpc_metadata_batch* b) { static bool header_has_authority(const grpc_metadata_batch* b) {
bool found = false; return b->get_pointer(grpc_core::HttpAuthorityMetadata()) != nullptr;
b->ForEach([&](grpc_mdelem elem) {
if (grpc_slice_eq_static_interned(GRPC_MDKEY(elem), GRPC_MDSTR_AUTHORITY)) {
found = true;
}
});
return found;
} }
/* /*

@ -1097,19 +1097,19 @@ ServerConfigSelector::CallConfig XdsServerConfigFetcher::ListenerWatcher::
FilterChainMatchManager::XdsServerConfigSelector::GetCallConfig( FilterChainMatchManager::XdsServerConfigSelector::GetCallConfig(
grpc_metadata_batch* metadata) { grpc_metadata_batch* metadata) {
CallConfig call_config; CallConfig call_config;
if (metadata->legacy_index()->named.path == nullptr) { if (metadata->get_pointer(HttpPathMetadata()) == nullptr) {
call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No path found"); call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No path found");
return call_config; return call_config;
} }
absl::string_view path = StringViewFromSlice( absl::string_view path =
GRPC_MDVALUE(metadata->legacy_index()->named.path->md)); metadata->get_pointer(HttpPathMetadata())->as_string_view();
if (metadata->legacy_index()->named.authority == nullptr) { if (metadata->get_pointer(HttpAuthorityMetadata()) == nullptr) {
call_config.error = call_config.error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No authority found"); GRPC_ERROR_CREATE_FROM_STATIC_STRING("No authority found");
return call_config; return call_config;
} }
absl::string_view authority = StringViewFromSlice( absl::string_view authority =
GRPC_MDVALUE(metadata->legacy_index()->named.authority->md)); metadata->get_pointer(HttpAuthorityMetadata())->as_string_view();
auto vhost_index = XdsRouting::FindVirtualHostForDomain( auto vhost_index = XdsRouting::FindVirtualHostForDomain(
VirtualHostListIterator(&virtual_hosts_), authority); VirtualHostListIterator(&virtual_hosts_), authority);
if (!vhost_index.has_value()) { if (!vhost_index.has_value()) {

@ -81,14 +81,13 @@ EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context,
} }
absl::string_view EvaluateArgs::GetPath() const { absl::string_view EvaluateArgs::GetPath() const {
absl::string_view path; if (metadata_ != nullptr) {
if (metadata_ != nullptr && const auto* path = metadata_->get_pointer(HttpPathMetadata());
metadata_->legacy_index()->named.path != nullptr) { if (path != nullptr) {
grpc_linked_mdelem* elem = metadata_->legacy_index()->named.path; return path->as_string_view();
const grpc_slice& val = GRPC_MDVALUE(elem->md); }
path = StringViewFromSlice(val);
} }
return path; return absl::string_view();
} }
absl::string_view EvaluateArgs::GetHost() const { absl::string_view EvaluateArgs::GetHost() const {
@ -102,14 +101,13 @@ absl::string_view EvaluateArgs::GetHost() const {
} }
absl::string_view EvaluateArgs::GetMethod() const { absl::string_view EvaluateArgs::GetMethod() const {
absl::string_view method; if (metadata_ != nullptr) {
if (metadata_ != nullptr && auto method_md = metadata_->get(HttpMethodMetadata());
metadata_->legacy_index()->named.method != nullptr) { if (method_md.has_value()) {
grpc_linked_mdelem* elem = metadata_->legacy_index()->named.method; return HttpMethodMetadata::Encode(*method_md).as_string_view();
const grpc_slice& val = GRPC_MDVALUE(elem->md); }
method = StringViewFromSlice(val); }
} return absl::string_view();
return method;
} }
absl::optional<absl::string_view> EvaluateArgs::GetHeaderValue( absl::optional<absl::string_view> EvaluateArgs::GetHeaderValue(

@ -65,6 +65,8 @@ struct channel_data {
struct call_data { struct call_data {
call_data(grpc_call_element* elem, const grpc_call_element_args& args) call_data(grpc_call_element* elem, const grpc_call_element_args& args)
: owning_call(args.call_stack), call_combiner(args.call_combiner) { : owning_call(args.call_stack), call_combiner(args.call_combiner) {
host.Init();
method.Init();
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
GPR_ASSERT(args.context != nullptr); GPR_ASSERT(args.context != nullptr);
if (args.context[GRPC_CONTEXT_SECURITY].value == nullptr) { if (args.context[GRPC_CONTEXT_SECURITY].value == nullptr) {
@ -89,16 +91,16 @@ struct call_data {
void destroy() { void destroy() {
grpc_credentials_mdelem_array_destroy(&md_array); grpc_credentials_mdelem_array_destroy(&md_array);
creds.reset(); creds.reset();
grpc_slice_unref_internal(host);
grpc_slice_unref_internal(method);
grpc_auth_metadata_context_reset(&auth_md_context); grpc_auth_metadata_context_reset(&auth_md_context);
host.Destroy();
method.Destroy();
} }
grpc_call_stack* owning_call; grpc_call_stack* owning_call;
grpc_core::CallCombiner* call_combiner; grpc_core::CallCombiner* call_combiner;
grpc_core::RefCountedPtr<grpc_call_credentials> creds; grpc_core::RefCountedPtr<grpc_call_credentials> creds;
grpc_slice host = grpc_empty_slice(); grpc_core::ManualConstructor<grpc_core::Slice> host;
grpc_slice method = grpc_empty_slice(); grpc_core::ManualConstructor<grpc_core::Slice> method;
/* pollset{_set} bound to this call; if we need to make external /* pollset{_set} bound to this call; if we need to make external
network requests, they should be done under a pollset added to this network requests, they should be done under a pollset added to this
pollset_set so that work can progress when this call wants work to progress pollset_set so that work can progress when this call wants work to progress
@ -304,8 +306,9 @@ static void send_security_metadata(grpc_call_element* elem,
} }
grpc_auth_metadata_context_build( grpc_auth_metadata_context_build(
chand->security_connector->url_scheme(), calld->host, calld->method, chand->security_connector->url_scheme(), calld->host->c_slice(),
chand->auth_context.get(), &calld->auth_md_context); calld->method->c_slice(), chand->auth_context.get(),
&calld->auth_md_context);
GPR_ASSERT(calld->pollent != nullptr); GPR_ASSERT(calld->pollent != nullptr);
GRPC_CALL_STACK_REF(calld->owning_call, "get_request_metadata"); GRPC_CALL_STACK_REF(calld->owning_call, "get_request_metadata");
@ -340,11 +343,11 @@ static void on_host_checked(void* arg, grpc_error_handle error) {
} else { } else {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
batch, batch,
grpc_error_set_int( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat( "Invalid host ", calld->host->as_string_view(),
"Invalid host ", grpc_core::StringViewFromSlice(calld->host), " set in :authority metadata.")),
" set in :authority metadata.")), GRPC_ERROR_INT_GRPC_STATUS,
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED), GRPC_STATUS_UNAUTHENTICATED),
calld->call_combiner); calld->call_combiner);
} }
GRPC_CALL_STACK_UNREF(calld->owning_call, "check_call_host"); GRPC_CALL_STACK_UNREF(calld->owning_call, "check_call_host");
@ -372,18 +375,18 @@ static void client_auth_start_transport_stream_op_batch(
if (batch->send_initial_metadata) { if (batch->send_initial_metadata) {
grpc_metadata_batch* metadata = grpc_metadata_batch* metadata =
batch->payload->send_initial_metadata.send_initial_metadata; batch->payload->send_initial_metadata.send_initial_metadata;
if (metadata->legacy_index()->named.path != nullptr) { if (metadata->get_pointer(grpc_core::HttpPathMetadata()) != nullptr) {
calld->method = grpc_slice_ref_internal( *calld->method =
GRPC_MDVALUE(metadata->legacy_index()->named.path->md)); metadata->get_pointer(grpc_core::HttpPathMetadata())->Ref();
} }
if (metadata->legacy_index()->named.authority != nullptr) { if (metadata->get_pointer(grpc_core::HttpAuthorityMetadata()) != nullptr) {
calld->host = grpc_slice_ref_internal( *calld->host =
GRPC_MDVALUE(metadata->legacy_index()->named.authority->md)); metadata->get_pointer(grpc_core::HttpAuthorityMetadata())->Ref();
batch->handler_private.extra_arg = elem; batch->handler_private.extra_arg = elem;
GRPC_CALL_STACK_REF(calld->owning_call, "check_call_host"); GRPC_CALL_STACK_REF(calld->owning_call, "check_call_host");
GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch, GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
absl::string_view call_host(grpc_core::StringViewFromSlice(calld->host)); absl::string_view call_host = calld->host->as_string_view();
grpc_error_handle error = GRPC_ERROR_NONE; grpc_error_handle error = GRPC_ERROR_NONE;
if (chand->security_connector->check_call_host( if (chand->security_connector->check_call_host(
call_host, chand->auth_context.get(), call_host, chand->auth_context.get(),

@ -328,6 +328,11 @@ class Slice : public slice_detail::BaseSlice,
return Slice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n)); return Slice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n));
} }
// Return a sub slice of this one. Adds a reference to the underlying slice.
Slice RefSubSlice(size_t pos, size_t n) const {
return Slice(grpc_slice_sub(c_slice(), pos, pos + n));
}
Slice Ref() const { return Slice(grpc_slice_ref_internal(c_slice())); } Slice Ref() const { return Slice(grpc_slice_ref_internal(c_slice())); }
Slice Copy() const { return Slice(grpc_slice_copy(c_slice())); } Slice Copy() const { return Slice(grpc_slice_copy(c_slice())); }

@ -30,59 +30,59 @@
namespace grpc_core { namespace grpc_core {
const uint8_t g_static_metadata_bytes[] = { const uint8_t g_static_metadata_bytes[] = {
58, 112, 97, 116, 104, 58, 109, 101, 116, 104, 111, 100, 58, 115, 116, 103, 114, 112, 99, 45, 101, 110, 99, 111, 100, 105, 110, 103, 103, 114,
97, 116, 117, 115, 58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 58, 112, 99, 45, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, 111, 100,
115, 99, 104, 101, 109, 101, 103, 114, 112, 99, 45, 101, 110, 99, 111, 105, 110, 103, 99, 111, 110, 116, 101, 110, 116, 45, 101, 110, 99, 111,
100, 105, 110, 103, 103, 114, 112, 99, 45, 97, 99, 99, 101, 112, 116, 100, 105, 110, 103, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, 111,
45, 101, 110, 99, 111, 100, 105, 110, 103, 99, 111, 110, 116, 101, 110, 100, 105, 110, 103, 103, 114, 112, 99, 45, 105, 110, 116, 101, 114, 110,
116, 45, 116, 121, 112, 101, 99, 111, 110, 116, 101, 110, 116, 45, 101, 97, 108, 45, 101, 110, 99, 111, 100, 105, 110, 103, 45, 114, 101, 113,
110, 99, 111, 100, 105, 110, 103, 97, 99, 99, 101, 112, 116, 45, 101, 117, 101, 115, 116, 103, 114, 112, 99, 45, 116, 105, 109, 101, 111, 117,
110, 99, 111, 100, 105, 110, 103, 103, 114, 112, 99, 45, 105, 110, 116, 116, 47, 103, 114, 112, 99, 46, 108, 98, 46, 118, 49, 46, 76, 111,
101, 114, 110, 97, 108, 45, 101, 110, 99, 111, 100, 105, 110, 103, 45, 97, 100, 66, 97, 108, 97, 110, 99, 101, 114, 47, 66, 97, 108, 97,
114, 101, 113, 117, 101, 115, 116, 103, 114, 112, 99, 45, 116, 105, 109, 110, 99, 101, 76, 111, 97, 100, 47, 101, 110, 118, 111, 121, 46, 115,
101, 111, 117, 116, 47, 103, 114, 112, 99, 46, 108, 98, 46, 118, 49, 101, 114, 118, 105, 99, 101, 46, 108, 111, 97, 100, 95, 115, 116, 97,
46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99, 101, 114, 47, 66, 116, 115, 46, 118, 50, 46, 76, 111, 97, 100, 82, 101, 112, 111, 114,
97, 108, 97, 110, 99, 101, 76, 111, 97, 100, 47, 101, 110, 118, 111, 116, 105, 110, 103, 83, 101, 114, 118, 105, 99, 101, 47, 83, 116, 114,
121, 46, 115, 101, 114, 118, 105, 99, 101, 46, 108, 111, 97, 100, 95, 101, 97, 109, 76, 111, 97, 100, 83, 116, 97, 116, 115, 47, 101, 110,
115, 116, 97, 116, 115, 46, 118, 50, 46, 76, 111, 97, 100, 82, 101, 118, 111, 121, 46, 115, 101, 114, 118, 105, 99, 101, 46, 108, 111, 97,
112, 111, 114, 116, 105, 110, 103, 83, 101, 114, 118, 105, 99, 101, 47, 100, 95, 115, 116, 97, 116, 115, 46, 118, 51, 46, 76, 111, 97, 100,
83, 116, 114, 101, 97, 109, 76, 111, 97, 100, 83, 116, 97, 116, 115, 82, 101, 112, 111, 114, 116, 105, 110, 103, 83, 101, 114, 118, 105, 99,
101, 47, 83, 116, 114, 101, 97, 109, 76, 111, 97, 100, 83, 116, 97,
116, 115, 47, 103, 114, 112, 99, 46, 104, 101, 97, 108, 116, 104, 46,
118, 49, 46, 72, 101, 97, 108, 116, 104, 47, 87, 97, 116, 99, 104,
47, 101, 110, 118, 111, 121, 46, 115, 101, 114, 118, 105, 99, 101, 46, 47, 101, 110, 118, 111, 121, 46, 115, 101, 114, 118, 105, 99, 101, 46,
108, 111, 97, 100, 95, 115, 116, 97, 116, 115, 46, 118, 51, 46, 76, 100, 105, 115, 99, 111, 118, 101, 114, 121, 46, 118, 50, 46, 65, 103,
111, 97, 100, 82, 101, 112, 111, 114, 116, 105, 110, 103, 83, 101, 114, 103, 114, 101, 103, 97, 116, 101, 100, 68, 105, 115, 99, 111, 118, 101,
118, 105, 99, 101, 47, 83, 116, 114, 101, 97, 109, 76, 111, 97, 100, 114, 121, 83, 101, 114, 118, 105, 99, 101, 47, 83, 116, 114, 101, 97,
83, 116, 97, 116, 115, 47, 103, 114, 112, 99, 46, 104, 101, 97, 108, 109, 65, 103, 103, 114, 101, 103, 97, 116, 101, 100, 82, 101, 115, 111,
116, 104, 46, 118, 49, 46, 72, 101, 97, 108, 116, 104, 47, 87, 97, 117, 114, 99, 101, 115, 47, 101, 110, 118, 111, 121, 46, 115, 101, 114,
116, 99, 104, 47, 101, 110, 118, 111, 121, 46, 115, 101, 114, 118, 105, 118, 105, 99, 101, 46, 100, 105, 115, 99, 111, 118, 101, 114, 121, 46,
99, 101, 46, 100, 105, 115, 99, 111, 118, 101, 114, 121, 46, 118, 50, 118, 51, 46, 65, 103, 103, 114, 101, 103, 97, 116, 101, 100, 68, 105,
46, 65, 103, 103, 114, 101, 103, 97, 116, 101, 100, 68, 105, 115, 99, 115, 99, 111, 118, 101, 114, 121, 83, 101, 114, 118, 105, 99, 101, 47,
111, 118, 101, 114, 121, 83, 101, 114, 118, 105, 99, 101, 47, 83, 116, 83, 116, 114, 101, 97, 109, 65, 103, 103, 114, 101, 103, 97, 116, 101,
114, 101, 97, 109, 65, 103, 103, 114, 101, 103, 97, 116, 101, 100, 82, 100, 82, 101, 115, 111, 117, 114, 99, 101, 115, 100, 101, 102, 108, 97,
101, 115, 111, 117, 114, 99, 101, 115, 47, 101, 110, 118, 111, 121, 46, 116, 101, 103, 122, 105, 112, 115, 116, 114, 101, 97, 109, 47, 103, 122,
115, 101, 114, 118, 105, 99, 101, 46, 100, 105, 115, 99, 111, 118, 101, 105, 112, 116, 101, 116, 114, 97, 105, 108, 101, 114, 115, 58, 97, 117,
114, 121, 46, 118, 51, 46, 65, 103, 103, 114, 101, 103, 97, 116, 101, 116, 104, 111, 114, 105, 116, 121, 58, 109, 101, 116, 104, 111, 100, 71,
100, 68, 105, 115, 99, 111, 118, 101, 114, 121, 83, 101, 114, 118, 105, 69, 84, 80, 79, 83, 84, 58, 112, 97, 116, 104, 47, 47, 105, 110,
99, 101, 47, 83, 116, 114, 101, 97, 109, 65, 103, 103, 114, 101, 103, 100, 101, 120, 46, 104, 116, 109, 108, 58, 115, 99, 104, 101, 109, 101,
97, 116, 101, 100, 82, 101, 115, 111, 117, 114, 99, 101, 115, 100, 101, 104, 116, 116, 112, 104, 116, 116, 112, 115, 58, 115, 116, 97, 116, 117,
102, 108, 97, 116, 101, 103, 122, 105, 112, 115, 116, 114, 101, 97, 109, 115, 50, 48, 48, 50, 48, 52, 50, 48, 54, 51, 48, 52, 52, 48,
47, 103, 122, 105, 112, 116, 101, 116, 114, 97, 105, 108, 101, 114, 115, 48, 52, 48, 52, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, 99,
71, 69, 84, 80, 79, 83, 84, 47, 47, 105, 110, 100, 101, 120, 46, 104, 97, 114, 115, 101, 116, 103, 122, 105, 112, 44, 32, 100, 101, 102,
104, 116, 109, 108, 104, 116, 116, 112, 104, 116, 116, 112, 115, 50, 48, 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, 103,
48, 50, 48, 52, 50, 48, 54, 51, 48, 52, 52, 48, 48, 52, 48, 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, 103,
52, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, 99, 104, 97, 114, 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, 45,
115, 101, 116, 103, 122, 105, 112, 44, 32, 100, 101, 102, 108, 97, 116, 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, 111,
101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, 103, 117, 97, 103, 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, 117,
101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, 103, 101, 115, 97, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104,
99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, 45, 99, 111, 110, 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110,
116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, 111, 114, 105, 103, 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111,
105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, 117, 116, 104, 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 99,
114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104, 101, 45, 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99, 111,
111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110, 116, 45, 100, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110, 99,
105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111, 110, 116, 101, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111, 110,
110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 99, 111, 110, 116, 116, 101, 110, 116, 45, 116, 121, 112, 101, 99, 111, 111, 107, 105, 101,
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, 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, 104, 111, 115, 116, 105, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 104, 111, 115, 116, 105,
102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100, 105, 102, 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100, 105, 102,
@ -102,14 +102,13 @@ const uint8_t g_static_metadata_bytes[] = {
114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, 100, 105, 110, 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, 100, 105, 110,
103, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 118, 97, 114, 121, 103, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 118, 97, 114, 121,
118, 105, 97, 119, 119, 119, 45, 97, 117, 116, 104, 101, 110, 116, 105, 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, 97, 112, 112, 99, 97, 116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 103, 114, 112,
108, 105, 99, 97, 116, 105, 111, 110, 47, 103, 114, 112, 99, 103, 114, 99, 80, 85, 84, 108, 98, 45, 99, 111, 115, 116, 45, 98, 105, 110,
112, 99, 80, 85, 84, 108, 98, 45, 99, 111, 115, 116, 45, 98, 105, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116,
110, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, 103, 122, 105, 112, 100,
116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, 103, 122, 105, 112, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112, 105, 100, 101, 110,
100, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112, 105, 100, 101, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 44, 103, 122,
110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 44, 103, 105, 112};
122, 105, 112};
grpc_slice_refcount StaticSliceRefcount::kStaticSubRefcount; grpc_slice_refcount StaticSliceRefcount::kStaticSubRefcount;
@ -161,116 +160,115 @@ StaticSliceRefcount g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT] =
StaticSliceRefcount(84), StaticSliceRefcount(85), StaticSliceRefcount(84), StaticSliceRefcount(85),
StaticSliceRefcount(86), StaticSliceRefcount(87), StaticSliceRefcount(86), StaticSliceRefcount(87),
StaticSliceRefcount(88), StaticSliceRefcount(89), StaticSliceRefcount(88), StaticSliceRefcount(89),
StaticSliceRefcount(90),
}; };
const StaticMetadataSlice const StaticMetadataSlice
g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT] = { g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 13,
g_static_metadata_bytes + 0), g_static_metadata_bytes + 0),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 5), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 16,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 33),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 10, StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 15,
g_static_metadata_bytes + 19),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7,
g_static_metadata_bytes + 29),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 13,
g_static_metadata_bytes + 36),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 30,
g_static_metadata_bytes + 69), g_static_metadata_bytes + 64),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 12,
g_static_metadata_bytes + 81), g_static_metadata_bytes + 94),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 15, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 97), g_static_metadata_bytes + 106),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 30, StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 36,
g_static_metadata_bytes + 112), g_static_metadata_bytes + 106),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[11].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 65,
g_static_metadata_bytes + 142), g_static_metadata_bytes + 142),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 65,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 207),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[13].base, 36, StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 28,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 272),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 65, StaticMetadataSlice(&g_static_metadata_slice_refcounts[11].base, 80,
g_static_metadata_bytes + 190), g_static_metadata_bytes + 300),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[15].base, 65, StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 80,
g_static_metadata_bytes + 255), g_static_metadata_bytes + 380),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[16].base, 28, StaticMetadataSlice(&g_static_metadata_slice_refcounts[13].base, 7,
g_static_metadata_bytes + 320), g_static_metadata_bytes + 460),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[17].base, 80, StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 4,
g_static_metadata_bytes + 348), g_static_metadata_bytes + 467),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[18].base, 80, StaticMetadataSlice(&g_static_metadata_slice_refcounts[15].base, 11,
g_static_metadata_bytes + 428), g_static_metadata_bytes + 471),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[16].base, 2,
g_static_metadata_bytes + 482),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[17].base, 8,
g_static_metadata_bytes + 484),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[18].base, 10,
g_static_metadata_bytes + 492),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7,
g_static_metadata_bytes + 508), g_static_metadata_bytes + 502),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 3,
g_static_metadata_bytes + 515), g_static_metadata_bytes + 509),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[21].base, 11, StaticMetadataSlice(&g_static_metadata_slice_refcounts[21].base, 4,
g_static_metadata_bytes + 519), g_static_metadata_bytes + 512),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[22].base, 2, StaticMetadataSlice(&g_static_metadata_slice_refcounts[22].base, 5,
g_static_metadata_bytes + 530), g_static_metadata_bytes + 516),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[23].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[23].base, 1,
g_static_metadata_bytes + 532), g_static_metadata_bytes + 521),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[24].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[24].base, 11,
g_static_metadata_bytes + 522),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 7,
g_static_metadata_bytes + 533),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 4,
g_static_metadata_bytes + 540), g_static_metadata_bytes + 540),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 5,
g_static_metadata_bytes + 543), g_static_metadata_bytes + 544),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 1, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 547), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 11, StaticMetadataSlice(&g_static_metadata_slice_refcounts[29].base, 3,
g_static_metadata_bytes + 548), g_static_metadata_bytes + 556),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 4,
g_static_metadata_bytes + 559),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[29].base, 5,
g_static_metadata_bytes + 563),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[30].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[30].base, 3,
g_static_metadata_bytes + 568), g_static_metadata_bytes + 559),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[31].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[31].base, 3,
g_static_metadata_bytes + 571), g_static_metadata_bytes + 562),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[32].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[32].base, 3,
g_static_metadata_bytes + 574), g_static_metadata_bytes + 565),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[33].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[33].base, 3,
g_static_metadata_bytes + 577), g_static_metadata_bytes + 568),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[34].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[34].base, 3,
g_static_metadata_bytes + 580), g_static_metadata_bytes + 571),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[35].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[35].base, 3,
g_static_metadata_bytes + 583), g_static_metadata_bytes + 574),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[36].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[36].base, 14,
g_static_metadata_bytes + 586), g_static_metadata_bytes + 577),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[37].base, 14, StaticMetadataSlice(&g_static_metadata_slice_refcounts[37].base, 13,
g_static_metadata_bytes + 589), g_static_metadata_bytes + 591),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[38].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[38].base, 15,
g_static_metadata_bytes + 603), g_static_metadata_bytes + 604),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[39].base, 15, StaticMetadataSlice(&g_static_metadata_slice_refcounts[39].base, 13,
g_static_metadata_bytes + 616), g_static_metadata_bytes + 619),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[40].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[40].base, 6,
g_static_metadata_bytes + 631), g_static_metadata_bytes + 632),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[41].base, 6, StaticMetadataSlice(&g_static_metadata_slice_refcounts[41].base, 27,
g_static_metadata_bytes + 644), g_static_metadata_bytes + 638),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[42].base, 27, StaticMetadataSlice(&g_static_metadata_slice_refcounts[42].base, 3,
g_static_metadata_bytes + 650), g_static_metadata_bytes + 665),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[43].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[43].base, 5,
g_static_metadata_bytes + 677), g_static_metadata_bytes + 668),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[44].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[44].base, 13,
g_static_metadata_bytes + 680), g_static_metadata_bytes + 673),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[45].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[45].base, 13,
g_static_metadata_bytes + 685), g_static_metadata_bytes + 686),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[46].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[46].base, 19,
g_static_metadata_bytes + 698), g_static_metadata_bytes + 699),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[47].base, 19, StaticMetadataSlice(&g_static_metadata_slice_refcounts[47].base, 16,
g_static_metadata_bytes + 711), g_static_metadata_bytes + 718),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[48].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[48].base, 14,
g_static_metadata_bytes + 730), g_static_metadata_bytes + 734),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[49].base, 14, StaticMetadataSlice(&g_static_metadata_slice_refcounts[49].base, 16,
g_static_metadata_bytes + 746), g_static_metadata_bytes + 748),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[50].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[50].base, 13,
g_static_metadata_bytes + 760), g_static_metadata_bytes + 764),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[51].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[51].base, 12,
g_static_metadata_bytes + 776), g_static_metadata_bytes + 777),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[52].base, 6, StaticMetadataSlice(&g_static_metadata_slice_refcounts[52].base, 6,
g_static_metadata_bytes + 789), g_static_metadata_bytes + 789),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[53].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[53].base, 4,
@ -333,21 +331,19 @@ const StaticMetadataSlice
g_static_metadata_bytes + 1068), g_static_metadata_bytes + 1068),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8,
g_static_metadata_bytes + 1084), g_static_metadata_bytes + 1084),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[83].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[83].base, 4,
g_static_metadata_bytes + 1092), g_static_metadata_bytes + 1092),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[84].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[84].base, 3,
g_static_metadata_bytes + 1108), g_static_metadata_bytes + 1096),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[85].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[85].base, 11,
g_static_metadata_bytes + 1112), g_static_metadata_bytes + 1099),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[86].base, 11, StaticMetadataSlice(&g_static_metadata_slice_refcounts[86].base, 16,
g_static_metadata_bytes + 1115), g_static_metadata_bytes + 1110),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 13,
g_static_metadata_bytes + 1126), g_static_metadata_bytes + 1126),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 12,
g_static_metadata_bytes + 1142), g_static_metadata_bytes + 1139),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[89].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[89].base, 21,
g_static_metadata_bytes + 1155), g_static_metadata_bytes + 1151),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 21,
g_static_metadata_bytes + 1167),
}; };
} // namespace grpc_core } // namespace grpc_core

@ -38,137 +38,137 @@
static_assert( static_assert(
std::is_trivially_destructible<grpc_core::StaticMetadataSlice>::value, std::is_trivially_destructible<grpc_core::StaticMetadataSlice>::value,
"StaticMetadataSlice must be trivially destructible."); "StaticMetadataSlice must be trivially destructible.");
#define GRPC_STATIC_MDSTR_COUNT 91 #define GRPC_STATIC_MDSTR_COUNT 90
/* ":path" */
#define GRPC_MDSTR_PATH (::grpc_core::g_static_metadata_slice_table[0])
/* ":method" */
#define GRPC_MDSTR_METHOD (::grpc_core::g_static_metadata_slice_table[1])
/* ":status" */
#define GRPC_MDSTR_STATUS (::grpc_core::g_static_metadata_slice_table[2])
/* ":authority" */
#define GRPC_MDSTR_AUTHORITY (::grpc_core::g_static_metadata_slice_table[3])
/* ":scheme" */
#define GRPC_MDSTR_SCHEME (::grpc_core::g_static_metadata_slice_table[4])
/* "grpc-encoding" */ /* "grpc-encoding" */
#define GRPC_MDSTR_GRPC_ENCODING (::grpc_core::g_static_metadata_slice_table[5]) #define GRPC_MDSTR_GRPC_ENCODING (::grpc_core::g_static_metadata_slice_table[0])
/* "grpc-accept-encoding" */ /* "grpc-accept-encoding" */
#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING \ #define GRPC_MDSTR_GRPC_ACCEPT_ENCODING \
(::grpc_core::g_static_metadata_slice_table[6]) (::grpc_core::g_static_metadata_slice_table[1])
/* "content-type" */
#define GRPC_MDSTR_CONTENT_TYPE (::grpc_core::g_static_metadata_slice_table[7])
/* "content-encoding" */ /* "content-encoding" */
#define GRPC_MDSTR_CONTENT_ENCODING \ #define GRPC_MDSTR_CONTENT_ENCODING \
(::grpc_core::g_static_metadata_slice_table[8]) (::grpc_core::g_static_metadata_slice_table[2])
/* "accept-encoding" */ /* "accept-encoding" */
#define GRPC_MDSTR_ACCEPT_ENCODING \ #define GRPC_MDSTR_ACCEPT_ENCODING \
(::grpc_core::g_static_metadata_slice_table[9]) (::grpc_core::g_static_metadata_slice_table[3])
/* "grpc-internal-encoding-request" */ /* "grpc-internal-encoding-request" */
#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST \ #define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST \
(::grpc_core::g_static_metadata_slice_table[10]) (::grpc_core::g_static_metadata_slice_table[4])
/* "grpc-timeout" */ /* "grpc-timeout" */
#define GRPC_MDSTR_GRPC_TIMEOUT (::grpc_core::g_static_metadata_slice_table[11]) #define GRPC_MDSTR_GRPC_TIMEOUT (::grpc_core::g_static_metadata_slice_table[5])
/* "" */ /* "" */
#define GRPC_MDSTR_EMPTY (::grpc_core::g_static_metadata_slice_table[12]) #define GRPC_MDSTR_EMPTY (::grpc_core::g_static_metadata_slice_table[6])
/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */ /* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */
#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \ #define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \
(::grpc_core::g_static_metadata_slice_table[13]) (::grpc_core::g_static_metadata_slice_table[7])
/* "/envoy.service.load_stats.v2.LoadReportingService/StreamLoadStats" */ /* "/envoy.service.load_stats.v2.LoadReportingService/StreamLoadStats" */
#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V2_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \ #define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V2_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \
(::grpc_core::g_static_metadata_slice_table[14]) (::grpc_core::g_static_metadata_slice_table[8])
/* "/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats" */ /* "/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats" */
#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \ #define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \
(::grpc_core::g_static_metadata_slice_table[15]) (::grpc_core::g_static_metadata_slice_table[9])
/* "/grpc.health.v1.Health/Watch" */ /* "/grpc.health.v1.Health/Watch" */
#define GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH \ #define GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH \
(::grpc_core::g_static_metadata_slice_table[16]) (::grpc_core::g_static_metadata_slice_table[10])
/* "/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources" /* "/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources"
*/ */
#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \ #define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \
(::grpc_core::g_static_metadata_slice_table[17]) (::grpc_core::g_static_metadata_slice_table[11])
/* "/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources" /* "/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources"
*/ */
#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V3_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \ #define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V3_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \
(::grpc_core::g_static_metadata_slice_table[18]) (::grpc_core::g_static_metadata_slice_table[12])
/* "deflate" */ /* "deflate" */
#define GRPC_MDSTR_DEFLATE (::grpc_core::g_static_metadata_slice_table[19]) #define GRPC_MDSTR_DEFLATE (::grpc_core::g_static_metadata_slice_table[13])
/* "gzip" */ /* "gzip" */
#define GRPC_MDSTR_GZIP (::grpc_core::g_static_metadata_slice_table[20]) #define GRPC_MDSTR_GZIP (::grpc_core::g_static_metadata_slice_table[14])
/* "stream/gzip" */ /* "stream/gzip" */
#define GRPC_MDSTR_STREAM_SLASH_GZIP \ #define GRPC_MDSTR_STREAM_SLASH_GZIP \
(::grpc_core::g_static_metadata_slice_table[21]) (::grpc_core::g_static_metadata_slice_table[15])
/* "te" */ /* "te" */
#define GRPC_MDSTR_TE (::grpc_core::g_static_metadata_slice_table[22]) #define GRPC_MDSTR_TE (::grpc_core::g_static_metadata_slice_table[16])
/* "trailers" */ /* "trailers" */
#define GRPC_MDSTR_TRAILERS (::grpc_core::g_static_metadata_slice_table[23]) #define GRPC_MDSTR_TRAILERS (::grpc_core::g_static_metadata_slice_table[17])
/* ":authority" */
#define GRPC_MDSTR_AUTHORITY (::grpc_core::g_static_metadata_slice_table[18])
/* ":method" */
#define GRPC_MDSTR_METHOD (::grpc_core::g_static_metadata_slice_table[19])
/* "GET" */ /* "GET" */
#define GRPC_MDSTR_GET (::grpc_core::g_static_metadata_slice_table[24]) #define GRPC_MDSTR_GET (::grpc_core::g_static_metadata_slice_table[20])
/* "POST" */ /* "POST" */
#define GRPC_MDSTR_POST (::grpc_core::g_static_metadata_slice_table[25]) #define GRPC_MDSTR_POST (::grpc_core::g_static_metadata_slice_table[21])
/* ":path" */
#define GRPC_MDSTR_PATH (::grpc_core::g_static_metadata_slice_table[22])
/* "/" */ /* "/" */
#define GRPC_MDSTR_SLASH (::grpc_core::g_static_metadata_slice_table[26]) #define GRPC_MDSTR_SLASH (::grpc_core::g_static_metadata_slice_table[23])
/* "/index.html" */ /* "/index.html" */
#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML \ #define GRPC_MDSTR_SLASH_INDEX_DOT_HTML \
(::grpc_core::g_static_metadata_slice_table[27]) (::grpc_core::g_static_metadata_slice_table[24])
/* ":scheme" */
#define GRPC_MDSTR_SCHEME (::grpc_core::g_static_metadata_slice_table[25])
/* "http" */ /* "http" */
#define GRPC_MDSTR_HTTP (::grpc_core::g_static_metadata_slice_table[28]) #define GRPC_MDSTR_HTTP (::grpc_core::g_static_metadata_slice_table[26])
/* "https" */ /* "https" */
#define GRPC_MDSTR_HTTPS (::grpc_core::g_static_metadata_slice_table[29]) #define GRPC_MDSTR_HTTPS (::grpc_core::g_static_metadata_slice_table[27])
/* ":status" */
#define GRPC_MDSTR_STATUS (::grpc_core::g_static_metadata_slice_table[28])
/* "200" */ /* "200" */
#define GRPC_MDSTR_200 (::grpc_core::g_static_metadata_slice_table[30]) #define GRPC_MDSTR_200 (::grpc_core::g_static_metadata_slice_table[29])
/* "204" */ /* "204" */
#define GRPC_MDSTR_204 (::grpc_core::g_static_metadata_slice_table[31]) #define GRPC_MDSTR_204 (::grpc_core::g_static_metadata_slice_table[30])
/* "206" */ /* "206" */
#define GRPC_MDSTR_206 (::grpc_core::g_static_metadata_slice_table[32]) #define GRPC_MDSTR_206 (::grpc_core::g_static_metadata_slice_table[31])
/* "304" */ /* "304" */
#define GRPC_MDSTR_304 (::grpc_core::g_static_metadata_slice_table[33]) #define GRPC_MDSTR_304 (::grpc_core::g_static_metadata_slice_table[32])
/* "400" */ /* "400" */
#define GRPC_MDSTR_400 (::grpc_core::g_static_metadata_slice_table[34]) #define GRPC_MDSTR_400 (::grpc_core::g_static_metadata_slice_table[33])
/* "404" */ /* "404" */
#define GRPC_MDSTR_404 (::grpc_core::g_static_metadata_slice_table[35]) #define GRPC_MDSTR_404 (::grpc_core::g_static_metadata_slice_table[34])
/* "500" */ /* "500" */
#define GRPC_MDSTR_500 (::grpc_core::g_static_metadata_slice_table[36]) #define GRPC_MDSTR_500 (::grpc_core::g_static_metadata_slice_table[35])
/* "accept-charset" */ /* "accept-charset" */
#define GRPC_MDSTR_ACCEPT_CHARSET \ #define GRPC_MDSTR_ACCEPT_CHARSET \
(::grpc_core::g_static_metadata_slice_table[37]) (::grpc_core::g_static_metadata_slice_table[36])
/* "gzip, deflate" */ /* "gzip, deflate" */
#define GRPC_MDSTR_GZIP_COMMA_DEFLATE \ #define GRPC_MDSTR_GZIP_COMMA_DEFLATE \
(::grpc_core::g_static_metadata_slice_table[38]) (::grpc_core::g_static_metadata_slice_table[37])
/* "accept-language" */ /* "accept-language" */
#define GRPC_MDSTR_ACCEPT_LANGUAGE \ #define GRPC_MDSTR_ACCEPT_LANGUAGE \
(::grpc_core::g_static_metadata_slice_table[39]) (::grpc_core::g_static_metadata_slice_table[38])
/* "accept-ranges" */ /* "accept-ranges" */
#define GRPC_MDSTR_ACCEPT_RANGES \ #define GRPC_MDSTR_ACCEPT_RANGES \
(::grpc_core::g_static_metadata_slice_table[40]) (::grpc_core::g_static_metadata_slice_table[39])
/* "accept" */ /* "accept" */
#define GRPC_MDSTR_ACCEPT (::grpc_core::g_static_metadata_slice_table[41]) #define GRPC_MDSTR_ACCEPT (::grpc_core::g_static_metadata_slice_table[40])
/* "access-control-allow-origin" */ /* "access-control-allow-origin" */
#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN \ #define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN \
(::grpc_core::g_static_metadata_slice_table[42]) (::grpc_core::g_static_metadata_slice_table[41])
/* "age" */ /* "age" */
#define GRPC_MDSTR_AGE (::grpc_core::g_static_metadata_slice_table[43]) #define GRPC_MDSTR_AGE (::grpc_core::g_static_metadata_slice_table[42])
/* "allow" */ /* "allow" */
#define GRPC_MDSTR_ALLOW (::grpc_core::g_static_metadata_slice_table[44]) #define GRPC_MDSTR_ALLOW (::grpc_core::g_static_metadata_slice_table[43])
/* "authorization" */ /* "authorization" */
#define GRPC_MDSTR_AUTHORIZATION \ #define GRPC_MDSTR_AUTHORIZATION \
(::grpc_core::g_static_metadata_slice_table[45]) (::grpc_core::g_static_metadata_slice_table[44])
/* "cache-control" */ /* "cache-control" */
#define GRPC_MDSTR_CACHE_CONTROL \ #define GRPC_MDSTR_CACHE_CONTROL \
(::grpc_core::g_static_metadata_slice_table[46]) (::grpc_core::g_static_metadata_slice_table[45])
/* "content-disposition" */ /* "content-disposition" */
#define GRPC_MDSTR_CONTENT_DISPOSITION \ #define GRPC_MDSTR_CONTENT_DISPOSITION \
(::grpc_core::g_static_metadata_slice_table[47]) (::grpc_core::g_static_metadata_slice_table[46])
/* "content-language" */ /* "content-language" */
#define GRPC_MDSTR_CONTENT_LANGUAGE \ #define GRPC_MDSTR_CONTENT_LANGUAGE \
(::grpc_core::g_static_metadata_slice_table[48]) (::grpc_core::g_static_metadata_slice_table[47])
/* "content-length" */ /* "content-length" */
#define GRPC_MDSTR_CONTENT_LENGTH \ #define GRPC_MDSTR_CONTENT_LENGTH \
(::grpc_core::g_static_metadata_slice_table[49]) (::grpc_core::g_static_metadata_slice_table[48])
/* "content-location" */ /* "content-location" */
#define GRPC_MDSTR_CONTENT_LOCATION \ #define GRPC_MDSTR_CONTENT_LOCATION \
(::grpc_core::g_static_metadata_slice_table[50]) (::grpc_core::g_static_metadata_slice_table[49])
/* "content-range" */ /* "content-range" */
#define GRPC_MDSTR_CONTENT_RANGE \ #define GRPC_MDSTR_CONTENT_RANGE \
(::grpc_core::g_static_metadata_slice_table[51]) (::grpc_core::g_static_metadata_slice_table[50])
/* "content-type" */
#define GRPC_MDSTR_CONTENT_TYPE (::grpc_core::g_static_metadata_slice_table[51])
/* "cookie" */ /* "cookie" */
#define GRPC_MDSTR_COOKIE (::grpc_core::g_static_metadata_slice_table[52]) #define GRPC_MDSTR_COOKIE (::grpc_core::g_static_metadata_slice_table[52])
/* "date" */ /* "date" */
@ -240,27 +240,24 @@ static_assert(
(::grpc_core::g_static_metadata_slice_table[81]) (::grpc_core::g_static_metadata_slice_table[81])
/* "identity" */ /* "identity" */
#define GRPC_MDSTR_IDENTITY (::grpc_core::g_static_metadata_slice_table[82]) #define GRPC_MDSTR_IDENTITY (::grpc_core::g_static_metadata_slice_table[82])
/* "application/grpc" */
#define GRPC_MDSTR_APPLICATION_SLASH_GRPC \
(::grpc_core::g_static_metadata_slice_table[83])
/* "grpc" */ /* "grpc" */
#define GRPC_MDSTR_GRPC (::grpc_core::g_static_metadata_slice_table[84]) #define GRPC_MDSTR_GRPC (::grpc_core::g_static_metadata_slice_table[83])
/* "PUT" */ /* "PUT" */
#define GRPC_MDSTR_PUT (::grpc_core::g_static_metadata_slice_table[85]) #define GRPC_MDSTR_PUT (::grpc_core::g_static_metadata_slice_table[84])
/* "lb-cost-bin" */ /* "lb-cost-bin" */
#define GRPC_MDSTR_LB_COST_BIN (::grpc_core::g_static_metadata_slice_table[86]) #define GRPC_MDSTR_LB_COST_BIN (::grpc_core::g_static_metadata_slice_table[85])
/* "identity,deflate" */ /* "identity,deflate" */
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE \ #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE \
(::grpc_core::g_static_metadata_slice_table[87]) (::grpc_core::g_static_metadata_slice_table[86])
/* "identity,gzip" */ /* "identity,gzip" */
#define GRPC_MDSTR_IDENTITY_COMMA_GZIP \ #define GRPC_MDSTR_IDENTITY_COMMA_GZIP \
(::grpc_core::g_static_metadata_slice_table[88]) (::grpc_core::g_static_metadata_slice_table[87])
/* "deflate,gzip" */ /* "deflate,gzip" */
#define GRPC_MDSTR_DEFLATE_COMMA_GZIP \ #define GRPC_MDSTR_DEFLATE_COMMA_GZIP \
(::grpc_core::g_static_metadata_slice_table[89]) (::grpc_core::g_static_metadata_slice_table[88])
/* "identity,deflate,gzip" */ /* "identity,deflate,gzip" */
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
(::grpc_core::g_static_metadata_slice_table[90]) (::grpc_core::g_static_metadata_slice_table[89])
namespace grpc_core { namespace grpc_core {
extern StaticSliceRefcount extern StaticSliceRefcount

@ -75,8 +75,6 @@
- status/close recv (depending on client/server) */ - status/close recv (depending on client/server) */
#define MAX_CONCURRENT_BATCHES 6 #define MAX_CONCURRENT_BATCHES 6
#define MAX_SEND_EXTRA_METADATA_COUNT 3
// Used to create arena for the first call. // Used to create arena for the first call.
#define ESTIMATED_MDELEM_COUNT 16 #define ESTIMATED_MDELEM_COUNT 16
@ -219,10 +217,6 @@ struct grpc_call {
/* Contexts for various subsystems (security, tracing, ...). */ /* Contexts for various subsystems (security, tracing, ...). */
grpc_call_context_element context[GRPC_CONTEXT_COUNT] = {}; grpc_call_context_element context[GRPC_CONTEXT_COUNT] = {};
/* for the client, extra metadata is initial metadata; for the
server, it's trailing metadata */
grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT];
int send_extra_metadata_count;
grpc_millis send_deadline; grpc_millis send_deadline;
grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> sending_stream; grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> sending_stream;
@ -342,7 +336,7 @@ size_t grpc_call_get_initial_size_estimate() {
sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT; sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT;
} }
grpc_error_handle grpc_call_create(const grpc_call_create_args* args, grpc_error_handle grpc_call_create(grpc_call_create_args* args,
grpc_call** out_call) { grpc_call** out_call) {
GPR_TIMER_SCOPE("grpc_call_create", 0); GPR_TIMER_SCOPE("grpc_call_create", 0);
@ -373,24 +367,17 @@ grpc_error_handle grpc_call_create(const grpc_call_create_args* args,
call->final_op.client.status = nullptr; call->final_op.client.status = nullptr;
call->final_op.client.error_string = nullptr; call->final_op.client.error_string = nullptr;
GRPC_STATS_INC_CLIENT_CALLS_CREATED(); GRPC_STATS_INC_CLIENT_CALLS_CREATED();
GPR_ASSERT(args->add_initial_metadata_count < path = grpc_slice_ref_internal(args->path->c_slice());
MAX_SEND_EXTRA_METADATA_COUNT); call->send_initial_metadata.Set(grpc_core::HttpPathMetadata(),
for (size_t i = 0; i < args->add_initial_metadata_count; i++) { std::move(*args->path));
call->send_extra_metadata[i].md = args->add_initial_metadata[i]; if (args->authority.has_value()) {
if (grpc_slice_eq_static_interned( call->send_initial_metadata.Set(grpc_core::HttpAuthorityMetadata(),
GRPC_MDKEY(args->add_initial_metadata[i]), GRPC_MDSTR_PATH)) { std::move(*args->authority));
path = grpc_slice_ref_internal(
GRPC_MDVALUE(args->add_initial_metadata[i]));
}
} }
call->send_extra_metadata_count =
static_cast<int>(args->add_initial_metadata_count);
} else { } else {
GRPC_STATS_INC_SERVER_CALLS_CREATED(); GRPC_STATS_INC_SERVER_CALLS_CREATED();
call->final_op.server.cancelled = nullptr; call->final_op.server.cancelled = nullptr;
call->final_op.server.core_server = args->server; call->final_op.server.core_server = args->server;
GPR_ASSERT(args->add_initial_metadata_count == 0);
call->send_extra_metadata_count = 0;
} }
grpc_millis send_deadline = args->send_deadline; grpc_millis send_deadline = args->send_deadline;
@ -551,9 +538,6 @@ static void destroy_call(void* call, grpc_error_handle /*error*/) {
if (pc != nullptr) { if (pc != nullptr) {
pc->~parent_call(); pc->~parent_call();
} }
for (int i = 0; i < c->send_extra_metadata_count; i++) {
GRPC_MDELEM_UNREF(c->send_extra_metadata[i].md);
}
if (c->cq) { if (c->cq) {
GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
} }
@ -915,8 +899,16 @@ static int prepare_application_metadata(grpc_call* call, int count,
// HTTP2 hpack encoding has a maximum limit. // HTTP2 hpack encoding has a maximum limit.
return 0; return 0;
} }
batch->Append(grpc_core::StringViewFromSlice(md->key), batch->Append(
grpc_core::Slice(grpc_slice_ref_internal(md->value))); grpc_core::StringViewFromSlice(md->key),
grpc_core::Slice(grpc_slice_ref_internal(md->value)),
[md](absl::string_view error, const grpc_core::Slice& value) {
gpr_log(
GPR_DEBUG, "Append error: %s",
absl::StrCat("key=", grpc_core::StringViewFromSlice(md->key),
" error=", error, " value=", value.as_string_view())
.c_str());
});
} }
return 1; return 1;
@ -1663,16 +1655,6 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
} }
stream_op->send_initial_metadata = true; stream_op->send_initial_metadata = true;
call->sent_initial_metadata = true; call->sent_initial_metadata = true;
if (call->is_client) {
// TODO(ctiller): this will turn into explicit Set() calls once we
// migrate :path, :authority.
for (int i = 0; i < call->send_extra_metadata_count; i++) {
GRPC_LOG_IF_ERROR("prepare_client_metadata",
call->send_initial_metadata.LinkTail(
&call->send_extra_metadata[i]));
}
call->send_extra_metadata_count = 0;
}
if (!prepare_application_metadata( if (!prepare_application_metadata(
call, static_cast<int>(op->data.send_initial_metadata.count), call, static_cast<int>(op->data.send_initial_metadata.count),
op->data.send_initial_metadata.metadata, 0, &compression_md, op->data.send_initial_metadata.metadata, 0, &compression_md,

@ -46,8 +46,8 @@ typedef struct grpc_call_create_args {
const void* server_transport_data; const void* server_transport_data;
grpc_mdelem* add_initial_metadata; absl::optional<grpc_core::Slice> path;
size_t add_initial_metadata_count; absl::optional<grpc_core::Slice> authority;
grpc_millis send_deadline; grpc_millis send_deadline;
} grpc_call_create_args; } grpc_call_create_args;
@ -55,7 +55,7 @@ typedef struct grpc_call_create_args {
/* Create a new call based on \a args. /* Create a new call based on \a args.
Regardless of success or failure, always returns a valid new call into *call Regardless of success or failure, always returns a valid new call into *call
*/ */
grpc_error_handle grpc_call_create(const grpc_call_create_args* args, grpc_error_handle grpc_call_create(grpc_call_create_args* args,
grpc_call** call); grpc_call** call);
void grpc_call_set_completion_queue(grpc_call* call, grpc_completion_queue* cq); void grpc_call_set_completion_queue(grpc_call* call, grpc_completion_queue* cq);

@ -343,19 +343,11 @@ void grpc_channel_reset_connect_backoff(grpc_channel* channel) {
static grpc_call* grpc_channel_create_call_internal( static grpc_call* grpc_channel_create_call_internal(
grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative, grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative,
grpc_mdelem path_mdelem, grpc_mdelem authority_mdelem, grpc_core::Slice path, absl::optional<grpc_core::Slice> authority,
grpc_millis deadline) { grpc_millis deadline) {
grpc_mdelem send_metadata[2];
size_t num_metadata = 0;
GPR_ASSERT(channel->is_client); GPR_ASSERT(channel->is_client);
GPR_ASSERT(!(cq != nullptr && pollset_set_alternative != nullptr)); GPR_ASSERT(!(cq != nullptr && pollset_set_alternative != nullptr));
send_metadata[num_metadata++] = path_mdelem;
if (!GRPC_MDISNULL(authority_mdelem)) {
send_metadata[num_metadata++] = authority_mdelem;
}
grpc_call_create_args args; grpc_call_create_args args;
args.channel = channel; args.channel = channel;
args.server = nullptr; args.server = nullptr;
@ -364,8 +356,8 @@ static grpc_call* grpc_channel_create_call_internal(
args.cq = cq; args.cq = cq;
args.pollset_set_alternative = pollset_set_alternative; args.pollset_set_alternative = pollset_set_alternative;
args.server_transport_data = nullptr; args.server_transport_data = nullptr;
args.add_initial_metadata = send_metadata; args.path = std::move(path);
args.add_initial_metadata_count = num_metadata; args.authority = std::move(authority);
args.send_deadline = deadline; args.send_deadline = deadline;
grpc_call* call; grpc_call* call;
@ -384,9 +376,10 @@ grpc_call* grpc_channel_create_call(grpc_channel* channel,
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
grpc_call* call = grpc_channel_create_call_internal( grpc_call* call = grpc_channel_create_call_internal(
channel, parent_call, propagation_mask, completion_queue, nullptr, channel, parent_call, propagation_mask, completion_queue, nullptr,
grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr), grpc_core::Slice(grpc_slice_ref_internal(method)),
host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr) host != nullptr
: GRPC_MDNULL, ? absl::optional<grpc_core::Slice>(grpc_slice_ref_internal(*host))
: absl::nullopt,
grpc_timespec_to_millis_round_up(deadline)); grpc_timespec_to_millis_round_up(deadline));
return call; return call;
@ -399,34 +392,31 @@ grpc_call* grpc_channel_create_pollset_set_call(
GPR_ASSERT(!reserved); GPR_ASSERT(!reserved);
return grpc_channel_create_call_internal( return grpc_channel_create_call_internal(
channel, parent_call, propagation_mask, nullptr, pollset_set, channel, parent_call, propagation_mask, nullptr, pollset_set,
grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr), grpc_core::Slice(method),
host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr) host != nullptr
: GRPC_MDNULL, ? absl::optional<grpc_core::Slice>(grpc_slice_ref_internal(*host))
: absl::nullopt,
deadline); deadline);
} }
namespace grpc_core { namespace grpc_core {
RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg) RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg) {
: path(method_arg != nullptr && method_arg[0] != 0 path = Slice::FromCopiedString(method_arg);
? grpc_mdelem_from_slices( if (host_arg != nullptr && host_arg[0] != 0) {
GRPC_MDSTR_PATH, grpc_slice_from_copied_string(method_arg)) authority = Slice::FromCopiedString(host_arg);
: GRPC_MDNULL), }
authority( }
host_arg != nullptr && host_arg[0] != 0
? grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
grpc_slice_from_copied_string(host_arg))
: GRPC_MDNULL) {}
RegisteredCall::RegisteredCall(const RegisteredCall& other) RegisteredCall::RegisteredCall(const RegisteredCall& other)
: path(GRPC_MDELEM_REF(other.path)), : path(other.path.Ref()) {
authority(GRPC_MDELEM_REF(other.authority)) {} if (other.authority.has_value()) {
authority = other.authority->Ref();
RegisteredCall::~RegisteredCall() { }
GRPC_MDELEM_UNREF(path);
GRPC_MDELEM_UNREF(authority);
} }
RegisteredCall::~RegisteredCall() {}
} // namespace grpc_core } // namespace grpc_core
void* grpc_channel_register_call(grpc_channel* channel, const char* method, void* grpc_channel_register_call(grpc_channel* channel, const char* method,
@ -473,7 +463,10 @@ grpc_call* grpc_channel_create_registered_call(
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
grpc_call* call = grpc_channel_create_call_internal( grpc_call* call = grpc_channel_create_call_internal(
channel, parent_call, propagation_mask, completion_queue, nullptr, channel, parent_call, propagation_mask, completion_queue, nullptr,
GRPC_MDELEM_REF(rc->path), GRPC_MDELEM_REF(rc->authority), rc->path.Ref(),
rc->authority.has_value()
? absl::optional<grpc_core::Slice>(rc->authority->Ref())
: absl::nullopt,
grpc_timespec_to_millis_round_up(deadline)); grpc_timespec_to_millis_round_up(deadline));
return call; return call;

@ -74,8 +74,8 @@ void grpc_channel_update_call_size_estimate(grpc_channel* channel, size_t size);
namespace grpc_core { namespace grpc_core {
struct RegisteredCall { struct RegisteredCall {
grpc_mdelem path; Slice path;
grpc_mdelem authority; absl::optional<Slice> authority;
explicit RegisteredCall(const char* method_arg, const char* host_arg); explicit RegisteredCall(const char* method_arg, const char* host_arg);
RegisteredCall(const RegisteredCall& other); RegisteredCall(const RegisteredCall& other);

@ -1124,8 +1124,6 @@ void Server::ChannelData::AcceptStream(void* arg, grpc_transport* /*transport*/,
args.cq = nullptr; args.cq = nullptr;
args.pollset_set_alternative = nullptr; args.pollset_set_alternative = nullptr;
args.server_transport_data = transport_server_data; args.server_transport_data = transport_server_data;
args.add_initial_metadata = nullptr;
args.add_initial_metadata_count = 0;
args.send_deadline = GRPC_MILLIS_INF_FUTURE; args.send_deadline = GRPC_MILLIS_INF_FUTURE;
grpc_call* call; grpc_call* call;
grpc_error_handle error = grpc_call_create(&args, &call); grpc_error_handle error = grpc_call_create(&args, &call);
@ -1200,12 +1198,6 @@ Server::CallData::CallData(grpc_call_element* elem,
Server::CallData::~CallData() { Server::CallData::~CallData() {
GPR_ASSERT(state_.load(std::memory_order_relaxed) != CallState::PENDING); GPR_ASSERT(state_.load(std::memory_order_relaxed) != CallState::PENDING);
GRPC_ERROR_UNREF(recv_initial_metadata_error_); GRPC_ERROR_UNREF(recv_initial_metadata_error_);
if (host_.has_value()) {
grpc_slice_unref_internal(*host_);
}
if (path_.has_value()) {
grpc_slice_unref_internal(*path_);
}
grpc_metadata_array_destroy(&initial_metadata_); grpc_metadata_array_destroy(&initial_metadata_);
grpc_byte_buffer_destroy(payload_); grpc_byte_buffer_destroy(payload_);
} }
@ -1258,8 +1250,9 @@ void Server::CallData::Publish(size_t cq_idx, RequestedCall* rc) {
case RequestedCall::Type::BATCH_CALL: case RequestedCall::Type::BATCH_CALL:
GPR_ASSERT(host_.has_value()); GPR_ASSERT(host_.has_value());
GPR_ASSERT(path_.has_value()); GPR_ASSERT(path_.has_value());
rc->data.batch.details->host = grpc_slice_ref_internal(*host_); rc->data.batch.details->host = grpc_slice_ref_internal(host_->c_slice());
rc->data.batch.details->method = grpc_slice_ref_internal(*path_); rc->data.batch.details->method =
grpc_slice_ref_internal(path_->c_slice());
rc->data.batch.details->deadline = rc->data.batch.details->deadline =
grpc_millis_to_timespec(deadline_, GPR_CLOCK_MONOTONIC); grpc_millis_to_timespec(deadline_, GPR_CLOCK_MONOTONIC);
rc->data.batch.details->flags = recv_initial_metadata_flags_; rc->data.batch.details->flags = recv_initial_metadata_flags_;
@ -1320,7 +1313,7 @@ void Server::CallData::StartNewRpc(grpc_call_element* elem) {
GRPC_SRM_PAYLOAD_NONE; GRPC_SRM_PAYLOAD_NONE;
if (path_.has_value() && host_.has_value()) { if (path_.has_value() && host_.has_value()) {
ChannelRegisteredMethod* rm = ChannelRegisteredMethod* rm =
chand->GetRegisteredMethod(*host_, *path_, chand->GetRegisteredMethod(host_->c_slice(), path_->c_slice(),
(recv_initial_metadata_flags_ & (recv_initial_metadata_flags_ &
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)); GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST));
if (rm != nullptr) { if (rm != nullptr) {
@ -1352,6 +1345,8 @@ void Server::CallData::RecvInitialMetadataBatchComplete(
grpc_call_element* elem = static_cast<grpc_call_element*>(arg); grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
auto* calld = static_cast<Server::CallData*>(elem->call_data); auto* calld = static_cast<Server::CallData*>(elem->call_data);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_DEBUG, "Failed call creation: %s",
grpc_error_std_string(error).c_str());
calld->FailCallCreation(); calld->FailCallCreation();
return; return;
} }
@ -1385,17 +1380,8 @@ void Server::CallData::RecvInitialMetadataReady(void* arg,
grpc_call_element* elem = static_cast<grpc_call_element*>(arg); grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
CallData* calld = static_cast<CallData*>(elem->call_data); CallData* calld = static_cast<CallData*>(elem->call_data);
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
GPR_DEBUG_ASSERT( calld->path_ = calld->recv_initial_metadata_->Take(HttpPathMetadata());
calld->recv_initial_metadata_->legacy_index()->named.path != nullptr); calld->host_ = calld->recv_initial_metadata_->Take(HttpAuthorityMetadata());
GPR_DEBUG_ASSERT(
calld->recv_initial_metadata_->legacy_index()->named.authority !=
nullptr);
calld->path_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE(
calld->recv_initial_metadata_->legacy_index()->named.path->md)));
calld->host_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE(
calld->recv_initial_metadata_->legacy_index()->named.authority->md)));
calld->recv_initial_metadata_->Remove(GRPC_BATCH_PATH);
calld->recv_initial_metadata_->Remove(GRPC_BATCH_AUTHORITY);
} else { } else {
(void)GRPC_ERROR_REF(error); (void)GRPC_ERROR_REF(error);
} }

@ -293,8 +293,8 @@ class Server : public InternallyRefCounted<Server>,
std::atomic<CallState> state_{CallState::NOT_STARTED}; std::atomic<CallState> state_{CallState::NOT_STARTED};
absl::optional<grpc_slice> path_; absl::optional<Slice> path_;
absl::optional<grpc_slice> host_; absl::optional<Slice> host_;
grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
grpc_completion_queue* cq_new_ = nullptr; grpc_completion_queue* cq_new_ = nullptr;

@ -87,9 +87,10 @@ struct GrpcTimeoutMetadata {
using ValueType = grpc_millis; using ValueType = grpc_millis;
using MementoType = grpc_millis; using MementoType = grpc_millis;
static absl::string_view key() { return "grpc-timeout"; } static absl::string_view key() { return "grpc-timeout"; }
static MementoType ParseMemento(Slice value) { static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
grpc_millis timeout; grpc_millis timeout;
if (GPR_UNLIKELY(!grpc_http2_decode_timeout(value.c_slice(), &timeout))) { if (GPR_UNLIKELY(!grpc_http2_decode_timeout(value.c_slice(), &timeout))) {
on_error("invalid value", value);
timeout = GRPC_MILLIS_INF_FUTURE; timeout = GRPC_MILLIS_INF_FUTURE;
} }
return timeout; return timeout;
@ -119,10 +120,12 @@ struct TeMetadata {
}; };
using MementoType = ValueType; using MementoType = ValueType;
static absl::string_view key() { return "te"; } static absl::string_view key() { return "te"; }
static MementoType ParseMemento(Slice value) { static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
auto out = kInvalid; auto out = kInvalid;
if (value == "trailers") { if (value == "trailers") {
out = kTrailers; out = kTrailers;
} else {
on_error("invalid value", value);
} }
return out; return out;
} }
@ -141,10 +144,167 @@ struct TeMetadata {
} }
}; };
// content-type metadata trait.
struct ContentTypeMetadata {
// gRPC says that content-type can be application/grpc[;something]
// Core has only ever verified the prefix.
// IF we want to start verifying more, we can expand this type.
enum ValueType {
kApplicationGrpc,
kEmpty,
kInvalid,
};
using MementoType = ValueType;
static absl::string_view key() { return "content-type"; }
static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
auto out = kInvalid;
auto value_string = value.as_string_view();
if (value_string == "application/grpc") {
out = kApplicationGrpc;
} else if (absl::StartsWith(value_string, "application/grpc;")) {
out = kApplicationGrpc;
} else if (absl::StartsWith(value_string, "application/grpc+")) {
out = kApplicationGrpc;
} else if (value_string.empty()) {
out = kEmpty;
} else {
on_error("invalid value", value);
}
return out;
}
static ValueType MementoToValue(MementoType content_type) {
return content_type;
}
static StaticSlice Encode(ValueType x) {
switch (x) {
case kEmpty:
return StaticSlice::FromStaticString("");
case kApplicationGrpc:
return StaticSlice::FromStaticString("application/grpc");
case kInvalid:
abort();
}
GPR_UNREACHABLE_CODE(
return StaticSlice::FromStaticString("unrepresentable value"));
}
static const char* DisplayValue(MementoType content_type) {
switch (content_type) {
case ValueType::kApplicationGrpc:
return "application/grpc";
case ValueType::kEmpty:
return "";
default:
return "<discarded-invalid-value>";
}
}
};
// scheme metadata trait.
struct HttpSchemeMetadata {
enum ValueType {
kHttp,
kHttps,
kInvalid,
};
using MementoType = ValueType;
static absl::string_view key() { return ":scheme"; }
static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
return Parse(value.as_string_view(), on_error);
}
static ValueType Parse(absl::string_view value,
MetadataParseErrorFn on_error) {
if (value == "http") {
return kHttp;
} else if (value == "https") {
return kHttps;
}
on_error("invalid value", Slice::FromCopiedBuffer(value));
return kInvalid;
}
static ValueType MementoToValue(MementoType content_type) {
return content_type;
}
static StaticSlice Encode(ValueType x) {
switch (x) {
case kHttp:
return StaticSlice::FromStaticString("http");
case kHttps:
return StaticSlice::FromStaticString("https");
default:
abort();
}
}
static const char* DisplayValue(MementoType content_type) {
switch (content_type) {
case kHttp:
return "http";
case kHttps:
return "https";
default:
return "<discarded-invalid-value>";
}
}
};
// method metadata trait.
struct HttpMethodMetadata {
enum ValueType {
kPost,
kPut,
kGet,
kInvalid,
};
using MementoType = ValueType;
static absl::string_view key() { return ":method"; }
static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
auto out = kInvalid;
auto value_string = value.as_string_view();
if (value_string == "POST") {
out = kPost;
} else if (value_string == "PUT") {
out = kPut;
} else if (value_string == "GET") {
out = kGet;
} else {
on_error("invalid value", value);
}
return out;
}
static ValueType MementoToValue(MementoType content_type) {
return content_type;
}
static StaticSlice Encode(ValueType x) {
switch (x) {
case kPost:
return StaticSlice::FromStaticString("POST");
case kPut:
return StaticSlice::FromStaticString("PUT");
case kGet:
return StaticSlice::FromStaticString("GET");
default:
abort();
}
}
static const char* DisplayValue(MementoType content_type) {
switch (content_type) {
case kPost:
return "POST";
case kPut:
return "PUT";
case kGet:
return "GET";
default:
return "<discarded-invalid-value>";
}
}
};
struct SimpleSliceBasedMetadata { struct SimpleSliceBasedMetadata {
using ValueType = Slice; using ValueType = Slice;
using MementoType = Slice; using MementoType = Slice;
static MementoType ParseMemento(Slice value) { return value.TakeOwned(); } static MementoType ParseMemento(Slice value, MetadataParseErrorFn) {
return value.TakeOwned();
}
static ValueType MementoToValue(MementoType value) { return value; } static ValueType MementoToValue(MementoType value) { return value; }
static Slice Encode(const ValueType& x) { return x.Ref(); } static Slice Encode(const ValueType& x) { return x.Ref(); }
static absl::string_view DisplayValue(const MementoType& value) { static absl::string_view DisplayValue(const MementoType& value) {
@ -187,6 +347,16 @@ struct GrpcTagsBinMetadata : public SimpleSliceBasedMetadata {
static absl::string_view key() { return "grpc-tags-bin"; } static absl::string_view key() { return "grpc-tags-bin"; }
}; };
// :authority metadata trait.
struct HttpAuthorityMetadata : public SimpleSliceBasedMetadata {
static absl::string_view key() { return ":authority"; }
};
// :path metadata trait.
struct HttpPathMetadata : public SimpleSliceBasedMetadata {
static absl::string_view key() { return ":path"; }
};
// We separate SimpleIntBasedMetadata into two pieces: one that does not depend // We separate SimpleIntBasedMetadata into two pieces: one that does not depend
// on the invalid value, and one that does. This allows the compiler to easily // on the invalid value, and one that does. This allows the compiler to easily
// see the functions that are shared, and helps reduce code bloat here. // see the functions that are shared, and helps reduce code bloat here.
@ -202,9 +372,10 @@ struct SimpleIntBasedMetadataBase {
template <typename Int, Int kInvalidValue> template <typename Int, Int kInvalidValue>
struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> { struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> {
static constexpr Int invalid_value() { return kInvalidValue; } static constexpr Int invalid_value() { return kInvalidValue; }
static Int ParseMemento(Slice value) { static Int ParseMemento(Slice value, MetadataParseErrorFn on_error) {
Int out; Int out;
if (!absl::SimpleAtoi(value.as_string_view(), &out)) { if (!absl::SimpleAtoi(value.as_string_view(), &out)) {
on_error("not an integer", value);
out = kInvalidValue; out = kInvalidValue;
} }
return out; return out;
@ -229,6 +400,12 @@ struct GrpcRetryPushbackMsMetadata
static absl::string_view key() { return "grpc-retry-pushback-ms"; } static absl::string_view key() { return "grpc-retry-pushback-ms"; }
}; };
// :status metadata trait.
// TODO(ctiller): consider moving to uint16_t
struct HttpStatusMetadata : public SimpleIntBasedMetadata<uint32_t, 0> {
static absl::string_view key() { return ":status"; }
};
namespace metadata_detail { namespace metadata_detail {
// Helper type - maps a string name to a trait. // Helper type - maps a string name to a trait.
@ -264,9 +441,11 @@ struct NameLookup<> {
template <typename ParseMementoFn, typename MementoToValueFn> template <typename ParseMementoFn, typename MementoToValueFn>
struct ParseValue { struct ParseValue {
template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value> template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value>
static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value) static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value,
-> decltype(memento_to_value(parse_memento(std::move(*value)))) { MetadataParseErrorFn on_error)
return memento_to_value(parse_memento(std::move(*value))); -> decltype(memento_to_value(parse_memento(std::move(*value),
on_error))) {
return memento_to_value(parse_memento(std::move(*value), on_error));
} }
}; };
@ -276,8 +455,10 @@ struct ParseValue {
template <typename Container> template <typename Container>
class ParseHelper { class ParseHelper {
public: public:
ParseHelper(Slice value, size_t transport_size) ParseHelper(Slice value, MetadataParseErrorFn on_error, size_t transport_size)
: value_(std::move(value)), transport_size_(transport_size) {} : value_(std::move(value)),
on_error_(on_error),
transport_size_(transport_size) {}
template <typename Trait> template <typename Trait>
GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) { GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) {
@ -296,12 +477,13 @@ class ParseHelper {
} }
private: private:
template <typename T, T (*parse_memento)(Slice)> template <typename T, T (*parse_memento)(Slice, MetadataParseErrorFn)>
GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() { GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() {
return parse_memento(std::move(value_)); return parse_memento(std::move(value_), on_error_);
} }
Slice value_; Slice value_;
MetadataParseErrorFn on_error_;
const size_t transport_size_; const size_t transport_size_;
}; };
@ -311,8 +493,8 @@ class ParseHelper {
template <typename Container> template <typename Container>
class AppendHelper { class AppendHelper {
public: public:
AppendHelper(Container* container, Slice value) AppendHelper(Container* container, Slice value, MetadataParseErrorFn on_error)
: container_(container), value_(std::move(value)) {} : container_(container), value_(std::move(value)), on_error_(on_error) {}
template <typename Trait> template <typename Trait>
GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) { GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
@ -320,7 +502,7 @@ class AppendHelper {
trait, ParseValue<decltype(Trait::ParseMemento), trait, ParseValue<decltype(Trait::ParseMemento),
decltype(Trait::MementoToValue)>:: decltype(Trait::MementoToValue)>::
template Parse<Trait::ParseMemento, Trait::MementoToValue>( template Parse<Trait::ParseMemento, Trait::MementoToValue>(
&value_)); &value_, on_error_));
} }
GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) { GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
@ -336,6 +518,7 @@ class AppendHelper {
private: private:
Container* const container_; Container* const container_;
Slice value_; Slice value_;
MetadataParseErrorFn on_error_;
}; };
} // namespace metadata_detail } // namespace metadata_detail
@ -380,7 +563,9 @@ MetadataValueAsSlice(typename Which::ValueType value) {
// static absl::string_view key() { return "grpc-xyz"; } // static absl::string_view key() { return "grpc-xyz"; }
// // Parse a memento from a slice // // Parse a memento from a slice
// // Takes ownership of value // // Takes ownership of value
// static MementoType ParseMemento(Slice value) { ... } // // Calls fn in the case of an error that should be reported to the user
// static MementoType ParseMemento(Slice value, MementoParseErrorFn fn) { ...
// }
// // Convert a memento to a value // // Convert a memento to a value
// static ValueType MementoToValue(MementoType memento) { ... } // static ValueType MementoToValue(MementoType memento) { ... }
// // Convert a value to its canonical text wire format (the format that // // Convert a value to its canonical text wire format (the format that
@ -436,10 +621,10 @@ class MetadataMap {
// transitions. // transitions.
template <typename Encoder> template <typename Encoder>
void Encode(Encoder* encoder) const { void Encode(Encoder* encoder) const {
table_.ForEach(EncodeWrapper<Encoder>{encoder});
for (auto* l = list_.head; l; l = l->next) { for (auto* l = list_.head; l; l = l->next) {
encoder->Encode(l->md); encoder->Encode(l->md);
} }
table_.ForEach(EncodeWrapper<Encoder>{encoder});
} }
// Get the pointer to the value of some known metadata. // Get the pointer to the value of some known metadata.
@ -503,9 +688,10 @@ class MetadataMap {
// TODO(ctiller): key should probably be an absl::string_view. // TODO(ctiller): key should probably be an absl::string_view.
// Once we don't care about interning anymore, make that change! // Once we don't care about interning anymore, make that change!
static ParsedMetadata<MetadataMap> Parse(absl::string_view key, Slice value, static ParsedMetadata<MetadataMap> Parse(absl::string_view key, Slice value,
uint32_t transport_size) { uint32_t transport_size,
MetadataParseErrorFn on_error) {
metadata_detail::ParseHelper<MetadataMap> helper(value.TakeOwned(), metadata_detail::ParseHelper<MetadataMap> helper(value.TakeOwned(),
transport_size); on_error, transport_size);
return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper); return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
} }
@ -516,8 +702,10 @@ class MetadataMap {
} }
// Append a key/value pair - takes ownership of value // Append a key/value pair - takes ownership of value
void Append(absl::string_view key, Slice value) { void Append(absl::string_view key, Slice value,
metadata_detail::AppendHelper<MetadataMap> helper(this, value.TakeOwned()); MetadataParseErrorFn on_error) {
metadata_detail::AppendHelper<MetadataMap> helper(this, value.TakeOwned(),
on_error);
metadata_detail::NameLookup<Traits...>::Lookup(key, &helper); metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
} }
@ -653,6 +841,22 @@ class MetadataMap {
} }
}; };
// Encoder to compute TransportSize
class TransportSizeEncoder {
public:
void Encode(grpc_mdelem elem) { size_ += GRPC_MDELEM_LENGTH(elem); }
template <typename Which>
void Encode(Which, const typename Which::ValueType& value) {
size_ += Which::key().length() + Which::Encode(value).length() + 32;
}
size_t size() const { return size_; }
private:
uint32_t size_ = 0;
};
void AssertValidCallouts(); void AssertValidCallouts();
grpc_error_handle LinkCallout(grpc_linked_mdelem* storage, grpc_error_handle LinkCallout(grpc_linked_mdelem* storage,
grpc_metadata_batch_callouts_index idx) grpc_metadata_batch_callouts_index idx)
@ -1010,12 +1214,9 @@ void MetadataMap<Traits...>::Clear() {
template <typename... Traits> template <typename... Traits>
size_t MetadataMap<Traits...>::TransportSize() const { size_t MetadataMap<Traits...>::TransportSize() const {
size_t size = 0; TransportSizeEncoder enc;
for (grpc_linked_mdelem* elem = list_.head; elem != nullptr; Encode(&enc);
elem = elem->next) { return enc.size();
size += GRPC_MDELEM_LENGTH(elem->md);
}
return size;
} }
template <typename... Traits> template <typename... Traits>
@ -1037,11 +1238,17 @@ bool MetadataMap<Traits...>::ReplaceIfExists(grpc_slice key, grpc_slice value) {
} // namespace grpc_core } // namespace grpc_core
using grpc_metadata_batch = grpc_core::MetadataMap< using grpc_metadata_batch = grpc_core::MetadataMap<
// Colon prefixed headers first
grpc_core::HttpPathMetadata, grpc_core::HttpAuthorityMetadata,
grpc_core::HttpMethodMetadata, grpc_core::HttpStatusMetadata,
grpc_core::HttpSchemeMetadata,
// Non-colon prefixed headers begin here
grpc_core::ContentTypeMetadata, grpc_core::TeMetadata,
grpc_core::GrpcStatusMetadata, grpc_core::GrpcTimeoutMetadata, grpc_core::GrpcStatusMetadata, grpc_core::GrpcTimeoutMetadata,
grpc_core::GrpcPreviousRpcAttemptsMetadata, grpc_core::GrpcPreviousRpcAttemptsMetadata,
grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::TeMetadata, grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::UserAgentMetadata,
grpc_core::UserAgentMetadata, grpc_core::GrpcMessageMetadata, grpc_core::GrpcMessageMetadata, grpc_core::HostMetadata,
grpc_core::HostMetadata, grpc_core::XEndpointLoadMetricsBinMetadata, grpc_core::XEndpointLoadMetricsBinMetadata,
grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata, grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata,
grpc_core::GrpcTagsBinMetadata>; grpc_core::GrpcTagsBinMetadata>;

@ -30,6 +30,9 @@
namespace grpc_core { namespace grpc_core {
using MetadataParseErrorFn =
absl::FunctionRef<void(absl::string_view error, const Slice& value)>;
namespace metadata_detail { namespace metadata_detail {
// Helper to determine whether a traits metadata is inlinable inside a memento, // Helper to determine whether a traits metadata is inlinable inside a memento,
@ -171,16 +174,18 @@ class ParsedMetadata {
// HTTP2 defined storage size of this metadatum. // HTTP2 defined storage size of this metadatum.
uint32_t transport_size() const { return transport_size_; } uint32_t transport_size() const { return transport_size_; }
// Create a new parsed metadata with the same key but a different value. // Create a new parsed metadata with the same key but a different value.
ParsedMetadata WithNewValue(Slice value) const { ParsedMetadata WithNewValue(Slice value,
MetadataParseErrorFn on_error) const {
ParsedMetadata result; ParsedMetadata result;
result.vtable_ = vtable_; result.vtable_ = vtable_;
result.value_ = value_; result.value_ = value_;
result.transport_size_ = result.transport_size_ =
TransportSize(vtable_->key_length(value_), value.length()); TransportSize(vtable_->key(value_).length(), value.length());
vtable_->with_new_value(&value, &result); vtable_->with_new_value(&value, on_error, &result);
return result; return result;
} }
std::string DebugString() const { return vtable_->debug_string(value_); } std::string DebugString() const { return vtable_->debug_string(value_); }
absl::string_view key() const { return vtable_->key(value_); }
// TODO(ctiller): move to transport // TODO(ctiller): move to transport
static uint32_t TransportSize(uint32_t key_size, uint32_t value_size) { static uint32_t TransportSize(uint32_t key_size, uint32_t value_size) {
@ -197,11 +202,11 @@ class ParsedMetadata {
grpc_error_handle (*const set)(const Buffer& value, grpc_error_handle (*const set)(const Buffer& value,
MetadataContainer* container); MetadataContainer* container);
// result is a bitwise copy of the originating ParsedMetadata. // result is a bitwise copy of the originating ParsedMetadata.
void (*const with_new_value)(Slice* new_value, ParsedMetadata* result); void (*const with_new_value)(Slice* new_value,
MetadataParseErrorFn on_error,
ParsedMetadata* result);
std::string (*const debug_string)(const Buffer& value); std::string (*const debug_string)(const Buffer& value);
// TODO(ctiller): when we delete mdelem, make this a simple integer constant absl::string_view (*const key)(const Buffer& value);
// on the vtable
size_t (*const key_length)(const Buffer& value);
}; };
static const VTable* EmptyVTable(); static const VTable* EmptyVTable();
@ -214,17 +219,18 @@ class ParsedMetadata {
template <bool kIsBinaryHeader> template <bool kIsBinaryHeader>
static const VTable* MdelemVtable(); static const VTable* MdelemVtable();
template <Slice (*ParseMemento)(Slice)> template <Slice (*ParseMemento)(Slice, MetadataParseErrorFn)>
GPR_ATTRIBUTE_NOINLINE static void WithNewValueSetSlice( GPR_ATTRIBUTE_NOINLINE static void WithNewValueSetSlice(
Slice* slice, ParsedMetadata* result) { Slice* slice, MetadataParseErrorFn on_error, ParsedMetadata* result) {
result->value_.slice = ParseMemento(std::move(*slice)).TakeCSlice(); result->value_.slice =
ParseMemento(std::move(*slice), on_error).TakeCSlice();
} }
template <typename T, T (*ParseMemento)(Slice)> template <typename T, T (*ParseMemento)(Slice, MetadataParseErrorFn)>
GPR_ATTRIBUTE_NOINLINE static void WithNewValueSetTrivial( GPR_ATTRIBUTE_NOINLINE static void WithNewValueSetTrivial(
Slice* slice, ParsedMetadata* result) { Slice* slice, MetadataParseErrorFn on_error, ParsedMetadata* result) {
result->value_.trivial = result->value_.trivial =
static_cast<uint64_t>(ParseMemento(std::move(*slice))); static_cast<uint64_t>(ParseMemento(std::move(*slice), on_error));
} }
const VTable* vtable_; const VTable* vtable_;
@ -244,11 +250,11 @@ ParsedMetadata<MetadataContainer>::EmptyVTable() {
// set // set
[](const Buffer&, MetadataContainer*) { return GRPC_ERROR_NONE; }, [](const Buffer&, MetadataContainer*) { return GRPC_ERROR_NONE; },
// with_new_value // with_new_value
[](Slice*, ParsedMetadata*) {}, [](Slice*, MetadataParseErrorFn, ParsedMetadata*) {},
// debug_string // debug_string
[](const Buffer&) -> std::string { return "empty"; }, [](const Buffer&) -> std::string { return "empty"; },
// key_length // key
[](const Buffer&) -> size_t { return 0; }, [](const Buffer&) -> absl::string_view { return ""; },
}; };
return &vtable; return &vtable;
} }
@ -277,8 +283,8 @@ ParsedMetadata<MetadataContainer>::TrivialTraitVTable() {
metadata_detail::FieldFromTrivial<typename Which::MementoType>, metadata_detail::FieldFromTrivial<typename Which::MementoType>,
Which::DisplayValue); Which::DisplayValue);
}, },
// key_length // key
[](const Buffer&) { return Which::key().size(); }, [](const Buffer&) { return Which::key(); },
}; };
return &vtable; return &vtable;
} }
@ -300,9 +306,9 @@ ParsedMetadata<MetadataContainer>::NonTrivialTraitVTable() {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
}, },
// with_new_value // with_new_value
[](Slice* value, ParsedMetadata* result) { [](Slice* value, MetadataParseErrorFn on_error, ParsedMetadata* result) {
result->value_.pointer = new result->value_.pointer = new typename Which::MementoType(
typename Which::MementoType(Which::ParseMemento(std::move(*value))); Which::ParseMemento(std::move(*value), on_error));
}, },
// debug_string // debug_string
[](const Buffer& value) { [](const Buffer& value) {
@ -311,8 +317,8 @@ ParsedMetadata<MetadataContainer>::NonTrivialTraitVTable() {
metadata_detail::FieldFromPointer<typename Which::MementoType>, metadata_detail::FieldFromPointer<typename Which::MementoType>,
Which::DisplayValue); Which::DisplayValue);
}, },
// key_length // key
[](const Buffer&) { return Which::key().size(); }, [](const Buffer&) { return Which::key(); },
}; };
return &vtable; return &vtable;
} }
@ -339,8 +345,8 @@ ParsedMetadata<MetadataContainer>::SliceTraitVTable() {
Which::key(), value, metadata_detail::SliceFromBuffer, Which::key(), value, metadata_detail::SliceFromBuffer,
Which::DisplayValue); Which::DisplayValue);
}, },
// key_length // key
[](const Buffer&) { return Which::key().size(); }, [](const Buffer&) { return Which::key(); },
}; };
return &vtable; return &vtable;
} }
@ -365,7 +371,7 @@ ParsedMetadata<MetadataContainer>::MdelemVtable() {
return err; return err;
}, },
// with_new_value // with_new_value
[](Slice* value_slice, ParsedMetadata* result) { [](Slice* value_slice, MetadataParseErrorFn, ParsedMetadata* result) {
result->value_.mdelem = grpc_mdelem_from_slices( result->value_.mdelem = grpc_mdelem_from_slices(
static_cast<const ManagedMemorySlice&>( static_cast<const ManagedMemorySlice&>(
grpc_slice_ref_internal(GRPC_MDKEY(result->value_.mdelem))), grpc_slice_ref_internal(GRPC_MDKEY(result->value_.mdelem))),
@ -377,9 +383,9 @@ ParsedMetadata<MetadataContainer>::MdelemVtable() {
StringViewFromSlice(GRPC_MDKEY(value.mdelem)), StringViewFromSlice(GRPC_MDKEY(value.mdelem)),
StringViewFromSlice(GRPC_MDVALUE(value.mdelem))); StringViewFromSlice(GRPC_MDVALUE(value.mdelem)));
}, },
// key_length // key
[](const Buffer& value) { [](const Buffer& value) {
return GRPC_SLICE_LENGTH(GRPC_MDKEY(value.mdelem)); return StringViewFromSlice(GRPC_MDKEY(value.mdelem));
}}; }};
return &vtable; return &vtable;
} }

@ -33,491 +33,485 @@
namespace grpc_core { namespace grpc_core {
StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 10, StaticMetadataSlice(&g_static_metadata_slice_refcounts[18].base, 10,
g_static_metadata_bytes + 19), g_static_metadata_bytes + 492),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
0), 0),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7,
g_static_metadata_bytes + 5), g_static_metadata_bytes + 502),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[24].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 3,
g_static_metadata_bytes + 540), g_static_metadata_bytes + 509),
1), 1),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7,
g_static_metadata_bytes + 5), g_static_metadata_bytes + 502),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[21].base, 4,
g_static_metadata_bytes + 543), g_static_metadata_bytes + 512),
2), 2),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[22].base, 5,
g_static_metadata_bytes + 0), g_static_metadata_bytes + 516),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 1, StaticMetadataSlice(&g_static_metadata_slice_refcounts[23].base, 1,
g_static_metadata_bytes + 547), g_static_metadata_bytes + 521),
3), 3),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[22].base, 5,
g_static_metadata_bytes + 0), g_static_metadata_bytes + 516),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 11, StaticMetadataSlice(&g_static_metadata_slice_refcounts[24].base, 11,
g_static_metadata_bytes + 548), g_static_metadata_bytes + 522),
4), 4),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 7,
g_static_metadata_bytes + 29), g_static_metadata_bytes + 533),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 4,
g_static_metadata_bytes + 559), g_static_metadata_bytes + 540),
5), 5),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 7,
g_static_metadata_bytes + 29), g_static_metadata_bytes + 533),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[29].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 5,
g_static_metadata_bytes + 563), g_static_metadata_bytes + 544),
6), 6),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[30].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[29].base, 3,
g_static_metadata_bytes + 568), g_static_metadata_bytes + 556),
7), 7),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[31].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[30].base, 3,
g_static_metadata_bytes + 571), g_static_metadata_bytes + 559),
8), 8),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[32].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[31].base, 3,
g_static_metadata_bytes + 574), g_static_metadata_bytes + 562),
9), 9),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[33].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[32].base, 3,
g_static_metadata_bytes + 577), g_static_metadata_bytes + 565),
10), 10),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[34].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[33].base, 3,
g_static_metadata_bytes + 580), g_static_metadata_bytes + 568),
11), 11),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[35].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[34].base, 3,
g_static_metadata_bytes + 583), g_static_metadata_bytes + 571),
12), 12),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 7,
g_static_metadata_bytes + 12), g_static_metadata_bytes + 549),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[36].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[35].base, 3,
g_static_metadata_bytes + 586), g_static_metadata_bytes + 574),
13), 13),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[37].base, 14, StaticMetadataSlice(&g_static_metadata_slice_refcounts[36].base, 14,
g_static_metadata_bytes + 589), g_static_metadata_bytes + 577),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
14), 14),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 15, StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 15,
g_static_metadata_bytes + 97), g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[38].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[37].base, 13,
g_static_metadata_bytes + 603), g_static_metadata_bytes + 591),
15), 15),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[39].base, 15, StaticMetadataSlice(&g_static_metadata_slice_refcounts[38].base, 15,
g_static_metadata_bytes + 616), g_static_metadata_bytes + 604),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
16), 16),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[40].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[39].base, 13,
g_static_metadata_bytes + 631), g_static_metadata_bytes + 619),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
17), 17),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[41].base, 6, StaticMetadataSlice(&g_static_metadata_slice_refcounts[40].base, 6,
g_static_metadata_bytes + 644), g_static_metadata_bytes + 632),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
18), 18),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[42].base, 27, StaticMetadataSlice(&g_static_metadata_slice_refcounts[41].base, 27,
g_static_metadata_bytes + 650), g_static_metadata_bytes + 638),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
19), 19),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[43].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[42].base, 3,
g_static_metadata_bytes + 677), g_static_metadata_bytes + 665),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
20), 20),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[44].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[43].base, 5,
g_static_metadata_bytes + 680), g_static_metadata_bytes + 668),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
21), 21),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[45].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[44].base, 13,
g_static_metadata_bytes + 685), g_static_metadata_bytes + 673),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
22), 22),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[46].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[45].base, 13,
g_static_metadata_bytes + 698), g_static_metadata_bytes + 686),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
23), 23),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[47].base, 19, StaticMetadataSlice(&g_static_metadata_slice_refcounts[46].base, 19,
g_static_metadata_bytes + 711), g_static_metadata_bytes + 699),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
24), 24),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 16,
g_static_metadata_bytes + 81), g_static_metadata_bytes + 33),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
25), 25),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[48].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[47].base, 16,
g_static_metadata_bytes + 730), g_static_metadata_bytes + 718),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
26), 26),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[49].base, 14, StaticMetadataSlice(&g_static_metadata_slice_refcounts[48].base, 14,
g_static_metadata_bytes + 746), g_static_metadata_bytes + 734),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
27), 27),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[50].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[49].base, 16,
g_static_metadata_bytes + 760), g_static_metadata_bytes + 748),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
28), 28),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[51].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[50].base, 13,
g_static_metadata_bytes + 776), g_static_metadata_bytes + 764),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
29), 29),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[51].base, 12,
g_static_metadata_bytes + 69), g_static_metadata_bytes + 777),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
30), 30),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[52].base, 6, StaticMetadataSlice(&g_static_metadata_slice_refcounts[52].base, 6,
g_static_metadata_bytes + 789), g_static_metadata_bytes + 789),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
31), 31),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[53].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[53].base, 4,
g_static_metadata_bytes + 795), g_static_metadata_bytes + 795),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
32), 32),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[54].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[54].base, 4,
g_static_metadata_bytes + 799), g_static_metadata_bytes + 799),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
33), 33),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[55].base, 6, StaticMetadataSlice(&g_static_metadata_slice_refcounts[55].base, 6,
g_static_metadata_bytes + 803), g_static_metadata_bytes + 803),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
34), 34),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[56].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[56].base, 7,
g_static_metadata_bytes + 809), g_static_metadata_bytes + 809),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
35), 35),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[57].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[57].base, 4,
g_static_metadata_bytes + 816), g_static_metadata_bytes + 816),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
36), 36),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[58].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[58].base, 4,
g_static_metadata_bytes + 820), g_static_metadata_bytes + 820),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
37), 37),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[59].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[59].base, 8,
g_static_metadata_bytes + 824), g_static_metadata_bytes + 824),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
38), 38),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[60].base, 17, StaticMetadataSlice(&g_static_metadata_slice_refcounts[60].base, 17,
g_static_metadata_bytes + 832), g_static_metadata_bytes + 832),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
39), 39),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[61].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[61].base, 13,
g_static_metadata_bytes + 849), g_static_metadata_bytes + 849),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
40), 40),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[62].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[62].base, 8,
g_static_metadata_bytes + 862), g_static_metadata_bytes + 862),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
41), 41),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[63].base, 19, StaticMetadataSlice(&g_static_metadata_slice_refcounts[63].base, 19,
g_static_metadata_bytes + 870), g_static_metadata_bytes + 870),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
42), 42),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[64].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[64].base, 13,
g_static_metadata_bytes + 889), g_static_metadata_bytes + 889),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
43), 43),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[65].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[65].base, 4,
g_static_metadata_bytes + 902), g_static_metadata_bytes + 902),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
44), 44),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[66].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[66].base, 8,
g_static_metadata_bytes + 906), g_static_metadata_bytes + 906),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
45), 45),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[67].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[67].base, 12,
g_static_metadata_bytes + 914), g_static_metadata_bytes + 914),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
46), 46),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[68].base, 18, StaticMetadataSlice(&g_static_metadata_slice_refcounts[68].base, 18,
g_static_metadata_bytes + 926), g_static_metadata_bytes + 926),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
47), 47),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[69].base, 19, StaticMetadataSlice(&g_static_metadata_slice_refcounts[69].base, 19,
g_static_metadata_bytes + 944), g_static_metadata_bytes + 944),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
48), 48),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[70].base, 5, StaticMetadataSlice(&g_static_metadata_slice_refcounts[70].base, 5,
g_static_metadata_bytes + 963), g_static_metadata_bytes + 963),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
49), 49),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[71].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[71].base, 7,
g_static_metadata_bytes + 968), g_static_metadata_bytes + 968),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
50), 50),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[72].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[72].base, 7,
g_static_metadata_bytes + 975), g_static_metadata_bytes + 975),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
51), 51),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[73].base, 11, StaticMetadataSlice(&g_static_metadata_slice_refcounts[73].base, 11,
g_static_metadata_bytes + 982), g_static_metadata_bytes + 982),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
52), 52),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[74].base, 6, StaticMetadataSlice(&g_static_metadata_slice_refcounts[74].base, 6,
g_static_metadata_bytes + 993), g_static_metadata_bytes + 993),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
53), 53),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[75].base, 10, StaticMetadataSlice(&g_static_metadata_slice_refcounts[75].base, 10,
g_static_metadata_bytes + 999), g_static_metadata_bytes + 999),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
54), 54),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[76].base, 25, StaticMetadataSlice(&g_static_metadata_slice_refcounts[76].base, 25,
g_static_metadata_bytes + 1009), g_static_metadata_bytes + 1009),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
55), 55),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[77].base, 17, StaticMetadataSlice(&g_static_metadata_slice_refcounts[77].base, 17,
g_static_metadata_bytes + 1034), g_static_metadata_bytes + 1034),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
56), 56),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[78].base, 10, StaticMetadataSlice(&g_static_metadata_slice_refcounts[78].base, 10,
g_static_metadata_bytes + 1051), g_static_metadata_bytes + 1051),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
57), 57),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[79].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[79].base, 4,
g_static_metadata_bytes + 1061), g_static_metadata_bytes + 1061),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
58), 58),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[80].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[80].base, 3,
g_static_metadata_bytes + 1065), g_static_metadata_bytes + 1065),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
59), 59),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[81].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[81].base, 16,
g_static_metadata_bytes + 1068), g_static_metadata_bytes + 1068),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 154), g_static_metadata_bytes + 106),
60), 60),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 13,
g_static_metadata_bytes + 36), g_static_metadata_bytes + 0),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8,
g_static_metadata_bytes + 1084), g_static_metadata_bytes + 1084),
61), 61),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 13,
g_static_metadata_bytes + 36), g_static_metadata_bytes + 0),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 4,
g_static_metadata_bytes + 515), g_static_metadata_bytes + 467),
62), 62),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 13,
g_static_metadata_bytes + 36), g_static_metadata_bytes + 0),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[13].base, 7,
g_static_metadata_bytes + 508), g_static_metadata_bytes + 460),
63), 63),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 7,
g_static_metadata_bytes + 69), g_static_metadata_bytes + 533),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[83].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[83].base, 4,
g_static_metadata_bytes + 1092), g_static_metadata_bytes + 1092),
64), 64),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7,
g_static_metadata_bytes + 29), g_static_metadata_bytes + 502),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[84].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[84].base, 3,
g_static_metadata_bytes + 1108), g_static_metadata_bytes + 1096),
65), 65),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 15,
g_static_metadata_bytes + 5), g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[85].base, 3, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 1112), g_static_metadata_bytes + 106),
66), 66),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 15, StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 16,
g_static_metadata_bytes + 97), g_static_metadata_bytes + 33),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0,
g_static_metadata_bytes + 154),
67),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 16,
g_static_metadata_bytes + 81),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8,
g_static_metadata_bytes + 1084), g_static_metadata_bytes + 1084),
67),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 16,
g_static_metadata_bytes + 33),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 4,
g_static_metadata_bytes + 467),
68), 68),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[85].base, 11,
g_static_metadata_bytes + 81), g_static_metadata_bytes + 1099),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 0,
g_static_metadata_bytes + 515), g_static_metadata_bytes + 106),
69), 69),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[86].base, 11, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 1115), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 0,
g_static_metadata_bytes + 154),
70),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20,
g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8,
g_static_metadata_bytes + 1084), g_static_metadata_bytes + 1084),
70),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[13].base, 7,
g_static_metadata_bytes + 460),
71), 71),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 7, StaticMetadataSlice(&g_static_metadata_slice_refcounts[86].base, 16,
g_static_metadata_bytes + 508), g_static_metadata_bytes + 1110),
72), 72),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 16, StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 4,
g_static_metadata_bytes + 1126), g_static_metadata_bytes + 467),
73), 73),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 13,
g_static_metadata_bytes + 515), g_static_metadata_bytes + 1126),
74), 74),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 13, StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 12,
g_static_metadata_bytes + 1142), g_static_metadata_bytes + 1139),
75), 75),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20, StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 20,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 13),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[89].base, 12, StaticMetadataSlice(&g_static_metadata_slice_refcounts[89].base, 21,
g_static_metadata_bytes + 1155), g_static_metadata_bytes + 1151),
76), 76),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 20, StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 15,
g_static_metadata_bytes + 49), g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 21,
g_static_metadata_bytes + 1167),
77),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 15,
g_static_metadata_bytes + 97),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8, StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 8,
g_static_metadata_bytes + 1084), g_static_metadata_bytes + 1084),
77),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 15,
g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 4,
g_static_metadata_bytes + 467),
78), 78),
StaticMetadata( StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 15, StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 15,
g_static_metadata_bytes + 97), g_static_metadata_bytes + 49),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 4, StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 13,
g_static_metadata_bytes + 515), g_static_metadata_bytes + 1126),
79), 79),
StaticMetadata(
StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 15,
g_static_metadata_bytes + 97),
StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 13,
g_static_metadata_bytes + 1142),
80),
}; };
/* Warning: the core static metadata currently operates under the soft /* Warning: the core static metadata currently operates under the soft
@ -849,112 +843,107 @@ grpc_mdelem g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT] = {
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[63].data(), &g_static_mdelem_table[63].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC:
"content-type": "application/grpc" */
GRPC_MAKE_MDELEM(
&g_static_mdelem_table[64].data(),
GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_SCHEME_GRPC: /* GRPC_MDELEM_SCHEME_GRPC:
":scheme": "grpc" */ ":scheme": "grpc" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[65].data(), &g_static_mdelem_table[64].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_METHOD_PUT: /* GRPC_MDELEM_METHOD_PUT:
":method": "PUT" */ ":method": "PUT" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[66].data(), &g_static_mdelem_table[65].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_ACCEPT_ENCODING_EMPTY: /* GRPC_MDELEM_ACCEPT_ENCODING_EMPTY:
"accept-encoding": "" */ "accept-encoding": "" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[67].data(), &g_static_mdelem_table[66].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_CONTENT_ENCODING_IDENTITY: /* GRPC_MDELEM_CONTENT_ENCODING_IDENTITY:
"content-encoding": "identity" */ "content-encoding": "identity" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[68].data(), &g_static_mdelem_table[67].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_CONTENT_ENCODING_GZIP: /* GRPC_MDELEM_CONTENT_ENCODING_GZIP:
"content-encoding": "gzip" */ "content-encoding": "gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[69].data(), &g_static_mdelem_table[68].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_LB_COST_BIN_EMPTY: /* GRPC_MDELEM_LB_COST_BIN_EMPTY:
"lb-cost-bin": "" */ "lb-cost-bin": "" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[70].data(), &g_static_mdelem_table[69].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY:
"grpc-accept-encoding": "identity" */ "grpc-accept-encoding": "identity" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[71].data(), &g_static_mdelem_table[70].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE:
"grpc-accept-encoding": "deflate" */ "grpc-accept-encoding": "deflate" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[72].data(), &g_static_mdelem_table[71].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE:
"grpc-accept-encoding": "identity,deflate" */ "grpc-accept-encoding": "identity,deflate" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[73].data(), &g_static_mdelem_table[72].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP:
"grpc-accept-encoding": "gzip" */ "grpc-accept-encoding": "gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[74].data(), &g_static_mdelem_table[73].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP:
"grpc-accept-encoding": "identity,gzip" */ "grpc-accept-encoding": "identity,gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[75].data(), &g_static_mdelem_table[74].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP:
"grpc-accept-encoding": "deflate,gzip" */ "grpc-accept-encoding": "deflate,gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[76].data(), &g_static_mdelem_table[75].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP: /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP:
"grpc-accept-encoding": "identity,deflate,gzip" */ "grpc-accept-encoding": "identity,deflate,gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[77].data(), &g_static_mdelem_table[76].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY: /* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY:
"accept-encoding": "identity" */ "accept-encoding": "identity" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[78].data(), &g_static_mdelem_table[77].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_ACCEPT_ENCODING_GZIP: /* GRPC_MDELEM_ACCEPT_ENCODING_GZIP:
"accept-encoding": "gzip" */ "accept-encoding": "gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[79].data(), &g_static_mdelem_table[78].data(),
GRPC_MDELEM_STORAGE_STATIC), GRPC_MDELEM_STORAGE_STATIC),
/* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP: /* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP:
"accept-encoding": "identity,gzip" */ "accept-encoding": "identity,gzip" */
GRPC_MAKE_MDELEM( GRPC_MAKE_MDELEM(
&g_static_mdelem_table[80].data(), &g_static_mdelem_table[79].data(),
GRPC_MDELEM_STORAGE_STATIC) GRPC_MDELEM_STORAGE_STATIC)
// clang-format on // clang-format on
}; };
} // namespace grpc_core } // namespace grpc_core
uintptr_t grpc_static_mdelem_user_data[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, 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, 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, 2, 4, 4}; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8, 2, 4, 4};
static const int8_t elems_r[] = { static const int8_t elems_r[] = {
15, 10, -8, 0, 2, 15, 2, 20, 12, 5, 0, 0, 0, 0, 0, 10, -2, 7, 2, 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, -10, -32, -1, 0, -39, 0, 0, -46, -11, 0, -70, 0,
0, 0, 0, 0, 0, 0, 0, -39, 0, -41, -42, -43, -44, -45, -46, 0, 0, 0, 0, 0, 0, -43, 0, -46, -47, -48, -49, -50, -51, -52,
-47, -48, -49, -50, -51, -52, -52, 0, 36, 35, 34, 33, 32, 31, 30, -53, -54, -54, 0, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23,
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8,
14, 13, 12, 11, 10, 9, 8, 7, 0, 0, 0, 0, -2, 0}; 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, -7, 0};
static uint32_t elems_phash(uint32_t i) { static uint32_t elems_phash(uint32_t i) {
i -= 26; i -= 13;
uint32_t x = i % 89; uint32_t x = i % 88;
uint32_t y = i / 89; uint32_t y = i / 88;
uint32_t h = x; uint32_t h = x;
if (y < GPR_ARRAY_SIZE(elems_r)) { if (y < GPR_ARRAY_SIZE(elems_r)) {
uint32_t delta = static_cast<uint32_t>(elems_r[y]); uint32_t delta = static_cast<uint32_t>(elems_r[y]);
@ -964,25 +953,25 @@ static uint32_t elems_phash(uint32_t i) {
} }
static const uint16_t elem_keys[] = { static const uint16_t elem_keys[] = {
212, 213, 214, 215, 216, 217, 218, 565, 566, 831, 115, 116, 103, 104, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 284, 13, 14,
392, 393, 740, 26, 27, 839, 474, 475, 649, 3379, 748, 3561, 194, 1730, 1731, 2003, 2004, 2276, 2277, 1626, 1794, 2333, 3246, 3426,
3652, 3743, 3834, 3925, 4016, 4107, 4198, 4289, 4380, 4471, 4562, 857, 3516, 3606, 3696, 3786, 3876, 3966, 4056, 4146, 307, 4236, 4326, 4416,
4653, 4744, 4835, 4926, 5017, 5108, 5199, 5290, 5381, 5472, 5563, 5654, 4506, 4596, 4686, 4776, 4866, 4956, 5046, 5136, 5226, 5316, 5406, 5496,
5745, 5836, 5927, 6018, 6109, 6200, 6291, 6382, 6473, 6564, 6655, 6746, 5586, 5676, 5766, 5856, 5946, 6036, 6126, 6216, 6306, 6396, 6486, 6576,
6837, 6928, 7019, 7110, 7201, 7292, 7383, 7838, 448, 0, 628, 176, 6666, 6756, 6846, 6936, 7026, 7116, 7206, 7296, 7656, 172, 0, 0,
0, 285, 0, 633, 634, 635, 636, 901, 0, 537, 0, 0, 0, 176, 177, 178, 179, 352, 0, 82, 262, 0, 357, 186,
810, 907, 0, 0, 0, 0, 0, 720}; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276};
static const uint8_t elem_idxs[] = { static const uint8_t elem_idxs[] = {
7, 8, 9, 10, 11, 12, 13, 72, 74, 67, 1, 2, 5, 6, 25, 3, 71, 73, 7, 8, 9, 10, 11, 12, 13, 78, 63, 62, 68, 1, 2, 3,
4, 79, 63, 62, 30, 14, 69, 16, 17, 18, 19, 20, 21, 22, 23, 24, 4, 5, 6, 0, 65, 64, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24,
26, 27, 28, 15, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 15, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
58, 59, 60, 70, 65, 255, 71, 66, 255, 0, 255, 73, 75, 76, 77, 78, 57, 58, 59, 60, 69, 70, 255, 255, 255, 72, 74, 75, 76, 77, 255, 61,
255, 61, 255, 255, 68, 80, 255, 255, 255, 255, 255, 64}; 67, 255, 79, 25, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 66};
grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) { grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {
if (a == -1 || b == -1) return GRPC_MDNULL; if (a == -1 || b == -1) return GRPC_MDNULL;
uint32_t k = static_cast<uint32_t>(a * 91 + b); uint32_t k = static_cast<uint32_t>(a * 90 + b);
uint32_t h = elems_phash(k); uint32_t h = elems_phash(k);
return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k && return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k &&
elem_idxs[h] != 255 elem_idxs[h] != 255
@ -992,7 +981,7 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {
: GRPC_MDNULL; : GRPC_MDNULL;
} }
const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 71, 72, 73, const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 70, 71, 72,
74, 75, 76, 77}; 73, 74, 75, 76};
const uint8_t grpc_static_accept_stream_encoding_metadata[4] = {0, 78, 79, 80}; const uint8_t grpc_static_accept_stream_encoding_metadata[4] = {0, 77, 78, 79};

@ -34,7 +34,7 @@
#include "src/core/lib/slice/static_slice.h" #include "src/core/lib/slice/static_slice.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#define GRPC_STATIC_MDELEM_COUNT 81 #define GRPC_STATIC_MDELEM_COUNT 80
namespace grpc_core { namespace grpc_core {
extern StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; extern StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
@ -201,66 +201,57 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "grpc-encoding": "deflate" */ /* "grpc-encoding": "deflate" */
#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \ #define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \
(::grpc_core::g_static_mdelem_manifested[63]) (::grpc_core::g_static_mdelem_manifested[63])
/* "content-type": "application/grpc" */
#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \
(::grpc_core::g_static_mdelem_manifested[64])
/* ":scheme": "grpc" */ /* ":scheme": "grpc" */
#define GRPC_MDELEM_SCHEME_GRPC (::grpc_core::g_static_mdelem_manifested[65]) #define GRPC_MDELEM_SCHEME_GRPC (::grpc_core::g_static_mdelem_manifested[64])
/* ":method": "PUT" */ /* ":method": "PUT" */
#define GRPC_MDELEM_METHOD_PUT (::grpc_core::g_static_mdelem_manifested[66]) #define GRPC_MDELEM_METHOD_PUT (::grpc_core::g_static_mdelem_manifested[65])
/* "accept-encoding": "" */ /* "accept-encoding": "" */
#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \ #define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \
(::grpc_core::g_static_mdelem_manifested[67]) (::grpc_core::g_static_mdelem_manifested[66])
/* "content-encoding": "identity" */ /* "content-encoding": "identity" */
#define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \ #define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \
(::grpc_core::g_static_mdelem_manifested[68]) (::grpc_core::g_static_mdelem_manifested[67])
/* "content-encoding": "gzip" */ /* "content-encoding": "gzip" */
#define GRPC_MDELEM_CONTENT_ENCODING_GZIP \ #define GRPC_MDELEM_CONTENT_ENCODING_GZIP \
(::grpc_core::g_static_mdelem_manifested[69]) (::grpc_core::g_static_mdelem_manifested[68])
/* "lb-cost-bin": "" */ /* "lb-cost-bin": "" */
#define GRPC_MDELEM_LB_COST_BIN_EMPTY \ #define GRPC_MDELEM_LB_COST_BIN_EMPTY \
(::grpc_core::g_static_mdelem_manifested[70]) (::grpc_core::g_static_mdelem_manifested[69])
/* "grpc-accept-encoding": "identity" */ /* "grpc-accept-encoding": "identity" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
(::grpc_core::g_static_mdelem_manifested[71]) (::grpc_core::g_static_mdelem_manifested[70])
/* "grpc-accept-encoding": "deflate" */ /* "grpc-accept-encoding": "deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \
(::grpc_core::g_static_mdelem_manifested[72]) (::grpc_core::g_static_mdelem_manifested[71])
/* "grpc-accept-encoding": "identity,deflate" */ /* "grpc-accept-encoding": "identity,deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
(::grpc_core::g_static_mdelem_manifested[73]) (::grpc_core::g_static_mdelem_manifested[72])
/* "grpc-accept-encoding": "gzip" */ /* "grpc-accept-encoding": "gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \
(::grpc_core::g_static_mdelem_manifested[74]) (::grpc_core::g_static_mdelem_manifested[73])
/* "grpc-accept-encoding": "identity,gzip" */ /* "grpc-accept-encoding": "identity,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
(::grpc_core::g_static_mdelem_manifested[75]) (::grpc_core::g_static_mdelem_manifested[74])
/* "grpc-accept-encoding": "deflate,gzip" */ /* "grpc-accept-encoding": "deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
(::grpc_core::g_static_mdelem_manifested[76]) (::grpc_core::g_static_mdelem_manifested[75])
/* "grpc-accept-encoding": "identity,deflate,gzip" */ /* "grpc-accept-encoding": "identity,deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ #define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
(::grpc_core::g_static_mdelem_manifested[77]) (::grpc_core::g_static_mdelem_manifested[76])
/* "accept-encoding": "identity" */ /* "accept-encoding": "identity" */
#define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY \ #define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY \
(::grpc_core::g_static_mdelem_manifested[78]) (::grpc_core::g_static_mdelem_manifested[77])
/* "accept-encoding": "gzip" */ /* "accept-encoding": "gzip" */
#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP \ #define GRPC_MDELEM_ACCEPT_ENCODING_GZIP \
(::grpc_core::g_static_mdelem_manifested[79]) (::grpc_core::g_static_mdelem_manifested[78])
/* "accept-encoding": "identity,gzip" */ /* "accept-encoding": "identity,gzip" */
#define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ #define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
(::grpc_core::g_static_mdelem_manifested[80]) (::grpc_core::g_static_mdelem_manifested[79])
grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b); grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b);
typedef enum { typedef enum {
GRPC_BATCH_PATH,
GRPC_BATCH_METHOD,
GRPC_BATCH_STATUS,
GRPC_BATCH_AUTHORITY,
GRPC_BATCH_SCHEME,
GRPC_BATCH_GRPC_ENCODING, GRPC_BATCH_GRPC_ENCODING,
GRPC_BATCH_GRPC_ACCEPT_ENCODING, GRPC_BATCH_GRPC_ACCEPT_ENCODING,
GRPC_BATCH_CONTENT_TYPE,
GRPC_BATCH_CONTENT_ENCODING, GRPC_BATCH_CONTENT_ENCODING,
GRPC_BATCH_ACCEPT_ENCODING, GRPC_BATCH_ACCEPT_ENCODING,
GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST, GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST,
@ -270,14 +261,8 @@ typedef enum {
typedef union { typedef union {
struct grpc_linked_mdelem* array[GRPC_BATCH_CALLOUTS_COUNT]; struct grpc_linked_mdelem* array[GRPC_BATCH_CALLOUTS_COUNT];
struct { 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* grpc_encoding; struct grpc_linked_mdelem* grpc_encoding;
struct grpc_linked_mdelem* grpc_accept_encoding; struct grpc_linked_mdelem* grpc_accept_encoding;
struct grpc_linked_mdelem* content_type;
struct grpc_linked_mdelem* content_encoding; struct grpc_linked_mdelem* content_encoding;
struct grpc_linked_mdelem* accept_encoding; struct grpc_linked_mdelem* accept_encoding;
struct grpc_linked_mdelem* grpc_internal_encoding_request; struct grpc_linked_mdelem* grpc_internal_encoding_request;

@ -717,11 +717,11 @@ alts_handshaker_client* alts_grpc_handshaker_client_create(
channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties, channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties,
grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice, grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice,
GRPC_MILLIS_INF_FUTURE, nullptr); GRPC_MILLIS_INF_FUTURE, nullptr);
grpc_slice_unref_internal(slice);
GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, grpc_cb, client, GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, grpc_cb, client,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&client->on_status_received, on_status_received, client, GRPC_CLOSURE_INIT(&client->on_status_received, on_status_received, client,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_slice_unref_internal(slice);
return &client->base; return &client->base;
} }

@ -199,7 +199,7 @@ void OpenCensusCallTracer::OpenCensusCallAttemptTracer::RecordEnd(
OpenCensusCallTracer::OpenCensusCallTracer(const grpc_call_element_args* args) OpenCensusCallTracer::OpenCensusCallTracer(const grpc_call_element_args* args)
: call_context_(args->context), : call_context_(args->context),
path_(grpc_slice_ref_internal(args->path)), path_(grpc_slice_ref_internal(args->path)),
method_(GetMethod(&path_)), method_(GetMethod(path_)),
arena_(args->arena) {} arena_(args->arena) {}
OpenCensusCallTracer::~OpenCensusCallTracer() { OpenCensusCallTracer::~OpenCensusCallTracer() {
@ -211,7 +211,6 @@ OpenCensusCallTracer::~OpenCensusCallTracer() {
{RpcClientTransparentRetriesPerCall(), transparent_retries_}, {RpcClientTransparentRetriesPerCall(), transparent_retries_},
{RpcClientRetryDelayPerCall(), ToDoubleMilliseconds(retry_delay_)}}, {RpcClientRetryDelayPerCall(), ToDoubleMilliseconds(retry_delay_)}},
tags); tags);
grpc_slice_unref_internal(path_);
} }
void OpenCensusCallTracer::GenerateContext() { void OpenCensusCallTracer::GenerateContext() {

@ -126,15 +126,12 @@ uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info);
// Returns a string representation of the StatusCode enum. // Returns a string representation of the StatusCode enum.
absl::string_view StatusCodeToString(grpc_status_code code); absl::string_view StatusCodeToString(grpc_status_code code);
inline absl::string_view GetMethod(const grpc_slice* path) { inline absl::string_view GetMethod(const grpc_core::Slice& path) {
if (GRPC_SLICE_IS_EMPTY(*path)) { if (path.empty()) {
return ""; return "";
} }
// Check for leading '/' and trim it if present. // Check for leading '/' and trim it if present.
return absl::StripPrefix(absl::string_view(reinterpret_cast<const char*>( return absl::StripPrefix(path.as_string_view(), "/");
GRPC_SLICE_START_PTR(*path)),
GRPC_SLICE_LENGTH(*path)),
"/");
} }
} // namespace grpc } // namespace grpc

@ -84,7 +84,7 @@ class OpenCensusCallTracer : public grpc_core::CallTracer {
private: private:
const grpc_call_context_element* call_context_; const grpc_call_context_element* call_context_;
// Client method. // Client method.
grpc_slice path_; grpc_core::Slice path_;
absl::string_view method_; absl::string_view method_;
CensusContext context_; CensusContext context_;
grpc_core::Arena* arena_; grpc_core::Arena* arena_;

@ -38,16 +38,16 @@ namespace {
// server metadata elements // server metadata elements
struct ServerMetadataElements { struct ServerMetadataElements {
grpc_slice path; grpc_core::Slice path;
grpc_core::Slice tracing_slice; grpc_core::Slice tracing_slice;
grpc_core::Slice census_proto; grpc_core::Slice census_proto;
}; };
void FilterInitialMetadata(grpc_metadata_batch* b, void FilterInitialMetadata(grpc_metadata_batch* b,
ServerMetadataElements* sml) { ServerMetadataElements* sml) {
if (b->legacy_index()->named.path != nullptr) { const auto* path = b->get_pointer(grpc_core::HttpPathMetadata());
sml->path = grpc_slice_ref_internal( if (path != nullptr) {
GRPC_MDVALUE(b->legacy_index()->named.path->md)); sml->path = path->Ref();
} }
auto grpc_trace_bin = b->Take(grpc_core::GrpcTraceBinMetadata()); auto grpc_trace_bin = b->Take(grpc_core::GrpcTraceBinMetadata());
if (grpc_trace_bin.has_value()) { if (grpc_trace_bin.has_value()) {
@ -88,14 +88,12 @@ void CensusServerCallData::OnDoneRecvInitialMetadataCb(
grpc_metadata_batch* initial_metadata = calld->recv_initial_metadata_; grpc_metadata_batch* initial_metadata = calld->recv_initial_metadata_;
GPR_ASSERT(initial_metadata != nullptr); GPR_ASSERT(initial_metadata != nullptr);
ServerMetadataElements sml; ServerMetadataElements sml;
sml.path = grpc_empty_slice();
FilterInitialMetadata(initial_metadata, &sml); FilterInitialMetadata(initial_metadata, &sml);
calld->path_ = grpc_slice_ref_internal(sml.path); calld->path_ = std::move(sml.path);
calld->method_ = GetMethod(&calld->path_); calld->method_ = GetMethod(calld->path_);
calld->qualified_method_ = absl::StrCat("Recv.", calld->method_); calld->qualified_method_ = absl::StrCat("Recv.", calld->method_);
GenerateServerContext(sml.tracing_slice.as_string_view(), GenerateServerContext(sml.tracing_slice.as_string_view(),
calld->qualified_method_, &calld->context_); calld->qualified_method_, &calld->context_);
grpc_slice_unref_internal(sml.path);
grpc_census_call_set_context( grpc_census_call_set_context(
calld->gc_, reinterpret_cast<census_context*>(&calld->context_)); calld->gc_, reinterpret_cast<census_context*>(&calld->context_));
} }
@ -166,7 +164,6 @@ void CensusServerCallData::Destroy(grpc_call_element* /*elem*/,
{RpcServerReceivedMessagesPerRpc(), recv_message_count_}}, {RpcServerReceivedMessagesPerRpc(), recv_message_count_}},
{{ServerMethodTagKey(), method_}, {{ServerMethodTagKey(), method_},
{ServerStatusTagKey(), StatusCodeToString(final_info->final_status)}}); {ServerStatusTagKey(), StatusCodeToString(final_info->final_status)}});
grpc_slice_unref_internal(path_);
context_.EndSpan(); context_.EndSpan();
} }

@ -51,7 +51,6 @@ class CensusServerCallData : public CallData {
recv_message_count_(0), recv_message_count_(0),
sent_message_count_(0) { sent_message_count_(0) {
memset(&census_bin_, 0, sizeof(grpc_linked_mdelem)); memset(&census_bin_, 0, sizeof(grpc_linked_mdelem));
memset(&path_, 0, sizeof(grpc_slice));
memset(&on_done_recv_initial_metadata_, 0, sizeof(grpc_closure)); memset(&on_done_recv_initial_metadata_, 0, sizeof(grpc_closure));
memset(&on_done_recv_message_, 0, sizeof(grpc_closure)); memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
} }
@ -75,7 +74,7 @@ class CensusServerCallData : public CallData {
// server method // server method
absl::string_view method_; absl::string_view method_;
std::string qualified_method_; std::string qualified_method_;
grpc_slice path_; grpc_core::Slice path_;
// Pointer to the grpc_call element // Pointer to the grpc_call element
grpc_call* gc_; grpc_call* gc_;
// Authorization context for the call. // Authorization context for the call.

@ -1,12 +1,6 @@
# hpack fuzzing dictionary # hpack fuzzing dictionary
"\x05:path"
"\x07:method"
"\x07:status"
"\x0A:authority"
"\x07:scheme"
"\x0Dgrpc-encoding" "\x0Dgrpc-encoding"
"\x14grpc-accept-encoding" "\x14grpc-accept-encoding"
"\x0Ccontent-type"
"\x10content-encoding" "\x10content-encoding"
"\x0Faccept-encoding" "\x0Faccept-encoding"
"\x1Egrpc-internal-encoding-request" "\x1Egrpc-internal-encoding-request"
@ -23,12 +17,17 @@
"\x0Bstream/gzip" "\x0Bstream/gzip"
"\x02te" "\x02te"
"\x08trailers" "\x08trailers"
"\x0A:authority"
"\x07:method"
"\x03GET" "\x03GET"
"\x04POST" "\x04POST"
"\x05:path"
"\x01/" "\x01/"
"\x0B/index.html" "\x0B/index.html"
"\x07:scheme"
"\x04http" "\x04http"
"\x05https" "\x05https"
"\x07:status"
"\x03200" "\x03200"
"\x03204" "\x03204"
"\x03206" "\x03206"
@ -51,6 +50,7 @@
"\x0Econtent-length" "\x0Econtent-length"
"\x10content-location" "\x10content-location"
"\x0Dcontent-range" "\x0Dcontent-range"
"\x0Ccontent-type"
"\x06cookie" "\x06cookie"
"\x04date" "\x04date"
"\x04etag" "\x04etag"
@ -82,7 +82,6 @@
"\x03via" "\x03via"
"\x10www-authenticate" "\x10www-authenticate"
"\x08identity" "\x08identity"
"\x10application/grpc"
"\x04grpc" "\x04grpc"
"\x03PUT" "\x03PUT"
"\x0Blb-cost-bin" "\x0Blb-cost-bin"
@ -154,7 +153,6 @@
"\x00\x0Dgrpc-encoding\x08identity" "\x00\x0Dgrpc-encoding\x08identity"
"\x00\x0Dgrpc-encoding\x04gzip" "\x00\x0Dgrpc-encoding\x04gzip"
"\x00\x0Dgrpc-encoding\x07deflate" "\x00\x0Dgrpc-encoding\x07deflate"
"\x00\x0Ccontent-type\x10application/grpc"
"\x00\x07:scheme\x04grpc" "\x00\x07:scheme\x04grpc"
"\x00\x07:method\x03PUT" "\x00\x07:method\x03PUT"
"\x00\x0Faccept-encoding\x00" "\x00\x0Faccept-encoding\x00"

@ -266,11 +266,10 @@ static void server_start_transport_stream_op_batch(
if (data->call == g_server_call_stack) { if (data->call == g_server_call_stack) {
if (op->send_initial_metadata) { if (op->send_initial_metadata) {
auto* batch = op->payload->send_initial_metadata.send_initial_metadata; auto* batch = op->payload->send_initial_metadata.send_initial_metadata;
if (batch->legacy_index()->named.status != nullptr) { auto* status = batch->get_pointer(grpc_core::HttpStatusMetadata());
if (status != nullptr) {
/* Replace the HTTP status with 404 */ /* Replace the HTTP status with 404 */
GPR_ASSERT(GRPC_LOG_IF_ERROR( *status = 404;
"Substitute", batch->Substitute(batch->legacy_index()->named.status,
GRPC_MDELEM_STATUS_404)));
} }
} }
} }

@ -166,7 +166,8 @@ static void test_retry_exceeds_buffer_size_in_delay(
grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv); grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details); grpc_call_details_init(&call_details);
grpc_slice status_details = grpc_slice_from_static_string("xyz"); grpc_slice status_details1 = grpc_slice_from_static_string("message1");
grpc_slice status_details2 = grpc_slice_from_static_string("message2");
// Client sends initial metadata and starts the recv ops. // Client sends initial metadata and starts the recv ops.
memset(ops, 0, sizeof(ops)); memset(ops, 0, sizeof(ops));
@ -215,7 +216,7 @@ static void test_retry_exceeds_buffer_size_in_delay(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; op->data.send_status_from_server.status = GRPC_STATUS_ABORTED;
op->data.send_status_from_server.status_details = &status_details; op->data.send_status_from_server.status_details = &status_details1;
op++; op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled; op->data.recv_close_on_server.cancelled = &was_cancelled;
@ -269,7 +270,7 @@ static void test_retry_exceeds_buffer_size_in_delay(
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; op->data.send_status_from_server.status = GRPC_STATUS_ABORTED;
op->data.send_status_from_server.status_details = &status_details; op->data.send_status_from_server.status_details = &status_details2;
op++; op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled; op->data.recv_close_on_server.cancelled = &was_cancelled;
@ -282,7 +283,7 @@ static void test_retry_exceeds_buffer_size_in_delay(
cq_verify(cqv); cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_ABORTED); GPR_ASSERT(status == GRPC_STATUS_ABORTED);
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "message2"));
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
GPR_ASSERT(0 == call_details.flags); GPR_ASSERT(0 == call_details.flags);
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);

@ -163,7 +163,8 @@ static void test_retry_server_pushback_delay(grpc_end2end_test_config config) {
grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv); grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details); grpc_call_details_init(&call_details);
grpc_slice status_details = grpc_slice_from_static_string("xyz"); grpc_slice status_details1 = grpc_slice_from_static_string("message1");
grpc_slice status_details2 = grpc_slice_from_static_string("message2");
memset(ops, 0, sizeof(ops)); memset(ops, 0, sizeof(ops));
op = ops; op = ops;
@ -215,7 +216,7 @@ static void test_retry_server_pushback_delay(grpc_end2end_test_config config) {
op->data.send_status_from_server.trailing_metadata_count = 1; op->data.send_status_from_server.trailing_metadata_count = 1;
op->data.send_status_from_server.trailing_metadata = &pushback_md; op->data.send_status_from_server.trailing_metadata = &pushback_md;
op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; op->data.send_status_from_server.status = GRPC_STATUS_ABORTED;
op->data.send_status_from_server.status_details = &status_details; op->data.send_status_from_server.status_details = &status_details1;
op++; op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled; op->data.recv_close_on_server.cancelled = &was_cancelled;
@ -270,7 +271,7 @@ static void test_retry_server_pushback_delay(grpc_end2end_test_config config) {
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK; op->data.send_status_from_server.status = GRPC_STATUS_OK;
op->data.send_status_from_server.status_details = &status_details; op->data.send_status_from_server.status_details = &status_details2;
op++; op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled; op->data.recv_close_on_server.cancelled = &was_cancelled;
@ -284,7 +285,7 @@ static void test_retry_server_pushback_delay(grpc_end2end_test_config config) {
cq_verify(cqv); cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_OK); GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "message2"));
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
GPR_ASSERT(0 == call_details.flags); GPR_ASSERT(0 == call_details.flags);
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);

@ -132,14 +132,42 @@ void MockCallback(void* arg, grpc_error_handle error) {
} }
} }
std::string MetadataString(const Metadata& a) {
return absl::StrCat(
"{",
absl::StrJoin(
a, ", ",
[](std::string* out, const std::pair<std::string, std::string>& kv) {
out->append(
absl::StrCat("\"", kv.first, "\": \"", kv.second, "\""));
}),
"}");
}
bool MetadataEquivalent(Metadata a, Metadata b) {
std::sort(a.begin(), a.end());
std::sort(b.begin(), b.end());
return a == b;
}
// Matches with transactions having the desired flag, method_ref, // Matches with transactions having the desired flag, method_ref,
// initial_metadata, and message_data. // initial_metadata, and message_data.
MATCHER_P4(TransactionMatches, flag, method_ref, initial_metadata, message_data, MATCHER_P4(TransactionMatches, flag, method_ref, initial_metadata, message_data,
"") { "") {
if (arg.GetFlags() != flag) return false; if (arg.GetFlags() != flag) return false;
if (flag & kFlagPrefix) { if (flag & kFlagPrefix) {
if (arg.GetMethodRef() != method_ref) return false; if (arg.GetMethodRef() != method_ref) {
if (arg.GetPrefixMetadata() != initial_metadata) return false; printf("METHOD REF NOT EQ: %s %s\n",
std::string(arg.GetMethodRef()).c_str(),
std::string(method_ref).c_str());
return false;
}
if (!MetadataEquivalent(arg.GetPrefixMetadata(), initial_metadata)) {
printf("METADATA NOT EQUIVALENT: %s %s\n",
MetadataString(arg.GetPrefixMetadata()).c_str(),
MetadataString(initial_metadata).c_str());
return false;
}
} }
if (flag & kFlagMessageData) { if (flag & kFlagMessageData) {
if (arg.GetMessageData() != message_data) return false; if (arg.GetMessageData() != message_data) return false;
@ -181,33 +209,24 @@ void VerifyMetadataEqual(const Metadata& md,
const grpc_metadata_batch& grpc_md) { const grpc_metadata_batch& grpc_md) {
MetadataEncoder encoder; MetadataEncoder encoder;
grpc_md.Encode(&encoder); grpc_md.Encode(&encoder);
EXPECT_EQ(encoder.metadata(), md); EXPECT_TRUE(MetadataEquivalent(encoder.metadata(), md));
} }
// RAII helper classes for constructing gRPC metadata and receiving callbacks. // RAII helper classes for constructing gRPC metadata and receiving callbacks.
struct MakeSendInitialMetadata { struct MakeSendInitialMetadata {
MakeSendInitialMetadata(const Metadata& initial_metadata, MakeSendInitialMetadata(const Metadata& initial_metadata,
const std::string& method_ref, const std::string& method_ref,
grpc_transport_stream_op_batch* op) grpc_transport_stream_op_batch* op) {
: storage(initial_metadata.size()) {
size_t i = 0;
for (const auto& md : initial_metadata) { for (const auto& md : initial_metadata) {
const std::string& key = md.first; const std::string& key = md.first;
const std::string& value = md.second; const std::string& value = md.second;
EXPECT_EQ(grpc_metadata_batch_add_tail( grpc_initial_metadata.Append(
&grpc_initial_metadata, &storage[i], key, grpc_core::Slice::FromCopiedString(value),
grpc_mdelem_from_slices(grpc_slice_from_cpp_string(key), [](absl::string_view, const grpc_core::Slice&) { abort(); });
grpc_slice_from_cpp_string(value))),
GRPC_ERROR_NONE);
i++;
} }
if (!method_ref.empty()) { if (!method_ref.empty()) {
EXPECT_EQ( grpc_initial_metadata.Set(grpc_core::HttpPathMetadata(),
grpc_metadata_batch_add_tail( grpc_core::Slice::FromCopiedString(method_ref));
&grpc_initial_metadata, &method_ref_storage,
grpc_mdelem_from_slices(GRPC_MDSTR_PATH,
grpc_slice_from_cpp_string(method_ref))),
GRPC_ERROR_NONE);
} }
op->send_initial_metadata = true; op->send_initial_metadata = true;
op->payload->send_initial_metadata.send_initial_metadata = op->payload->send_initial_metadata.send_initial_metadata =
@ -215,8 +234,6 @@ struct MakeSendInitialMetadata {
} }
~MakeSendInitialMetadata() {} ~MakeSendInitialMetadata() {}
std::vector<grpc_linked_mdelem> storage;
grpc_linked_mdelem method_ref_storage;
grpc_core::ScopedArenaPtr arena = grpc_core::ScopedArenaPtr arena =
grpc_core::MakeScopedArena(1024, g_memory_allocator); grpc_core::MakeScopedArena(1024, g_memory_allocator);
grpc_metadata_batch grpc_initial_metadata{arena.get()}; grpc_metadata_batch grpc_initial_metadata{arena.get()};

@ -122,8 +122,9 @@ class ParseTest : public ::testing::TestWithParam<Test> {
} }
template <typename T, typename V> template <typename T, typename V>
void Encode(T, const V&) { void Encode(T, const V& v) {
abort(); // not implemented out_.append(
absl::StrCat(T::key(), ": ", T::Encode(v).as_string_view(), "\n"));
} }
private: private:
@ -169,24 +170,24 @@ INSTANTIATE_TEST_SUITE_P(
/* D.3.1 */ /* D.3.1 */
{"8286 8441 0f77 7777 2e65 7861 6d70 6c65" {"8286 8441 0f77 7777 2e65 7861 6d70 6c65"
"2e63 6f6d", "2e63 6f6d",
":method: GET\n"
":scheme: http\n"
":path: /\n" ":path: /\n"
":authority: www.example.com\n"}, ":authority: www.example.com\n"
":method: GET\n"
":scheme: http\n"},
/* D.3.2 */ /* D.3.2 */
{"8286 84be 5808 6e6f 2d63 6163 6865", {"8286 84be 5808 6e6f 2d63 6163 6865",
":method: GET\n"
":scheme: http\n"
":path: /\n" ":path: /\n"
":authority: www.example.com\n" ":authority: www.example.com\n"
":method: GET\n"
":scheme: http\n"
"cache-control: no-cache\n"}, "cache-control: no-cache\n"},
/* D.3.3 */ /* D.3.3 */
{"8287 85bf 400a 6375 7374 6f6d 2d6b 6579" {"8287 85bf 400a 6375 7374 6f6d 2d6b 6579"
"0c63 7573 746f 6d2d 7661 6c75 65", "0c63 7573 746f 6d2d 7661 6c75 65",
":method: GET\n"
":scheme: https\n"
":path: /index.html\n" ":path: /index.html\n"
":authority: www.example.com\n" ":authority: www.example.com\n"
":method: GET\n"
":scheme: https\n"
"custom-key: custom-value\n"}, "custom-key: custom-value\n"},
}}, }},
Test{{}, Test{{},
@ -194,24 +195,24 @@ INSTANTIATE_TEST_SUITE_P(
/* D.4.1 */ /* D.4.1 */
{"8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4" {"8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4"
"ff", "ff",
":method: GET\n"
":scheme: http\n"
":path: /\n" ":path: /\n"
":authority: www.example.com\n"}, ":authority: www.example.com\n"
":method: GET\n"
":scheme: http\n"},
/* D.4.2 */ /* D.4.2 */
{"8286 84be 5886 a8eb 1064 9cbf", {"8286 84be 5886 a8eb 1064 9cbf",
":method: GET\n"
":scheme: http\n"
":path: /\n" ":path: /\n"
":authority: www.example.com\n" ":authority: www.example.com\n"
":method: GET\n"
":scheme: http\n"
"cache-control: no-cache\n"}, "cache-control: no-cache\n"},
/* D.4.3 */ /* D.4.3 */
{"8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925" {"8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925"
"a849 e95b b8e8 b4bf", "a849 e95b b8e8 b4bf",
":method: GET\n"
":scheme: https\n"
":path: /index.html\n" ":path: /index.html\n"
":authority: www.example.com\n" ":authority: www.example.com\n"
":method: GET\n"
":scheme: https\n"
"custom-key: custom-value\n"}, "custom-key: custom-value\n"},
}}, }},
Test{{256}, Test{{256},

@ -32,7 +32,9 @@ struct CharTrait {
static char test_value() { return 'a'; } static char test_value() { return 'a'; }
static size_t test_memento_transport_size() { return 34; } static size_t test_memento_transport_size() { return 34; }
static char MementoToValue(char memento) { return memento; } static char MementoToValue(char memento) { return memento; }
static char ParseMemento(Slice slice) { return slice[0]; } static char ParseMemento(Slice slice, MetadataParseErrorFn) {
return slice[0];
}
static std::string DisplayValue(char value) { return std::string(1, value); } static std::string DisplayValue(char value) { return std::string(1, value); }
}; };
@ -43,7 +45,7 @@ struct Int32Trait {
static int32_t test_value() { return -1; } static int32_t test_value() { return -1; }
static size_t test_memento_transport_size() { return 478; } static size_t test_memento_transport_size() { return 478; }
static int32_t MementoToValue(int32_t memento) { return memento; } static int32_t MementoToValue(int32_t memento) { return memento; }
static int32_t ParseMemento(Slice slice) { static int32_t ParseMemento(Slice slice, MetadataParseErrorFn) {
int32_t out; int32_t out;
GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out)); GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
return out; return out;
@ -60,7 +62,7 @@ struct Int64Trait {
static int64_t test_value() { return -83481847284179298; } static int64_t test_value() { return -83481847284179298; }
static size_t test_memento_transport_size() { return 87; } static size_t test_memento_transport_size() { return 87; }
static int64_t MementoToValue(int64_t memento) { return -memento; } static int64_t MementoToValue(int64_t memento) { return -memento; }
static int64_t ParseMemento(Slice slice) { static int64_t ParseMemento(Slice slice, MetadataParseErrorFn) {
int64_t out; int64_t out;
GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out)); GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
return out; return out;
@ -77,7 +79,7 @@ struct IntptrTrait {
static intptr_t test_value() { return test_memento() / 2; } static intptr_t test_value() { return test_memento() / 2; }
static size_t test_memento_transport_size() { return 800; } static size_t test_memento_transport_size() { return 800; }
static intptr_t MementoToValue(intptr_t memento) { return memento / 2; } static intptr_t MementoToValue(intptr_t memento) { return memento / 2; }
static intptr_t ParseMemento(Slice slice) { static intptr_t ParseMemento(Slice slice, MetadataParseErrorFn) {
intptr_t out; intptr_t out;
GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out)); GPR_ASSERT(absl::SimpleAtoi(slice.as_string_view(), &out));
return out; return out;
@ -96,7 +98,7 @@ struct StringTrait {
static std::string MementoToValue(std::string memento) { static std::string MementoToValue(std::string memento) {
return "hi " + memento; return "hi " + memento;
} }
static std::string ParseMemento(Slice slice) { static std::string ParseMemento(Slice slice, MetadataParseErrorFn) {
auto view = slice.as_string_view(); auto view = slice.as_string_view();
return std::string(view.begin(), view.end()); return std::string(view.begin(), view.end());
} }

@ -34,7 +34,11 @@ class EvaluateArgsTestUtil {
void AddPairToMetadata(const char* key, const char* value) { void AddPairToMetadata(const char* key, const char* value) {
metadata_.Append( metadata_.Append(
key, Slice(grpc_slice_intern(grpc_slice_from_static_string(value)))); key, Slice(grpc_slice_intern(grpc_slice_from_static_string(value))),
[](absl::string_view, const Slice&) {
// We should never ever see an error here.
abort();
});
} }
void SetLocalEndpoint(absl::string_view local_uri) { void SetLocalEndpoint(absl::string_view local_uri) {

@ -25,6 +25,7 @@
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -262,30 +263,26 @@ class RepresentativeClientInitialMetadata {
public: public:
static constexpr bool kEnableTrueBinary = true; static constexpr bool kEnableTrueBinary = true;
static void Prepare(grpc_metadata_batch* b) { static void Prepare(grpc_metadata_batch* b) {
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_SCHEME_HTTP))); b->Set(grpc_core::HttpSchemeMetadata(),
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_METHOD_POST))); grpc_core::HttpSchemeMetadata::kHttp);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::HttpMethodMetadata(),
"addmd", grpc_core::HttpMethodMetadata::kPost);
b->Append(grpc_mdelem_from_slices( b->Set(
GRPC_MDSTR_PATH, grpc_core::HttpPathMetadata(),
grpc_slice_intern(grpc_slice_from_static_string("/foo/bar")))))); grpc_core::Slice(grpc_core::StaticSlice::FromStaticString("/foo/bar")));
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::HttpAuthorityMetadata(),
"addmd", b->Append(grpc_mdelem_from_slices( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
GRPC_MDSTR_AUTHORITY, "foo.test.google.fr:1234")));
grpc_slice_intern(grpc_slice_from_static_string(
"foo.test.google.fr:1234"))))));
GPR_ASSERT(GRPC_LOG_IF_ERROR( GPR_ASSERT(GRPC_LOG_IF_ERROR(
"addmd", "addmd",
b->Append( b->Append(
GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP))); GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers); b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::ContentTypeMetadata(),
"addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC))); grpc_core::ContentTypeMetadata::kApplicationGrpc);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::UserAgentMetadata(),
"addmd", b->Append(grpc_mdelem_from_slices( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
GRPC_MDSTR_USER_AGENT, "grpc-c/3.0.0-dev (linux; chttp2; green)")));
grpc_slice_intern(grpc_slice_from_static_string(
"grpc-c/3.0.0-dev (linux; chttp2; green)"))))));
} }
}; };
@ -296,18 +293,16 @@ class MoreRepresentativeClientInitialMetadata {
public: public:
static constexpr bool kEnableTrueBinary = true; static constexpr bool kEnableTrueBinary = true;
static void Prepare(grpc_metadata_batch* b) { static void Prepare(grpc_metadata_batch* b) {
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_SCHEME_HTTP))); b->Set(grpc_core::HttpSchemeMetadata(),
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_METHOD_POST))); grpc_core::HttpSchemeMetadata::kHttp);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::HttpMethodMetadata(),
"addmd", grpc_core::HttpMethodMetadata::kPost);
b->Append(grpc_mdelem_from_slices( b->Set(grpc_core::HttpPathMetadata(),
GRPC_MDSTR_PATH, grpc_slice_intern(grpc_slice_from_static_string( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
"/grpc.test.FooService/BarMethod")))))); "/grpc.test.FooService/BarMethod")));
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::HttpAuthorityMetadata(),
"addmd", b->Append(grpc_mdelem_from_slices( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
GRPC_MDSTR_AUTHORITY, "foo.test.google.fr:1234")));
grpc_slice_intern(grpc_slice_from_static_string(
"foo.test.google.fr:1234"))))));
b->Set(grpc_core::GrpcTraceBinMetadata(), b->Set(grpc_core::GrpcTraceBinMetadata(),
grpc_core::Slice(grpc_core::StaticSlice::FromStaticString( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
"\x00\x01\x02\x03\x04\x05\x06\x07\x08" "\x00\x01\x02\x03\x04\x05\x06\x07\x08"
@ -327,13 +322,11 @@ class MoreRepresentativeClientInitialMetadata {
b->Append( b->Append(
GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP))); GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers); b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::ContentTypeMetadata(),
"addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC))); grpc_core::ContentTypeMetadata::kApplicationGrpc);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::UserAgentMetadata(),
"addmd", b->Append(grpc_mdelem_from_slices( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
GRPC_MDSTR_USER_AGENT, "grpc-c/3.0.0-dev (linux; chttp2; green)")));
grpc_slice_intern(grpc_slice_from_static_string(
"grpc-c/3.0.0-dev (linux; chttp2; green)"))))));
} }
}; };
@ -341,9 +334,9 @@ class RepresentativeServerInitialMetadata {
public: public:
static constexpr bool kEnableTrueBinary = true; static constexpr bool kEnableTrueBinary = true;
static void Prepare(grpc_metadata_batch* b) { static void Prepare(grpc_metadata_batch* b) {
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_STATUS_200))); b->Set(grpc_core::HttpStatusMetadata(), 200);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::ContentTypeMetadata(),
"addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC))); grpc_core::ContentTypeMetadata::kApplicationGrpc);
GPR_ASSERT(GRPC_LOG_IF_ERROR( GPR_ASSERT(GRPC_LOG_IF_ERROR(
"addmd", "addmd",
b->Append( b->Append(
@ -468,9 +461,9 @@ BENCHMARK(BM_HpackParserInitDestroy);
template <class Fixture> template <class Fixture>
static void BM_HpackParserParseHeader(benchmark::State& state) { static void BM_HpackParserParseHeader(benchmark::State& state) {
TrackCounters track_counters; TrackCounters track_counters;
grpc_core::ExecCtx exec_ctx;
std::vector<grpc_slice> init_slices = Fixture::GetInitSlices(); std::vector<grpc_slice> init_slices = Fixture::GetInitSlices();
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices(); std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
grpc_core::ExecCtx exec_ctx;
grpc_core::HPackParser p; grpc_core::HPackParser p;
const int kArenaSize = 4096 * 4096; const int kArenaSize = 4096 * 4096;
auto* arena = grpc_core::Arena::Create(kArenaSize, g_memory_allocator); auto* arena = grpc_core::Arena::Create(kArenaSize, g_memory_allocator);
@ -481,14 +474,16 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
grpc_core::HPackParser::Priority::None, grpc_core::HPackParser::Priority::None,
grpc_core::HPackParser::LogInfo{ grpc_core::HPackParser::LogInfo{
1, grpc_core::HPackParser::LogInfo::kHeaders, false}); 1, grpc_core::HPackParser::LogInfo::kHeaders, false});
for (auto slice : init_slices) { auto parse_vec = [&p](const std::vector<grpc_slice>& slices) {
GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice, false)); for (size_t i = 0; i < slices.size(); ++i) {
} auto error = p.Parse(slices[i], i == slices.size() - 1);
GPR_ASSERT(error == GRPC_ERROR_NONE);
}
};
parse_vec(init_slices);
while (state.KeepRunning()) { while (state.KeepRunning()) {
b->Clear(); b->Clear();
for (auto slice : benchmark_slices) { parse_vec(benchmark_slices);
GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice, false));
}
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
// Recreate arena every 4k iterations to avoid oom // Recreate arena every 4k iterations to avoid oom
if (0 == (state.iterations() & 0xfff)) { if (0 == (state.iterations() & 0xfff)) {
@ -514,6 +509,57 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
namespace hpack_parser_fixtures { namespace hpack_parser_fixtures {
template <class EncoderFixture>
class FromEncoderFixture {
public:
static std::vector<grpc_slice> GetInitSlices() { return Generate(0); }
static std::vector<grpc_slice> GetBenchmarkSlices() { return Generate(1); }
private:
static std::vector<grpc_slice> Generate(int iteration) {
grpc_core::ExecCtx exec_ctx;
auto arena = grpc_core::MakeScopedArena(1024, g_memory_allocator);
grpc_metadata_batch b(arena.get());
EncoderFixture::Prepare(&b);
grpc_core::HPackCompressor c;
grpc_transport_one_way_stats stats;
std::vector<grpc_slice> out;
stats = {};
bool done = false;
int i = 0;
while (!done) {
grpc_slice_buffer outbuf;
grpc_slice_buffer_init(&outbuf);
c.EncodeHeaders(
grpc_core::HPackCompressor::EncodeHeaderOptions{
static_cast<uint32_t>(i),
false,
EncoderFixture::kEnableTrueBinary,
1024 * 1024,
&stats,
},
b, &outbuf);
if (i == iteration) {
for (size_t s = 0; s < outbuf.count; s++) {
out.push_back(grpc_slice_ref_internal(outbuf.slices[s]));
}
done = true;
}
grpc_slice_buffer_reset_and_unref_internal(&outbuf);
grpc_core::ExecCtx::Get()->Flush();
grpc_slice_buffer_destroy_internal(&outbuf);
i++;
}
// Remove the HTTP header.
GPR_ASSERT(!out.empty());
GPR_ASSERT(GRPC_SLICE_LENGTH(out[0]) > 9);
out[0] = grpc_slice_sub_no_ref(out[0], 9, GRPC_SLICE_LENGTH(out[0]));
return out;
}
};
class EmptyBatch { class EmptyBatch {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static std::vector<grpc_slice> GetInitSlices() { return {}; }
@ -549,7 +595,7 @@ class KeyIndexedSingleStaticElem {
{0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0x7e, 0x03, 'd', 'e', 'f'})}; return {MakeSlice({0x7e, 0x03, '4', '0', '4'})};
} }
}; };
@ -671,135 +717,14 @@ class NonIndexedBinaryElem<100, false> {
} }
}; };
class RepresentativeClientInitialMetadata { using RepresentativeClientInitialMetadata = FromEncoderFixture<
public: hpack_encoder_fixtures::RepresentativeClientInitialMetadata>;
static std::vector<grpc_slice> GetInitSlices() { using RepresentativeServerInitialMetadata = FromEncoderFixture<
return {grpc_slice_from_static_string( hpack_encoder_fixtures::RepresentativeServerInitialMetadata>;
// generated with: using RepresentativeServerTrailingMetadata = FromEncoderFixture<
// ``` hpack_encoder_fixtures::RepresentativeServerTrailingMetadata>;
// tools/codegen/core/gen_header_frame.py --compression inc --no_framing using MoreRepresentativeClientInitialMetadata = FromEncoderFixture<
// < test/core/bad_client/tests/simple_request.headers hpack_encoder_fixtures::MoreRepresentativeClientInitialMetadata>;
// ```
"@\x05:path\x08/foo/bar"
"@\x07:scheme\x04http"
"@\x07:method\x04POST"
"@\x0a:authority\x09localhost"
"@\x0c"
"content-type\x10"
"application/grpc"
"@\x14grpc-accept-encoding\x15identity,deflate,gzip"
"@\x02te\x08trailers"
"@\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)")};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
// generated with:
// ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex < test/core/bad_client/tests/simple_request.headers
// ```
return {MakeSlice({0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe})};
}
};
// This fixture reflects how initial metadata are sent by a production client,
// with non-indexed :path and binary headers. The metadata here are the same as
// the corresponding encoder benchmark above.
class MoreRepresentativeClientInitialMetadata {
public:
static std::vector<grpc_slice> GetInitSlices() {
return {MakeSlice(
{0x40, 0x07, ':', 's', 'c', 'h', 'e', 'm', 'e', 0x04, 'h', 't',
't', 'p', 0x40, 0x07, ':', 'm', 'e', 't', 'h', 'o', 'd', 0x04,
'P', 'O', 'S', 'T', 0x40, 0x05, ':', 'p', 'a', 't', 'h', 0x1f,
'/', 'g', 'r', 'p', 'c', '.', 't', 'e', 's', 't', '.', 'F',
'o', 'o', 'S', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'B', 'a',
'r', 'M', 'e', 't', 'h', 'o', 'd', 0x40, 0x0a, ':', 'a', 'u',
't', 'h', 'o', 'r', 'i', 't', 'y', 0x09, 'l', 'o', 'c', 'a',
'l', 'h', 'o', 's', 't', 0x40, 0x0e, 'g', 'r', 'p', 'c', '-',
't', 'r', 'a', 'c', 'e', '-', 'b', 'i', 'n', 0x31, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x40,
0x0d, 'g', 'r', 'p', 'c', '-', 't', 'a', 'g', 's', '-', 'b',
'i', 'n', 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x40,
0x0c, 'c', 'o', 'n', 't', 'e', 'n', 't', '-', 't', 'y', 'p',
'e', 0x10, 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o',
'n', '/', 'g', 'r', 'p', 'c', 0x40, 0x14, 'g', 'r', 'p', 'c',
'-', 'a', 'c', 'c', 'e', 'p', 't', '-', 'e', 'n', 'c', 'o',
'd', 'i', 'n', 'g', 0x15, 'i', 'd', 'e', 'n', 't', 'i', 't',
'y', ',', 'd', 'e', 'f', 'l', 'a', 't', 'e', ',', 'g', 'z',
'i', 'p', 0x40, 0x02, 't', 'e', 0x08, 't', 'r', 'a', 'i', 'l',
'e', 'r', 's', 0x40, 0x0a, 'u', 's', 'e', 'r', '-', 'a', 'g',
'e', 'n', 't', 0x22, 'b', 'a', 'd', '-', 'c', 'l', 'i', 'e',
'n', 't', ' ', 'g', 'r', 'p', 'c', '-', 'c', '/', '0', '.',
'1', '2', '.', '0', '.', '0', ' ', '(', 'l', 'i', 'n', 'u',
'x', ')'})};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({
0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
})};
}
};
class RepresentativeServerInitialMetadata {
public:
static std::vector<grpc_slice> GetInitSlices() {
return {grpc_slice_from_static_string(
// generated with:
// ```
// tools/codegen/core/gen_header_frame.py --compression inc --no_framing
// <
// test/cpp/microbenchmarks/representative_server_initial_metadata.headers
// ```
"@\x07:status\x03"
"200"
"@\x0c"
"content-type\x10"
"application/grpc"
"@\x14grpc-accept-encoding\x15identity,deflate,gzip")};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
// generated with:
// ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex <
// test/cpp/microbenchmarks/representative_server_initial_metadata.headers
// ```
return {MakeSlice({0xc0, 0xbf, 0xbe})};
}
};
class RepresentativeServerTrailingMetadata {
public:
static std::vector<grpc_slice> GetInitSlices() {
return {grpc_slice_from_static_string(
// generated with:
// ```
// tools/codegen/core/gen_header_frame.py --compression inc --no_framing
// <
// test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
// ```
"@\x0bgrpc-status\x01"
"0"
"@\x0cgrpc-message\x00")};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
// generated with:
// ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex <
// test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
// ```
return {MakeSlice({0xbf, 0xbe})};
}
};
// Send the same deadline repeatedly // Send the same deadline repeatedly
class SameDeadline { class SameDeadline {

@ -294,30 +294,26 @@ BENCHMARK(BM_StreamCreateDestroy);
class RepresentativeClientInitialMetadata { class RepresentativeClientInitialMetadata {
public: public:
static void Prepare(grpc_metadata_batch* b) { static void Prepare(grpc_metadata_batch* b) {
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_SCHEME_HTTP))); b->Set(grpc_core::HttpSchemeMetadata(),
GPR_ASSERT(GRPC_LOG_IF_ERROR("addmd", b->Append(GRPC_MDELEM_METHOD_POST))); grpc_core::HttpSchemeMetadata::kHttp);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::HttpMethodMetadata(),
"addmd", grpc_core::HttpMethodMetadata::kPost);
b->Append(grpc_mdelem_from_slices( b->Set(grpc_core::HttpPathMetadata(),
GRPC_MDSTR_PATH, grpc_slice_intern(grpc_slice_from_static_string( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
"/foo/bar/bm_chttp2_transport")))))); "/foo/bar/bm_chttp2_transport")));
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::HttpAuthorityMetadata(),
"addmd", b->Append(grpc_mdelem_from_slices( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
GRPC_MDSTR_AUTHORITY, "foo.test.google.fr:1234")));
grpc_slice_intern(grpc_slice_from_static_string(
"foo.test.google.fr:1234"))))));
GPR_ASSERT(GRPC_LOG_IF_ERROR( GPR_ASSERT(GRPC_LOG_IF_ERROR(
"addmd", "addmd",
b->Append( b->Append(
GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP))); GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP)));
b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers); b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::ContentTypeMetadata(),
"addmd", b->Append(GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC))); grpc_core::ContentTypeMetadata::kApplicationGrpc);
GPR_ASSERT(GRPC_LOG_IF_ERROR( b->Set(grpc_core::UserAgentMetadata(),
"addmd", b->Append(grpc_mdelem_from_slices( grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
GRPC_MDSTR_USER_AGENT, "grpc-c/3.0.0-dev (linux; chttp2; green)")));
grpc_slice_intern(grpc_slice_from_static_string(
"grpc-c/3.0.0-dev (linux; chttp2; green)"))))));
} }
}; };

@ -1,4 +0,0 @@
:status: 200
content-type: application/grpc
grpc-accept-encoding: identity,deflate,gzip

@ -36,10 +36,8 @@ import perfection
CONFIG = [ CONFIG = [
# metadata strings # metadata strings
'grpc-internal-encoding-request', 'grpc-internal-encoding-request',
':path',
'grpc-encoding', 'grpc-encoding',
'grpc-accept-encoding', 'grpc-accept-encoding',
':authority',
'grpc-timeout', 'grpc-timeout',
'', '',
# well known method names # well known method names
@ -123,7 +121,6 @@ CONFIG = [
('grpc-encoding', 'identity'), ('grpc-encoding', 'identity'),
('grpc-encoding', 'gzip'), ('grpc-encoding', 'gzip'),
('grpc-encoding', 'deflate'), ('grpc-encoding', 'deflate'),
('content-type', 'application/grpc'),
(':scheme', 'grpc'), (':scheme', 'grpc'),
(':method', 'PUT'), (':method', 'PUT'),
('accept-encoding', ''), ('accept-encoding', ''),
@ -135,14 +132,8 @@ CONFIG = [
# All entries here are ignored when counting non-default initial metadata that # All entries here are ignored when counting non-default initial metadata that
# prevents the chttp2 server from sending a Trailers-Only response. # prevents the chttp2 server from sending a Trailers-Only response.
METADATA_BATCH_CALLOUTS = [ METADATA_BATCH_CALLOUTS = [
':path',
':method',
':status',
':authority',
':scheme',
'grpc-encoding', 'grpc-encoding',
'grpc-accept-encoding', 'grpc-accept-encoding',
'content-type',
'content-encoding', 'content-encoding',
'accept-encoding', 'accept-encoding',
'grpc-internal-encoding-request', 'grpc-internal-encoding-request',

Loading…
Cancel
Save