aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/surface/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/surface/server.c')
-rw-r--r--src/core/lib/surface/server.c142
1 files changed, 72 insertions, 70 deletions
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 3782b49122..addb7c4fbc 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -98,9 +98,8 @@ 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;
+ grpc_mdstr *method;
+ grpc_mdstr *host;
} channel_registered_method;
struct channel_data {
@@ -145,10 +144,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;
+ grpc_mdstr *path;
+ grpc_mdstr *host;
gpr_timespec deadline;
grpc_completion_queue *cq_new;
@@ -280,20 +277,18 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg,
}
static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
- bool send_goaway, grpc_error *send_disconnect) {
+ int send_goaway, grpc_error *send_disconnect) {
struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc));
grpc_closure_init(&sc->closure, shutdown_cleanup, sc,
grpc_schedule_on_exec_ctx);
grpc_transport_op *op = grpc_make_transport_op(&sc->closure);
grpc_channel_element *elem;
- op->goaway_error =
- send_goaway
- ? grpc_error_set_int(GRPC_ERROR_CREATE("Server shutdown"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK)
- : GRPC_ERROR_NONE;
+ op->send_goaway = send_goaway;
op->set_accept_stream = true;
sc->slice = grpc_slice_from_copied_string("Server shutdown");
+ op->goaway_message = &sc->slice;
+ op->goaway_status = GRPC_STATUS_OK;
op->disconnect_with_error = send_disconnect;
elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
@@ -453,6 +448,7 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand,
if (grpc_server_channel_trace && error != GRPC_ERROR_NONE) {
const char *msg = grpc_error_string(error);
gpr_log(GPR_INFO, "Disconnected client: %s", msg);
+ grpc_error_free_string(msg);
}
GRPC_ERROR_UNREF(error);
@@ -465,6 +461,17 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand,
op);
}
+static void cpstr(char **dest, size_t *capacity, grpc_mdstr *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;
@@ -493,10 +500,12 @@ 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_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);
+ 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);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
(calld->recv_idempotent_request
@@ -618,39 +627,35 @@ 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_set && calld->host_set) {
+ if (chand->registered_methods && calld->path && calld->host) {
/* TODO(ctiller): unify these two searches */
/* check for an exact match with host */
- hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host),
- grpc_slice_hash(calld->path));
+ hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
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->has_host) continue;
- if (!grpc_slice_eq(rm->host, calld->host)) continue;
- if (!grpc_slice_eq(rm->method, calld->path)) continue;
+ if (rm->host != calld->host) continue;
+ if (rm->method != calld->path) 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, grpc_slice_hash(calld->path));
+ hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
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->has_host) continue;
- if (!grpc_slice_eq(rm->method, calld->path)) continue;
+ if (rm->host != NULL) continue;
+ if (rm->method != calld->path) 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);
@@ -739,40 +744,43 @@ static void maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
}
}
+static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, 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);
+ }
+ return NULL;
+ } else if (md->key == GRPC_MDSTR_AUTHORITY) {
+ if (calld->host == NULL) {
+ calld->host = GRPC_MDSTR_REF(md->value);
+ }
+ return NULL;
+ }
+ return md;
+}
+
static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
grpc_error *error) {
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
gpr_timespec op_deadline;
- if (error == GRPC_ERROR_NONE) {
- GPR_ASSERT(calld->recv_initial_metadata->idx.named.path != NULL);
- GPR_ASSERT(calld->recv_initial_metadata->idx.named.authority != NULL);
- calld->path = grpc_slice_ref_internal(
- GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md));
- calld->host = grpc_slice_ref_internal(
- GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.authority->md));
- calld->path_set = true;
- calld->host_set = true;
- grpc_metadata_batch_remove(exec_ctx, calld->recv_initial_metadata,
- calld->recv_initial_metadata->idx.named.path);
- grpc_metadata_batch_remove(
- exec_ctx, calld->recv_initial_metadata,
- calld->recv_initial_metadata->idx.named.authority);
- } else {
- GRPC_ERROR_REF(error);
- }
+ GRPC_ERROR_REF(error);
+ grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata,
+ server_filter, elem);
op_deadline = calld->recv_initial_metadata->deadline;
if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
calld->deadline = op_deadline;
}
- if (calld->host_set && calld->path_set) {
+ if (calld->host && calld->path) {
/* do nothing */
} else {
- grpc_error *src_error = error;
+ GRPC_ERROR_UNREF(error);
error =
GRPC_ERROR_CREATE_REFERENCING("Missing :authority or :path", &error, 1);
- GRPC_ERROR_UNREF(src_error);
}
grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, error);
@@ -902,11 +910,11 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GPR_ASSERT(calld->state != PENDING);
- if (calld->host_set) {
- grpc_slice_unref_internal(exec_ctx, calld->host);
+ if (calld->host) {
+ GRPC_MDSTR_UNREF(exec_ctx, calld->host);
}
- if (calld->path_set) {
- grpc_slice_unref_internal(exec_ctx, calld->path);
+ if (calld->path) {
+ GRPC_MDSTR_UNREF(exec_ctx, calld->path);
}
grpc_metadata_array_destroy(&calld->initial_metadata);
@@ -938,9 +946,11 @@ 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++) {
- 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);
+ 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);
}
}
gpr_free(chand->registered_methods);
@@ -1138,6 +1148,8 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
channel_registered_method *crm;
grpc_channel *channel;
channel_data *chand;
+ grpc_mdstr *host;
+ grpc_mdstr *method;
uint32_t hash;
size_t slots;
uint32_t probes;
@@ -1176,18 +1188,9 @@ 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) {
- grpc_slice host;
- bool has_host;
- grpc_slice method;
- if (rm->host != NULL) {
- host = grpc_slice_intern(grpc_slice_from_static_string(rm->host));
- has_host = true;
- } else {
- has_host = false;
- }
- method = grpc_slice_intern(grpc_slice_from_static_string(rm->method));
- hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0,
- grpc_slice_hash(method));
+ 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);
for (probes = 0; chand->registered_methods[(hash + probes) % slots]
.server_registered_method != NULL;
probes++)
@@ -1196,7 +1199,6 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
crm = &chand->registered_methods[(hash + probes) % slots];
crm->server_registered_method = rm;
crm->flags = rm->flags;
- crm->has_host = has_host;
crm->host = host;
crm->method = method;
}