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;
  }
}
Beispiel #2
0
/** 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));
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
  }
}
Beispiel #7
0
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;
  }
}
Beispiel #8
0
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]);
  }
}
Beispiel #9
0
/* 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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
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));
    }
}
Beispiel #12
0
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;
}
Beispiel #13
0
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;
  }
}
Beispiel #14
0
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;
}
Beispiel #15
0
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);
}
Beispiel #16
0
/* 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;
  }
}
Beispiel #17
0
/** 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);
  }
}
Beispiel #18
0
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;
}
Beispiel #19
0
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);
}
Beispiel #20
0
    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;
  }
Beispiel #21
0
/* 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;
  }
}