grpc_call *grpc_channel_create_registered_call( grpc_channel *channel, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline) { registered_call *rc = registered_call_handle; return grpc_channel_create_call_internal( channel, completion_queue, grpc_mdelem_ref(rc->path), grpc_mdelem_ref(rc->authority), deadline); }
static void jwt_get_request_metadata(grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds; gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, 0}; /* See if we can return a cached jwt. */ grpc_mdelem *jwt_md = NULL; { gpr_mu_lock(&c->cache_mu); if (c->cached.service_url != NULL && strcmp(c->cached.service_url, service_url) == 0 && c->cached.jwt_md != NULL && (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()), refresh_threshold) > 0)) { jwt_md = grpc_mdelem_ref(c->cached.jwt_md); } gpr_mu_unlock(&c->cache_mu); } if (jwt_md == NULL) { char *jwt = NULL; /* Generate a new jwt. */ gpr_mu_lock(&c->cache_mu); jwt_reset_cache(c); jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL); if (jwt != NULL) { char *md_value; gpr_asprintf(&md_value, "Bearer %s", jwt); gpr_free(jwt); c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime); c->cached.service_url = gpr_strdup(service_url); c->cached.jwt_md = grpc_mdelem_from_strings( c->md_ctx, GRPC_AUTHORIZATION_METADATA_KEY, md_value); gpr_free(md_value); jwt_md = grpc_mdelem_ref(c->cached.jwt_md); } gpr_mu_unlock(&c->cache_mu); } if (jwt_md != NULL) { cb(user_data, &jwt_md, 1, GRPC_CREDENTIALS_OK); grpc_mdelem_unref(jwt_md); } else { cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); } }
static void hs_mutate_op(grpc_call_element *elem, grpc_transport_op *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; size_t i; if (op->send_ops && !calld->sent_status) { size_t nops = op->send_ops->nops; grpc_stream_op *ops = op->send_ops->ops; for (i = 0; i < nops; i++) { grpc_stream_op *op = &ops[i]; if (op->type != GRPC_OP_METADATA) continue; calld->sent_status = 1; grpc_metadata_batch_add_head(&op->data.metadata, &calld->status, grpc_mdelem_ref(channeld->status_ok)); break; } } if (op->recv_ops && !calld->got_initial_metadata) { /* substitute our callback for the higher callback */ calld->recv_ops = op->recv_ops; calld->on_done_recv = op->on_done_recv; calld->recv_user_data = op->recv_user_data; op->on_done_recv = hs_on_recv; op->recv_user_data = elem; } }
static void oauth2_token_fetcher_get_request_metadata( grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, 0}; grpc_mdelem *cached_access_token_md = NULL; { gpr_mu_lock(&c->mu); if (c->access_token_md != NULL && (gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()), refresh_threshold) > 0)) { cached_access_token_md = grpc_mdelem_ref(c->access_token_md); } gpr_mu_unlock(&c->mu); } if (cached_access_token_md != NULL) { cb(user_data, &cached_access_token_md, 1, GRPC_CREDENTIALS_OK); grpc_mdelem_unref(cached_access_token_md); } else { c->fetch_func( grpc_credentials_metadata_request_create(creds, cb, user_data), on_oauth2_token_fetcher_http_response, gpr_time_add(gpr_now(), refresh_threshold)); } }
/* Called either: - in response to an API call (or similar) from above, to send something - a network event (or similar) from below, to receive something op contains type and call direction information, in addition to the data that is being sent or received. */ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_op *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { case GRPC_RECV_METADATA: grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem); if (!calld->got_initial_metadata) { calld->got_initial_metadata = 1; /* Have we seen the required http2 transport headers? (:method, :scheme, content-type, with :path and :authority covered at the channel level right now) */ if (calld->seen_post && calld->seen_scheme && calld->seen_te_trailers && calld->seen_path) { grpc_call_next_op(elem, op); } else { if (!calld->seen_path) { gpr_log(GPR_ERROR, "Missing :path header"); } if (!calld->seen_post) { gpr_log(GPR_ERROR, "Missing :method header"); } if (!calld->seen_scheme) { gpr_log(GPR_ERROR, "Missing :scheme header"); } if (!calld->seen_te_trailers) { gpr_log(GPR_ERROR, "Missing te trailers header"); } /* Error this call out */ grpc_metadata_batch_destroy(&op->data.metadata); op->done_cb(op->user_data, GRPC_OP_OK); grpc_call_element_send_cancel(elem); } } else { grpc_call_next_op(elem, op); } break; case GRPC_SEND_METADATA: /* If we haven't sent status 200 yet, we need to so so because it needs to come before any non : prefixed metadata. */ if (!calld->sent_status) { calld->sent_status = 1; grpc_metadata_batch_add_head(&op->data.metadata, &calld->status, grpc_mdelem_ref(channeld->status_ok)); } grpc_call_next_op(elem, op); break; default: /* pass control up or down the stack depending on op->dir */ grpc_call_next_op(elem, op); break; } }
static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_op *op) { channel_data *channeld = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { case GRPC_SEND_START: grpc_call_recv_metadata(elem, grpc_mdelem_ref(channeld->status)); grpc_call_recv_metadata(elem, grpc_mdelem_ref(channeld->message)); grpc_call_stream_closed(elem); break; case GRPC_SEND_METADATA: grpc_mdelem_unref(op->data.metadata); break; default: break; } op->done_cb(op->user_data, GRPC_OP_ERROR); }
grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) { if (i >= 0 && i < NUM_CACHED_STATUS_ELEMS) { return grpc_mdelem_ref(channel->grpc_status_elem[i]); } else { char tmp[GPR_LTOA_MIN_BUFSIZE]; gpr_ltoa(i, tmp); return grpc_mdelem_from_metadata_strings( channel->metadata_context, grpc_mdstr_ref(channel->grpc_status_string), grpc_mdstr_from_string(channel->metadata_context, tmp)); } }
static void send_up_cancelled_ops(grpc_call_element *elem) { grpc_call_op finish_op; channel_data *chand = elem->channel_data; /* send up a synthesized status */ finish_op.type = GRPC_RECV_METADATA; finish_op.dir = GRPC_CALL_UP; finish_op.flags = 0; finish_op.data.metadata = grpc_mdelem_ref(chand->cancel_status); finish_op.done_cb = do_nothing; finish_op.user_data = NULL; grpc_call_next_op(elem, &finish_op); /* send up a finish */ finish_op.type = GRPC_RECV_FINISH; finish_op.dir = GRPC_CALL_UP; finish_op.flags = 0; finish_op.done_cb = do_nothing; finish_op.user_data = NULL; grpc_call_next_op(elem, &finish_op); }
static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems, size_t num_md, grpc_credentials_status status) { grpc_composite_credentials_metadata_context *ctx = (grpc_composite_credentials_metadata_context *)user_data; size_t i; if (status != GRPC_CREDENTIALS_OK) { ctx->cb(ctx->user_data, NULL, 0, status); return; } /* Copy the metadata in the context. */ if (num_md > 0) { ctx->md_elems = gpr_realloc(ctx->md_elems, (ctx->num_md + num_md) * sizeof(grpc_mdelem *)); for (i = 0; i < num_md; i++) { ctx->md_elems[i + ctx->num_md] = grpc_mdelem_ref(md_elems[i]); } ctx->num_md += num_md; } /* See if we need to get some more metadata. */ while (ctx->creds_index < ctx->composite_creds->inner.num_creds) { grpc_credentials *inner_creds = ctx->composite_creds->inner.creds_array[ctx->creds_index++]; if (grpc_credentials_has_request_metadata(inner_creds)) { grpc_credentials_get_request_metadata(inner_creds, ctx->service_url, composite_metadata_cb, ctx); return; } } /* We're done!. */ ctx->cb(ctx->user_data, ctx->md_elems, ctx->num_md, GRPC_CREDENTIALS_OK); composite_md_context_destroy(ctx); }