int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp = NULL; grpc_server_secure_state *state = NULL; size_t i; unsigned count = 0; int port_num = -1; int port_temp; grpc_security_status status = GRPC_SECURITY_ERROR; grpc_server_security_connector *sc = NULL; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_server_add_secure_http2_port(" "server=%p, addr=%s, creds=%p)", 3, (server, addr, creds)); /* create security context */ if (creds == NULL) goto error; status = grpc_server_credentials_create_security_connector(creds, &sc); if (status != GRPC_SECURITY_OK) { gpr_log(GPR_ERROR, "Unable to create secure server with credentials of type %s.", creds->type); goto error; } sc->channel_args = grpc_server_get_channel_args(server); /* resolve address */ resolved = grpc_blocking_resolve_address(addr, "https"); if (!resolved) { goto error; } state = gpr_malloc(sizeof(*state)); memset(state, 0, sizeof(*state)); grpc_closure_init(&state->destroy_closure, destroy_done, state); tcp = grpc_tcp_server_create(&state->destroy_closure); if (!tcp) { goto error; } state->server = server; state->tcp = tcp; state->sc = sc; state->creds = grpc_server_credentials_ref(creds); state->is_shutdown = 0; gpr_mu_init(&state->mu); gpr_ref_init(&state->refcount, 1); for (i = 0; i < resolved->naddrs; i++) { port_temp = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len); if (port_temp > 0) { if (port_num == -1) { port_num = port_temp; } else { GPR_ASSERT(port_num == port_temp); } count++; } } if (count == 0) { gpr_log(GPR_ERROR, "No address added out of total %d resolved", resolved->naddrs); goto error; } if (count != resolved->naddrs) { gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved", count, resolved->naddrs); /* if it's an error, don't we want to goto error; here ? */ } grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ grpc_server_add_listener(&exec_ctx, server, state, start, destroy); grpc_exec_ctx_finish(&exec_ctx); return port_num; /* Error path: cleanup and return */ error: if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp) { grpc_tcp_server_unref(&exec_ctx, tcp); } else { if (sc) { GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); } if (state) { gpr_free(state); } } grpc_exec_ctx_finish(&exec_ctx); return 0; }
/* 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_arg connector_arg; grpc_channel_args *args_copy; grpc_channel_args *new_args_from_connector; grpc_channel_security_connector *security_connector; client_channel_factory *f; 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); 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."); } 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."); } connector_arg = grpc_security_connector_to_arg(&security_connector->base); args_copy = grpc_channel_args_copy_and_add( new_args_from_connector != NULL ? new_args_from_connector : args, &connector_arg, 1); f = gpr_malloc(sizeof(*f)); memset(f, 0, sizeof(*f)); f->base.vtable = &client_channel_factory_vtable; gpr_ref_init(&f->refs, 1); f->merge_args = grpc_channel_args_copy(args_copy); grpc_channel_args_destroy(args_copy); if (new_args_from_connector != NULL) { grpc_channel_args_destroy(new_args_from_connector); } GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "grpc_secure_channel_create"); f->security_connector = security_connector; grpc_channel *channel = client_channel_factory_create_channel( &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); if (channel != NULL) { f->master = channel; GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_secure_channel_create"); } grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_exec_ctx_finish(&exec_ctx); return channel; /* may be NULL */ }
static void request_call(void) { call_state *tag = gpr_malloc(sizeof(*tag)); gpr_ref_init(&tag->pending_ops, 2); tag->bytes_read = 0; grpc_server_request_call_old(server, tag); }
static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx, gpr_uint8 is_client) { size_t i; int j; GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); memset(t, 0, sizeof(*t)); t->base.vtable = &vtable; t->ep = ep; /* one ref is for destroy, the other for when ep becomes NULL */ gpr_ref_init(&t->refs, 2); /* ref is dropped at transport close() */ gpr_ref_init(&t->shutdown_ep_refs, 1); gpr_mu_init(&t->mu); grpc_mdctx_ref(mdctx); t->peer_string = grpc_endpoint_get_peer(ep); t->metadata_context = mdctx; t->endpoint_reading = 1; t->global.next_stream_id = is_client ? 1 : 2; t->global.is_client = is_client; t->global.outgoing_window = DEFAULT_WINDOW; t->global.incoming_window = DEFAULT_WINDOW; t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET; t->global.ping_counter = 1; t->global.pings.next = t->global.pings.prev = &t->global.pings; t->parsing.is_client = is_client; t->parsing.str_grpc_timeout = grpc_mdstr_from_string(t->metadata_context, "grpc-timeout"); t->parsing.deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; t->writing.is_client = is_client; grpc_connectivity_state_init( &t->channel_callback.state_tracker, GRPC_CHANNEL_READY, is_client ? "client_transport" : "server_transport"); gpr_slice_buffer_init(&t->global.qbuf); gpr_slice_buffer_init(&t->writing.outbuf); grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor, mdctx); grpc_closure_init(&t->writing_action, writing_action, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser, t->metadata_context); grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, &t->writing); grpc_closure_init(&t->recv_data, recv_data, t); gpr_slice_buffer_init(&t->read_buffer); if (is_client) { gpr_slice_buffer_add( &t->global.qbuf, gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); } /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet large enough that the exponential growth should happen nicely when it's needed. TODO(ctiller): tune this */ grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8); grpc_chttp2_stream_map_init(&t->new_stream_map, 8); /* copy in initial settings to all setting sets */ for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value; for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { t->global.settings[j][i] = grpc_chttp2_settings_parameters[i].default_value; } } t->global.dirtied_local_settings = 1; /* Hack: it's common for implementations to assume 65536 bytes initial send window -- this should by rights be 0 */ t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->global.sent_local_settings = 0; /* configure http2 the way we like it */ if (is_client) { push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); } push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); if (channel_args) { for (i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) { if (is_client) { gpr_log(GPR_ERROR, "%s: is ignored on the client", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else { push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, (gpr_uint32)channel_args->args[i].value.integer); } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { if (channel_args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); } else if ((t->global.next_stream_id & 1) != (channel_args->args[i].value.integer & 1)) { gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, t->global.next_stream_id & 1, is_client ? "client" : "server"); } else { t->global.next_stream_id = (gpr_uint32)channel_args->args[i].value.integer; } } } } }
/* Create a secure client channel: Asynchronously: - resolve target - connect to it (trying alternatives as presented) - perform handshakes */ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) { grpc_channel *channel; grpc_arg connector_arg; grpc_channel_args *args_copy; grpc_channel_args *new_args_from_connector; grpc_channel_security_connector *connector; grpc_mdctx *mdctx; grpc_resolver *resolver; subchannel_factory *f; #define MAX_FILTERS 3 const grpc_channel_filter *filters[MAX_FILTERS]; size_t n = 0; GPR_ASSERT(reserved == NULL); if (grpc_find_security_connector_in_args(args) != NULL) { gpr_log(GPR_ERROR, "Cannot set security context in channel args."); return grpc_lame_client_channel_create( target, GRPC_STATUS_INVALID_ARGUMENT, "Security connector exists in channel args."); } if (grpc_credentials_create_security_connector( creds, target, args, NULL, &connector, &new_args_from_connector) != GRPC_SECURITY_OK) { return grpc_lame_client_channel_create( target, GRPC_STATUS_INVALID_ARGUMENT, "Failed to create security connector."); } mdctx = grpc_mdctx_create(); connector_arg = grpc_security_connector_to_arg(&connector->base); args_copy = grpc_channel_args_copy_and_add( new_args_from_connector != NULL ? new_args_from_connector : args, &connector_arg, 1); if (grpc_channel_args_is_census_enabled(args)) { filters[n++] = &grpc_client_census_filter; } filters[n++] = &grpc_compress_filter; filters[n++] = &grpc_client_channel_filter; GPR_ASSERT(n <= MAX_FILTERS); channel = grpc_channel_create_from_filters(target, filters, n, args_copy, mdctx, 1); f = gpr_malloc(sizeof(*f)); f->base.vtable = &subchannel_factory_vtable; gpr_ref_init(&f->refs, 1); grpc_mdctx_ref(mdctx); f->mdctx = mdctx; GRPC_SECURITY_CONNECTOR_REF(&connector->base, "subchannel_factory"); f->security_connector = connector; f->merge_args = grpc_channel_args_copy(args_copy); f->master = channel; GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory"); resolver = grpc_resolver_create(target, &f->base); if (!resolver) { return NULL; } grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel), resolver); GRPC_RESOLVER_UNREF(resolver, "create"); grpc_subchannel_factory_unref(&f->base); GRPC_SECURITY_CONNECTOR_UNREF(&connector->base, "channel_create"); grpc_channel_args_destroy(args_copy); if (new_args_from_connector != NULL) { grpc_channel_args_destroy(new_args_from_connector); } return channel; }
grpc_security_status grpc_ssl_channel_security_connector_create( grpc_credentials *request_metadata_creds, const grpc_ssl_config *config, const char *target_name, const char *overridden_target_name, grpc_channel_security_connector **sc) { size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); const unsigned char **alpn_protocol_strings = gpr_malloc(sizeof(const char *) * num_alpn_protocols); unsigned char *alpn_protocol_string_lengths = gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); tsi_result result = TSI_OK; grpc_ssl_channel_security_connector *c; size_t i; const unsigned char *pem_root_certs; size_t pem_root_certs_size; char *port; for (i = 0; i < num_alpn_protocols; i++) { alpn_protocol_strings[i] = (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); alpn_protocol_string_lengths[i] = (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); } if (config == NULL || target_name == NULL) { gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); goto error; } if (!check_request_metadata_creds(request_metadata_creds)) { goto error; } if (config->pem_root_certs == NULL) { pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs); if (pem_root_certs == NULL || pem_root_certs_size == 0) { gpr_log(GPR_ERROR, "Could not get default pem root certs."); goto error; } } else { pem_root_certs = config->pem_root_certs; pem_root_certs_size = config->pem_root_certs_size; } c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector)); memset(c, 0, sizeof(grpc_ssl_channel_security_connector)); gpr_ref_init(&c->base.base.refcount, 1); c->base.base.vtable = &ssl_channel_vtable; c->base.base.is_client_side = 1; c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds); c->base.check_call_host = ssl_channel_check_call_host; gpr_split_host_port(target_name, &c->target_name, &port); gpr_free(port); if (overridden_target_name != NULL) { c->overridden_target_name = gpr_strdup(overridden_target_name); } result = tsi_create_ssl_client_handshaker_factory( config->pem_private_key, config->pem_private_key_size, config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs, pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols, &c->handshaker_factory); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", tsi_result_to_string(result)); ssl_channel_destroy(&c->base.base); *sc = NULL; goto error; } *sc = &c->base; gpr_free(alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); return GRPC_SECURITY_OK; error: gpr_free(alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); return GRPC_SECURITY_ERROR; }
grpc_channel *grpc_channel_create_from_filters( grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_filter **filters, size_t num_filters, const grpc_channel_args *args, int is_client) { size_t i; size_t size = sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters); grpc_channel *channel = gpr_malloc(size); memset(channel, 0, sizeof(*channel)); channel->target = gpr_strdup(target); GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); channel->is_client = is_client; /* decremented by grpc_channel_destroy */ gpr_ref_init(&channel->refs, 1); gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH; if (args) { for (i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) { if (args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s ignored: it must be an integer", GRPC_ARG_MAX_MESSAGE_LENGTH); } else if (args->args[i].value.integer < 0) { gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", GRPC_ARG_MAX_MESSAGE_LENGTH); } else { channel->max_message_length = (gpr_uint32)args->args[i].value.integer; } } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s: must be an string", GRPC_ARG_DEFAULT_AUTHORITY); } else { if (channel->default_authority) { /* setting this takes precedence over anything else */ GRPC_MDELEM_UNREF(channel->default_authority); } channel->default_authority = grpc_mdelem_from_strings( ":authority", args->args[i].value.string); } } else if (0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s: must be an string", GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); } else { if (channel->default_authority) { /* other ways of setting this (notably ssl) take precedence */ gpr_log(GPR_ERROR, "%s: default host already set some other way", GRPC_ARG_DEFAULT_AUTHORITY); } else { channel->default_authority = grpc_mdelem_from_strings( ":authority", args->args[i].value.string); } } } } } if (channel->is_client && channel->default_authority == NULL && target != NULL) { char *default_authority = grpc_get_default_authority(target); if (default_authority) { channel->default_authority = grpc_mdelem_from_strings(":authority", default_authority); } gpr_free(default_authority); } grpc_channel_stack_init(exec_ctx, filters, num_filters, channel, args, CHANNEL_STACK_FROM_CHANNEL(channel)); return channel; }
void grpc_lb_policy_init(grpc_lb_policy *policy, const grpc_lb_policy_vtable *vtable) { policy->vtable = vtable; gpr_ref_init(&policy->refs, 1); }
static grpc_resolver *sockaddr_create( grpc_resolver_args *args, const char *default_lb_policy_name, int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) { size_t i; int errors_found = 0; /* GPR_FALSE */ sockaddr_resolver *r; gpr_slice path_slice; gpr_slice_buffer path_parts; if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } r = gpr_malloc(sizeof(sockaddr_resolver)); memset(r, 0, sizeof(*r)); r->lb_policy_name = NULL; if (0 != strcmp(args->uri->query, "")) { gpr_slice query_slice; gpr_slice_buffer query_parts; query_slice = gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing); gpr_slice_buffer_init(&query_parts); gpr_slice_split(query_slice, "=", &query_parts); GPR_ASSERT(query_parts.count == 2); if (0 == gpr_slice_str_cmp(query_parts.slices[0], "lb_policy")) { r->lb_policy_name = gpr_dump_slice(query_parts.slices[1], GPR_DUMP_ASCII); } gpr_slice_buffer_destroy(&query_parts); gpr_slice_unref(query_slice); } if (r->lb_policy_name == NULL) { r->lb_policy_name = gpr_strdup(default_lb_policy_name); } path_slice = gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); r->num_addrs = path_parts.count; r->addrs = gpr_malloc(sizeof(struct sockaddr_storage) * r->num_addrs); r->addrs_len = gpr_malloc(sizeof(*r->addrs_len) * r->num_addrs); for (i = 0; i < r->num_addrs; i++) { grpc_uri ith_uri = *args->uri; char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); ith_uri.path = part_str; if (!parse(&ith_uri, &r->addrs[i], &r->addrs_len[i])) { errors_found = 1; /* GPR_TRUE */ } gpr_free(part_str); if (errors_found) break; } gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { gpr_free(r->lb_policy_name); gpr_free(r->addrs); gpr_free(r->addrs_len); gpr_free(r); return NULL; } gpr_ref_init(&r->refs, 1); gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); r->subchannel_factory = args->subchannel_factory; grpc_subchannel_factory_ref(r->subchannel_factory); return &r->base; }
grpc_client_config *grpc_client_config_create() { grpc_client_config *c = gpr_malloc(sizeof(*c)); memset(c, 0, sizeof(*c)); gpr_ref_init(&c->refs, 1); return c; }
void grpc_resolver_init(grpc_resolver *resolver, const grpc_resolver_vtable *vtable) { resolver->vtable = vtable; gpr_ref_init(&resolver->refs, 1); }
grpc_channel *grpc_channel_create_from_filters( grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_filter **filters, size_t num_filters, const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client) { size_t i; size_t size = sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters); grpc_channel *channel = gpr_malloc(size); memset(channel, 0, sizeof(*channel)); channel->target = gpr_strdup(target); GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); channel->is_client = is_client; /* decremented by grpc_channel_destroy */ gpr_ref_init(&channel->refs, 1); channel->metadata_context = mdctx; channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status", 0); channel->grpc_compression_algorithm_string = grpc_mdstr_from_string(mdctx, "grpc-encoding", 0); channel->grpc_encodings_accepted_by_peer_string = grpc_mdstr_from_string(mdctx, "grpc-accept-encoding", 0); channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message", 0); for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { char buf[GPR_LTOA_MIN_BUFSIZE]; gpr_ltoa((long)i, buf); channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings( mdctx, GRPC_MDSTR_REF(channel->grpc_status_string), grpc_mdstr_from_string(mdctx, buf, 0)); } channel->path_string = grpc_mdstr_from_string(mdctx, ":path", 0); channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority", 0); gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH; if (args) { for (i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) { if (args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s ignored: it must be an integer", GRPC_ARG_MAX_MESSAGE_LENGTH); } else if (args->args[i].value.integer < 0) { gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", GRPC_ARG_MAX_MESSAGE_LENGTH); } else { channel->max_message_length = (gpr_uint32)args->args[i].value.integer; } } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s: must be an string", GRPC_ARG_DEFAULT_AUTHORITY); } else { if (channel->default_authority) { /* setting this takes precedence over anything else */ GRPC_MDELEM_UNREF(channel->default_authority); } channel->default_authority = grpc_mdelem_from_strings( mdctx, ":authority", args->args[i].value.string); } } else if (0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s: must be an string", GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); } else { if (channel->default_authority) { /* other ways of setting this (notably ssl) take precedence */ gpr_log(GPR_ERROR, "%s: default host already set some other way", GRPC_ARG_DEFAULT_AUTHORITY); } else { channel->default_authority = grpc_mdelem_from_strings( mdctx, ":authority", args->args[i].value.string); } } } } } if (channel->is_client && channel->default_authority == NULL && target != NULL) { char *default_authority = grpc_get_default_authority(target); if (default_authority) { channel->default_authority = grpc_mdelem_from_strings( channel->metadata_context, ":authority", default_authority); } gpr_free(default_authority); } grpc_channel_stack_init(exec_ctx, filters, num_filters, channel, args, channel->metadata_context, CHANNEL_STACK_FROM_CHANNEL(channel)); return channel; }
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp = NULL; grpc_server_secure_state *state = NULL; size_t i; unsigned count = 0; int port_num = -1; int port_temp; grpc_security_status status = GRPC_SECURITY_ERROR; grpc_security_context *ctx = NULL; /* create security context */ if (creds == NULL) goto error; if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL) == 0) { status = grpc_ssl_server_security_context_create( grpc_ssl_server_credentials_get_config(creds), &ctx); } else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY) == 0) { ctx = grpc_fake_server_security_context_create(); status = GRPC_SECURITY_OK; } if (status != GRPC_SECURITY_OK) { gpr_log(GPR_ERROR, "Unable to create secure server with credentials of type %s.", creds->type); goto error; } /* resolve address */ resolved = grpc_blocking_resolve_address(addr, "https"); if (!resolved) { goto error; } tcp = grpc_tcp_server_create(); if (!tcp) { goto error; } for (i = 0; i < resolved->naddrs; i++) { port_temp = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len); if (port_temp >= 0) { if (port_num == -1) { port_num = port_temp; } else { GPR_ASSERT(port_num == port_temp); } count++; } } if (count == 0) { gpr_log(GPR_ERROR, "No address added out of total %d resolved", resolved->naddrs); goto error; } if (count != resolved->naddrs) { gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved", count, resolved->naddrs); /* if it's an error, don't we want to goto error; here ? */ } grpc_resolved_addresses_destroy(resolved); state = gpr_malloc(sizeof(*state)); state->server = server; state->tcp = tcp; state->ctx = ctx; state->is_shutdown = 0; gpr_mu_init(&state->mu); gpr_ref_init(&state->refcount, 1); /* Register with the server only upon success */ grpc_server_add_listener(server, state, start, destroy); return port_num; /* Error path: cleanup and return */ error: if (ctx) { grpc_security_context_unref(ctx); } if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp) { grpc_tcp_server_destroy(tcp, NULL, NULL); } if (state) { gpr_free(state); } return 0; }
static grpc_resolver *sockaddr_create( grpc_resolver_args *args, const char *default_lb_policy_name, int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) { bool errors_found = false; sockaddr_resolver *r; gpr_slice path_slice; gpr_slice_buffer path_parts; if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } r = gpr_malloc(sizeof(sockaddr_resolver)); memset(r, 0, sizeof(*r)); r->lb_policy_name = gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy")); const char *lb_enabled_qpart = grpc_uri_get_query_arg(args->uri, "lb_enabled"); /* anything other than "0" is interpreted as true */ const bool lb_enabled = (lb_enabled_qpart != NULL && (strcmp("0", lb_enabled_qpart) != 0)); if (r->lb_policy_name != NULL && strcmp("grpclb", r->lb_policy_name) == 0 && !lb_enabled) { /* we want grpclb but the "resolved" addresses aren't LB enabled. Bail * out, as this is meant mostly for tests. */ gpr_log(GPR_ERROR, "Requested 'grpclb' LB policy but resolved addresses don't " "support load balancing."); abort(); } if (r->lb_policy_name == NULL) { r->lb_policy_name = gpr_strdup(default_lb_policy_name); } path_slice = gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); r->addresses = grpc_lb_addresses_create(path_parts.count); for (size_t i = 0; i < r->addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); ith_uri.path = part_str; if (!parse(&ith_uri, (struct sockaddr_storage *)(&r->addresses->addresses[i] .address.addr), &r->addresses->addresses[i].address.len)) { errors_found = true; } gpr_free(part_str); r->addresses->addresses[i].is_balancer = lb_enabled; if (errors_found) break; } r->target_name = gpr_strdup(args->uri->path); gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { gpr_free(r->lb_policy_name); gpr_free(r->target_name); grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */); gpr_free(r); return NULL; } gpr_ref_init(&r->refs, 1); gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); return &r->base; }
static void on_new_call(void *arg, int success) { grpc_end2end_proxy *proxy = arg; grpc_call_error err; if (success) { grpc_op op; proxy_call *pc = gpr_malloc(sizeof(*pc)); memset(pc, 0, sizeof(*pc)); pc->proxy = proxy; GPR_SWAP(grpc_metadata_array, pc->c2p_initial_metadata, proxy->new_call_metadata); 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.deadline, NULL); gpr_ref_init(&pc->refs, 1); op.reserved = NULL; op.op = GRPC_OP_RECV_INITIAL_METADATA; op.flags = 0; op.data.recv_initial_metadata = &pc->p2s_initial_metadata; refpc(pc, "on_p2s_recv_initial_metadata"); err = grpc_call_start_batch( pc->p2s, &op, 1, new_closure(on_p2s_recv_initial_metadata, pc), NULL); GPR_ASSERT(err == GRPC_CALL_OK); op.op = GRPC_OP_SEND_INITIAL_METADATA; op.flags = proxy->new_call_details.flags; op.data.send_initial_metadata.count = pc->c2p_initial_metadata.count; op.data.send_initial_metadata.metadata = pc->c2p_initial_metadata.metadata; refpc(pc, "on_p2s_sent_initial_metadata"); err = grpc_call_start_batch( pc->p2s, &op, 1, new_closure(on_p2s_sent_initial_metadata, pc), NULL); GPR_ASSERT(err == GRPC_CALL_OK); op.op = GRPC_OP_RECV_MESSAGE; op.flags = 0; op.data.recv_message = &pc->c2p_msg; refpc(pc, "on_c2p_recv_msg"); err = grpc_call_start_batch(pc->c2p, &op, 1, new_closure(on_c2p_recv_msg, pc), NULL); GPR_ASSERT(err == GRPC_CALL_OK); op.op = GRPC_OP_RECV_MESSAGE; op.flags = 0; op.data.recv_message = &pc->p2s_msg; refpc(pc, "on_p2s_recv_msg"); err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_recv_msg, pc), NULL); GPR_ASSERT(err == GRPC_CALL_OK); op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; op.flags = 0; op.data.recv_status_on_client.trailing_metadata = &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); GPR_ASSERT(err == GRPC_CALL_OK); op.op = GRPC_OP_RECV_CLOSE_ON_SERVER; op.flags = 0; op.data.recv_close_on_server.cancelled = &pc->c2p_server_cancelled; refpc(pc, "on_c2p_closed"); err = grpc_call_start_batch(pc->c2p, &op, 1, new_closure(on_c2p_closed, pc), NULL); GPR_ASSERT(err == GRPC_CALL_OK); request_call(proxy); unrefpc(pc, "init"); } else { GPR_ASSERT(proxy->new_call == NULL); } }