static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { size_t i; channel_data *chand = elem->channel_data; if (chand->registered_methods) { for (i = 0; i < chand->registered_method_slots; i++) { if (chand->registered_methods[i].method) { GRPC_MDSTR_UNREF(chand->registered_methods[i].method); } if (chand->registered_methods[i].host) { GRPC_MDSTR_UNREF(chand->registered_methods[i].host); } } gpr_free(chand->registered_methods); } if (chand->server) { gpr_mu_lock(&chand->server->mu_global); chand->next->prev = chand->prev; chand->prev->next = chand->next; chand->next = chand->prev = chand; maybe_finish_shutdown(exec_ctx, chand->server); gpr_mu_unlock(&chand->server->mu_global); server_unref(exec_ctx, chand->server); } }
/* Destructor for call_data */ static void destroy_call_elem(grpc_call_element *elem) { call_data *calld = elem->call_data; grpc_credentials_unref(calld->creds); if (calld->host != NULL) { GRPC_MDSTR_UNREF(calld->host); } if (calld->method != NULL) { GRPC_MDSTR_UNREF(calld->method); } }
/* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_stats *stats, void *ignored) { call_data *calld = elem->call_data; grpc_call_credentials_unref(calld->creds); if (calld->host != NULL) { GRPC_MDSTR_UNREF(calld->host); } if (calld->method != NULL) { GRPC_MDSTR_UNREF(calld->method); } reset_auth_metadata_context(&calld->auth_md_context); }
/* Destructor for channel data */ static void destroy_channel_elem(grpc_channel_element *elem) { channel_data *channeld = elem->channel_data; grpc_compression_algorithm algo_idx; GRPC_MDSTR_UNREF(channeld->mdstr_request_compression_algorithm_key); GRPC_MDSTR_UNREF(channeld->mdstr_outgoing_compression_algorithm_key); GRPC_MDSTR_UNREF(channeld->mdstr_compression_capabilities_key); for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { GRPC_MDELEM_UNREF(channeld->mdelem_compression_algorithms[algo_idx]); } GRPC_MDELEM_UNREF(channeld->mdelem_accept_encoding); }
/* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; grpc_credentials_unref(calld->creds); if (calld->host != NULL) { GRPC_MDSTR_UNREF(calld->host); } if (calld->method != NULL) { GRPC_MDSTR_UNREF(calld->method); } reset_service_url(calld); }
/* 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) { /* 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_with_status == GRPC_STATUS_OK) { 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 (md->key == GRPC_MDSTR_AUTHORITY) { if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host); calld->host = GRPC_MDSTR_REF(md->value); } else if (md->key == GRPC_MDSTR_PATH) { if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method); calld->method = GRPC_MDSTR_REF(md->value); } } if (calld->host != NULL) { const char *call_host = grpc_mdstr_as_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); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); }
static void test_things_stick_around(void) { grpc_mdctx *ctx; size_t i, j; char *buffer; size_t nstrs = 1000; grpc_mdstr **strs = gpr_malloc(sizeof(grpc_mdstr *) * nstrs); size_t *shuf = gpr_malloc(sizeof(size_t) * nstrs); grpc_mdstr *test; LOG_TEST("test_things_stick_around"); ctx = grpc_mdctx_create(); for (i = 0; i < nstrs; i++) { gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", i); strs[i] = grpc_mdstr_from_string(ctx, buffer); shuf[i] = i; gpr_free(buffer); } for (i = 0; i < nstrs; i++) { GRPC_MDSTR_REF(strs[i]); GRPC_MDSTR_UNREF(strs[i]); } for (i = 0; i < nstrs; i++) { size_t p = (size_t)rand() % nstrs; size_t q = (size_t)rand() % nstrs; size_t temp = shuf[p]; shuf[p] = shuf[q]; shuf[q] = temp; } for (i = 0; i < nstrs; i++) { GRPC_MDSTR_UNREF(strs[shuf[i]]); for (j = i + 1; j < nstrs; j++) { gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]); test = grpc_mdstr_from_string(ctx, buffer); GPR_ASSERT(test == strs[shuf[j]]); GRPC_MDSTR_UNREF(test); gpr_free(buffer); } } grpc_mdctx_unref(ctx); gpr_free(strs); gpr_free(shuf); }
static void destroy_channel_elem(grpc_channel_element* elem) { channel_data* chand = elem->channel_data; GPR_ASSERT(chand != NULL); if (chand->path_str != NULL) { GRPC_MDSTR_UNREF(chand->path_str); } }
/* Destructor for channel data */ static void destroy_channel_elem(grpc_channel_element *elem) { /* grab pointers to our data from the channel element */ channel_data *channeld = elem->channel_data; GRPC_MDELEM_UNREF(channeld->te_trailers); GRPC_MDELEM_UNREF(channeld->status_ok); GRPC_MDELEM_UNREF(channeld->status_not_found); GRPC_MDELEM_UNREF(channeld->method_post); GRPC_MDELEM_UNREF(channeld->http_scheme); GRPC_MDELEM_UNREF(channeld->https_scheme); GRPC_MDELEM_UNREF(channeld->grpc_scheme); GRPC_MDELEM_UNREF(channeld->content_type); GRPC_MDSTR_UNREF(channeld->path_key); GRPC_MDSTR_UNREF(channeld->authority_key); GRPC_MDSTR_UNREF(channeld->host_key); }
static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, int success) { size_t i; int ii; grpc_call *c = call; GPR_TIMER_BEGIN("destroy_call", 0); for (i = 0; i < 2; i++) { grpc_metadata_batch_destroy( &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]); } if (c->receiving_stream != NULL) { grpc_byte_stream_destroy(c->receiving_stream); } grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c)); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->channel, "call"); gpr_mu_destroy(&c->mu); for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (c->status[i].details) { GRPC_MDSTR_UNREF(c->status[i].details); } } for (ii = 0; ii < c->send_extra_metadata_count; ii++) { GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md); } for (i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (c->context[i].destroy) { c->context[i].destroy(c->context[i].value); } } if (c->cq) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } gpr_free(c); GPR_TIMER_END("destroy_call", 0); }
static void set_status_details(grpc_call *call, status_source source, grpc_mdstr *status) { if (call->status[source].details != NULL) { GRPC_MDSTR_UNREF(call->status[source].details); } call->status[source].details = status; }
void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) { int i; for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { if (c->entries_keys[i]) GRPC_MDSTR_UNREF(c->entries_keys[i]); if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]); } gpr_free(c->table_elem_size); }
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; GPR_ASSERT(calld->state != PENDING); if (calld->host) { GRPC_MDSTR_UNREF(calld->host); } if (calld->path) { GRPC_MDSTR_UNREF(calld->path); } gpr_mu_destroy(&calld->mu_state); server_unref(exec_ctx, chand->server); }
static void test_create_string(void) { grpc_mdstr *s1, *s2, *s3; LOG_TEST("test_create_string"); grpc_init(); s1 = grpc_mdstr_from_string("hello"); s2 = grpc_mdstr_from_string("hello"); s3 = grpc_mdstr_from_string("very much not hello"); GPR_ASSERT(s1 == s2); GPR_ASSERT(s3 != s1); GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0); GPR_ASSERT(gpr_slice_str_cmp(s3->slice, "very much not hello") == 0); GRPC_MDSTR_UNREF(s1); GRPC_MDSTR_UNREF(s2); GRPC_MDSTR_UNREF(s3); grpc_shutdown(); }
/* Destructor for channel data */ static void destroy_channel_elem(grpc_channel_element *elem) { /* grab pointers to our data from the channel element */ channel_data *chand = elem->channel_data; grpc_channel_security_connector *ctx = chand->security_connector; if (ctx != NULL) GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter"); if (chand->authority_string != NULL) { GRPC_MDSTR_UNREF(chand->authority_string); } if (chand->error_msg_key != NULL) { GRPC_MDSTR_UNREF(chand->error_msg_key); } if (chand->status_key != NULL) { GRPC_MDSTR_UNREF(chand->status_key); } if (chand->path_string != NULL) { GRPC_MDSTR_UNREF(chand->path_string); } }
static void test_create_string(void) { grpc_mdctx *ctx; grpc_mdstr *s1, *s2, *s3; LOG_TEST("test_create_string"); ctx = grpc_mdctx_create(); s1 = grpc_mdstr_from_string(ctx, "hello"); s2 = grpc_mdstr_from_string(ctx, "hello"); s3 = grpc_mdstr_from_string(ctx, "very much not hello"); GPR_ASSERT(s1 == s2); GPR_ASSERT(s3 != s1); GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0); GPR_ASSERT(gpr_slice_str_cmp(s3->slice, "very much not hello") == 0); GRPC_MDSTR_UNREF(s1); GRPC_MDSTR_UNREF(s2); grpc_mdctx_unref(ctx); GRPC_MDSTR_UNREF(s3); }
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_stats *stats, void *ignored) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; GPR_ASSERT(calld->state != PENDING); if (calld->host) { GRPC_MDSTR_UNREF(calld->host); } if (calld->path) { GRPC_MDSTR_UNREF(calld->path); } grpc_metadata_array_destroy(&calld->initial_metadata); gpr_mu_destroy(&calld->mu_state); server_unref(exec_ctx, chand->server); }
static void destroy_channel(grpc_exec_ctx *exec_ctx, grpc_channel *channel) { size_t i; grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel)); for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]); } GRPC_MDSTR_UNREF(channel->grpc_status_string); GRPC_MDSTR_UNREF(channel->grpc_compression_algorithm_string); GRPC_MDSTR_UNREF(channel->grpc_encodings_accepted_by_peer_string); GRPC_MDSTR_UNREF(channel->grpc_message_string); GRPC_MDSTR_UNREF(channel->path_string); GRPC_MDSTR_UNREF(channel->authority_string); while (channel->registered_calls) { registered_call *rc = channel->registered_calls; channel->registered_calls = rc->next; GRPC_MDELEM_UNREF(rc->path); if (rc->authority) { GRPC_MDELEM_UNREF(rc->authority); } gpr_free(rc); } if (channel->default_authority != NULL) { GRPC_MDELEM_UNREF(channel->default_authority); } grpc_mdctx_unref(channel->metadata_context); gpr_mu_destroy(&channel->registered_call_mu); gpr_free(channel->target); gpr_free(channel); }
static void test_slices_work(void) { /* ensure no memory leaks when switching representation from mdstr to slice */ grpc_mdstr *str; gpr_slice slice; LOG_TEST("test_slices_work"); grpc_init(); str = grpc_mdstr_from_string( "123456789012345678901234567890123456789012345678901234567890"); slice = gpr_slice_ref(str->slice); GRPC_MDSTR_UNREF(str); gpr_slice_unref(slice); str = grpc_mdstr_from_string( "123456789012345678901234567890123456789012345678901234567890"); slice = gpr_slice_ref(str->slice); gpr_slice_unref(slice); GRPC_MDSTR_UNREF(str); grpc_shutdown(); }
static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { size_t i; gpr_mu_lock(&t->mu); GPR_ASSERT(t->ep == NULL); gpr_slice_buffer_destroy(&t->global.qbuf); gpr_slice_buffer_destroy(&t->writing.outbuf); grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor); gpr_slice_buffer_destroy(&t->parsing.qbuf); gpr_slice_buffer_destroy(&t->read_buffer); grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser); grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser); GRPC_MDSTR_UNREF(t->parsing.str_grpc_timeout); for (i = 0; i < STREAM_LIST_COUNT; i++) { GPR_ASSERT(t->lists[i].head == NULL); GPR_ASSERT(t->lists[i].tail == NULL); } GPR_ASSERT(grpc_chttp2_stream_map_size(&t->parsing_stream_map) == 0); GPR_ASSERT(grpc_chttp2_stream_map_size(&t->new_stream_map) == 0); grpc_chttp2_stream_map_destroy(&t->parsing_stream_map); grpc_chttp2_stream_map_destroy(&t->new_stream_map); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); gpr_mu_unlock(&t->mu); gpr_mu_destroy(&t->mu); /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ while (t->global.pings.next != &t->global.pings) { grpc_chttp2_outstanding_ping *ping = t->global.pings.next; grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, 0); ping->next->prev = ping->prev; ping->prev->next = ping->next; gpr_free(ping); } grpc_mdctx_unref(t->metadata_context); gpr_free(t->peer_string); gpr_free(t); }
static void destroy_channel(void *p, int ok) { grpc_channel *channel = p; size_t i; grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel)); for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]); } GRPC_MDSTR_UNREF(channel->grpc_status_string); GRPC_MDSTR_UNREF(channel->grpc_compression_level_string); GRPC_MDSTR_UNREF(channel->grpc_message_string); GRPC_MDSTR_UNREF(channel->path_string); GRPC_MDSTR_UNREF(channel->authority_string); while (channel->registered_calls) { registered_call *rc = channel->registered_calls; channel->registered_calls = rc->next; GRPC_MDELEM_UNREF(rc->path); GRPC_MDELEM_UNREF(rc->authority); gpr_free(rc); } grpc_mdctx_unref(channel->metadata_context); gpr_mu_destroy(&channel->registered_call_mu); gpr_free(channel); }
static void test_base64_and_huffman_works(void) { grpc_mdstr *str; gpr_slice slice1; gpr_slice slice2; LOG_TEST("test_base64_and_huffman_works"); grpc_init(); str = grpc_mdstr_from_string("abcdefg"); slice1 = grpc_mdstr_as_base64_encoded_and_huffman_compressed(str); slice2 = grpc_chttp2_base64_encode_and_huffman_compress(str->slice); GPR_ASSERT(0 == gpr_slice_cmp(slice1, slice2)); gpr_slice_unref(slice2); GRPC_MDSTR_UNREF(str); grpc_shutdown(); }
grpc_mdstr_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_mdstr_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_mdstr_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_mdstr_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_mdstr_hash_table* method_config_table = NULL; if (entries != NULL) { method_config_table = grpc_mdstr_hash_table_create(num_entries, entries); // Clean up. for (size_t i = 0; i < num_entries; ++i) { GRPC_MDSTR_UNREF(exec_ctx, entries[i].key); vtable->destroy_value(exec_ctx, entries[i].value); } gpr_free(entries); } return method_config_table; }
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table, const grpc_mdstr* path) { void* value = grpc_mdstr_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) { const char* path_str = grpc_mdstr_as_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_mdstr* wildcard_path = grpc_mdstr_from_string(buf); gpr_free(buf); value = grpc_mdstr_hash_table_get(table, wildcard_path); GRPC_MDSTR_UNREF(wildcard_path); } return value; }
/* Destructor for call_data */ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, const grpc_call_final_info *final_info, void *and_free_memory) { call_data *calld = elem->call_data; grpc_deadline_state_destroy(exec_ctx, elem); GRPC_MDSTR_UNREF(calld->path); GRPC_ERROR_UNREF(calld->cancel_error); grpc_subchannel_call *call = GET_CALL(calld); if (call != NULL && call != CANCELLED_CALL) { GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); } GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING); gpr_mu_destroy(&calld->mu); GPR_ASSERT(calld->waiting_ops_count == 0); if (calld->connected_subchannel != NULL) { GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel, "picked"); } gpr_free(calld->waiting_ops); gpr_free(and_free_memory); }
/* 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) { /* 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; size_t i; grpc_client_security_context *sec_ctx = NULL; if (calld->security_context_set == 0 && op->cancel_with_status == GRPC_STATUS_OK) { 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->security_connector->base.auth_context, "client_auth_filter"); } if (op->bind_pollset != NULL) { calld->pollset = op->bind_pollset; } if (op->send_ops != NULL && !calld->sent_initial_metadata) { size_t nops = op->send_ops->nops; grpc_stream_op *ops = op->send_ops->ops; for (i = 0; i < nops; i++) { grpc_stream_op *sop = &ops[i]; if (sop->type != GRPC_OP_METADATA) continue; calld->op_md_idx = i; calld->sent_initial_metadata = 1; for (l = sop->data.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 (md->key == chand->authority_string) { if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host); calld->host = GRPC_MDSTR_REF(md->value); } else if (md->key == chand->path_string) { if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method); calld->method = GRPC_MDSTR_REF(md->value); } } if (calld->host != NULL) { grpc_security_status status; const char *call_host = grpc_mdstr_as_c_string(calld->host); calld->op = *op; /* Copy op (originates from the caller's stack). */ status = grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, on_host_checked, elem); if (status != GRPC_SECURITY_OK) { if (status == GRPC_SECURITY_ERROR) { char *error_msg; gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", call_host); bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, error_msg); gpr_free(error_msg); } return; /* early exit */ } } send_security_metadata(exec_ctx, elem, op); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); }
/* add an element to the decoder table */ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) { uint32_t key_hash = elem->key->hash; uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->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 (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 (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 (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) { /* 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 (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) { /* 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(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(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 (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) { c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) { c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) { c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key); c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) { c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key); 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_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_2(key_hash)]); c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key); c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; } else { GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_3(key_hash)]); c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key); c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; } }
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_mdstr *path = grpc_mdstr_from_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); grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, NULL, NULL, path, gpr_now(GPR_CLOCK_MONOTONIC), gpr_inf_future(GPR_CLOCK_MONOTONIC), call_stack); 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_exec_ctx_finish(&exec_ctx); GRPC_MDSTR_UNREF(path); }