/* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *calld = (call_data *)elem->call_data; /* TODO(dgq): do something with the data channel_data *chand = elem->channel_data; grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION, (intptr_t)chand->id, (intptr_t)calld->id, final_info, calld->initial_md_string, calld->trailing_md_string, calld->service_method}; */ if (calld->have_initial_md_string) { grpc_slice_unref_internal(exec_ctx, calld->initial_md_string); } if (calld->have_trailing_md_string) { grpc_slice_unref_internal(exec_ctx, calld->trailing_md_string); } if (calld->have_service_method) { grpc_slice_unref_internal(exec_ctx, calld->service_method); } }
void grpc_call_details_destroy(grpc_call_details* cd) { GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_unref_internal(&exec_ctx, cd->method); grpc_slice_unref_internal(&exec_ctx, cd->host); grpc_exec_ctx_finish(&exec_ctx); }
/* Asynchronous callback from the IOCP, or the background thread. */ static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) { grpc_tcp *tcp = tcpp; grpc_closure *cb = tcp->read_cb; grpc_winsocket *socket = tcp->socket; grpc_slice sub; grpc_winsocket_callback_info *info = &socket->read_info; GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE) { if (info->wsa_error != 0 && !tcp->shutting_down) { char *utf8_message = gpr_format_message(info->wsa_error); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(utf8_message); gpr_free(utf8_message); grpc_slice_unref_internal(exec_ctx, tcp->read_slice); } else { if (info->bytes_transfered != 0 && !tcp->shutting_down) { sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); grpc_slice_buffer_add(tcp->read_slices, sub); } else { grpc_slice_unref_internal(exec_ctx, tcp->read_slice); error = tcp->shutting_down ? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "TCP stream shutting down", &tcp->shutdown_error, 1) : GRPC_ERROR_CREATE_FROM_STATIC_STRING("End of TCP stream"); } } } tcp->read_cb = NULL; TCP_UNREF(exec_ctx, tcp, "read"); GRPC_CLOSURE_SCHED(exec_ctx, cb, error); }
static void plugin_md_request_metadata_ready(void *request, const grpc_metadata *md, size_t num_md, grpc_status_code status, const char *error_details) { /* called from application code */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER( GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP, NULL, NULL); grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; if (status != GRPC_STATUS_OK) { if (error_details != NULL) { gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", error_details); } r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, error_details); } else { size_t i; bool seen_illegal_header = false; grpc_credentials_md *md_array = NULL; for (i = 0; i < num_md; i++) { if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin", grpc_validate_header_key_is_legal(md[i].key))) { seen_illegal_header = true; break; } else if (!grpc_is_binary_header(md[i].key) && !GRPC_LOG_IF_ERROR( "validate_metadata_from_plugin", grpc_validate_header_nonbin_value_is_legal(md[i].value))) { gpr_log(GPR_ERROR, "Plugin added invalid metadata value."); seen_illegal_header = true; break; } } if (seen_illegal_header) { r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, "Illegal metadata"); } else if (num_md > 0) { md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); for (i = 0; i < num_md; i++) { md_array[i].key = grpc_slice_ref_internal(md[i].key); md_array[i].value = grpc_slice_ref_internal(md[i].value); } r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL); for (i = 0; i < num_md; i++) { grpc_slice_unref_internal(&exec_ctx, md_array[i].key); grpc_slice_unref_internal(&exec_ctx, md_array[i].value); } gpr_free(md_array); } else if (num_md == 0) { r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL); } } gpr_free(r); grpc_exec_ctx_finish(&exec_ctx); }
void grpc_inproc_transport_shutdown(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_unref_internal(&exec_ctx, g_empty_slice); grpc_slice_unref_internal(&exec_ctx, g_fake_path_key); grpc_slice_unref_internal(&exec_ctx, g_fake_path_value); grpc_slice_unref_internal(&exec_ctx, g_fake_auth_key); grpc_slice_unref_internal(&exec_ctx, g_fake_auth_value); grpc_exec_ctx_finish(&exec_ctx); }
/** Returns a copy of percent decoded \a src[begin, end) */ static char *decode_and_copy_component(grpc_exec_ctx *exec_ctx, const char *src, size_t begin, size_t end) { grpc_slice component = grpc_slice_from_copied_buffer(src + begin, end - begin); grpc_slice decoded_component = grpc_permissive_percent_decode_slice(component); char *out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII); grpc_slice_unref_internal(exec_ctx, component); grpc_slice_unref_internal(exec_ctx, decoded_component); return out; }
static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) { secure_endpoint *ep = secure_ep; grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep); tsi_frame_protector_destroy(ep->protector); grpc_slice_buffer_destroy_internal(exec_ctx, &ep->leftover_bytes); grpc_slice_unref_internal(exec_ctx, ep->read_staging_buffer); grpc_slice_unref_internal(exec_ctx, ep->write_staging_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &ep->output_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &ep->source_buffer); gpr_mu_destroy(&ep->protector_mu); gpr_free(ep); }
/* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, void *ignored) { call_data *calld = elem->call_data; grpc_call_credentials_unref(exec_ctx, calld->creds); if (calld->have_host) { grpc_slice_unref_internal(exec_ctx, calld->host); } if (calld->have_method) { grpc_slice_unref_internal(exec_ctx, calld->method); } reset_auth_metadata_context(&calld->auth_md_context); }
static int zlib_compress(grpc_exec_ctx* exec_ctx, grpc_slice_buffer* input, grpc_slice_buffer* output, int gzip) { z_stream zs; int r; size_t i; size_t count_before = output->count; size_t length_before = output->length; memset(&zs, 0, sizeof(zs)); zs.zalloc = zalloc_gpr; zs.zfree = zfree_gpr; r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0), 8, Z_DEFAULT_STRATEGY); GPR_ASSERT(r == Z_OK); r = zlib_body(exec_ctx, &zs, input, output, deflate) && output->length < input->length; if (!r) { for (i = count_before; i < output->count; i++) { grpc_slice_unref_internal(exec_ctx, output->slices[i]); } output->count = count_before; output->length = length_before; } deflateEnd(&zs); return r; }
static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { grpc_endpoint_test_fixture f = config.create_fixture(slice_size); grpc_slice_buffer incoming; grpc_slice s = grpc_slice_from_copied_string("hello world 12345678900987654321"); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; int n = 0; grpc_closure done_closure; gpr_log(GPR_INFO, "Start test left over"); grpc_slice_buffer_init(&incoming); grpc_closure_init(&done_closure, inc_call_ctr, &n, grpc_schedule_on_exec_ctx); grpc_endpoint_read(&exec_ctx, f.client_ep, &incoming, &done_closure); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(n == 1); GPR_ASSERT(incoming.count == 1); GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0])); grpc_endpoint_shutdown(&exec_ctx, f.client_ep, GRPC_ERROR_CREATE("test_leftover end")); grpc_endpoint_shutdown(&exec_ctx, f.server_ep, GRPC_ERROR_CREATE("test_leftover end")); grpc_endpoint_destroy(&exec_ctx, f.client_ep); grpc_endpoint_destroy(&exec_ctx, f.server_ep); grpc_exec_ctx_finish(&exec_ctx); grpc_slice_unref_internal(&exec_ctx, s); grpc_slice_buffer_destroy_internal(&exec_ctx, &incoming); clean_up(); }
static void test_algorithm_mesh(void) { int i; gpr_log(GPR_DEBUG, "test_algorithm_mesh"); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { const char *name; grpc_compression_algorithm parsed; grpc_slice mdstr; grpc_mdelem mdelem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT( grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name)); GPR_ASSERT(grpc_compression_algorithm_parse( grpc_slice_from_static_string(name), &parsed)); GPR_ASSERT((int)parsed == i); mdstr = grpc_slice_from_copied_string(name); GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed))); GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr)); mdelem = grpc_compression_encoding_mdelem(parsed); GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr)); GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING)); grpc_slice_unref_internal(&exec_ctx, mdstr); GRPC_MDELEM_UNREF(&exec_ctx, mdelem); grpc_exec_ctx_finish(&exec_ctx); } /* test failure */ GPR_ASSERT(GRPC_MDISNULL( grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT))); }
/* Takes ownership of creds_path if not NULL. */ static grpc_error *create_default_creds_from_path( grpc_exec_ctx *exec_ctx, char *creds_path, grpc_call_credentials **creds) { grpc_json *json = NULL; grpc_auth_json_key key; grpc_auth_refresh_token token; grpc_call_credentials *result = NULL; grpc_slice creds_data = grpc_empty_slice(); grpc_error *error = GRPC_ERROR_NONE; if (creds_path == NULL) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("creds_path unset"); goto end; } error = grpc_load_file(creds_path, 0, &creds_data); if (error != GRPC_ERROR_NONE) { goto end; } json = grpc_json_parse_string_with_len( (char *)GRPC_SLICE_START_PTR(creds_data), GRPC_SLICE_LENGTH(creds_data)); if (json == NULL) { error = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse JSON"), GRPC_ERROR_STR_RAW_BYTES, grpc_slice_ref_internal(creds_data)); goto end; } /* First, try an auth json key. */ key = grpc_auth_json_key_create_from_json(json); if (grpc_auth_json_key_is_valid(&key)) { result = grpc_service_account_jwt_access_credentials_create_from_auth_json_key( exec_ctx, key, grpc_max_auth_token_lifetime()); if (result == NULL) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "grpc_service_account_jwt_access_credentials_create_from_auth_json_" "key failed"); } goto end; } /* Then try a refresh token if the auth json key was invalid. */ token = grpc_auth_refresh_token_create_from_json(json); if (grpc_auth_refresh_token_is_valid(&token)) { result = grpc_refresh_token_credentials_create_from_auth_refresh_token(token); if (result == NULL) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "grpc_refresh_token_credentials_create_from_auth_refresh_token " "failed"); } goto end; } end: GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1); if (creds_path != NULL) gpr_free(creds_path); grpc_slice_unref_internal(exec_ctx, creds_data); if (json != NULL) grpc_json_destroy(json); *creds = result; return error; }
void grpc_inproc_transport_init(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL, grpc_schedule_on_exec_ctx); g_empty_slice = grpc_slice_from_static_buffer(NULL, 0); grpc_slice key_tmp = grpc_slice_from_static_string(":path"); g_fake_path_key = grpc_slice_intern(key_tmp); grpc_slice_unref_internal(&exec_ctx, key_tmp); g_fake_path_value = grpc_slice_from_static_string("/"); grpc_slice auth_tmp = grpc_slice_from_static_string(":authority"); g_fake_auth_key = grpc_slice_intern(auth_tmp); grpc_slice_unref_internal(&exec_ctx, auth_tmp); g_fake_auth_value = grpc_slice_from_static_string("inproc-fail"); grpc_exec_ctx_finish(&exec_ctx); }
/* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, grpc_closure *ignored) { call_data *calld = elem->call_data; grpc_credentials_mdelem_array_destroy(exec_ctx, &calld->md_array); grpc_call_credentials_unref(exec_ctx, calld->creds); if (calld->have_host) { grpc_slice_unref_internal(exec_ctx, calld->host); } if (calld->have_method) { grpc_slice_unref_internal(exec_ctx, calld->method); } reset_auth_metadata_context(&calld->auth_md_context); gpr_mu_destroy(&calld->security_context_mu); gpr_atm cancel_state = gpr_atm_acq_load(&calld->cancellation_state); grpc_error *cancel_error = GRPC_ERROR_NONE; grpc_closure *cancel_func = NULL; decode_cancel_state(cancel_state, &cancel_func, &cancel_error); GRPC_ERROR_UNREF(cancel_error); }
static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { security_handshaker *h = arg; gpr_mu_lock(&h->mu); if (error != GRPC_ERROR_NONE || h->shutdown) { security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error)); goto done; } // Create frame protector. tsi_frame_protector *protector; tsi_result result = tsi_handshaker_result_create_frame_protector( h->handshaker_result, NULL, &protector); if (result != TSI_OK) { error = grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"), result); security_handshake_failed_locked(exec_ctx, h, error); goto done; } // Get unused bytes. unsigned char *unused_bytes = NULL; size_t unused_bytes_size = 0; result = tsi_handshaker_result_get_unused_bytes( h->handshaker_result, &unused_bytes, &unused_bytes_size); // Create secure endpoint. if (unused_bytes_size > 0) { grpc_slice slice = grpc_slice_from_copied_buffer((char *)unused_bytes, unused_bytes_size); h->args->endpoint = grpc_secure_endpoint_create(protector, h->args->endpoint, &slice, 1); grpc_slice_unref_internal(exec_ctx, slice); } else { h->args->endpoint = grpc_secure_endpoint_create(protector, h->args->endpoint, NULL, 0); } tsi_handshaker_result_destroy(h->handshaker_result); h->handshaker_result = NULL; // Clear out the read buffer before it gets passed to the transport. grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer); // Add auth context to channel args. grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); grpc_channel_args *tmp_args = h->args->args; h->args->args = grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); grpc_channel_args_destroy(exec_ctx, tmp_args); // Invoke callback. GRPC_CLOSURE_SCHED(exec_ctx, h->on_handshake_done, GRPC_ERROR_NONE); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. h->shutdown = true; done: gpr_mu_unlock(&h->mu); security_handshaker_unref(exec_ctx, h); }
void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c) { int i; for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { if (c->entries_keys[i].refcount != &terminal_slice_refcount) { grpc_slice_unref_internal(exec_ctx, c->entries_keys[i]); } GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]); } gpr_free(c->table_elem_size); }
void grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx, grpc_slice_hash_table* table) { if (table != NULL && gpr_unref(&table->refs)) { for (size_t i = 0; i < table->size; ++i) { grpc_slice_hash_table_entry* entry = &table->entries[i]; if (!is_empty(entry)) { grpc_slice_unref_internal(exec_ctx, entry->key); table->destroy_value(exec_ctx, entry->value); } } gpr_free(table->entries); gpr_free(table); } }
static int zlib_body(grpc_exec_ctx* exec_ctx, z_stream* zs, grpc_slice_buffer* input, grpc_slice_buffer* output, int (*flate)(z_stream* zs, int flush)) { int r; int flush; size_t i; grpc_slice outbuf = GRPC_SLICE_MALLOC(OUTPUT_BLOCK_SIZE); const uInt uint_max = ~(uInt)0; GPR_ASSERT(GRPC_SLICE_LENGTH(outbuf) <= uint_max); zs->avail_out = (uInt)GRPC_SLICE_LENGTH(outbuf); zs->next_out = GRPC_SLICE_START_PTR(outbuf); flush = Z_NO_FLUSH; for (i = 0; i < input->count; i++) { if (i == input->count - 1) flush = Z_FINISH; GPR_ASSERT(GRPC_SLICE_LENGTH(input->slices[i]) <= uint_max); zs->avail_in = (uInt)GRPC_SLICE_LENGTH(input->slices[i]); zs->next_in = GRPC_SLICE_START_PTR(input->slices[i]); do { if (zs->avail_out == 0) { grpc_slice_buffer_add_indexed(output, outbuf); outbuf = GRPC_SLICE_MALLOC(OUTPUT_BLOCK_SIZE); GPR_ASSERT(GRPC_SLICE_LENGTH(outbuf) <= uint_max); zs->avail_out = (uInt)GRPC_SLICE_LENGTH(outbuf); zs->next_out = GRPC_SLICE_START_PTR(outbuf); } r = flate(zs, flush); if (r < 0 && r != Z_BUF_ERROR /* not fatal */) { gpr_log(GPR_INFO, "zlib error (%d)", r); goto error; } } while (zs->avail_out == 0); if (zs->avail_in) { gpr_log(GPR_INFO, "zlib: not all input consumed"); goto error; } } GPR_ASSERT(outbuf.refcount); outbuf.data.refcounted.length -= zs->avail_out; grpc_slice_buffer_add_indexed(output, outbuf); return 1; error: grpc_slice_unref_internal(exec_ctx, outbuf); return 0; }
static grpc_error *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *b) { if (b->idx.named.grpc_message != NULL) { grpc_slice pct_encoded_msg = grpc_percent_encode_slice( GRPC_MDVALUE(b->idx.named.grpc_message->md), grpc_compatible_percent_encoding_unreserved_bytes); if (grpc_slice_is_equivalent(pct_encoded_msg, GRPC_MDVALUE(b->idx.named.grpc_message->md))) { grpc_slice_unref_internal(exec_ctx, pct_encoded_msg); } else { grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message, pct_encoded_msg); } } return GRPC_ERROR_NONE; }
grpc_slice_hash_table* grpc_service_config_create_method_config_table( grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config, void* (*create_value)(const grpc_json* method_config_json), const grpc_slice_hash_table_vtable* vtable) { const grpc_json* json = service_config->json_tree; // Traverse parsed JSON tree. if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL; size_t num_entries = 0; grpc_slice_hash_table_entry* entries = NULL; for (grpc_json* field = json->child; field != NULL; field = field->next) { if (field->key == NULL) return NULL; if (strcmp(field->key, "methodConfig") == 0) { if (entries != NULL) return NULL; // Duplicate. if (field->type != GRPC_JSON_ARRAY) return NULL; // Find number of entries. for (grpc_json* method = field->child; method != NULL; method = method->next) { num_entries += count_names_in_method_config_json(method); } // Populate method config table entries. entries = gpr_malloc(num_entries * sizeof(grpc_slice_hash_table_entry)); size_t idx = 0; for (grpc_json* method = field->child; method != NULL; method = method->next) { if (!parse_json_method_config(exec_ctx, method, create_value, vtable, entries, &idx)) { return NULL; } } GPR_ASSERT(idx == num_entries); } } // Instantiate method config table. grpc_slice_hash_table* method_config_table = NULL; if (entries != NULL) { method_config_table = grpc_slice_hash_table_create(num_entries, entries); // Clean up. for (size_t i = 0; i < num_entries; ++i) { grpc_slice_unref_internal(exec_ctx, entries[i].key); vtable->destroy_value(exec_ctx, entries[i].value); } gpr_free(entries); } return method_config_table; }
static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx, grpc_resolver_args *args, bool parse(const grpc_uri *uri, grpc_resolved_address *dst)) { 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; } /* Construct addresses. */ grpc_slice path_slice = grpc_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); grpc_slice_buffer path_parts; grpc_slice_buffer_init(&path_parts); grpc_slice_split(path_slice, ",", &path_parts); grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char *part_str = grpc_slice_to_c_string(path_parts.slices[i]); ith_uri.path = part_str; if (!parse(&ith_uri, &addresses->addresses[i].address)) { errors_found = true; /* GPR_TRUE */ } gpr_free(part_str); if (errors_found) break; } grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts); grpc_slice_unref_internal(exec_ctx, path_slice); if (errors_found) { grpc_lb_addresses_destroy(exec_ctx, addresses); return NULL; } /* Instantiate resolver. */ sockaddr_resolver *r = gpr_zalloc(sizeof(sockaddr_resolver)); r->addresses = addresses; r->channel_args = grpc_channel_args_copy(args->args); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable, args->combiner); return &r->base; }
void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, const grpc_slice_hash_table* table, grpc_slice path) { void* value = grpc_slice_hash_table_get(table, path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). if (value == NULL) { char* path_str = grpc_slice_to_c_string(path); const char* sep = strrchr(path_str, '/') + 1; const size_t len = (size_t)(sep - path_str); char* buf = gpr_malloc(len + 2); // '*' and NUL memcpy(buf, path_str, len); buf[len] = '*'; buf[len + 1] = '\0'; grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); gpr_free(buf); value = grpc_slice_hash_table_get(table, wildcard_path); grpc_slice_unref_internal(exec_ctx, wildcard_path); gpr_free(path_str); } return value; }
static void test_algorithm_failure(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice mdstr; gpr_log(GPR_DEBUG, "test_algorithm_failure"); GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT, NULL) == 0); GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT + 1, NULL) == 0); mdstr = grpc_slice_from_static_string("this-is-an-invalid-algorithm"); GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) == GRPC_COMPRESS_ALGORITHMS_COUNT); GPR_ASSERT(grpc_slice_eq( grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT), grpc_empty_slice())); GPR_ASSERT(grpc_slice_eq( grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT + 1), grpc_empty_slice())); grpc_slice_unref_internal(&exec_ctx, mdstr); grpc_exec_ctx_finish(&exec_ctx); }
static void auth_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *batch) { GPR_TIMER_BEGIN("auth_start_transport_stream_op_batch", 0); /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; if (batch->cancel_stream) { while (true) { // Decode the original cancellation state. gpr_atm original_state = gpr_atm_acq_load(&calld->cancellation_state); grpc_error *cancel_error = GRPC_ERROR_NONE; grpc_closure *func = NULL; decode_cancel_state(original_state, &func, &cancel_error); // If we had already set a cancellation error, there's nothing // more to do. if (cancel_error != GRPC_ERROR_NONE) break; // If there's a cancel func, call it. // Note that even if the cancel func has been changed by some // other thread between when we decoded it and now, it will just // be a no-op. cancel_error = GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error); if (func != NULL) { GRPC_CLOSURE_SCHED(exec_ctx, func, GRPC_ERROR_REF(cancel_error)); } // Encode the new error into cancellation state. if (gpr_atm_full_cas(&calld->cancellation_state, original_state, encode_cancel_state_error(cancel_error))) { break; // Success. } // The cas failed, so try again. } } else { /* double checked lock over security context to ensure it's set once */ if (gpr_atm_acq_load(&calld->security_context_set) == 0) { gpr_mu_lock(&calld->security_context_mu); if (gpr_atm_acq_load(&calld->security_context_set) == 0) { GPR_ASSERT(batch->payload->context != NULL); if (batch->payload->context[GRPC_CONTEXT_SECURITY].value == NULL) { batch->payload->context[GRPC_CONTEXT_SECURITY].value = grpc_client_security_context_create(); batch->payload->context[GRPC_CONTEXT_SECURITY].destroy = grpc_client_security_context_destroy; } grpc_client_security_context *sec_ctx = batch->payload->context[GRPC_CONTEXT_SECURITY].value; GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter"); gpr_atm_rel_store(&calld->security_context_set, 1); } gpr_mu_unlock(&calld->security_context_mu); } } if (batch->send_initial_metadata) { for (grpc_linked_mdelem *l = batch->payload->send_initial_metadata .send_initial_metadata->list.head; l != NULL; l = l->next) { grpc_mdelem md = l->md; /* Pointer comparison is OK for md_elems created from the same context. */ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) { if (calld->have_host) { grpc_slice_unref_internal(exec_ctx, calld->host); } calld->host = grpc_slice_ref_internal(GRPC_MDVALUE(md)); calld->have_host = true; } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { if (calld->have_method) { grpc_slice_unref_internal(exec_ctx, calld->method); } calld->method = grpc_slice_ref_internal(GRPC_MDVALUE(md)); calld->have_method = true; } } if (calld->have_host) { grpc_error *cancel_error = set_cancel_func(elem, cancel_check_call_host); if (cancel_error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, cancel_error); } else { char *call_host = grpc_slice_to_c_string(calld->host); batch->handler_private.extra_arg = elem; grpc_error *error = GRPC_ERROR_NONE; if (grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, GRPC_CLOSURE_INIT(&calld->closure, on_host_checked, batch, grpc_schedule_on_exec_ctx), &error)) { // Synchronous return; invoke on_host_checked() directly. on_host_checked(exec_ctx, batch, error); GRPC_ERROR_UNREF(error); } gpr_free(call_host); } GPR_TIMER_END("auth_start_transport_stream_op_batch", 0); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, batch); GPR_TIMER_END("auth_start_transport_stream_op_batch", 0); }
static void test_create_channel_stack(void) { const grpc_channel_filter filter = { call_func, channel_func, sizeof(int), call_init_func, grpc_call_stack_ignore_set_pollset_or_pollset_set, call_destroy_func, sizeof(int), channel_init_func, channel_destroy_func, get_peer, grpc_channel_next_get_info, "some_test_filter"}; const grpc_channel_filter *filters = &filter; grpc_channel_stack *channel_stack; grpc_call_stack *call_stack; grpc_channel_element *channel_elem; grpc_call_element *call_elem; grpc_arg arg; grpc_channel_args chan_args; int *channel_data; int *call_data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice path = grpc_slice_from_static_string("/service/method"); arg.type = GRPC_ARG_INTEGER; arg.key = "test_key"; arg.value.integer = 42; chan_args.num_args = 1; chan_args.args = &arg; channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, 1, &chan_args, NULL, "test", channel_stack); GPR_ASSERT(channel_stack->count == 1); channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_data = (int *)channel_elem->channel_data; GPR_ASSERT(*channel_data == 0); call_stack = gpr_malloc(channel_stack->call_stack_size); const grpc_call_element_args args = { .call_stack = call_stack, .server_transport_data = NULL, .context = NULL, .path = path, .start_time = gpr_now(GPR_CLOCK_MONOTONIC), .deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC), .arena = NULL}; grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, &args); GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(call_stack->count == 1); call_elem = grpc_call_stack_element(call_stack, 0); GPR_ASSERT(call_elem->filter == channel_elem->filter); GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data); call_data = (int *)call_elem->call_data; GPR_ASSERT(*call_data == 0); GPR_ASSERT(*channel_data == 1); GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done"); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(*channel_data == 2); GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done"); grpc_slice_unref_internal(&exec_ctx, path); grpc_exec_ctx_finish(&exec_ctx); }
/* 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 auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { GPR_TIMER_BEGIN("auth_start_transport_op", 0); /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_linked_mdelem *l; grpc_client_security_context *sec_ctx = NULL; if (calld->security_context_set == 0 && op->cancel_error == GRPC_ERROR_NONE) { calld->security_context_set = 1; GPR_ASSERT(op->context); if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) { op->context[GRPC_CONTEXT_SECURITY].value = grpc_client_security_context_create(); op->context[GRPC_CONTEXT_SECURITY].destroy = grpc_client_security_context_destroy; } sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value; GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter"); } if (op->send_initial_metadata != NULL) { for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) { grpc_mdelem md = l->md; /* Pointer comparison is OK for md_elems created from the same context. */ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) { if (calld->have_host) { grpc_slice_unref_internal(exec_ctx, calld->host); } calld->host = grpc_slice_ref_internal(GRPC_MDVALUE(md)); calld->have_host = true; } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { if (calld->have_method) { grpc_slice_unref_internal(exec_ctx, calld->method); } calld->method = grpc_slice_ref_internal(GRPC_MDVALUE(md)); calld->have_method = true; } } if (calld->have_host) { char *call_host = grpc_slice_to_c_string(calld->host); calld->op = *op; /* Copy op (originates from the caller's stack). */ grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, on_host_checked, elem); gpr_free(call_host); GPR_TIMER_END("auth_start_transport_op", 0); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); GPR_TIMER_END("auth_start_transport_op", 0); }
grpc_error *grpc_deframe_unprocessed_incoming_frames( grpc_exec_ctx *exec_ctx, grpc_chttp2_data_parser *p, grpc_chttp2_stream *s, grpc_slice_buffer *slices, grpc_slice *slice_out, grpc_byte_stream **stream_out) { grpc_error *error = GRPC_ERROR_NONE; grpc_chttp2_transport *t = s->t; while (slices->count > 0) { uint8_t *beg = NULL; uint8_t *end = NULL; uint8_t *cur = NULL; grpc_slice slice = grpc_slice_buffer_take_first(slices); beg = GRPC_SLICE_START_PTR(slice); end = GRPC_SLICE_END_PTR(slice); cur = beg; uint32_t message_flags; char *msg; if (cur == end) { grpc_slice_unref_internal(exec_ctx, slice); continue; } switch (p->state) { case GRPC_CHTTP2_DATA_ERROR: p->state = GRPC_CHTTP2_DATA_ERROR; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_REF(p->error); case GRPC_CHTTP2_DATA_FH_0: p->frame_type = *cur; switch (p->frame_type) { case 0: p->is_frame_compressed = false; /* GPR_FALSE */ break; case 1: p->is_frame_compressed = true; /* GPR_TRUE */ break; default: gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type); p->error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID, (intptr_t)s->id); gpr_free(msg); msg = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); p->error = grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_copied_string(msg)); gpr_free(msg); p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg); p->state = GRPC_CHTTP2_DATA_ERROR; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_REF(p->error); } if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_1; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_1: p->frame_size = ((uint32_t)*cur) << 24; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_2; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_2: p->frame_size |= ((uint32_t)*cur) << 16; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_3; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_3: p->frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_4; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_4: GPR_ASSERT(stream_out != NULL); GPR_ASSERT(p->parsing_frame == NULL); p->frame_size |= ((uint32_t)*cur); p->state = GRPC_CHTTP2_DATA_FRAME; ++cur; message_flags = 0; if (p->is_frame_compressed) { message_flags |= GRPC_WRITE_INTERNAL_COMPRESS; } p->parsing_frame = grpc_chttp2_incoming_byte_stream_create( exec_ctx, t, s, p->frame_size, message_flags); *stream_out = &p->parsing_frame->base; if (p->parsing_frame->remaining_bytes == 0) { GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished( exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true)); p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; } s->pending_byte_stream = true; if (cur != end) { grpc_slice_buffer_undo_take_first( &s->unprocessed_incoming_frames_buffer, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); } grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; case GRPC_CHTTP2_DATA_FRAME: { GPR_ASSERT(p->parsing_frame != NULL); GPR_ASSERT(slice_out != NULL); if (cur == end) { grpc_slice_unref_internal(exec_ctx, slice); continue; } uint32_t remaining = (uint32_t)(end - cur); if (remaining == p->frame_size) { if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)), slice_out))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_finished( exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; } else if (remaining < p->frame_size) { if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)), slice_out))) { return error; } p->frame_size -= remaining; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; } else { GPR_ASSERT(remaining > p->frame_size); if (GRPC_ERROR_NONE != (grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(cur + p->frame_size - beg)), slice_out))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_finished( exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; cur += p->frame_size; grpc_slice_buffer_undo_take_first( &s->unprocessed_incoming_frames_buffer, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; } } } } return GRPC_ERROR_NONE; }
/* Public API */ void grpc_slice_unref(grpc_slice slice) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_slice_unref_internal(&exec_ctx, slice); grpc_exec_ctx_finish(&exec_ctx); }
/* add an element to the decoder table */ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, grpc_mdelem elem) { GPR_ASSERT(GRPC_MDELEM_IS_INTERNED(elem)); uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem)); uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem)); uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash); uint32_t new_index = c->tail_remote_index + c->table_elems + 1; size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem); GPR_ASSERT(elem_size < 65536); if (elem_size > c->max_table_size) { while (c->table_size > 0) { evict_entry(c); } return; } /* Reserve space for this element in the remote table: if this overflows the current table, drop elements until it fits, matching the decompressor algorithm */ while (c->table_size + elem_size > c->max_table_size) { evict_entry(c); } GPR_ASSERT(c->table_elems < c->max_table_size); c->table_elem_size[new_index % c->cap_table_elems] = (uint16_t)elem_size; c->table_size = (uint16_t)(c->table_size + elem_size); c->table_elems++; /* Store this element into {entries,indices}_elem */ if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) { /* already there: update with new index */ c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; } else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem)) { /* already there (cuckoo): update with new index */ c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) { /* not there, but a free element: add */ c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) { /* not there (cuckoo), but a free element: add */ c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] < c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) { /* not there: replace oldest */ GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_2(elem_hash)]); c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; } else { /* not there: replace oldest */ GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_3(elem_hash)]); c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; } /* do exactly the same for the key (so we can find by that again too) */ if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)], GRPC_MDKEY(elem))) { c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)], GRPC_MDKEY(elem))) { c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)].refcount == &terminal_slice_refcount) { c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)].refcount == &terminal_slice_refcount) { c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] < c->indices_keys[HASH_FRAGMENT_3(key_hash)]) { grpc_slice_unref_internal(exec_ctx, c->entries_keys[HASH_FRAGMENT_2(key_hash)]); c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else { grpc_slice_unref_internal(exec_ctx, c->entries_keys[HASH_FRAGMENT_3(key_hash)]); c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_slice_ref_internal(GRPC_MDKEY(elem)); c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } }