diff options
Diffstat (limited to 'src/core/lib/surface/server.c')
-rw-r--r-- | src/core/lib/surface/server.c | 142 |
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; } |