Progress towards mdstr elimination

reviewable/pr8842/r1
Craig Tiller 8 years ago
parent 4eecdde403
commit 68208fe422
  1. 7
      include/grpc/grpc.h
  2. 5
      include/grpc/impl/codegen/compression_types.h
  3. 39
      include/grpc/impl/codegen/grpc_types.h
  4. 4
      src/core/lib/compression/algorithm_metadata.h
  5. 4
      src/core/lib/compression/compression.c
  6. 3
      src/core/lib/slice/slice_string_helpers.h
  7. 122
      src/core/lib/surface/call.c
  8. 6
      src/core/lib/surface/call_details.c
  9. 19
      src/core/lib/surface/call_log_batch.c
  10. 62
      src/core/lib/surface/channel.c
  11. 5
      src/core/lib/surface/channel.h
  12. 9
      src/core/lib/surface/lame_client.c
  13. 93
      src/core/lib/surface/server.c
  14. 4
      src/core/lib/transport/metadata.h
  15. 10
      test/core/compression/algorithm_test.c
  16. 4
      test/core/end2end/cq_verifier.c
  17. 10
      test/core/end2end/fixtures/proxy.c

@ -178,8 +178,8 @@ GRPCAPI void grpc_channel_watch_connectivity_state(
possible values). */
GRPCAPI grpc_call *grpc_channel_create_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
grpc_completion_queue *completion_queue, const char *method,
const char *host, gpr_timespec deadline, void *reserved);
grpc_completion_queue *completion_queue, grpc_slice method,
const grpc_slice *host, gpr_timespec deadline, void *reserved);
/** Ping the channels peer (load balanced channels will select one sub-channel
to ping); if the channel is not connected, posts a failed. */
@ -397,13 +397,16 @@ GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled);
/** Check whether a metadata key is legal (will be accepted by core) */
GRPCAPI int grpc_header_key_is_legal(const char *key, size_t length);
GRPCAPI int grpc_header_key_slice_is_legal(grpc_slice slice);
/** Check whether a non-binary metadata value is legal (will be accepted by
core) */
GRPCAPI int grpc_header_nonbin_value_is_legal(const char *value, size_t length);
GRPCAPI int grpc_header_nonbin_value_slice_is_legal(grpc_slice slice);
/** Check whether a metadata key corresponds to a binary value */
GRPCAPI int grpc_is_binary_header(const char *key, size_t length);
GRPCAPI int grpc_slice_is_binary_header(grpc_slice slice);
/** Convert grpc_call_error values to a string */
GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error);

