void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel, const char *reason) { gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel, channel->refs.count, channel->refs.count - 1, reason); #else void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel) { #endif if (gpr_unref(&channel->refs)) { destroy_channel(exec_ctx, channel); } } void grpc_channel_destroy(grpc_channel *channel) { grpc_transport_op op; grpc_channel_element *elem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel)); memset(&op, 0, sizeof(op)); op.disconnect = 1; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); elem->filter->start_transport_op(&exec_ctx, elem, &op); GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel"); grpc_exec_ctx_finish(&exec_ctx); }
void grpc_channel_get_info(grpc_channel *channel, const grpc_channel_info *channel_info) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_element *elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); elem->filter->get_channel_info(&exec_ctx, elem, channel_info); grpc_exec_ctx_finish(&exec_ctx); }
static void test_create_channel_stack(void) { const grpc_channel_filter filter = { call_func, channel_func, sizeof(int), call_init_func, grpc_call_stack_ignore_set_pollset_or_pollset_set, call_destroy_func, sizeof(int), channel_init_func, channel_destroy_func, get_peer, "some_test_filter"}; const grpc_channel_filter *filters = &filter; grpc_channel_stack *channel_stack; grpc_call_stack *call_stack; grpc_channel_element *channel_elem; grpc_call_element *call_elem; grpc_arg arg; grpc_channel_args chan_args; int *channel_data; int *call_data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; arg.type = GRPC_ARG_INTEGER; arg.key = "test_key"; arg.value.integer = 42; chan_args.num_args = 1; chan_args.args = &arg; channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, 1, &chan_args, NULL, "test", channel_stack); GPR_ASSERT(channel_stack->count == 1); channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_data = (int *)channel_elem->channel_data; GPR_ASSERT(*channel_data == 0); call_stack = gpr_malloc(channel_stack->call_stack_size); grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, NULL, NULL, call_stack); GPR_ASSERT(call_stack->count == 1); call_elem = grpc_call_stack_element(call_stack, 0); GPR_ASSERT(call_elem->filter == channel_elem->filter); GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data); call_data = (int *)call_elem->call_data; GPR_ASSERT(*call_data == 0); GPR_ASSERT(*channel_data == 1); GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done"); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(*channel_data == 2); GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); grpc_exec_ctx_finish(&exec_ctx); }
static void finish_shutdown_channel(void *cd, int success) { channel_data *chand = cd; grpc_channel_op op; op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; channel_op(grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), NULL, &op); grpc_channel_internal_unref(chand->channel); }
static void test_create_channel_stack(void) { const grpc_channel_filter filter = { call_func, channel_func, sizeof(int), call_init_func, call_destroy_func, sizeof(int), channel_init_func, channel_destroy_func, "some_test_filter"}; const grpc_channel_filter *filters = &filter; grpc_channel_stack *channel_stack; grpc_call_stack *call_stack; grpc_channel_element *channel_elem; grpc_call_element *call_elem; grpc_arg arg; grpc_channel_args chan_args; grpc_mdctx *metadata_context; int *channel_data; int *call_data; LOG_TEST_NAME(); metadata_context = grpc_mdctx_create(); arg.type = GRPC_ARG_INTEGER; arg.key = "test_key"; arg.value.integer = 42; chan_args.num_args = 1; chan_args.args = &arg; channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); grpc_channel_stack_init(&filters, 1, &chan_args, metadata_context, channel_stack); GPR_ASSERT(channel_stack->count == 1); channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_data = (int *)channel_elem->channel_data; GPR_ASSERT(*channel_data == 0); call_stack = gpr_malloc(channel_stack->call_stack_size); grpc_call_stack_init(channel_stack, NULL, NULL, call_stack); GPR_ASSERT(call_stack->count == 1); call_elem = grpc_call_stack_element(call_stack, 0); GPR_ASSERT(call_elem->filter == channel_elem->filter); GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data); call_data = (int *)call_elem->call_data; GPR_ASSERT(*call_data == 0); GPR_ASSERT(*channel_data == 1); grpc_call_stack_destroy(call_stack); gpr_free(call_stack); GPR_ASSERT(*channel_data == 2); grpc_channel_stack_destroy(channel_stack); gpr_free(channel_stack); grpc_mdctx_unref(metadata_context); }
static void finish_shutdown_channel(void *p, int success) { shutdown_channel_args *sca = p; grpc_channel_op op; if (sca->send_goaway) { op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown"); channel_op(grpc_channel_stack_element( grpc_channel_get_channel_stack(sca->chand->channel), 0), NULL, &op); } if (sca->send_disconnect) { op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; channel_op(grpc_channel_stack_element( grpc_channel_get_channel_stack(sca->chand->channel), 0), NULL, &op); } GRPC_CHANNEL_INTERNAL_UNREF(sca->chand->channel, "shutdown"); gpr_free(sca); }
void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { grpc_transport_op op; ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); memset(&op, 0, sizeof(op)); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); op.send_ping = &pr->closure; op.bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op); grpc_exec_ctx_finish(&exec_ctx); }
void grpc_channel_destroy(grpc_channel *channel) { grpc_channel_op op; grpc_channel_element *elem; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Client disconnect"); elem->filter->channel_op(elem, NULL, &op); op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; elem->filter->channel_op(elem, NULL, &op); grpc_channel_internal_unref(channel); }
static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); maybe_finish_shutdown(exec_ctx, chand->server); chand->finish_destroy_channel_closure.cb = finish_destroy_channel; chand->finish_destroy_channel_closure.cb_arg = chand; grpc_transport_op op; memset(&op, 0, sizeof(op)); op.set_accept_stream = true; op.on_consumed = &chand->finish_destroy_channel_closure; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), &op); }
void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4, (channel, cq, tag, reserved)); grpc_transport_op *op = grpc_make_transport_op(NULL); ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); op->send_ping = &pr->closure; op->bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); top_elem->filter->start_transport_op(&exec_ctx, top_elem, op); grpc_exec_ctx_finish(&exec_ctx); }
static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, int send_goaway, grpc_error *send_disconnect) { grpc_transport_op op; struct shutdown_cleanup_args *sc; grpc_channel_element *elem; memset(&op, 0, sizeof(op)); op.send_goaway = send_goaway; sc = gpr_malloc(sizeof(*sc)); sc->slice = gpr_slice_from_copied_string("Server shutdown"); op.goaway_message = &sc->slice; op.goaway_status = GRPC_STATUS_OK; op.disconnect_with_error = send_disconnect; grpc_closure_init(&sc->closure, shutdown_cleanup, sc); op.on_consumed = &sc->closure; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); elem->filter->start_transport_op(exec_ctx, elem, &op); }
grpc_channel *grpc_lame_client_channel_create(const char *target, grpc_status_code error_code, const char *error_message) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_element *elem; channel_data *chand; grpc_channel *channel = grpc_channel_create(&exec_ctx, target, NULL, GRPC_CLIENT_LAME_CHANNEL, NULL); elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); GRPC_API_TRACE( "grpc_lame_client_channel_create(target=%s, error_code=%d, " "error_message=%s)", 3, (target, (int)error_code, error_message)); GPR_ASSERT(elem->filter == &grpc_lame_filter); chand = (channel_data *)elem->channel_data; chand->error_code = error_code; chand->error_message = error_message; grpc_exec_ctx_finish(&exec_ctx); return channel; }
static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, grpc_error *error) { channel_data *chand = cd; grpc_server *server = chand->server; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { grpc_transport_op op; memset(&op, 0, sizeof(op)); op.on_connectivity_state_change = &chand->channel_connectivity_changed, op.connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), &op); } else { gpr_mu_lock(&server->mu_global); destroy_channel(exec_ctx, chand); gpr_mu_unlock(&server->mu_global); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity"); } }
grpc_channel *grpc_lame_client_channel_create(const char *target, grpc_status_code error_code, const char *error_message) { grpc_channel *channel; grpc_channel_element *elem; channel_data *chand; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; static const grpc_channel_filter *filters[] = {&lame_filter}; channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, 1, NULL, grpc_mdctx_create(), 1); elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); GRPC_API_TRACE( "grpc_lame_client_channel_create(target=%s, error_code=%d, " "error_message=%s)", 3, (target, (int)error_code, error_message)); GPR_ASSERT(elem->filter == &lame_filter); chand = (channel_data *)elem->channel_data; chand->error_code = error_code; chand->error_message = error_message; grpc_exec_ctx_finish(&exec_ctx); return channel; }
void test_transport_op(grpc_channel *channel) { grpc_transport_op *op; grpc_channel_element *elem; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_closure_init(&transport_op_cb, verify_connectivity, &state, grpc_schedule_on_exec_ctx); op = grpc_make_transport_op(NULL); op->on_connectivity_state_change = &transport_op_cb; op->connectivity_state = &state; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); elem->filter->start_transport_op(&exec_ctx, elem, op); grpc_exec_ctx_finish(&exec_ctx); grpc_closure_init(&transport_op_cb, do_nothing, NULL, grpc_schedule_on_exec_ctx); op = grpc_make_transport_op(&transport_op_cb); elem->filter->start_transport_op(&exec_ctx, elem, op); grpc_exec_ctx_finish(&exec_ctx); }
void grpc_channel_internal_unref(grpc_channel *channel, const char *reason) { gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel, channel->refs.count, channel->refs.count - 1, reason); #else void grpc_channel_internal_unref(grpc_channel *channel) { #endif if (gpr_unref(&channel->refs)) { channel->destroy_closure.cb = destroy_channel; channel->destroy_closure.cb_arg = channel; grpc_iomgr_add_callback(&channel->destroy_closure); } } void grpc_channel_destroy(grpc_channel *channel) { grpc_transport_op op; grpc_channel_element *elem; memset(&op, 0, sizeof(op)); op.disconnect = 1; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); elem->filter->start_transport_op(elem, &op); GRPC_CHANNEL_INTERNAL_UNREF(channel, "channel"); }
grpc_channel_element *grpc_channel_stack_last_element( grpc_channel_stack *channel_stack) { return grpc_channel_stack_element(channel_stack, channel_stack->count - 1); }
static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, void *shutdown_tag) { listener *l; requested_call_array requested_calls; channel_data **channels; channel_data *c; size_t nchannels; size_t i, j; grpc_channel_op op; grpc_channel_element *elem; registered_method *rm; /* lock, and gather up some stuff to do */ gpr_mu_lock(&server->mu); if (have_shutdown_tag) { for (i = 0; i < server->cq_count; i++) { grpc_cq_begin_op(server->cqs[i], NULL, GRPC_SERVER_SHUTDOWN); } server->shutdown_tags = gpr_realloc(server->shutdown_tags, sizeof(void *) * (server->num_shutdown_tags + 1)); server->shutdown_tags[server->num_shutdown_tags++] = shutdown_tag; } if (server->shutdown) { gpr_mu_unlock(&server->mu); return; } nchannels = 0; for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { nchannels++; } channels = gpr_malloc(sizeof(channel_data *) * nchannels); i = 0; for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { grpc_channel_internal_ref(c->channel); channels[i] = c; i++; } /* collect all unregistered then registered calls */ requested_calls = server->requested_calls; memset(&server->requested_calls, 0, sizeof(server->requested_calls)); for (rm = server->registered_methods; rm; rm = rm->next) { if (requested_calls.count + rm->requested.count > requested_calls.capacity) { requested_calls.capacity = GPR_MAX(requested_calls.count + rm->requested.count, 2 * requested_calls.capacity); requested_calls.calls = gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) * requested_calls.capacity); } memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls, sizeof(*requested_calls.calls) * rm->requested.count); requested_calls.count += rm->requested.count; gpr_free(rm->requested.calls); memset(&rm->requested, 0, sizeof(rm->requested)); } server->shutdown = 1; if (server->lists[ALL_CALLS] == NULL) { for (i = 0; i < server->num_shutdown_tags; i++) { for (j = 0; j < server->cq_count; j++) { grpc_cq_end_server_shutdown(server->cqs[j], server->shutdown_tags[i]); } } } gpr_mu_unlock(&server->mu); for (i = 0; i < nchannels; i++) { c = channels[i]; elem = grpc_channel_stack_element( grpc_channel_get_channel_stack(c->channel), 0); op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown"); elem->filter->channel_op(elem, NULL, &op); grpc_channel_internal_unref(c->channel); } gpr_free(channels); /* terminate all the requested calls */ for (i = 0; i < requested_calls.count; i++) { fail_call(server, &requested_calls.calls[i]); } gpr_free(requested_calls.calls); /* Shutdown listeners */ for (l = server->listeners; l; l = l->next) { l->destroy(server, l->arg); } }
grpc_transport_setup_result grpc_server_setup_transport( grpc_server *s, grpc_transport *transport, grpc_channel_filter const **extra_filters, size_t num_extra_filters, grpc_mdctx *mdctx) { size_t num_filters = s->channel_filter_count + num_extra_filters + 1; grpc_channel_filter const **filters = gpr_malloc(sizeof(grpc_channel_filter *) * num_filters); size_t i; size_t num_registered_methods; size_t alloc; registered_method *rm; channel_registered_method *crm; grpc_channel *channel; channel_data *chand; grpc_mdstr *host; grpc_mdstr *method; gpr_uint32 hash; gpr_uint32 slots; gpr_uint32 probes; gpr_uint32 max_probes = 0; grpc_transport_setup_result result; for (i = 0; i < s->channel_filter_count; i++) { filters[i] = s->channel_filters[i]; } for (; i < s->channel_filter_count + num_extra_filters; i++) { filters[i] = extra_filters[i - s->channel_filter_count]; } filters[i] = &grpc_connected_channel_filter; for (i = 0; i < s->cq_count; i++) { grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i])); } channel = grpc_channel_create_from_filters(filters, num_filters, s->channel_args, mdctx, 0); chand = (channel_data *)grpc_channel_stack_element( grpc_channel_get_channel_stack(channel), 0) ->channel_data; chand->server = s; server_ref(s); chand->channel = channel; num_registered_methods = 0; for (rm = s->registered_methods; rm; rm = rm->next) { num_registered_methods++; } /* build a lookup table phrased in terms of mdstr's in this channels context to quickly find registered methods */ if (num_registered_methods > 0) { slots = 2 * num_registered_methods; alloc = sizeof(channel_registered_method) * slots; 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(mdctx, rm->host) : NULL; method = grpc_mdstr_from_string(mdctx, 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++) ; if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; crm->host = host; crm->method = method; } chand->registered_method_slots = slots; chand->registered_method_max_probes = max_probes; } result = grpc_connected_channel_bind_transport( grpc_channel_get_channel_stack(channel), transport); gpr_mu_lock(&s->mu); chand->next = &s->root_channel_data; chand->prev = chand->next->prev; chand->next->prev = chand->prev->next = chand; gpr_mu_unlock(&s->mu); gpr_free(filters); return result; }
static void test_create_channel_stack(void) { const grpc_channel_filter filter = { call_func, channel_func, sizeof(int), call_init_func, grpc_call_stack_ignore_set_pollset_or_pollset_set, call_destroy_func, sizeof(int), channel_init_func, channel_destroy_func, get_peer, grpc_channel_next_get_info, "some_test_filter"}; const grpc_channel_filter *filters = &filter; grpc_channel_stack *channel_stack; grpc_call_stack *call_stack; grpc_channel_element *channel_elem; grpc_call_element *call_elem; grpc_arg arg; grpc_channel_args chan_args; int *channel_data; int *call_data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_mdstr *path = grpc_mdstr_from_string("/service/method"); arg.type = GRPC_ARG_INTEGER; arg.key = "test_key"; arg.value.integer = 42; chan_args.num_args = 1; chan_args.args = &arg; channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, 1, &chan_args, NULL, "test", channel_stack); GPR_ASSERT(channel_stack->count == 1); channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_data = (int *)channel_elem->channel_data; GPR_ASSERT(*channel_data == 0); call_stack = gpr_malloc(channel_stack->call_stack_size); grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, NULL, NULL, path, gpr_now(GPR_CLOCK_MONOTONIC), gpr_inf_future(GPR_CLOCK_MONOTONIC), call_stack); GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(call_stack->count == 1); call_elem = grpc_call_stack_element(call_stack, 0); GPR_ASSERT(call_elem->filter == channel_elem->filter); GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data); call_data = (int *)call_elem->call_data; GPR_ASSERT(*call_data == 0); GPR_ASSERT(*channel_data == 1); GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done"); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(*channel_data == 2); GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); grpc_exec_ctx_finish(&exec_ctx); GRPC_MDSTR_UNREF(path); }
void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, grpc_transport *transport, grpc_channel_filter const **extra_filters, size_t num_extra_filters, const grpc_channel_args *args) { size_t num_filters = s->channel_filter_count + num_extra_filters + 1; grpc_channel_filter const **filters = gpr_malloc(sizeof(grpc_channel_filter *) * num_filters); size_t i; size_t num_registered_methods; size_t alloc; registered_method *rm; 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; uint32_t max_probes = 0; grpc_transport_op op; for (i = 0; i < s->channel_filter_count; i++) { filters[i] = s->channel_filters[i]; } for (; i < s->channel_filter_count + num_extra_filters; i++) { filters[i] = extra_filters[i - s->channel_filter_count]; } filters[i] = &grpc_connected_channel_filter; for (i = 0; i < s->cq_count; i++) { memset(&op, 0, sizeof(op)); op.bind_pollset = grpc_cq_pollset(s->cqs[i]); grpc_transport_perform_op(exec_ctx, transport, &op); } channel = grpc_channel_create_from_filters(exec_ctx, NULL, filters, num_filters, args, 0); chand = (channel_data *)grpc_channel_stack_element( grpc_channel_get_channel_stack(channel), 0)->channel_data; chand->server = s; server_ref(s); chand->channel = channel; num_registered_methods = 0; for (rm = s->registered_methods; rm; rm = rm->next) { num_registered_methods++; } /* build a lookup table phrased in terms of mdstr's in this channels context to quickly find registered methods */ if (num_registered_methods > 0) { slots = 2 * num_registered_methods; alloc = sizeof(channel_registered_method) * slots; 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); for (probes = 0; chand->registered_methods[(hash + probes) % slots] .server_registered_method != NULL; probes++) ; if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; crm->host = host; crm->method = method; } GPR_ASSERT(slots <= UINT32_MAX); chand->registered_method_slots = (uint32_t)slots; chand->registered_method_max_probes = max_probes; } grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel), transport); gpr_mu_lock(&s->mu_global); chand->next = &s->root_channel_data; chand->prev = chand->next->prev; chand->next->prev = chand->prev->next = chand; gpr_mu_unlock(&s->mu_global); gpr_free((void *)filters); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); memset(&op, 0, sizeof(op)); op.set_accept_stream = accept_stream; op.set_accept_stream_user_data = chand; op.on_connectivity_state_change = &chand->channel_connectivity_changed; op.connectivity_state = &chand->connectivity_state; op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0; grpc_transport_perform_op(exec_ctx, transport, &op); }
void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, grpc_transport *transport, grpc_pollset *accepting_pollset, const grpc_channel_args *args) { size_t num_registered_methods; size_t alloc; registered_method *rm; 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; uint32_t max_probes = 0; grpc_transport_op op; channel = grpc_channel_create(exec_ctx, NULL, args, GRPC_SERVER_CHANNEL, transport); chand = (channel_data *)grpc_channel_stack_element( grpc_channel_get_channel_stack(channel), 0) ->channel_data; chand->server = s; server_ref(s); chand->channel = channel; size_t cq_idx; grpc_completion_queue *accepting_cq = grpc_cq_from_pollset(accepting_pollset); for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) { if (s->cqs[cq_idx] == accepting_cq) break; } if (cq_idx == s->cq_count) { /* completion queue not found: pick a random one to publish new calls to */ cq_idx = (size_t)rand() % s->cq_count; } chand->cq_idx = cq_idx; num_registered_methods = 0; for (rm = s->registered_methods; rm; rm = rm->next) { num_registered_methods++; } /* build a lookup table phrased in terms of mdstr's in this channels context to quickly find registered methods */ if (num_registered_methods > 0) { slots = 2 * num_registered_methods; alloc = sizeof(channel_registered_method) * slots; 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); for (probes = 0; chand->registered_methods[(hash + probes) % slots] .server_registered_method != NULL; probes++) ; if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; crm->flags = rm->flags; crm->host = host; crm->method = method; } GPR_ASSERT(slots <= UINT32_MAX); chand->registered_method_slots = (uint32_t)slots; chand->registered_method_max_probes = max_probes; } gpr_mu_lock(&s->mu_global); chand->next = &s->root_channel_data; chand->prev = chand->next->prev; chand->next->prev = chand->prev->next = chand; gpr_mu_unlock(&s->mu_global); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); memset(&op, 0, sizeof(op)); op.set_accept_stream = true; op.set_accept_stream_fn = accept_stream; op.set_accept_stream_user_data = chand; op.on_connectivity_state_change = &chand->channel_connectivity_changed; op.connectivity_state = &chand->connectivity_state; if (gpr_atm_acq_load(&s->shutdown_flag) != 0) { op.disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); } grpc_transport_perform_op(exec_ctx, transport, &op); }