static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (err == GRPC_ERROR_NONE) { server_filter_args a; a.elem = elem; a.exec_ctx = exec_ctx; grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, &a); /* 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_method && calld->seen_scheme && calld->seen_te_trailers && calld->seen_path && calld->seen_authority) { /* do nothing */ } else { err = GRPC_ERROR_CREATE("Bad incoming HTTP headers"); if (!calld->seen_path) { err = grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header")); } if (!calld->seen_authority) { err = grpc_error_add_child( err, GRPC_ERROR_CREATE("Missing :authority header")); } if (!calld->seen_method) { err = grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :method header")); } if (!calld->seen_scheme) { err = grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :scheme header")); } if (!calld->seen_te_trailers) { err = grpc_error_add_child( err, GRPC_ERROR_CREATE("Missing te: trailers header")); } /* Error this call out */ if (grpc_http_trace) { const char *error_str = grpc_error_string(err); gpr_log(GPR_ERROR, "Invalid http2 headers: %s", error_str); grpc_error_free_string(error_str); } grpc_call_element_send_cancel(exec_ctx, elem); } } else { GRPC_ERROR_REF(err); } calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, err); GRPC_ERROR_UNREF(err); }
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { call_data *calld = arg; gpr_mu_lock(&calld->mu); GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL); calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; if (calld->connected_subchannel == NULL) { gpr_atm_no_barrier_store(&calld->subchannel_call, 1); fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING( "Failed to create subchannel", &error, 1)); } else if (1 == gpr_atm_acq_load(&calld->subchannel_call)) { /* already cancelled before subchannel became ready */ fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING( "Cancelled before creating subchannel", &error, 1)); } else { grpc_subchannel_call *subchannel_call = NULL; grpc_error *new_error = grpc_connected_subchannel_create_call( exec_ctx, calld->connected_subchannel, calld->pollent, &subchannel_call); if (new_error != GRPC_ERROR_NONE) { new_error = grpc_error_add_child(new_error, error); subchannel_call = CANCELLED_CALL; fail_locked(exec_ctx, calld, new_error); } gpr_atm_rel_store(&calld->subchannel_call, (gpr_atm)(uintptr_t)subchannel_call); retry_waiting_locked(exec_ctx, calld); } gpr_mu_unlock(&calld->mu); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); }
static void add_error(grpc_error **combined, grpc_error *error) { if (error == GRPC_ERROR_NONE) return; if (*combined == GRPC_ERROR_NONE) { *combined = GRPC_ERROR_CREATE("Client auth metadata plugin error"); } *combined = grpc_error_add_child(*combined, error); }
// Callback invoked when we receive a message. Here we check the max // receive message size. static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, grpc_error* error) { grpc_call_element* elem = (grpc_call_element*)user_data; call_data* calld = (call_data*)elem->call_data; if (*calld->recv_message != NULL && calld->limits.max_recv_size >= 0 && (*calld->recv_message)->length > (size_t)calld->limits.max_recv_size) { char* message_string; gpr_asprintf(&message_string, "Received message larger than max (%u vs. %d)", (*calld->recv_message)->length, calld->limits.max_recv_size); grpc_error* new_error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED); if (error == GRPC_ERROR_NONE) { error = new_error; } else { error = grpc_error_add_child(error, new_error); GRPC_ERROR_UNREF(new_error); } gpr_free(message_string); } else { GRPC_ERROR_REF(error); } // Invoke the next callback. GRPC_CLOSURE_RUN(exec_ctx, calld->next_recv_message_ready, error); }
static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = (grpc_call_element *)user_data; call_data *calld = (call_data *)elem->call_data; if (err == GRPC_ERROR_NONE) { if (calld->recv_initial_metadata->idx.named.path != NULL) { calld->service_method = grpc_slice_ref_internal( GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md)); calld->have_service_method = true; } else { err = grpc_error_add_child( err, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing :path header")); } if (calld->recv_initial_metadata->idx.named.lb_token != NULL) { calld->initial_md_string = grpc_slice_ref_internal( GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md)); calld->have_initial_md_string = true; grpc_metadata_batch_remove( exec_ctx, calld->recv_initial_metadata, calld->recv_initial_metadata->idx.named.lb_token); } } else { GRPC_ERROR_REF(err); } calld->ops_recv_initial_metadata_ready->cb( exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err); GRPC_ERROR_UNREF(err); }
static bool append_error(grpc_error **composite, grpc_error *error, const char *desc) { if (error == GRPC_ERROR_NONE) return true; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); } *composite = grpc_error_add_child(*composite, error); return false; }
static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data, grpc_error *err) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (err == GRPC_ERROR_NONE) { recv_md_filter_args a; a.elem = elem; a.exec_ctx = exec_ctx; grpc_metadata_batch_filter(calld->recv_initial_metadata, recv_md_filter, &a); if (calld->service_method == NULL) { err = grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header")); } } else { GRPC_ERROR_REF(err); } calld->ops_recv_initial_metadata_ready->cb( exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err); GRPC_ERROR_UNREF(err); }
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element *elem = arg; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; gpr_mu_lock(&calld->mu); GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL); grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent, chand->interested_parties); calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; if (calld->connected_subchannel == NULL) { gpr_atm_no_barrier_store(&calld->subchannel_call, 1); fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING( "Failed to create subchannel", &error, 1)); } else if (GET_CALL(calld) == CANCELLED_CALL) { /* already cancelled before subchannel became ready */ fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING( "Cancelled before creating subchannel", &error, 1)); } else { /* Create call on subchannel. */ grpc_subchannel_call *subchannel_call = NULL; grpc_error *new_error = grpc_connected_subchannel_create_call( exec_ctx, calld->connected_subchannel, calld->pollent, calld->path, calld->deadline, &subchannel_call); if (new_error != GRPC_ERROR_NONE) { new_error = grpc_error_add_child(new_error, error); subchannel_call = CANCELLED_CALL; fail_locked(exec_ctx, calld, new_error); } gpr_atm_rel_store(&calld->subchannel_call, (gpr_atm)(uintptr_t)subchannel_call); retry_waiting_locked(exec_ctx, calld); } gpr_mu_unlock(&calld->mu); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); }
// Callback invoked when we receive a message. Here we check the max // receive message size. static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, grpc_error* error) { grpc_call_element* elem = user_data; call_data* calld = elem->call_data; if (*calld->recv_message != NULL && calld->max_recv_size >= 0 && (*calld->recv_message)->length > (size_t)calld->max_recv_size) { char* message_string; gpr_asprintf(&message_string, "Received message larger than max (%u vs. %d)", (*calld->recv_message)->length, calld->max_recv_size); grpc_error* new_error = grpc_error_set_int( GRPC_ERROR_CREATE(message_string), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INVALID_ARGUMENT); if (error == GRPC_ERROR_NONE) { error = new_error; } else { error = grpc_error_add_child(error, new_error); GRPC_ERROR_UNREF(new_error); } gpr_free(message_string); } // Invoke the next callback. grpc_exec_ctx_sched(exec_ctx, calld->next_recv_message_ready, error, NULL); }
grpc_channel_credentials *grpc_google_default_credentials_create(void) { grpc_channel_credentials *result = NULL; grpc_call_credentials *call_creds = NULL; grpc_error *error = GRPC_ERROR_CREATE("Failed to create Google credentials"); grpc_error *err; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); gpr_once_init(&g_once, init_default_credentials); gpr_mu_lock(&g_state_mu); if (default_credentials != NULL) { result = grpc_channel_credentials_ref(default_credentials); goto end; } /* First, try the environment variable. */ err = create_default_creds_from_path( &exec_ctx, gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds); if (err == GRPC_ERROR_NONE) goto end; error = grpc_error_add_child(error, err); /* Then the well-known file. */ err = create_default_creds_from_path( &exec_ctx, grpc_get_well_known_google_credentials_file_path(), &call_creds); if (err == GRPC_ERROR_NONE) goto end; error = grpc_error_add_child(error, err); /* At last try to see if we're on compute engine (do the detection only once since it requires a network test). */ if (!compute_engine_detection_done) { int need_compute_engine_creds = is_stack_running_on_compute_engine(&exec_ctx); compute_engine_detection_done = 1; if (need_compute_engine_creds) { call_creds = grpc_google_compute_engine_credentials_create(NULL); if (call_creds == NULL) { error = grpc_error_add_child( error, GRPC_ERROR_CREATE("Failed to get credentials from network")); } } } end: if (result == NULL) { if (call_creds != NULL) { /* Blend with default ssl credentials and add a global reference so that it can be cached and re-served. */ grpc_channel_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); default_credentials = grpc_channel_credentials_ref( grpc_composite_channel_credentials_create(ssl_creds, call_creds, NULL)); GPR_ASSERT(default_credentials != NULL); grpc_channel_credentials_unref(&exec_ctx, ssl_creds); grpc_call_credentials_unref(&exec_ctx, call_creds); result = default_credentials; } else { gpr_log(GPR_ERROR, "Could not create google default credentials."); } } gpr_mu_unlock(&g_state_mu); if (result == NULL) { GRPC_LOG_IF_ERROR("grpc_google_default_credentials_create", error); } else { GRPC_ERROR_UNREF(error); } grpc_exec_ctx_finish(&exec_ctx); return result; }
grpc_error *grpc_tcp_server_add_all_local_addrs(grpc_tcp_server *s, unsigned port_index, int requested_port, int *out_port) { struct ifaddrs *ifa = NULL; struct ifaddrs *ifa_it; unsigned fd_index = 0; grpc_tcp_listener *sp = NULL; grpc_error *err = GRPC_ERROR_NONE; if (requested_port == 0) { /* Note: There could be a race where some local addrs can listen on the selected port and some can't. The sane way to handle this would be to retry by recreating the whole grpc_tcp_server. Backing out individual listeners and orphaning the FDs looks like too much trouble. */ if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) { return err; } else if (requested_port <= 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad get_unused_port()"); } gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port); } if (getifaddrs(&ifa) != 0 || ifa == NULL) { return GRPC_OS_ERROR(errno, "getifaddrs"); } for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) { grpc_resolved_address addr; char *addr_str = NULL; grpc_dualstack_mode dsmode; grpc_tcp_listener *new_sp = NULL; const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>"); if (ifa_it->ifa_addr == NULL) { continue; } else if (ifa_it->ifa_addr->sa_family == AF_INET) { addr.len = sizeof(struct sockaddr_in); } else if (ifa_it->ifa_addr->sa_family == AF_INET6) { addr.len = sizeof(struct sockaddr_in6); } else { continue; } memcpy(addr.addr, ifa_it->ifa_addr, addr.len); if (!grpc_sockaddr_set_port(&addr, requested_port)) { /* Should never happen, because we check sa_family above. */ err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set port"); break; } if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) { addr_str = gpr_strdup("<error>"); } gpr_log(GPR_DEBUG, "Adding local addr from interface %s flags 0x%x to server: %s", ifa_name, ifa_it->ifa_flags, addr_str); /* We could have multiple interfaces with the same address (e.g., bonding), so look for duplicates. */ if (find_listener_with_addr(s, &addr) != NULL) { gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str, ifa_name); gpr_free(addr_str); continue; } if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode, &new_sp)) != GRPC_ERROR_NONE) { char *err_str = NULL; grpc_error *root_err; if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) { err_str = gpr_strdup("Failed to add listener"); } root_err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_str); gpr_free(err_str); gpr_free(addr_str); err = grpc_error_add_child(root_err, err); break; } else { GPR_ASSERT(requested_port == new_sp->port); ++fd_index; if (sp != NULL) { new_sp->is_sibling = 1; sp->sibling = new_sp; } sp = new_sp; } gpr_free(addr_str); } freeifaddrs(ifa); if (err != GRPC_ERROR_NONE) { return err; } else if (sp == NULL) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No local addresses"); } else { *out_port = sp->port; return GRPC_ERROR_NONE; } }