@ -41,11 +41,6 @@
extern "C" {
#endif
/** To be used as initial metadata key for the request of a concrete compression
* algorithm */
#define GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \
"grpc-internal-encoding-request"
/** To be used in channel arguments.
*
* \addtogroup grpc_arg_keys

@ -287,9 +287,8 @@ typedef enum grpc_call_error {
/** A single metadata element */
typedef struct grpc_metadata {
const char *key;
const char *value;
size_t value_length;
grpc_slice key;
grpc_slice value;
uint32_t flags;
/** The following fields are reserved for grpc internal use.
@ -331,10 +330,8 @@ typedef struct {
} grpc_metadata_array;
typedef struct {
char *method;
size_t method_capacity;
char *host;
size_t host_capacity;
grpc_slice method;
grpc_slice host;
gpr_timespec deadline;
uint32_t flags;
void *reserved;
@ -416,7 +413,10 @@ typedef struct grpc_op {
size_t trailing_metadata_count;
grpc_metadata *trailing_metadata;
grpc_status_code status;
const char *status_details;
/* optional: set to NULL if no details need sending, non-NULL if they do
* pointer will not be retained past the start_batch call
*/
grpc_slice *status_details;
} send_status_from_server;
/** ownership of the array is with the caller, but ownership of the elements
stays with the call object (ie key, value members are owned by the call
@ -437,28 +437,7 @@ typedef struct grpc_op {
value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
/** status_details is a buffer owned by the application before the op
completes and after the op has completed. During the operation
status_details may be reallocated to a size larger than
*status_details_capacity, in which case *status_details_capacity will
be updated with the new array capacity.
Pre-allocating space:
size_t my_capacity = 8;
char *my_details = gpr_malloc(my_capacity);
x.status_details = &my_details;
x.status_details_capacity = &my_capacity;
Not pre-allocating space:
size_t my_capacity = 0;
char *my_details = NULL;
x.status_details = &my_details;
x.status_details_capacity = &my_capacity;
After the call:
gpr_free(my_details); */
char **status_details;
size_t *status_details_capacity;
grpc_slice *status_details;
} recv_status_on_client;
struct {
/** out argument, set to 1 if the call failed in any way (seen as a

@ -38,7 +38,7 @@
#include "src/core/lib/transport/metadata.h"
/** Return compression algorithm based metadata value */
grpc_slice grpc_compression_algorithm_mdstr(
grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm);
/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
@ -47,7 +47,7 @@ grpc_mdelem *grpc_compression_encoding_mdelem(
/** Find compression algorithm based on passed in mdstr - returns
* GRPC_COMPRESS_ALGORITHM_COUNT on failure */
grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
grpc_compression_algorithm grpc_compression_algorithm_from_slice(
grpc_slice str);
#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */

@ -81,7 +81,7 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
return 0;
}
grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
grpc_compression_algorithm grpc_compression_algorithm_from_slice(
grpc_slice str) {
if (grpc_slice_cmp(str, GRPC_MDSTR_IDENTITY) == 0) return GRPC_COMPRESS_NONE;
if (grpc_slice_cmp(str, GRPC_MDSTR_DEFLATE) == 0)
@ -90,7 +90,7 @@ grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
return GRPC_COMPRESS_ALGORITHMS_COUNT;
}
grpc_slice grpc_compression_algorithm_mdstr(
grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm) {
switch (algorithm) {
case GRPC_COMPRESS_NONE:

@ -34,6 +34,7 @@
#ifndef GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
#define GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
#include <stdbool.h>
#include <stddef.h>
#include <grpc/slice.h>
@ -53,6 +54,8 @@ char *grpc_dump_slice(grpc_slice slice, uint32_t flags);
* should be a properly initialized instance. */
void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst);
bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result);
#ifdef __cplusplus
}
#endif

@ -196,8 +196,7 @@ struct grpc_call {
union {
struct {
grpc_status_code *status;
char **status_details;
size_t *status_details_capacity;
grpc_slice *status_details;
} client;
struct {
int *cancelled;
@ -383,7 +382,7 @@ static void get_final_status(grpc_call *call,
void *set_value_user_data) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) {
if (call->status[i].is_code_set) {
set_value(call->status[i].code, set_value_user_data);
return;
}
@ -411,8 +410,8 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
}
gpr_mu_destroy(&c->mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (c->status[i].details) {
GRPC_MDSTR_UNREF(exec_ctx, c->status[i].details);
if (c->status[i].is_details_set) {
grpc_slice_unref_internal(exec_ctx, c->status[i].details);
}
}
for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
@ -438,18 +437,19 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
static void set_status_code(grpc_call *call, status_source source,
uint32_t status) {
if (call->status[source].is_set) return;
if (call->status[source].is_code_set) return;
call->status[source].is_set = 1;
call->status[source].is_code_set = true;
call->status[source].code = (grpc_status_code)status;
}
static void set_status_details(grpc_exec_ctx *exec_ctx, grpc_call *call,
status_source source, grpc_slice status) {
if (call->status[source].details != NULL) {
GRPC_MDSTR_UNREF(exec_ctx, status);
if (call->status[source].is_details_set) {
grpc_slice_unref_internal(exec_ctx, status);
} else {
call->status[source].details = status;
call->status[source].is_details_set = true;
}
}
@ -459,7 +459,8 @@ static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
const char *msg;
grpc_error_get_status(error, &status, &msg);
set_status_code(call, source, (uint32_t)status);
set_status_details(exec_ctx, call, source, grpc_mdstr_from_string(msg));
set_status_details(exec_ctx, call, source,
grpc_slice_from_copied_string(msg));
}
static void set_incoming_compression_algorithm(
@ -509,7 +510,7 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
return;
}
accept_encoding_slice = mdel->value->slice;
accept_encoding_slice = mdel->value;
grpc_slice_buffer_init(&accept_encoding_parts);
grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
@ -518,15 +519,13 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
/* Always support no compression */
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
for (i = 0; i < accept_encoding_parts.count; i++) {
const grpc_slice *accept_encoding_entry_slice =
&accept_encoding_parts.slices[i];
if (grpc_compression_algorithm_parse(
(const char *)GRPC_SLICE_START_PTR(*accept_encoding_entry_slice),
GRPC_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
if (grpc_compression_algorithm_parse(accept_encoding_entry_slice,
&algorithm)) {
GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
} else {
char *accept_encoding_entry_str =
grpc_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
grpc_dump_slice(accept_encoding_entry_slice, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR,
"Invalid entry in accept encoding metadata: '%s'. Ignoring.",
accept_encoding_entry_str);
@ -549,21 +548,12 @@ uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
return encodings_accepted_by_peer;
}
static void get_final_details(grpc_call *call, char **out_details,
size_t *out_details_capacity) {
static void get_final_details(grpc_call *call, grpc_slice *out_details) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) {
if (call->status[i].details) {
grpc_slice details = call->status[i].details->slice;
size_t len = GRPC_SLICE_LENGTH(details);
if (len + 1 > *out_details_capacity) {
*out_details_capacity =
GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
*out_details = gpr_realloc(*out_details, *out_details_capacity);
}
memcpy(*out_details, GRPC_SLICE_START_PTR(details), len);
(*out_details)[len] = 0;
if (call->status[i].is_code_set) {
if (call->status[i].is_details_set) {
*out_details = grpc_slice_ref(call->status[i].details);
} else {
goto no_details;
}
@ -572,11 +562,7 @@ static void get_final_details(grpc_call *call, char **out_details,
}
no_details:
if (0 == *out_details_capacity) {
*out_details_capacity = 8;
*out_details = gpr_malloc(*out_details_capacity);
}
**out_details = 0;
*out_details = grpc_empty_slice();
}
static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
@ -605,19 +591,17 @@ static int prepare_application_metadata(
get_md_elem(metadata, additional_metadata, i, count);
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
l->md = grpc_mdelem_from_string_and_buffer(
exec_ctx, md->key, (const uint8_t *)md->value, md->value_length);
if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
GRPC_MDSTR_LENGTH(l->md->key))) {
gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
grpc_mdstr_as_c_string(l->md->key));
l->md = grpc_mdelem_from_slices(exec_ctx, md->key, md->value);
if (!grpc_header_key_slice_is_legal(l->md->key)) {
char *str = grpc_dump_slice(md->key, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s", str);
gpr_free(str);
break;
} else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
GRPC_MDSTR_LENGTH(l->md->key)) &&
!grpc_header_nonbin_value_is_legal(
grpc_mdstr_as_c_string(l->md->value),
GRPC_MDSTR_LENGTH(l->md->value))) {
gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
} else if (!grpc_slice_is_binary_header(l->md->key) &&
!grpc_header_nonbin_value_slice_is_legal(l->md->value)) {
char *str = grpc_dump_slice(md->value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "attempt to send invalid metadata value: %s", str);
gpr_free(str);
break;
}
}
@ -902,9 +886,7 @@ static uint32_t decode_status(grpc_mdelem *md) {
if (user_data != NULL) {
status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
} else {
if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
GRPC_SLICE_LENGTH(md->value->slice),
&status)) {
if (!grpc_parse_slice_to_uint32(md->value, &status)) {
status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
}
grpc_mdelem_set_user_data(md, destroy_status,
@ -915,13 +897,14 @@ static uint32_t decode_status(grpc_mdelem *md) {
static grpc_compression_algorithm decode_compression(grpc_mdelem *md) {
grpc_compression_algorithm algorithm =
grpc_compression_algorithm_from_mdstr(md->value);
grpc_compression_algorithm_from_slice(md->value);
if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
const char *md_c_str = grpc_mdstr_as_c_string(md->value);
char *md_c_str = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
gpr_log(GPR_ERROR,
"Invalid incoming compression algorithm: '%s'. Interpreting "
"incoming data as uncompressed.",
md_c_str);
gpr_free(md_c_str);
return GRPC_COMPRESS_NONE;
}
return algorithm;
@ -929,15 +912,15 @@ static grpc_compression_algorithm decode_compression(grpc_mdelem *md) {
static grpc_mdelem *recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_mdelem *elem) {
if (elem->key == GRPC_MDSTR_GRPC_STATUS) {
if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_STATUS) == 0) {
GPR_TIMER_BEGIN("status", 0);
set_status_code(call, STATUS_FROM_WIRE, decode_status(elem));
GPR_TIMER_END("status", 0);
return NULL;
} else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) {
} else if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_MESSAGE) == 0) {
GPR_TIMER_BEGIN("status-details", 0);
set_status_details(exec_ctx, call, STATUS_FROM_WIRE,
GRPC_MDSTR_REF(elem->value));
grpc_slice_ref_internal(elem->value));
GPR_TIMER_END("status-details", 0);
return NULL;
}
@ -956,9 +939,8 @@ static grpc_mdelem *publish_app_metadata(grpc_call *call, grpc_mdelem *elem,
gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
}
mdusr = &dest->metadata[dest->count++];
mdusr->key = grpc_mdstr_as_c_string(elem->key);
mdusr->value = grpc_mdstr_as_c_string(elem->value);
mdusr->value_length = GRPC_SLICE_LENGTH(elem->value->slice);
mdusr->key = grpc_slice_ref(elem->key);
mdusr->value = grpc_slice_ref(elem->value);
GPR_TIMER_END("publish_app_metadata", 0);
return elem;
}
@ -973,12 +955,12 @@ static grpc_mdelem *recv_initial_filter(void *args, grpc_mdelem *elem) {
elem = recv_common_filter(a->exec_ctx, a->call, elem);
if (elem == NULL) {
return NULL;
} else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
} else if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_ENCODING) == 0) {
GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
set_incoming_compression_algorithm(a->call, decode_compression(elem));
GPR_TIMER_END("incoming_compression_algorithm", 0);
return NULL;
} else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) {
} else if (grpc_slice_cmp(elem->key, GRPC_MDSTR_GRPC_ACCEPT_ENCODING) == 0) {
GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
set_encodings_accepted_by_peer(a->exec_ctx, a->call, elem);
GPR_TIMER_END("encodings_accepted_by_peer", 0);
@ -1328,8 +1310,7 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
if (call->is_client) {
get_final_status(call, set_status_value_directly,
call->final_op.client.status);
get_final_details(call, call->final_op.client.status_details,
call->final_op.client.status_details_capacity);
get_final_details(call, call->final_op.client.status_details);
} else {
get_final_status(call, set_cancelled_value,
call->final_op.server.cancelled);
@ -1427,13 +1408,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
const grpc_compression_algorithm calgo =
compression_algorithm_for_level_locked(
call, effective_compression_level);
char *calgo_name = NULL;
grpc_compression_algorithm_name(calgo, &calgo_name);
// the following will be picked up by the compress filter and used as
// the call's compression algorithm.
compression_md.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
compression_md.value = calgo_name;
compression_md.value_length = strlen(calgo_name);
compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
compression_md.value = grpc_compression_algorithm_slice(calgo);
additional_metadata_count++;
}
@ -1527,14 +1505,14 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
exec_ctx, call->channel, op->data.send_status_from_server.status);
if (op->data.send_status_from_server.status_details != NULL) {
call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings(
call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
grpc_mdstr_from_string(
op->data.send_status_from_server.status_details));
grpc_slice_ref_internal(
*op->data.send_status_from_server.status_details));
call->send_extra_metadata_count++;
set_status_details(
exec_ctx, call, STATUS_FROM_API_OVERRIDE,
GRPC_MDSTR_REF(call->send_extra_metadata[1].md->value));
grpc_slice_ref_internal(call->send_extra_metadata[1].md->value));
}
if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
set_status_code(call, STATUS_FROM_API_OVERRIDE,
@ -1611,8 +1589,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
call->final_op.client.status = op->data.recv_status_on_client.status;
call->final_op.client.status_details =
op->data.recv_status_on_client.status_details;
call->final_op.client.status_details_capacity =
op->data.recv_status_on_client.status_details_capacity;
bctl->recv_final_op = 1;
stream_op->recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];

