static void hs_mutate_op(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 *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)); grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type, GRPC_MDELEM_REF(channeld->content_type)); 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; op->on_done_recv = &calld->hs_on_recv; } }
/** Filter initial metadata */ static void process_send_initial_metadata( grpc_call_element *elem, grpc_metadata_batch *initial_metadata) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; /* Parse incoming request for compression. If any, it'll be available * at calld->compression_algorithm */ grpc_metadata_batch_filter(initial_metadata, compression_md_filter, elem); if (!calld->has_compression_algorithm) { /* If no algorithm was found in the metadata and we aren't * exceptionally skipping compression, fall back to the channel * default */ calld->compression_algorithm = channeld->default_compression_algorithm; calld->has_compression_algorithm = 1; /* GPR_TRUE */ } /* hint compression algorithm */ grpc_metadata_batch_add_tail( initial_metadata, &calld->compression_algorithm_storage, GRPC_MDELEM_REF( channeld ->mdelem_compression_algorithms[calld->compression_algorithm])); /* convey supported compression algorithms */ grpc_metadata_batch_add_tail( initial_metadata, &calld->accept_encoding_storage, GRPC_MDELEM_REF(channeld->mdelem_accept_encoding)); }
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); }
grpc_call *grpc_channel_create_registered_call( grpc_channel *channel, grpc_call *parent_call, gpr_uint32 propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved) { registered_call *rc = registered_call_handle; GPR_ASSERT(!reserved); return grpc_channel_create_call_internal( channel, parent_call, propagation_mask, completion_queue, GRPC_MDELEM_REF(rc->path), rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline); }
static grpc_call *grpc_channel_create_call_internal( grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, grpc_pollset_set *pollset_set_alternative, grpc_mdelem path_mdelem, grpc_mdelem authority_mdelem, gpr_timespec deadline) { grpc_mdelem send_metadata[2]; size_t num_metadata = 0; GPR_ASSERT(channel->is_client); GPR_ASSERT(!(cq != NULL && pollset_set_alternative != NULL)); send_metadata[num_metadata++] = path_mdelem; if (!GRPC_MDISNULL(authority_mdelem)) { send_metadata[num_metadata++] = authority_mdelem; } else if (!GRPC_MDISNULL(channel->default_authority)) { send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority); } grpc_call_create_args args; memset(&args, 0, sizeof(args)); args.channel = channel; args.parent_call = parent_call; args.propagation_mask = propagation_mask; args.cq = cq; args.pollset_set_alternative = pollset_set_alternative; args.server_transport_data = NULL; args.add_initial_metadata = send_metadata; args.add_initial_metadata_count = num_metadata; args.send_deadline = deadline; grpc_call *call; GRPC_LOG_IF_ERROR("call_create", grpc_call_create(exec_ctx, &args, &call)); return call; }
static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *input_error) { grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg; grpc_call_element *elem = batch->handler_private.extra_arg; call_data *calld = elem->call_data; reset_auth_metadata_context(&calld->auth_md_context); grpc_error *error = GRPC_ERROR_REF(input_error); if (error == GRPC_ERROR_NONE) { GPR_ASSERT(calld->md_array.size <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(batch->send_initial_metadata); grpc_metadata_batch *mdb = batch->payload->send_initial_metadata.send_initial_metadata; for (size_t i = 0; i < calld->md_array.size; ++i) { add_error(&error, grpc_metadata_batch_add_tail( exec_ctx, mdb, &calld->md_links[i], GRPC_MDELEM_REF(calld->md_array.md[i]))); } } if (error == GRPC_ERROR_NONE) { grpc_call_next_op(exec_ctx, elem, batch); } else { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED); grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, error); } }
static void hc_mutate_op(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 *channeld = elem->channel_data; if (op->send_initial_metadata != NULL) { grpc_metadata_batch_filter(op->send_initial_metadata, client_strip_filter, elem); /* Send : prefixed headers, which have to be before any application layer headers. */ grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method, GRPC_MDELEM_METHOD_POST); grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme, channeld->static_scheme); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS); grpc_metadata_batch_add_tail( op->send_initial_metadata, &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent)); } if (op->recv_initial_metadata != NULL) { /* substitute our callback for the higher callback */ calld->recv_initial_metadata = op->recv_initial_metadata; calld->on_done_recv = op->on_complete; op->on_complete = &calld->hc_on_recv; } }
void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array *dst, grpc_credentials_mdelem_array *src) { mdelem_list_ensure_capacity(dst, src->size); for (size_t i = 0; i < src->size; ++i) { dst->md[dst->size++] = GRPC_MDELEM_REF(src->md[i]); } }
/* The \a on_complete closure passed as part of the pick requires keeping a * reference to its associated round robin instance. We wrap this closure in * order to unref the round robin instance upon its invocation */ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { wrapped_rr_closure_arg *wc_arg = arg; if (wc_arg->rr_policy != NULL) { if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", (intptr_t)wc_arg->rr_policy); } GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); /* if target is NULL, no pick has been made by the RR policy (eg, all * addresses failed to connect). There won't be any user_data/token * available */ if (wc_arg->target != NULL) { initial_metadata_add_lb_token(wc_arg->initial_metadata, wc_arg->lb_token_mdelem_storage, GRPC_MDELEM_REF(wc_arg->lb_token)); } } GPR_ASSERT(wc_arg->wrapped_closure != NULL); grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error), NULL); GPR_ASSERT(wc_arg->free_when_done != NULL); gpr_free(wc_arg->free_when_done); }
grpc_call *grpc_channel_create_registered_call( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved) { registered_call *rc = registered_call_handle; GRPC_API_TRACE( "grpc_channel_create_registered_call(" "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, " "registered_call_handle=%p, " "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, " "reserved=%p)", 9, (channel, parent_call, (unsigned)propagation_mask, completion_queue, registered_call_handle, (long long)deadline.tv_sec, (int)deadline.tv_nsec, (int)deadline.clock_type, reserved)); GPR_ASSERT(!reserved); return grpc_channel_create_call_internal( channel, parent_call, propagation_mask, completion_queue, GRPC_MDELEM_REF(rc->path), rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline); }
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)); } }
grpc_call *grpc_channel_create_registered_call( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, void *registered_call_handle, gpr_timespec deadline, void *reserved) { registered_call *rc = registered_call_handle; GRPC_API_TRACE( "grpc_channel_create_registered_call(" "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, " "registered_call_handle=%p, " "deadline=gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "reserved=%p)", 9, (channel, parent_call, (unsigned)propagation_mask, completion_queue, registered_call_handle, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, 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, completion_queue, NULL, GRPC_MDELEM_REF(rc->path), GRPC_MDELEM_REF(rc->authority), deadline); grpc_exec_ctx_finish(&exec_ctx); return call; }
static void hc_mutate_op(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 *channeld = elem->channel_data; size_t i; if (op->send_ops && !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 *op = &ops[i]; if (op->type != GRPC_OP_METADATA) continue; calld->sent_initial_metadata = 1; grpc_metadata_batch_filter(&op->data.metadata, client_strip_filter, elem); /* Send : prefixed headers, which have to be before any application layer headers. */ grpc_metadata_batch_add_head(&op->data.metadata, &calld->method, GRPC_MDELEM_REF(channeld->method)); grpc_metadata_batch_add_head(&op->data.metadata, &calld->scheme, GRPC_MDELEM_REF(channeld->scheme)); grpc_metadata_batch_add_tail(&op->data.metadata, &calld->te_trailers, GRPC_MDELEM_REF(channeld->te_trailers)); grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type, GRPC_MDELEM_REF(channeld->content_type)); grpc_metadata_batch_add_tail(&op->data.metadata, &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent)); 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; op->on_done_recv = &calld->hc_on_recv; } }
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { /* determine how many bytes of buffer this entry represents */ size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) + GPR_SLICE_LENGTH(md->value->slice) + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; if (tbl->current_table_bytes > tbl->max_bytes) { if (grpc_http_trace) { gpr_log(GPR_ERROR, "HPACK max table size reduced to %d but not reflected by hpack " "stream (still at %d)", tbl->max_bytes, tbl->current_table_bytes); } return 0; } /* we can't add elements bigger than the max table size */ if (elem_bytes > tbl->current_table_bytes) { /* HPACK draft 10 section 4.4 states: * If the size of the new entry is less than or equal to the maximum * size, that entry is added to the table. It is not an error to * attempt to add an entry that is larger than the maximum size; an * attempt to add an entry larger than the entire table causes * the table * to be emptied of all existing entries, and results in an * empty table. */ while (tbl->num_ents) { evict1(tbl); } return 1; } /* evict entries to ensure no overflow */ while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) { evict1(tbl); } /* copy the finalized entry in */ tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] = GRPC_MDELEM_REF(md); /* update accounting values */ tbl->num_ents++; tbl->mem_used += (uint32_t)elem_bytes; return 1; }
static grpc_call *grpc_channel_create_call_internal( grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, grpc_mdelem *path_mdelem, grpc_mdelem *authority_mdelem, gpr_timespec deadline) { grpc_mdelem *send_metadata[2]; size_t num_metadata = 0; GPR_ASSERT(channel->is_client); send_metadata[num_metadata++] = path_mdelem; if (authority_mdelem != NULL) { send_metadata[num_metadata++] = authority_mdelem; } else if (channel->default_authority != NULL) { send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority); } return grpc_call_create(channel, parent_call, propagation_mask, cq, NULL, send_metadata, num_metadata, deadline); }
/* 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; } }
/** Filter's "main" function, called for any incoming grpc_transport_stream_op * instance that holds a non-zero number of send operations, accesible to this * function in \a send_ops. */ static void process_send_ops(grpc_call_element *elem, grpc_stream_op_buffer *send_ops) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; size_t i; int did_compress = 0; /* In streaming calls, we need to reset the previously accumulated slices */ gpr_slice_buffer_reset_and_unref(&calld->slices); for (i = 0; i < send_ops->nops; ++i) { grpc_stream_op *sop = &send_ops->ops[i]; switch (sop->type) { case GRPC_OP_BEGIN_MESSAGE: /* buffer up slices until we've processed all the expected ones (as * given by GRPC_OP_BEGIN_MESSAGE) */ calld->remaining_slice_bytes = sop->data.begin_message.length; if (sop->data.begin_message.flags & GRPC_WRITE_NO_COMPRESS) { calld->has_compression_algorithm = 1; /* GPR_TRUE */ calld->compression_algorithm = GRPC_COMPRESS_NONE; } break; case GRPC_OP_METADATA: if (!calld->written_initial_metadata) { /* Parse incoming request for compression. If any, it'll be available * at calld->compression_algorithm */ grpc_metadata_batch_filter(&(sop->data.metadata), compression_md_filter, elem); if (!calld->has_compression_algorithm) { /* If no algorithm was found in the metadata and we aren't * exceptionally skipping compression, fall back to the channel * default */ calld->compression_algorithm = channeld->default_compression_algorithm; calld->has_compression_algorithm = 1; /* GPR_TRUE */ } /* hint compression algorithm */ grpc_metadata_batch_add_tail( &(sop->data.metadata), &calld->compression_algorithm_storage, GRPC_MDELEM_REF(channeld->mdelem_compression_algorithms [calld->compression_algorithm])); /* convey supported compression algorithms */ grpc_metadata_batch_add_tail( &(sop->data.metadata), &calld->accept_encoding_storage, GRPC_MDELEM_REF(channeld->mdelem_accept_encoding)); calld->written_initial_metadata = 1; /* GPR_TRUE */ } break; case GRPC_OP_SLICE: if (skip_compression(channeld, calld)) continue; GPR_ASSERT(calld->remaining_slice_bytes > 0); /* Increase input ref count, gpr_slice_buffer_add takes ownership. */ gpr_slice_buffer_add(&calld->slices, gpr_slice_ref(sop->data.slice)); GPR_ASSERT(GPR_SLICE_LENGTH(sop->data.slice) >= calld->remaining_slice_bytes); calld->remaining_slice_bytes -= (gpr_uint32)GPR_SLICE_LENGTH(sop->data.slice); if (calld->remaining_slice_bytes == 0) { did_compress = compress_send_sb(calld->compression_algorithm, &calld->slices); } break; case GRPC_NO_OP: break; } } /* Modify the send_ops stream_op_buffer depending on whether compression was * carried out */ if (did_compress) { finish_compressed_sopb(send_ops, elem); } }
static int prepare_application_metadata(grpc_call *call, int count, grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata) { int i; grpc_metadata_batch *batch = &call->metadata_batch[0 /* is_receiving */][is_trailing]; if (prepend_extra_metadata) { if (call->send_extra_metadata_count == 0) { prepend_extra_metadata = 0; } else { for (i = 0; i < call->send_extra_metadata_count; i++) { GRPC_MDELEM_REF(call->send_extra_metadata[i].md); } for (i = 1; i < call->send_extra_metadata_count; i++) { call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1]; } for (i = 0; i < call->send_extra_metadata_count - 1; i++) { call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1]; } } } for (i = 0; i < count; i++) { grpc_metadata *md = &metadata[i]; grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data; GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data)); l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length); if (!grpc_mdstr_is_legal_header(l->md->key)) { gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s", grpc_mdstr_as_c_string(l->md->key)); return 0; } else if (!grpc_mdstr_is_bin_suffixed(l->md->key) && !grpc_mdstr_is_legal_nonbin_header(l->md->value)) { gpr_log(GPR_ERROR, "attempt to send invalid metadata value"); return 0; } } for (i = 1; i < count; i++) { linked_from_md(&metadata[i])->prev = linked_from_md(&metadata[i - 1]); } for (i = 0; i < count - 1; i++) { linked_from_md(&metadata[i])->next = linked_from_md(&metadata[i + 1]); } switch (prepend_extra_metadata * 2 + (count != 0)) { case 0: /* no prepend, no metadata => nothing to do */ batch->list.head = batch->list.tail = NULL; break; case 1: /* metadata, but no prepend */ batch->list.head = linked_from_md(&metadata[0]); batch->list.tail = linked_from_md(&metadata[count - 1]); batch->list.head->prev = NULL; batch->list.tail->next = NULL; break; case 2: /* prepend, but no md */ batch->list.head = &call->send_extra_metadata[0]; batch->list.tail = &call->send_extra_metadata[call->send_extra_metadata_count - 1]; batch->list.head->prev = NULL; batch->list.tail->next = NULL; break; case 3: /* prepend AND md */ batch->list.head = &call->send_extra_metadata[0]; call->send_extra_metadata[call->send_extra_metadata_count - 1].next = linked_from_md(&metadata[0]); linked_from_md(&metadata[0])->prev = &call->send_extra_metadata[call->send_extra_metadata_count - 1]; batch->list.tail = linked_from_md(&metadata[count - 1]); batch->list.head->prev = NULL; batch->list.tail->next = NULL; break; default: GPR_UNREACHABLE_CODE(return 0); } return 1; }
void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array *list, grpc_mdelem md) { mdelem_list_ensure_capacity(list, 1); list->md[list->size++] = GRPC_MDELEM_REF(md); }
grpc_metadata_batch_filter(op->send_initial_metadata, client_strip_filter, elem); /* Send : prefixed headers, which have to be before any application layer headers. */ grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method, method); grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme, channeld->static_scheme); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS); grpc_metadata_batch_add_tail( op->send_initial_metadata, &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent)); } if (op->recv_initial_metadata != NULL) { /* substitute our callback for the higher callback */ calld->recv_initial_metadata = op->recv_initial_metadata; calld->on_done_recv_initial_metadata = op->recv_initial_metadata_ready; op->recv_initial_metadata_ready = &calld->hc_on_recv_initial_metadata; } if (op->recv_trailing_metadata != NULL) { /* substitute our callback for the higher callback */ calld->recv_trailing_metadata = op->recv_trailing_metadata; calld->on_done_recv_trailing_metadata = op->on_complete; op->on_complete = &calld->hc_on_recv_trailing_metadata; }
/* 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; } }