static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, grpc_security_status status, grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context) { server_secure_connect *state = statep; if (status == GRPC_SECURITY_OK) { if (secure_endpoint) { gpr_mu_lock(&state->state->mu); if (!state->state->is_shutdown) { grpc_transport *transport = grpc_create_chttp2_transport( exec_ctx, grpc_server_get_channel_args(state->state->server), secure_endpoint, 0); grpc_arg args_to_add[2]; args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds); args_to_add[1] = grpc_auth_context_to_arg(auth_context); grpc_channel_args *args_copy = grpc_channel_args_copy_and_add( state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); grpc_server_setup_transport(exec_ctx, state->state->server, transport, state->accepting_pollset, args_copy); grpc_channel_args_destroy(args_copy); grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL); } else { /* We need to consume this here, because the server may already have * gone away. */ grpc_endpoint_destroy(exec_ctx, secure_endpoint); } gpr_mu_unlock(&state->state->mu); } } else { gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); } grpc_channel_args_destroy(state->args); state_unref(state->state); gpr_free(state); }
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { fake_resolver* r = (fake_resolver*)gr; grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(exec_ctx, r->results_upon_error); grpc_channel_args_destroy(exec_ctx, r->channel_args); gpr_free(r); }
void chttp2_tear_down_fullstack_compression(grpc_end2end_test_fixture *f) { fullstack_compression_fixture_data *ffd = f->fixture_data; grpc_channel_args_destroy(ffd->client_args_compression); grpc_channel_args_destroy(ffd->server_args_compression); gpr_free(ffd->localaddr); gpr_free(ffd); }
/* Create a secure client channel: Asynchronously: - resolve target - connect to it (trying alternatives as presented) - perform handshakes */ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "reserved=%p)", 4, (creds, target, args, reserved)); GPR_ASSERT(reserved == NULL); // Make sure security connector does not already exist in args. if (grpc_find_security_connector_in_args(args) != NULL) { gpr_log(GPR_ERROR, "Cannot set security context in channel args."); grpc_exec_ctx_finish(&exec_ctx); return grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Security connector exists in channel args."); } // Create security connector and construct new channel args. grpc_channel_security_connector *security_connector; grpc_channel_args *new_args_from_connector; if (grpc_channel_credentials_create_security_connector( creds, target, args, &security_connector, &new_args_from_connector) != GRPC_SECURITY_OK) { grpc_exec_ctx_finish(&exec_ctx); return grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create security connector."); } grpc_arg connector_arg = grpc_security_connector_to_arg(&security_connector->base); grpc_channel_args *new_args = grpc_channel_args_copy_and_add( new_args_from_connector != NULL ? new_args_from_connector : args, &connector_arg, 1); if (new_args_from_connector != NULL) { grpc_channel_args_destroy(new_args_from_connector); } // Create client channel factory. client_channel_factory *f = gpr_malloc(sizeof(*f)); memset(f, 0, sizeof(*f)); f->base.vtable = &client_channel_factory_vtable; gpr_ref_init(&f->refs, 1); GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "grpc_secure_channel_create"); f->security_connector = security_connector; // Create channel. grpc_channel *channel = client_channel_factory_create_channel( &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); // Clean up. GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, "secure_client_channel_factory_create_channel"); grpc_channel_args_destroy(new_args); grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_exec_ctx_finish(&exec_ctx); return channel; /* may be NULL */ }
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { dns_resolver *r = (dns_resolver *)gr; gpr_mu_destroy(&r->mu); if (r->resolved_result != NULL) { grpc_channel_args_destroy(r->resolved_result); } gpr_free(r->name_to_resolve); gpr_free(r->default_port); grpc_channel_args_destroy(r->channel_args); gpr_free(r); }
void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { on_resolution_arg *res = arg; res->was_called = true; // We only check the addresses channel arg because that's the only one // explicitly set by the test via // grpc_fake_resolver_response_generator_set_response. const grpc_lb_addresses *actual_lb_addresses = grpc_lb_addresses_find_channel_arg(res->resolver_result); const grpc_lb_addresses *expected_lb_addresses = grpc_lb_addresses_find_channel_arg(res->expected_resolver_result); GPR_ASSERT( grpc_lb_addresses_cmp(actual_lb_addresses, expected_lb_addresses) == 0); grpc_channel_args_destroy(exec_ctx, res->resolver_result); grpc_channel_args_destroy(exec_ctx, res->expected_resolver_result); }
static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_fake_resolver_response_generator* generator = (grpc_fake_resolver_response_generator*)arg; fake_resolver* r = generator->resolver; if (r->next_results != NULL) { grpc_channel_args_destroy(exec_ctx, r->next_results); } r->next_results = generator->next_response; if (r->results_upon_error != NULL) { grpc_channel_args_destroy(exec_ctx, r->results_upon_error); } r->results_upon_error = grpc_channel_args_copy(generator->next_response); fake_resolver_maybe_finish_next_locked(exec_ctx, r); }
static grpc_channel *client_channel_factory_create_channel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const char *target, grpc_client_channel_type type, grpc_channel_args *args) { client_channel_factory *f = (client_channel_factory *)cc_factory; grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args); grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args, GRPC_CLIENT_CHANNEL, NULL); grpc_channel_args_destroy(final_args); grpc_resolver *resolver = grpc_resolver_create(target, &f->base); if (resolver != NULL) { grpc_client_channel_set_resolver( exec_ctx, grpc_channel_get_channel_stack(channel), resolver); GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create"); } else { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "client_channel_factory_create_channel"); channel = NULL; } GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, "client_channel_factory_create_channel"); return channel; }
static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_security_status status, grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context) { connector *c = arg; grpc_closure *notify; grpc_channel_args *args_copy = NULL; gpr_mu_lock(&c->mu); if (c->connecting_endpoint == NULL) { memset(c->result, 0, sizeof(*c->result)); gpr_mu_unlock(&c->mu); } else if (status != GRPC_SECURITY_OK) { gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status); memset(c->result, 0, sizeof(*c->result)); c->connecting_endpoint = NULL; gpr_mu_unlock(&c->mu); } else { grpc_arg auth_context_arg; c->connecting_endpoint = NULL; gpr_mu_unlock(&c->mu); c->result->transport = grpc_create_chttp2_transport( exec_ctx, c->args.channel_args, secure_endpoint, 1); grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, 0); auth_context_arg = grpc_auth_context_to_arg(auth_context); args_copy = grpc_channel_args_copy_and_add(c->args.channel_args, &auth_context_arg, 1); c->result->channel_args = args_copy; } notify = c->notify; c->notify = NULL; /* look at c->args which are connector args. */ notify->cb(exec_ctx, notify->cb_arg, 1); if (args_copy != NULL) grpc_channel_args_destroy(args_copy); }
static void test_create(void) { grpc_arg arg_int; grpc_arg arg_string; grpc_arg to_add[2]; grpc_channel_args *ch_args; arg_int.key = "int_arg"; arg_int.type = GRPC_ARG_INTEGER; arg_int.value.integer = 123; arg_string.key = "str key"; arg_string.type = GRPC_ARG_STRING; arg_string.value.string = "str value"; to_add[0] = arg_int; to_add[1] = arg_string; ch_args = grpc_channel_args_copy_and_add(NULL, to_add, 2); GPR_ASSERT(ch_args->num_args == 2); GPR_ASSERT(strcmp(ch_args->args[0].key, arg_int.key) == 0); GPR_ASSERT(ch_args->args[0].type == arg_int.type); GPR_ASSERT(ch_args->args[0].value.integer == arg_int.value.integer); GPR_ASSERT(strcmp(ch_args->args[1].key, arg_string.key) == 0); GPR_ASSERT(ch_args->args[1].type == arg_string.type); GPR_ASSERT(strcmp(ch_args->args[1].value.string, arg_string.value.string) == 0); grpc_channel_args_destroy(ch_args); }
static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) { registered_method *rm; size_t i; grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu_global); gpr_mu_destroy(&server->mu_call); while ((rm = server->registered_methods) != NULL) { server->registered_methods = rm->next; if (server->started) { request_matcher_destroy(&rm->request_matcher); } gpr_free(rm->method); gpr_free(rm->host); gpr_free(rm); } if (server->started) { request_matcher_destroy(&server->unregistered_request_matcher); } for (i = 0; i < server->cq_count; i++) { GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server"); if (server->started) { gpr_stack_lockfree_destroy(server->request_freelist_per_cq[i]); gpr_free(server->requested_calls_per_cq[i]); } } gpr_free(server->request_freelist_per_cq); gpr_free(server->requested_calls_per_cq); gpr_free(server->cqs); gpr_free(server->pollsets); gpr_free(server->shutdown_tags); gpr_free(server); }
static void server_unref(grpc_server *server) { registered_method *rm; size_t i; if (gpr_unref(&server->internal_refcount)) { grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu); gpr_cv_destroy(&server->cv); gpr_free(server->channel_filters); requested_call_array_destroy(&server->requested_calls); while ((rm = server->registered_methods) != NULL) { server->registered_methods = rm->next; gpr_free(rm->method); gpr_free(rm->host); requested_call_array_destroy(&rm->requested); gpr_free(rm); } for (i = 0; i < server->cq_count; i++) { grpc_cq_internal_unref(server->cqs[i]); } gpr_free(server->cqs); gpr_free(server->pollsets); gpr_free(server->shutdown_tags); gpr_free(server); } }
static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *unused) { const grpc_channel_args *args = grpc_channel_stack_builder_get_channel_arguments(builder); for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY) || 0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) { return true; } } char *default_authority = grpc_get_default_authority( exec_ctx, grpc_channel_stack_builder_get_target(builder)); if (default_authority != NULL) { grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_DEFAULT_AUTHORITY; arg.value.string = default_authority; grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1); grpc_channel_stack_builder_set_channel_arguments(exec_ctx, builder, new_args); gpr_free(default_authority); grpc_channel_args_destroy(exec_ctx, new_args); } return true; }
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { fake_resolver* r = (fake_resolver*)gr; gpr_mu_destroy(&r->mu); grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_lb_addresses_destroy(exec_ctx, r->addresses); gpr_free(r); }
void grpc_channel_stack_builder_set_channel_arguments( grpc_channel_stack_builder *builder, const grpc_channel_args *args) { if (builder->args != NULL) { grpc_channel_args_destroy(builder->args); } builder->args = grpc_channel_args_copy(args); }
grpc_channel *grpc_insecure_channel_create_from_fd( const char *target, int fd, const grpc_channel_args *args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_insecure_channel_create(target=%p, fd=%d, args=%p)", 3, (target, fd, args)); grpc_arg default_authority_arg; default_authority_arg.type = GRPC_ARG_STRING; default_authority_arg.key = GRPC_ARG_DEFAULT_AUTHORITY; default_authority_arg.value.string = "test.authority"; grpc_channel_args *final_args = grpc_channel_args_copy_and_add(args, &default_authority_arg, 1); int flags = fcntl(fd, F_GETFL, 0); GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); grpc_endpoint *client = grpc_tcp_client_create_from_fd( &exec_ctx, grpc_fd_create(fd, "client"), args, "fd-client"); grpc_transport *transport = grpc_create_chttp2_transport(&exec_ctx, final_args, client, 1); GPR_ASSERT(transport); grpc_channel *channel = grpc_channel_create( &exec_ctx, target, final_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); grpc_channel_args_destroy(final_args); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); grpc_exec_ctx_finish(&exec_ctx); return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create client channel"); }
static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, grpc_channel_args *args, gpr_slice_buffer *read_buffer, void *user_data, grpc_error *error) { server_secure_connect *state = user_data; if (error != GRPC_ERROR_NONE) { const char *error_str = grpc_error_string(error); gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); grpc_error_free_string(error_str); GRPC_ERROR_UNREF(error); grpc_channel_args_destroy(args); gpr_free(read_buffer); grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr); grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); state_unref(state->state); gpr_free(state); return; } grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); state->handshake_mgr = NULL; // TODO(roth, jboeuf): Convert security connector handshaking to use new // handshake API, and then move the code from on_secure_handshake_done() // into this function. state->args = args; grpc_server_security_connector_do_handshake( exec_ctx, state->state->sc, state->acceptor, endpoint, read_buffer, state->deadline, on_secure_handshake_done, state); }
grpc_channel_args *grpc_channel_args_compression_algorithm_set_state( grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) { int *states_arg; grpc_channel_args *result = *a; const int states_arg_found = find_compression_algorithm_states_bitset(*a, &states_arg); if (states_arg_found) { if (state != 0) { GPR_BITSET((unsigned *)states_arg, algorithm); } else { GPR_BITCLEAR((unsigned *)states_arg, algorithm); } } else { /* create a new arg */ grpc_arg tmp; tmp.type = GRPC_ARG_INTEGER; tmp.key = GRPC_COMPRESSION_ALGORITHM_STATE_ARG; /* all enabled by default */ tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; if (state != 0) { GPR_BITSET((unsigned *)&tmp.value.integer, algorithm); } else { GPR_BITCLEAR((unsigned *)&tmp.value.integer, algorithm); } result = grpc_channel_args_copy_and_add(*a, &tmp, 1); grpc_channel_args_destroy(*a); *a = result; } return result; }
static grpc_subchannel *client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_subchannel_args *args) { client_channel_factory *f = (client_channel_factory *)cc_factory; connector *c = gpr_malloc(sizeof(*c)); grpc_channel_args *final_args = grpc_channel_args_merge(args->args, f->merge_args); grpc_subchannel *s; memset(c, 0, sizeof(*c)); c->base.vtable = &connector_vtable; gpr_ref_init(&c->refs, 1); c->handshake_mgr = grpc_handshake_manager_create(); char *proxy_name = grpc_get_http_proxy_server(); if (proxy_name != NULL) { grpc_handshake_manager_add( c->handshake_mgr, grpc_http_connect_handshaker_create(proxy_name, args->server_name)); gpr_free(proxy_name); } args->args = final_args; s = grpc_subchannel_create(exec_ctx, &c->base, args); grpc_connector_unref(exec_ctx, &c->base); grpc_channel_args_destroy(final_args); return s; }
grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds, grpc_credentials *request_metadata_creds, const char *target, const grpc_channel_args *args) { grpc_channel_security_context *ctx = NULL; grpc_channel *channel = NULL; grpc_security_status status = GRPC_SECURITY_OK; size_t i = 0; const char *overridden_target_name = NULL; grpc_arg arg; grpc_channel_args *new_args; for (i = 0; args && i < args->num_args; i++) { grpc_arg *arg = &args->args[i]; if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 && arg->type == GRPC_ARG_STRING) { overridden_target_name = arg->value.string; break; } } status = grpc_ssl_channel_security_context_create( request_metadata_creds, grpc_ssl_credentials_get_config(ssl_creds), target, overridden_target_name, &ctx); if (status != GRPC_SECURITY_OK) { return grpc_lame_client_channel_create(); } arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_HTTP2_SCHEME; arg.value.string = "https"; new_args = grpc_channel_args_copy_and_add(args, &arg); channel = grpc_secure_channel_create_internal(target, new_args, ctx); grpc_security_context_unref(&ctx->base); grpc_channel_args_destroy(new_args); return channel; }
static void destroy_setup(grpc_client_setup *s) { gpr_mu_destroy(&s->mu); gpr_cv_destroy(&s->cv); s->done(s->user_data); grpc_channel_args_destroy(s->args); grpc_pollset_set_destroy(&s->interested_parties); gpr_free(s); }
// Set args fields to NULL, saving the endpoint and read buffer for // later destruction. static void cleanup_args_for_failure_locked(security_handshaker *h) { h->endpoint_to_destroy = h->args->endpoint; h->args->endpoint = NULL; h->read_buffer_to_destroy = h->args->read_buffer; h->args->read_buffer = NULL; grpc_channel_args_destroy(h->args->args); h->args->args = NULL; }
static void merge_args_factory_unref(grpc_subchannel_factory *scf) { merge_args_factory *f = (merge_args_factory *)scf; if (gpr_unref(&f->refs)) { grpc_subchannel_factory_unref(f->wrapped); grpc_channel_args_destroy(f->merge_args); gpr_free(f); } }
static void client_channel_factory_unref( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) { client_channel_factory *f = (client_channel_factory *)cc_factory; if (gpr_unref(&f->refs)) { grpc_channel_args_destroy(f->merge_args); gpr_free(f); } }
static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_handshaker_args *args = arg; server_connection_state *connection_state = args->user_data; gpr_mu_lock(&connection_state->server_state->mu); if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) { const char *error_str = grpc_error_string(error); gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str); if (error == GRPC_ERROR_NONE && args->endpoint != NULL) { // We were shut down after handshaking completed successfully, so // destroy the endpoint here. // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE); grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_channel_args_destroy(exec_ctx, args->args); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); gpr_free(args->read_buffer); } } else { // If the handshaking succeeded but there is no endpoint, then the // handshaker may have handed off the connection to some external // code, so we can just clean up here without creating a transport. if (args->endpoint != NULL) { grpc_transport *transport = grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0); grpc_server_setup_transport( exec_ctx, connection_state->server_state->server, transport, connection_state->accepting_pollset, args->args); grpc_chttp2_transport_start_reading(exec_ctx, transport, args->read_buffer); grpc_channel_args_destroy(exec_ctx, args->args); } } grpc_handshake_manager_pending_list_remove( &connection_state->server_state->pending_handshake_mgrs, connection_state->handshake_mgr); gpr_mu_unlock(&connection_state->server_state->mu); grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server); gpr_free(connection_state->acceptor); gpr_free(connection_state); }
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf) { subchannel_factory *f = (subchannel_factory *)scf; if (gpr_unref(&f->refs)) { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory"); grpc_channel_args_destroy(f->merge_args); gpr_free(f); } }
// Set args fields to NULL, saving the endpoint and read buffer for // later destruction. static void cleanup_args_for_failure_locked( grpc_exec_ctx* exec_ctx, http_connect_handshaker* handshaker) { handshaker->endpoint_to_destroy = handshaker->args->endpoint; handshaker->args->endpoint = NULL; handshaker->read_buffer_to_destroy = handshaker->args->read_buffer; handshaker->args->read_buffer = NULL; grpc_channel_args_destroy(exec_ctx, handshaker->args->args); handshaker->args->args = NULL; }
void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { fullstack_fixture_data *ffd = f->fixture_data; grpc_arg arg = grpc_load_reporting_config_create_arg(g_client_lrc); client_args = grpc_channel_args_copy_and_add(client_args, &arg, 1); f->client = grpc_insecure_channel_create(ffd->localaddr, client_args, NULL); grpc_channel_args_destroy(client_args); GPR_ASSERT(f->client); }
static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { connector *c = (connector *)con; if (gpr_unref(&c->refs)) { /* c->initial_string_buffer does not need to be destroyed */ grpc_channel_args_destroy(c->tmp_args); grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); gpr_free(c); } }
static void subchannel_factory_unref(grpc_subchannel_factory *scf) { subchannel_factory *f = (subchannel_factory *)scf; if (gpr_unref(&f->refs)) { GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, "subchannel_factory"); grpc_channel_args_destroy(f->merge_args); grpc_mdctx_unref(f->mdctx); gpr_free(f); } }