@ -41,10 +41,12 @@
void grpc_call_details_init(grpc_call_details* cd) {
GRPC_API_TRACE("grpc_call_details_init(cd=%p)", 1, (cd));
memset(cd, 0, sizeof(*cd));
cd->method = grpc_empty_slice();
cd->host = grpc_empty_slice();
}
void grpc_call_details_destroy(grpc_call_details* cd) {
GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd));
gpr_free(cd->method);
gpr_free(cd->host);
grpc_slice_unref(cd->method);
grpc_slice_unref(cd->host);
}

@ -35,17 +35,18 @@
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
size_t i;
for (i = 0; i < count; i++) {
gpr_strvec_add(b, gpr_strdup("\nkey="));
gpr_strvec_add(b, gpr_strdup(md[i].key));
gpr_strvec_add(b, grpc_dump_slice(md[i].key, GPR_DUMP_ASCII));
gpr_strvec_add(b, gpr_strdup(" value="));
gpr_strvec_add(b, gpr_dump(md[i].value, md[i].value_length,
GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(b,
grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
}
@ -70,10 +71,16 @@ char *grpc_op_string(const grpc_op *op) {
gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=%s",
op->data.send_status_from_server.status,
op->data.send_status_from_server.status_details);
gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=",
op->data.send_status_from_server.status);
gpr_strvec_add(&b, tmp);
if (op->data.send_status_from_server.status_details != NULL) {
gpr_strvec_add(&b, grpc_dump_slice(
*op->data.send_status_from_server.status_details,
GPR_DUMP_ASCII));
} else {
gpr_strvec_add(&b, gpr_strdup("(null)"));
}
add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
op->data.send_status_from_server.trailing_metadata_count);
break;

@ -123,8 +123,9 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
/* setting this takes precedence over anything else */
GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority);
}
channel->default_authority = grpc_mdelem_from_strings(
exec_ctx, ":authority", args->args[i].value.string);
channel->default_authority = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_from_copied_string(args->args[i].value.string));
}
} else if (0 ==
strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
@ -138,8 +139,9 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
"%s ignored: default host already set some other way",
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
} else {
channel->default_authority = grpc_mdelem_from_strings(
exec_ctx, ":authority", args->args[i].value.string);
channel->default_authority = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_from_copied_string(args->args[i].value.string));
}
}
} else if (0 == strcmp(args->args[i].key,
@ -224,27 +226,17 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_call *parent_call,
uint32_t propagation_mask,
grpc_completion_queue *cq,
const char *method, const char *host,
grpc_slice method, const grpc_slice *host,
gpr_timespec deadline, void *reserved) {
GRPC_API_TRACE(
"grpc_channel_create_call("
"channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
"host=%s, "
"deadline=gpr_timespec { tv_sec: %" PRId64
", tv_nsec: %d, clock_type: %d }, "
"reserved=%p)",
10,
(channel, parent_call, (unsigned)propagation_mask, cq, method, host,
deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved));
GPR_ASSERT(!reserved);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_call *call = grpc_channel_create_call_internal(
&exec_ctx, channel, parent_call, propagation_mask, cq, NULL,
grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_PATH,
grpc_mdstr_from_string(method)),
host ? grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_mdstr_from_string(host))
: NULL,
grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_PATH,
grpc_slice_ref(method)),
host != NULL ? grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_ref(*host))
: NULL,
deadline);
grpc_exec_ctx_finish(&exec_ctx);
return call;
@ -252,17 +244,16 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_call *grpc_channel_create_pollset_set_call(
grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
uint32_t propagation_mask, grpc_pollset_set *pollset_set,
const char *method, const char *host, gpr_timespec deadline,
void *reserved) {
uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method,
const grpc_slice *host, gpr_timespec deadline, void *reserved) {
GPR_ASSERT(!reserved);
return grpc_channel_create_call_internal(
exec_ctx, channel, parent_call, propagation_mask, NULL, pollset_set,
grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_PATH,
grpc_mdstr_from_string(method)),
host ? grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_mdstr_from_string(host))
: NULL,
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH,
grpc_slice_ref(method)),
host != NULL ? grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_ref(*host))
: NULL,
deadline);
}
@ -274,11 +265,14 @@ void *grpc_channel_register_call(grpc_channel *channel, const char *method,
4, (channel, method, host, reserved));
GPR_ASSERT(!reserved);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
rc->path = grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_PATH,
grpc_mdstr_from_string(method));
rc->path = grpc_mdelem_from_slices(
&exec_ctx, GRPC_MDSTR_PATH,
grpc_slice_intern(grpc_slice_from_copied_string(method)));
rc->authority =
host ? grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_mdstr_from_string(host))
host ? grpc_mdelem_from_slices(
&exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_intern(grpc_slice_from_copied_string(host)))
: NULL;
gpr_mu_lock(&channel->registered_call_mu);
rc->next = channel->registered_calls;
@ -385,6 +379,6 @@ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
return GRPC_MDELEM_GRPC_STATUS_2;
}
gpr_ltoa(i, tmp);
return grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
grpc_mdstr_from_string(tmp));
return grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
grpc_slice_from_copied_string(tmp));
}

