grpc_call *grpc_channel_create_pollset_set_call( grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved) { GPR_ASSERT(!reserved); return grpc_channel_create_call_internal( exec_ctx, channel, parent_call, propagation_mask, NULL, pollset_set, grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH, grpc_slice_ref_internal(method)), host != NULL ? grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref_internal(*host)) : GRPC_MDNULL, deadline); }
static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status) { grpc_call_element *elem = (grpc_call_element *)user_data; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_transport_stream_op *op = &calld->op; grpc_metadata_batch *mdb; size_t i; reset_service_url(calld); if (status != GRPC_CREDENTIALS_OK) { bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, "Credentials failed to get metadata."); return; } GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(op->send_ops && op->send_ops->nops > calld->op_md_idx && op->send_ops->ops[calld->op_md_idx].type == GRPC_OP_METADATA); mdb = &op->send_ops->ops[calld->op_md_idx].data.metadata; for (i = 0; i < num_md; i++) { grpc_metadata_batch_add_tail( mdb, &calld->md_links[i], grpc_mdelem_from_slices(chand->md_ctx, gpr_slice_ref(md_elems[i].key), gpr_slice_ref(md_elems[i].value))); } grpc_call_next_op(exec_ctx, elem, op); }
static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status, const char *error_details) { grpc_call_element *elem = (grpc_call_element *)user_data; call_data *calld = elem->call_data; grpc_transport_stream_op *op = &calld->op; grpc_metadata_batch *mdb; size_t i; reset_auth_metadata_context(&calld->auth_md_context); if (status != GRPC_CREDENTIALS_OK) { bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, (error_details != NULL && strlen(error_details) > 0) ? error_details : "Credentials failed to get metadata."); return; } GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(op->send_initial_metadata != NULL); mdb = op->send_initial_metadata; for (i = 0; i < num_md; i++) { grpc_metadata_batch_add_tail( mdb, &calld->md_links[i], grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key), gpr_slice_ref(md_elems[i].value))); } grpc_call_next_op(exec_ctx, elem, op); }
static grpc_error *fill_in_metadata(grpc_exec_ctx *exec_ctx, inproc_stream *s, const grpc_metadata_batch *metadata, uint32_t flags, grpc_metadata_batch *out_md, uint32_t *outflags, bool *markfilled) { if (GRPC_TRACER_ON(grpc_inproc_trace)) { log_metadata(metadata, s->t->is_client, outflags != NULL); } if (outflags != NULL) { *outflags = flags; } if (markfilled != NULL) { *markfilled = true; } grpc_error *error = GRPC_ERROR_NONE; for (grpc_linked_mdelem *elem = metadata->list.head; (elem != NULL) && (error == GRPC_ERROR_NONE); elem = elem->next) { grpc_linked_mdelem *nelem = gpr_arena_alloc(s->arena, sizeof(*nelem)); nelem->md = grpc_mdelem_from_slices( exec_ctx, grpc_slice_intern(GRPC_MDKEY(elem->md)), grpc_slice_intern(GRPC_MDVALUE(elem->md))); error = grpc_metadata_batch_link_tail(exec_ctx, out_md, nelem); } return error; }
grpc_call *grpc_channel_create_call(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved) { GPR_ASSERT(!reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call *call = grpc_channel_create_call_internal( &exec_ctx, channel, parent_call, propagation_mask, cq, NULL, grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_PATH, grpc_slice_ref_internal(method)), host != NULL ? grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref_internal(*host)) : GRPC_MDNULL, deadline); grpc_exec_ctx_finish(&exec_ctx); return call; }
static void deadline_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, framer_state *st) { char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; grpc_mdelem mdelem; grpc_http2_encode_timeout( gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str); mdelem = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT, grpc_slice_from_copied_string(timeout_str)); hpack_enc(exec_ctx, c, mdelem, st); GRPC_MDELEM_UNREF(exec_ctx, mdelem); }
void *grpc_channel_register_call(grpc_channel *channel, const char *method, const char *host, void *reserved) { registered_call *rc = gpr_malloc(sizeof(registered_call)); GRPC_API_TRACE( "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)", 4, (channel, method, host, reserved)); GPR_ASSERT(!reserved); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; rc->path = grpc_mdelem_from_slices( &exec_ctx, GRPC_MDSTR_PATH, grpc_slice_intern(grpc_slice_from_static_string(method))); rc->authority = host ? grpc_mdelem_from_slices( &exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_intern(grpc_slice_from_static_string(host))) : GRPC_MDNULL; gpr_mu_lock(&channel->registered_call_mu); rc->next = channel->registered_calls; channel->registered_calls = rc; gpr_mu_unlock(&channel->registered_call_mu); grpc_exec_ctx_finish(&exec_ctx); return rc; }
static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status, const char *error_details) { grpc_call_element *elem = (grpc_call_element *)user_data; call_data *calld = elem->call_data; grpc_transport_stream_op *op = &calld->op; grpc_metadata_batch *mdb; size_t i; reset_auth_metadata_context(&calld->auth_md_context); grpc_error *error = GRPC_ERROR_NONE; if (status != GRPC_CREDENTIALS_OK) { error = grpc_error_set_int( GRPC_ERROR_CREATE(error_details != NULL && strlen(error_details) > 0 ? error_details : "Credentials failed to get metadata."), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED); } else { GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(op->send_initial_metadata != NULL); mdb = op->send_initial_metadata; for (i = 0; i < num_md; i++) { add_error(&error, grpc_metadata_batch_add_tail( exec_ctx, mdb, &calld->md_links[i], grpc_mdelem_from_slices( exec_ctx, grpc_slice_ref_internal(md_elems[i].key), grpc_slice_ref_internal(md_elems[i].value)))); } } if (error == GRPC_ERROR_NONE) { grpc_call_next_op(exec_ctx, elem, op); } else { grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error); } }
grpc_channel *grpc_channel_create_with_builder( grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, grpc_channel_stack_type channel_stack_type) { char *target = gpr_strdup(grpc_channel_stack_builder_get_target(builder)); grpc_channel_args *args = grpc_channel_args_copy( grpc_channel_stack_builder_get_channel_arguments(builder)); grpc_channel *channel; grpc_error *error = grpc_channel_stack_builder_finish( exec_ctx, builder, sizeof(grpc_channel), 1, destroy_channel, NULL, (void **)&channel); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "channel stack builder failed: %s", grpc_error_string(error)); GRPC_ERROR_UNREF(error); gpr_free(target); goto done; } memset(channel, 0, sizeof(*channel)); channel->target = target; channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; gpr_atm_no_barrier_store( &channel->call_size_estimate, (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size); grpc_compression_options_init(&channel->compression_options); for (size_t i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s ignored: it must be a string", GRPC_ARG_DEFAULT_AUTHORITY); } else { if (!GRPC_MDISNULL(channel->default_authority)) { /* setting this takes precedence over anything else */ GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority); } channel->default_authority = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_intern( grpc_slice_from_static_string(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 ignored: it must be a string", GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); } else { if (!GRPC_MDISNULL(channel->default_authority)) { /* other ways of setting this (notably ssl) take precedence */ gpr_log(GPR_ERROR, "%s ignored: default host already set some other way", GRPC_SSL_TARGET_NAME_OVERRIDE_ARG); } else { channel->default_authority = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_intern( grpc_slice_from_static_string(args->args[i].value.string))); } } } else if (0 == strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) { channel->compression_options.default_level.is_set = true; channel->compression_options.default_level.level = (grpc_compression_level)grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_COUNT - 1}); } else if (0 == strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM)) { channel->compression_options.default_algorithm.is_set = true; channel->compression_options.default_algorithm.algorithm = (grpc_compression_algorithm)grpc_channel_arg_get_integer( &args->args[i], (grpc_integer_options){GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_ALGORITHMS_COUNT - 1}); } else if (0 == strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET)) { channel->compression_options.enabled_algorithms_bitset = (uint32_t)args->args[i].value.integer | 0x1; /* always support no compression */ } } done: grpc_channel_args_destroy(exec_ctx, args); return channel; }
static void fail_helper_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s, grpc_error *error) { INPROC_LOG(GPR_DEBUG, "read_state_machine %p fail_helper", s); // If we're failing this side, we need to make sure that // we also send or have already sent trailing metadata if (!s->trailing_md_sent) { // Send trailing md to the other side indicating cancellation s->trailing_md_sent = true; grpc_metadata_batch fake_md; grpc_metadata_batch_init(&fake_md); inproc_stream *other = s->other_side; grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_trailing_md : &other->to_read_trailing_md; bool *destfilled = (other == NULL) ? &s->write_buffer_trailing_md_filled : &other->to_read_trailing_md_filled; fill_in_metadata(exec_ctx, s, &fake_md, 0, dest, NULL, destfilled); grpc_metadata_batch_destroy(exec_ctx, &fake_md); if (other != NULL) { if (other->cancel_other_error == GRPC_ERROR_NONE) { other->cancel_other_error = GRPC_ERROR_REF(error); } if (other->reads_needed) { if (!other->read_closure_scheduled) { GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure, GRPC_ERROR_REF(error)); other->read_closure_scheduled = true; } other->reads_needed = false; } } else if (s->write_buffer_cancel_error == GRPC_ERROR_NONE) { s->write_buffer_cancel_error = GRPC_ERROR_REF(error); } } if (s->recv_initial_md_op) { grpc_error *err; if (!s->t->is_client) { // If this is a server, provide initial metadata with a path and authority // since it expects that as well as no error yet grpc_metadata_batch fake_md; grpc_metadata_batch_init(&fake_md); grpc_linked_mdelem *path_md = gpr_arena_alloc(s->arena, sizeof(*path_md)); path_md->md = grpc_mdelem_from_slices(exec_ctx, g_fake_path_key, g_fake_path_value); GPR_ASSERT(grpc_metadata_batch_link_tail(exec_ctx, &fake_md, path_md) == GRPC_ERROR_NONE); grpc_linked_mdelem *auth_md = gpr_arena_alloc(s->arena, sizeof(*auth_md)); auth_md->md = grpc_mdelem_from_slices(exec_ctx, g_fake_auth_key, g_fake_auth_value); GPR_ASSERT(grpc_metadata_batch_link_tail(exec_ctx, &fake_md, auth_md) == GRPC_ERROR_NONE); fill_in_metadata( exec_ctx, s, &fake_md, 0, s->recv_initial_md_op->payload->recv_initial_metadata .recv_initial_metadata, s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags, NULL); grpc_metadata_batch_destroy(exec_ctx, &fake_md); err = GRPC_ERROR_NONE; } else { err = GRPC_ERROR_REF(error); } INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling initial-metadata-ready %p %p", s, error, err); GRPC_CLOSURE_SCHED(exec_ctx, s->recv_initial_md_op->payload->recv_initial_metadata .recv_initial_metadata_ready, err); // Last use of err so no need to REF and then UNREF it if ((s->recv_initial_md_op != s->recv_message_op) && (s->recv_initial_md_op != s->recv_trailing_md_op)) { INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling initial-metadata-on-complete %p", error, s); GRPC_CLOSURE_SCHED(exec_ctx, s->recv_initial_md_op->on_complete, GRPC_ERROR_REF(error)); } s->recv_initial_md_op = NULL; } if (s->recv_message_op) { INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-ready %p", s, error); GRPC_CLOSURE_SCHED( exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready, GRPC_ERROR_REF(error)); if (s->recv_message_op != s->recv_trailing_md_op) { INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-on-complete %p", s, error); GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete, GRPC_ERROR_REF(error)); } s->recv_message_op = NULL; } if (s->recv_trailing_md_op) { INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling trailing-md-on-complete %p", s, error); GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete, GRPC_ERROR_REF(error)); s->recv_trailing_md_op = NULL; } close_other_side_locked(exec_ctx, s, "fail_helper:other_side"); close_stream_locked(exec_ctx, s); GRPC_ERROR_UNREF(error); }