예제 #1
0
// Start transport stream op.
static void start_transport_stream_op_batch(
    grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
    grpc_transport_stream_op_batch* op) {
  call_data* calld = (call_data*)elem->call_data;
  // Check max send message size.
  if (op->send_message && calld->limits.max_send_size >= 0 &&
      op->payload->send_message.send_message->length >
          (size_t)calld->limits.max_send_size) {
    char* message_string;
    gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)",
                 op->payload->send_message.send_message->length,
                 calld->limits.max_send_size);
    grpc_transport_stream_op_batch_finish_with_failure(
        exec_ctx, op,
        grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string),
                           GRPC_ERROR_INT_GRPC_STATUS,
                           GRPC_STATUS_RESOURCE_EXHAUSTED),
        calld->call_combiner);
    gpr_free(message_string);
    return;
  }
  // Inject callback for receiving a message.
  if (op->recv_message) {
    calld->next_recv_message_ready =
        op->payload->recv_message.recv_message_ready;
    calld->recv_message = op->payload->recv_message.recv_message;
    op->payload->recv_message.recv_message_ready = &calld->recv_message_ready;
  }
  // Chain to the next filter.
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #2
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);
  }
}
예제 #3
0
static void on_credentials_metadata(void *user_data,
                                    grpc_credentials_md *md_elems,
                                    size_t num_md,
                                    grpc_credentials_status status) {
  grpc_call_element *elem = (grpc_call_element *)user_data;
  call_data *calld = elem->call_data;
  channel_data *chand = elem->channel_data;
  grpc_transport_stream_op *op = &calld->op;
  grpc_metadata_batch *mdb;
  size_t i;
  if (status != GRPC_CREDENTIALS_OK) {
    bubble_up_error(elem, GRPC_STATUS_UNAUTHENTICATED,
                    "Credentials failed to get metadata.");
    return;
  }
  GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
  GPR_ASSERT(op->send_ops && op->send_ops->nops > calld->op_md_idx &&
             op->send_ops->ops[calld->op_md_idx].type == GRPC_OP_METADATA);
  mdb = &op->send_ops->ops[calld->op_md_idx].data.metadata;
  for (i = 0; i < num_md; i++) {
    grpc_metadata_batch_add_tail(
        mdb, &calld->md_links[i],
        grpc_mdelem_from_slices(chand->md_ctx, gpr_slice_ref(md_elems[i].key),
                                gpr_slice_ref(md_elems[i].value)));
  }
  grpc_call_next_op(elem, op);
}
예제 #4
0
파일: client.c 프로젝트: IsaacCisneros/grpc
static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
                    grpc_call_op *op) {
  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);

  switch (op->type) {
    case GRPC_RECV_METADATA:
      grpc_call_recv_metadata(elem, &op->data.metadata);
      break;
    case GRPC_RECV_MESSAGE:
      grpc_call_recv_message(elem, op->data.message);
      op->done_cb(op->user_data, GRPC_OP_OK);
      break;
    case GRPC_RECV_HALF_CLOSE:
      grpc_call_read_closed(elem);
      break;
    case GRPC_RECV_FINISH:
      grpc_call_stream_closed(elem);
      break;
    case GRPC_RECV_SYNTHETIC_STATUS:
      grpc_call_recv_synthetic_status(elem, op->data.synthetic_status.status,
                                      op->data.synthetic_status.message);
      break;
    default:
      GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
      grpc_call_next_op(elem, op);
  }
}
예제 #5
0
파일: server.c 프로젝트: An-mol/grpc
static void server_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
                                             grpc_call_element *elem,
                                             grpc_transport_stream_op *op) {
  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
  server_mutate_op(elem, op);
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #6
0
static void lr_start_transport_stream_op_batch(
    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
    grpc_transport_stream_op_batch *op) {
  GPR_TIMER_BEGIN("lr_start_transport_stream_op_batch", 0);
  call_data *calld = (call_data *)elem->call_data;

  if (op->recv_initial_metadata) {
    /* substitute our callback for the higher callback */
    calld->recv_initial_metadata =
        op->payload->recv_initial_metadata.recv_initial_metadata;
    calld->ops_recv_initial_metadata_ready =
        op->payload->recv_initial_metadata.recv_initial_metadata_ready;
    op->payload->recv_initial_metadata.recv_initial_metadata_ready =
        &calld->on_initial_md_ready;
  } else if (op->send_trailing_metadata) {
    GRPC_LOG_IF_ERROR(
        "grpc_metadata_batch_filter",
        grpc_metadata_batch_filter(
            exec_ctx,
            op->payload->send_trailing_metadata.send_trailing_metadata,
            lr_trailing_md_filter, elem,
            "LR trailing metadata filtering error"));
  }
  grpc_call_next_op(exec_ctx, elem, op);

  GPR_TIMER_END("lr_start_transport_stream_op_batch", 0);
}
예제 #7
0
static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
                                    grpc_credentials_md *md_elems,
                                    size_t num_md,
                                    grpc_credentials_status status) {
  grpc_call_element *elem = (grpc_call_element *)user_data;
  call_data *calld = elem->call_data;
  grpc_transport_stream_op *op = &calld->op;
  grpc_metadata_batch *mdb;
  size_t i;
  reset_auth_metadata_context(&calld->auth_md_context);
  if (status != GRPC_CREDENTIALS_OK) {
    bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
                    "Credentials failed to get metadata.");
    return;
  }
  GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
  GPR_ASSERT(op->send_initial_metadata != NULL);
  mdb = op->send_initial_metadata;
  for (i = 0; i < num_md; i++) {
    grpc_metadata_batch_add_tail(
        mdb, &calld->md_links[i],
        grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key),
                                gpr_slice_ref(md_elems[i].value)));
  }
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #8
0
static void server_start_transport_op(grpc_call_element* elem,
                                      grpc_transport_stream_op* op) {
  call_data* calld = elem->call_data;
  GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0));
  server_mutate_op(elem, op);
  grpc_call_next_op(elem, op);
}
예제 #9
0
static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
                            grpc_status_code status, const char *error_msg) {
  call_data *calld = elem->call_data;
  gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
  grpc_transport_stream_op_add_cancellation(&calld->op, status);
  grpc_call_next_op(exec_ctx, elem, &calld->op);
}
예제 #10
0
void grpc_metadata_buffer_flush(grpc_metadata_buffer *buffer,
                                grpc_call_element *elem) {
  grpc_metadata_buffer_impl *impl = *buffer;
  grpc_call_op op;
  qelem *qe;
  size_t i;

  if (!impl) {
    /* nothing to send */
    return;
  }

  /* construct call_op's, and push them down the stack */
  op.type = GRPC_SEND_METADATA;
  op.dir = GRPC_CALL_DOWN;
  for (i = 0; i < impl->elems; i++) {
    qe = &ELEMS(impl)[i];
    op.done_cb = qe->cb;
    op.user_data = qe->user_data;
    op.flags = qe->flags;
    op.data.metadata = qe->md;
    grpc_call_next_op(elem, &op);
  }

  /* free data structures and reset to NULL: we can only flush once */
  gpr_free(impl);
  *buffer = NULL;
}
예제 #11
0
static void bubble_up_error(grpc_call_element *elem, const char *error_msg) {
  call_data *calld = elem->call_data;
  channel_data *chand = elem->channel_data;
  grpc_transport_stream_op_add_cancellation(
      &calld->op, GRPC_STATUS_UNAUTHENTICATED,
      grpc_mdstr_from_string(chand->md_ctx, error_msg, 0));
  grpc_call_next_op(elem, &calld->op);
}
예제 #12
0
/* 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 noop_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
                                           grpc_call_element *elem,
                                           grpc_transport_stream_op *op) {
  noop_mutate_op(elem, op);

  /* pass control down the stack */
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #13
0
파일: channel_stack.c 프로젝트: Abioy/kythe
void grpc_call_element_send_finish(grpc_call_element *cur_elem) {
  grpc_call_op finish_op;
  finish_op.type = GRPC_SEND_FINISH;
  finish_op.dir = GRPC_CALL_DOWN;
  finish_op.done_cb = do_nothing;
  finish_op.user_data = NULL;
  finish_op.flags = 0;
  grpc_call_next_op(cur_elem, &finish_op);
}
예제 #14
0
파일: channel_stack.c 프로젝트: Abioy/kythe
void grpc_call_element_send_cancel(grpc_call_element *cur_elem) {
  grpc_call_op cancel_op;
  cancel_op.type = GRPC_CANCEL_OP;
  cancel_op.dir = GRPC_CALL_DOWN;
  cancel_op.done_cb = do_nothing;
  cancel_op.user_data = NULL;
  cancel_op.flags = 0;
  grpc_call_next_op(cur_elem, &cancel_op);
}
예제 #15
0
static void send_security_metadata(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
                                   grpc_transport_stream_op_batch *batch) {
  call_data *calld = elem->call_data;
  channel_data *chand = elem->channel_data;
  grpc_client_security_context *ctx =
      (grpc_client_security_context *)batch->payload
          ->context[GRPC_CONTEXT_SECURITY]
          .value;
  grpc_call_credentials *channel_call_creds =
      chand->security_connector->request_metadata_creds;
  int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);

  if (channel_call_creds == NULL && !call_creds_has_md) {
    /* Skip sending metadata altogether. */
    grpc_call_next_op(exec_ctx, elem, batch);
    return;
  }

  if (channel_call_creds != NULL && call_creds_has_md) {
    calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
                                                          ctx->creds, NULL);
    if (calld->creds == NULL) {
      grpc_transport_stream_op_batch_finish_with_failure(
          exec_ctx, batch,
          grpc_error_set_int(
              GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                  "Incompatible credentials set on channel and call."),
              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED));
      return;
    }
  } else {
    calld->creds = grpc_call_credentials_ref(
        call_creds_has_md ? ctx->creds : channel_call_creds);
  }

  build_auth_metadata_context(&chand->security_connector->base,
                              chand->auth_context, calld);

  grpc_error *cancel_error = set_cancel_func(elem, cancel_get_request_metadata);
  if (cancel_error != GRPC_ERROR_NONE) {
    grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch,
                                                       cancel_error);
    return;
  }
  GPR_ASSERT(calld->pollent != NULL);
  GRPC_CLOSURE_INIT(&calld->closure, on_credentials_metadata, batch,
                    grpc_schedule_on_exec_ctx);
  grpc_error *error = GRPC_ERROR_NONE;
  if (grpc_call_credentials_get_request_metadata(
          exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
          &calld->md_array, &calld->closure, &error)) {
    // Synchronous return; invoke on_credentials_metadata() directly.
    on_credentials_metadata(exec_ctx, batch, error);
    GRPC_ERROR_UNREF(error);
  }
}
예제 #16
0
static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
                                  grpc_call_element *elem,
                                  grpc_transport_stream_op *op) {
  GPR_TIMER_BEGIN("hc_start_transport_op", 0);
  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
  hc_mutate_op(elem, op);
  GPR_TIMER_END("hc_start_transport_op", 0);
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #17
0
/* 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 compress_start_transport_stream_op(grpc_call_element *elem,
                                               grpc_transport_stream_op *op) {
  if (op->send_ops && op->send_ops->nops > 0) {
    process_send_ops(elem, op->send_ops);
  }

  /* pass control down the stack */
  grpc_call_next_op(elem, op);
}
예제 #18
0
static void send_up_cancelled_ops(grpc_call_element *elem) {
  grpc_call_op finish_op;
  channel_data *chand = elem->channel_data;
  /* send up a synthesized status */
  finish_op.type = GRPC_RECV_METADATA;
  finish_op.dir = GRPC_CALL_UP;
  finish_op.flags = 0;
  finish_op.data.metadata = grpc_mdelem_ref(chand->cancel_status);
  finish_op.done_cb = do_nothing;
  finish_op.user_data = NULL;
  grpc_call_next_op(elem, &finish_op);
  /* send up a finish */
  finish_op.type = GRPC_RECV_FINISH;
  finish_op.dir = GRPC_CALL_UP;
  finish_op.flags = 0;
  finish_op.done_cb = do_nothing;
  finish_op.user_data = NULL;
  grpc_call_next_op(elem, &finish_op);
}
예제 #19
0
파일: channel_stack.c 프로젝트: Abioy/kythe
void grpc_call_element_send_metadata(grpc_call_element *cur_elem,
                                     grpc_mdelem *mdelem) {
  grpc_call_op metadata_op;
  metadata_op.type = GRPC_SEND_METADATA;
  metadata_op.dir = GRPC_CALL_DOWN;
  metadata_op.done_cb = do_nothing;
  metadata_op.user_data = NULL;
  metadata_op.flags = 0;
  metadata_op.data.metadata = mdelem;
  grpc_call_next_op(cur_elem, &metadata_op);
}
예제 #20
0
static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
                                      grpc_call_element *elem,
                                      grpc_transport_stream_op *op) {
  /* TODO(ctiller): this code fails. I don't know why. I expect it's
                    incomplete, and someone should look at it soon.

  call_data *calld = elem->call_data;
  GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); */
  server_mutate_op(elem, op);
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #21
0
void grpc_call_element_recv_status(grpc_call_element *cur_elem,
                                   grpc_status_code status,
                                   const char *message) {
  grpc_call_op op;
  op.type = GRPC_RECV_SYNTHETIC_STATUS;
  op.dir = GRPC_CALL_UP;
  op.done_cb = do_nothing;
  op.user_data = NULL;
  op.data.synthetic_status.status = status;
  op.data.synthetic_status.message = message;
  grpc_call_next_op(cur_elem, &op);
}
예제 #22
0
static void start_transport_stream_op_batch(
    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
    grpc_transport_stream_op_batch *op) {
  call_data *calld = elem->call_data;
  if (op->recv_initial_metadata) {
    calld->recv_im_ready =
        op->payload->recv_initial_metadata.recv_initial_metadata_ready;
    op->payload->recv_initial_metadata.recv_initial_metadata_ready =
        grpc_closure_create(recv_im_ready, elem, grpc_schedule_on_exec_ctx);
  }
  grpc_call_next_op(exec_ctx, elem, op);
}
예제 #23
0
/* 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);
}
예제 #24
0
파일: noop_filter.c 프로젝트: Abioy/kythe
/* 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 call_op(grpc_call_element *elem, grpc_call_element *from_elem,
                    grpc_call_op *op) {
  /* grab pointers to our data from the call element */
  call_data *calld = elem->call_data;
  channel_data *channeld = elem->channel_data;

  ignore_unused(calld);
  ignore_unused(channeld);

  switch (op->type) {
    default:
      /* pass control up or down the stack depending on op->dir */
      grpc_call_next_op(elem, op);
      break;
  }
}
예제 #25
0
static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
  grpc_call_element *elem = elemp;
  call_data *calld = elem->call_data;
  calld->send_message_blocked = false;
  grpc_slice_buffer_add(&calld->slices, calld->incoming_slice);
  if (calld->send_length == calld->slices.length) {
    /* Pass down the original send_message op that was blocked.*/
    grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
                                  calld->send_flags);
    calld->send_op.send_message = &calld->replacement_stream.base;
    calld->post_send = calld->send_op.on_complete;
    calld->send_op.on_complete = &calld->send_done;
    grpc_call_next_op(exec_ctx, elem, &calld->send_op);
  } else {
    continue_send_message(exec_ctx, elem);
  }
}
예제 #26
0
static void finish_send_message(grpc_exec_ctx *exec_ctx,
                                grpc_call_element *elem) {
  call_data *calld = elem->call_data;
  int did_compress;
  grpc_slice_buffer tmp;
  grpc_slice_buffer_init(&tmp);
  did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm,
                                   &calld->slices, &tmp);
  if (did_compress) {
    if (GRPC_TRACER_ON(grpc_compression_trace)) {
      char *algo_name;
      const size_t before_size = calld->slices.length;
      const size_t after_size = tmp.length;
      const float savings_ratio = 1.0f - (float)after_size / (float)before_size;
      GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
                                                 &algo_name));
      gpr_log(GPR_DEBUG, "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR
                         " bytes (%.2f%% savings)",
              algo_name, before_size, after_size, 100 * savings_ratio);
    }
    grpc_slice_buffer_swap(&calld->slices, &tmp);
    calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
  } else {
    if (GRPC_TRACER_ON(grpc_compression_trace)) {
      char *algo_name;
      GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
                                                 &algo_name));
      gpr_log(GPR_DEBUG,
              "Algorithm '%s' enabled but decided not to compress. Input size: "
              "%" PRIuPTR,
              algo_name, calld->slices.length);
    }
  }

  grpc_slice_buffer_destroy_internal(exec_ctx, &tmp);

  grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
                                calld->send_flags);
  calld->send_op->payload->send_message.send_message =
      &calld->replacement_stream.base;
  calld->post_send = calld->send_op->on_complete;
  calld->send_op->on_complete = &calld->send_done;

  grpc_call_next_op(exec_ctx, elem, calld->send_op);
}
예제 #27
0
/* called from application code */
static void on_md_processing_done(
    void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md,
    const grpc_metadata *response_md, size_t num_response_md,
    grpc_status_code status, const char *error_details) {
  grpc_call_element *elem = user_data;
  call_data *calld = elem->call_data;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  /* TODO(jboeuf): Implement support for response_md. */
  if (response_md != NULL && num_response_md > 0) {
    gpr_log(GPR_INFO,
            "response_md in auth metadata processing not supported for now. "
            "Ignoring...");
  }

  if (status == GRPC_STATUS_OK) {
    calld->consumed_md = consumed_md;
    calld->num_consumed_md = num_consumed_md;
    grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md,
                               elem);
    grpc_metadata_array_destroy(&calld->md);
    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1);
  } else {
    gpr_slice message;
    grpc_transport_stream_op close_op;
    memset(&close_op, 0, sizeof(close_op));
    grpc_metadata_array_destroy(&calld->md);
    error_details = error_details != NULL
                        ? error_details
                        : "Authentication metadata processing failed.";
    message = gpr_slice_from_copied_string(error_details);
    calld->transport_op.send_initial_metadata = NULL;
    if (calld->transport_op.send_message != NULL) {
      grpc_byte_stream_destroy(calld->transport_op.send_message);
      calld->transport_op.send_message = NULL;
    }
    calld->transport_op.send_trailing_metadata = NULL;
    grpc_transport_stream_op_add_close(&close_op, status, &message);
    grpc_call_next_op(&exec_ctx, elem, &close_op);
    calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0);
  }

  grpc_exec_ctx_finish(&exec_ctx);
}
예제 #28
0
파일: server.c 프로젝트: mindis/grpc
static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn,
                    grpc_call_op *op) {
  channel_data *chand = elem->channel_data;
  call_data *calld = elem->call_data;
  grpc_mdelem *md;
  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
  switch (op->type) {
    case GRPC_RECV_METADATA:
      md = op->data.metadata;
      if (md->key == chand->path_key) {
        calld->path = grpc_mdstr_ref(md->value);
        grpc_mdelem_unref(md);
      } else if (md->key == chand->authority_key) {
        calld->host = grpc_mdstr_ref(md->value);
        grpc_mdelem_unref(md);
      } else {
        grpc_call_recv_metadata(elem, md);
      }
      break;
    case GRPC_RECV_END_OF_INITIAL_METADATA:
      start_new_rpc(elem);
      grpc_call_initial_metadata_complete(elem);
      break;
    case GRPC_RECV_MESSAGE:
      grpc_call_recv_message(elem, op->data.message);
      op->done_cb(op->user_data, GRPC_OP_OK);
      break;
    case GRPC_RECV_HALF_CLOSE:
      read_closed(elem);
      break;
    case GRPC_RECV_FINISH:
      stream_closed(elem);
      break;
    case GRPC_RECV_DEADLINE:
      grpc_call_set_deadline(elem, op->data.deadline);
      ((call_data *)elem->call_data)->deadline = op->data.deadline;
      break;
    default:
      GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
      grpc_call_next_op(elem, op);
      break;
  }
}
예제 #29
0
static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
                                         grpc_call_element *elem,
                                         grpc_transport_stream_op *op) {
  GPR_TIMER_BEGIN("lr_start_transport_stream_op", 0);
  call_data *calld = elem->call_data;

  if (op->recv_initial_metadata) {
    calld->recv_initial_metadata = op->recv_initial_metadata;
    /* substitute our callback for the higher callback */
    calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready;
    op->recv_initial_metadata_ready = &calld->on_initial_md_ready;
  } else if (op->send_trailing_metadata) {
    grpc_metadata_batch_filter(op->send_trailing_metadata,
                               lr_trailing_md_filter, elem);
  }
  grpc_call_next_op(exec_ctx, elem, op);

  GPR_TIMER_END("lr_start_transport_stream_op", 0);
}
예제 #30
0
static void send_security_metadata(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
                                   grpc_transport_stream_op *op) {
  call_data *calld = elem->call_data;
  channel_data *chand = elem->channel_data;
  grpc_client_security_context *ctx =
      (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
  grpc_call_credentials *channel_call_creds =
      chand->security_connector->request_metadata_creds;
  int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);

  if (channel_call_creds == NULL && !call_creds_has_md) {
    /* Skip sending metadata altogether. */
    grpc_call_next_op(exec_ctx, elem, op);
    return;
  }

  if (channel_call_creds != NULL && call_creds_has_md) {
    calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
                                                          ctx->creds, NULL);
    if (calld->creds == NULL) {
      grpc_transport_stream_op_finish_with_failure(
          exec_ctx, op,
          grpc_error_set_int(
              GRPC_ERROR_CREATE(
                  "Incompatible credentials set on channel and call."),
              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED));
      return;
    }
  } else {
    calld->creds = grpc_call_credentials_ref(
        call_creds_has_md ? ctx->creds : channel_call_creds);
  }

  build_auth_metadata_context(&chand->security_connector->base,
                              chand->auth_context, calld);
  calld->op = *op; /* Copy op (originates from the caller's stack). */
  GPR_ASSERT(calld->pollent != NULL);
  grpc_call_credentials_get_request_metadata(
      exec_ctx, calld->creds, calld->pollent, calld->auth_md_context,
      on_credentials_metadata, elem);
}