@ -52,9 +52,8 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
value of \a propagation_mask (see propagation_bits.h for possible values) */
grpc_call *grpc_channel_create_pollset_set_call(
grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
uint32_t propagation_mask, grpc_pollset_set *pollset_set,
const char *method, const char *host, gpr_timespec deadline,
void *reserved);
uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method,
const grpc_slice *host, gpr_timespec deadline, void *reserved);
/** Get a (borrowed) pointer to this channels underlying channel stack */
grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel);

@ -44,6 +44,7 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/static_metadata.h"
typedef struct {
grpc_linked_mdelem status;
@ -61,9 +62,11 @@ static void fill_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
channel_data *chand = elem->channel_data;
char tmp[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(chand->error_code, tmp);
calld->status.md = grpc_mdelem_from_strings(exec_ctx, "grpc-status", tmp);
calld->details.md =
grpc_mdelem_from_strings(exec_ctx, "grpc-message", chand->error_message);
calld->status.md = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(tmp));
calld->details.md = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
grpc_slice_from_copied_string(chand->error_message));
calld->status.prev = calld->details.next = NULL;
calld->status.next = &calld->details;
calld->details.prev = &calld->status;

@ -98,6 +98,7 @@ typedef struct requested_call {
typedef struct channel_registered_method {
registered_method *server_registered_method;
uint32_t flags;
bool has_host;
grpc_slice method;
grpc_slice host;
} channel_registered_method;
@ -144,6 +145,8 @@ struct call_data {
/** the current state of a call - see call_state */
call_state state;
bool path_set;
bool host_set;
grpc_slice path;
grpc_slice host;
gpr_timespec deadline;
@ -459,17 +462,6 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand,
op);
}
static void cpstr(char **dest, size_t *capacity, grpc_slice value) {
grpc_slice slice = value->slice;
size_t len = GRPC_SLICE_LENGTH(slice);
if (len + 1 > *capacity) {
*capacity = GPR_MAX(len + 1, *capacity * 2);
*dest = gpr_realloc(*dest, *capacity);
}
memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
}
static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
grpc_cq_completion *c) {
requested_call *rc = req;
@ -498,12 +490,10 @@ static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
switch (rc->type) {
case BATCH_CALL:
GPR_ASSERT(calld->host != NULL);
GPR_ASSERT(calld->path != NULL);
cpstr(&rc->data.batch.details->host,
&rc->data.batch.details->host_capacity, calld->host);
cpstr(&rc->data.batch.details->method,
&rc->data.batch.details->method_capacity, calld->path);
GPR_ASSERT(calld->host_set);
GPR_ASSERT(calld->path_set);
rc->data.batch.details->host = grpc_slice_ref_internal(calld->host);
rc->data.batch.details->method = grpc_slice_ref_internal(calld->path);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
(calld->recv_idempotent_request
@ -623,35 +613,39 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
uint32_t hash;
channel_registered_method *rm;
if (chand->registered_methods && calld->path && calld->host) {
if (chand->registered_methods && calld->path_set && calld->host_set) {
/* TODO(ctiller): unify these two searches */
/* check for an exact match with host */
hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host),
grpc_slice_hash(calld->path));
for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
if (rm->host != calld->host) continue;
if (rm->method != calld->path) continue;
if (!rm->has_host) continue;
if (grpc_slice_cmp(rm->host, calld->host) != 0) continue;
if (grpc_slice_cmp(rm->method, calld->path) != 0) continue;
if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
!calld->recv_idempotent_request)
!calld->recv_idempotent_request) {
continue;
}
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
return;
}
/* check for a wildcard method definition (no host set) */
hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash(calld->path));
for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
if (rm->host != NULL) continue;
if (rm->method != calld->path) continue;
if (rm->has_host) continue;
if (grpc_slice_cmp(rm->method, calld->path) != 0) continue;
if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
!calld->recv_idempotent_request)
!calld->recv_idempotent_request) {
continue;
}
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
@ -743,14 +737,14 @@ static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
if (md->key == GRPC_MDSTR_PATH) {
if (calld->path == NULL) {
calld->path = GRPC_MDSTR_REF(md->value);
if (grpc_slice_cmp(md->key, GRPC_MDSTR_PATH) == 0) {
if (!calld->path_set) {
calld->path = grpc_slice_ref(md->value);
}
return NULL;
} else if (md->key == GRPC_MDSTR_AUTHORITY) {
if (calld->host == NULL) {
calld->host = GRPC_MDSTR_REF(md->value);
} else if (grpc_slice_cmp(md->key, GRPC_MDSTR_AUTHORITY) == 0) {
if (!calld->host_set) {
calld->host = grpc_slice_ref(md->value);
}
return NULL;
}
@ -770,7 +764,7 @@ static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
calld->deadline = op_deadline;
}
if (calld->host && calld->path) {
if (calld->host_set && calld->path_set) {
/* do nothing */
} else {
GRPC_ERROR_UNREF(error);
@ -902,11 +896,11 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GPR_ASSERT(calld->state != PENDING);
if (calld->host) {
GRPC_MDSTR_UNREF(exec_ctx, calld->host);
if (calld->host_set) {
grpc_slice_unref_internal(exec_ctx, calld->host);
}
if (calld->path) {
GRPC_MDSTR_UNREF(exec_ctx, calld->path);
if (calld->path_set) {
grpc_slice_unref_internal(exec_ctx, calld->path);
}
grpc_metadata_array_destroy(&calld->initial_metadata);
@ -936,11 +930,9 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
channel_data *chand = elem->channel_data;
if (chand->registered_methods) {
for (i = 0; i < chand->registered_method_slots; i++) {
if (chand->registered_methods[i].method) {
GRPC_MDSTR_UNREF(exec_ctx, chand->registered_methods[i].method);
}
if (chand->registered_methods[i].host) {
GRPC_MDSTR_UNREF(exec_ctx, chand->registered_methods[i].host);
grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].method);
if (chand->registered_methods[i].has_host) {
grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].host);
}
}
gpr_free(chand->registered_methods);
@ -1136,8 +1128,6 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
channel_registered_method *crm;
grpc_channel *channel;
channel_data *chand;
grpc_slice host;
grpc_slice method;
uint32_t hash;
size_t slots;
uint32_t probes;
@ -1176,9 +1166,18 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
chand->registered_methods = gpr_malloc(alloc);
memset(chand->registered_methods, 0, alloc);
for (rm = s->registered_methods; rm; rm = rm->next) {
host = rm->host ? grpc_mdstr_from_string(rm->host) : NULL;
method = grpc_mdstr_from_string(rm->method);
hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
grpc_slice host;
bool has_host;
grpc_slice method;
if (rm->host != NULL) {
host = grpc_slice_intern(grpc_slice_from_copied_string(rm->host));
has_host = true;
} else {
has_host = false;
}
method = grpc_slice_intern(grpc_slice_from_copied_string(rm->method));
hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0,
grpc_slice_hash(method));
for (probes = 0; chand->registered_methods[(hash + probes) % slots]
.server_registered_method != NULL;
probes++)

@ -113,11 +113,9 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md);
#endif
#define GRPC_MDSTR_LENGTH(s) (GRPC_SLICE_LENGTH(s->slice))
/* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */
#define GRPC_MDELEM_LENGTH(e) \
(GRPC_MDSTR_LENGTH((e)->key) + GRPC_MDSTR_LENGTH((e)->value) + 32)
(GRPC_SLICE_LENGTH((e)->key) + GRPC_SLICE_LENGTH((e)->value) + 32)
#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))

@ -59,8 +59,8 @@ static void test_algorithm_mesh(void) {
GPR_ASSERT(grpc_compression_algorithm_parse(name, strlen(name), &parsed));
GPR_ASSERT((int)parsed == i);
mdstr = grpc_mdstr_from_string(name);
GPR_ASSERT(mdstr == grpc_compression_algorithm_mdstr(parsed));
GPR_ASSERT(parsed == grpc_compression_algorithm_from_mdstr(mdstr));
GPR_ASSERT(mdstr == grpc_compression_algorithm_slice(parsed));
GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr));
mdelem = grpc_compression_encoding_mdelem(parsed);
GPR_ASSERT(mdelem->value == mdstr);
GPR_ASSERT(mdelem->key == GRPC_MDSTR_GRPC_ENCODING);
@ -85,11 +85,11 @@ static void test_algorithm_failure(void) {
GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT + 1,
NULL) == 0);
mdstr = grpc_mdstr_from_string("this-is-an-invalid-algorithm");
GPR_ASSERT(grpc_compression_algorithm_from_mdstr(mdstr) ==
GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) ==
GRPC_COMPRESS_ALGORITHMS_COUNT);
GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT) ==
GPR_ASSERT(grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT) ==
NULL);
GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT +
GPR_ASSERT(grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT +
1) == NULL);
GRPC_MDSTR_UNREF(&exec_ctx, mdstr);
grpc_exec_ctx_finish(&exec_ctx);

@ -92,8 +92,8 @@ static int has_metadata(const grpc_metadata *md, size_t count, const char *key,
const char *value) {
size_t i;
for (i = 0; i < count; i++) {
if (0 == strcmp(key, md[i].key) && strlen(value) == md[i].value_length &&
0 == memcmp(md[i].value, value, md[i].value_length)) {
if (0 == grpc_slice_str_cmp(md[i].key, key) &&
0 == grpc_slice_str_cmp(md[i].value, value)) {
return 1;
}
}

@ -80,8 +80,7 @@ typedef struct {
grpc_metadata_array p2s_trailing_metadata;
grpc_status_code p2s_status;
char *p2s_status_details;
size_t p2s_status_details_capacity;
grpc_slice p2s_status_details;
int c2p_server_cancelled;
} proxy_call;
@ -153,7 +152,7 @@ static void unrefpc(proxy_call *pc, const char *reason) {
grpc_metadata_array_destroy(&pc->c2p_initial_metadata);
grpc_metadata_array_destroy(&pc->p2s_initial_metadata);
grpc_metadata_array_destroy(&pc->p2s_trailing_metadata);
gpr_free(pc->p2s_status_details);
grpc_slice_unref(pc->p2s_status_details);
gpr_free(pc);
}
}
@ -309,7 +308,6 @@ static void on_p2s_status(void *arg, int success) {
op.data.send_status_from_server.trailing_metadata =
pc->p2s_trailing_metadata.metadata;
op.data.send_status_from_server.status = pc->p2s_status;
op.data.send_status_from_server.status_details = pc->p2s_status_details;
refpc(pc, "on_c2p_sent_status");
err = grpc_call_start_batch(pc->c2p, &op, 1,
new_closure(on_c2p_sent_status, pc), NULL);
@ -339,7 +337,7 @@ static void on_new_call(void *arg, int success) {
pc->c2p = proxy->new_call;
pc->p2s = grpc_channel_create_call(
proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq,
proxy->new_call_details.method, proxy->new_call_details.host,
proxy->new_call_details.method, &proxy->new_call_details.host,
proxy->new_call_details.deadline, NULL);
gpr_ref_init(&pc->refs, 1);
@ -384,8 +382,6 @@ static void on_new_call(void *arg, int success) {
&pc->p2s_trailing_metadata;
op.data.recv_status_on_client.status = &pc->p2s_status;
op.data.recv_status_on_client.status_details = &pc->p2s_status_details;
op.data.recv_status_on_client.status_details_capacity =
&pc->p2s_status_details_capacity;
refpc(pc, "on_p2s_status");
err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_status, pc),
NULL);

Loading…
Cancel
Save