Example #1
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(&exec_ctx, 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);
}
Example #2
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);
}
static void hs_on_recv(void *user_data, int success) {
  grpc_call_element *elem = user_data;
  call_data *calld = elem->call_data;
  if (success) {
    size_t i;
    size_t nops = calld->recv_ops->nops;
    grpc_stream_op *ops = calld->recv_ops->ops;
    for (i = 0; i < nops; i++) {
      grpc_stream_op *op = &ops[i];
      if (op->type != GRPC_OP_METADATA) continue;
      calld->got_initial_metadata = 1;
      grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
      /* Have we seen the required http2 transport headers?
         (:method, :scheme, content-type, with :path and :authority covered
         at the channel level right now) */
      if (calld->seen_post && calld->seen_scheme && calld->seen_te_trailers &&
          calld->seen_path && calld->seen_authority) {
        /* do nothing */
      } else {
        if (!calld->seen_path) {
          gpr_log(GPR_ERROR, "Missing :path header");
        }
        if (!calld->seen_authority) {
          gpr_log(GPR_ERROR, "Missing :authority header");
        }
        if (!calld->seen_post) {
          gpr_log(GPR_ERROR, "Missing :method header");
        }
        if (!calld->seen_scheme) {
          gpr_log(GPR_ERROR, "Missing :scheme header");
        }
        if (!calld->seen_te_trailers) {
          gpr_log(GPR_ERROR, "Missing te trailers header");
        }
        /* Error this call out */
        success = 0;
        grpc_call_element_send_cancel(elem);
      }
    }
  }
  calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
}
Example #4
0
File: server.c Project: An-mol/grpc
static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
                                            bool success) {
  grpc_call_element *elem = ptr;
  call_data *calld = elem->call_data;
  gpr_timespec op_deadline;

  grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, elem);
  op_deadline = calld->recv_initial_metadata->deadline;
  if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
    calld->deadline = op_deadline;
  }
  if (calld->host && calld->path) {
    /* do nothing */
  } else {
    success = 0;
  }

  calld->on_done_recv_initial_metadata->cb(
      exec_ctx, calld->on_done_recv_initial_metadata->cb_arg, success);
}
Example #5
0
static void on_md_processing_done(void *user_data,
                                  const grpc_metadata *consumed_md,
                                  size_t num_consumed_md, int success) {
  grpc_call_element *elem = user_data;
  call_data *calld = elem->call_data;

  if (success) {
    calld->consumed_md = consumed_md;
    calld->num_consumed_md = num_consumed_md;
    grpc_metadata_batch_filter(&calld->md_op->data.metadata, remove_consumed_md,
                               elem);
    calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
  } else {
    gpr_slice message = gpr_slice_from_copied_string(
        "Authentication metadata processing failed.");
    grpc_sopb_reset(calld->recv_ops);
    grpc_transport_stream_op_add_close(&calld->transport_op,
                                       GRPC_STATUS_UNAUTHENTICATED, &message);
    grpc_call_next_op(elem, &calld->transport_op);
  }
}
Example #6
0
static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data,
                                grpc_error *err) {
  grpc_call_element *elem = user_data;
  call_data *calld = elem->call_data;

  if (err == GRPC_ERROR_NONE) {
    recv_md_filter_args a;
    a.elem = elem;
    a.exec_ctx = exec_ctx;
    grpc_metadata_batch_filter(calld->recv_initial_metadata, recv_md_filter,
                               &a);
    if (calld->service_method == NULL) {
      err =
          grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header"));
    }
  } else {
    GRPC_ERROR_REF(err);
  }
  calld->ops_recv_initial_metadata_ready->cb(
      exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err);
  GRPC_ERROR_UNREF(err);
}
Example #7
0
static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
                                            grpc_error *error) {
  grpc_call_element *elem = ptr;
  call_data *calld = elem->call_data;
  gpr_timespec op_deadline;

  GRPC_ERROR_REF(error);
  grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, elem);
  op_deadline = calld->recv_initial_metadata->deadline;
  if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
    calld->deadline = op_deadline;
  }
  if (calld->host && calld->path) {
    /* do nothing */
  } else {
    GRPC_ERROR_UNREF(error);
    error =
        GRPC_ERROR_CREATE_REFERENCING("Missing :authority or :path", &error, 1);
  }

  grpc_exec_ctx_sched(exec_ctx, calld->on_done_recv_initial_metadata, error,
                      NULL);
}
Example #8
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;
  }
}
static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
  grpc_call_element *elem = user_data;
  call_data *calld = elem->call_data;
  if (success) {
    server_filter_args a;
    a.elem = elem;
    a.exec_ctx = exec_ctx;
    grpc_metadata_batch_filter(calld->recv_initial_metadata, server_filter, &a);
    /* Have we seen the required http2 transport headers?
       (:method, :scheme, content-type, with :path and :authority covered
       at the channel level right now) */
    if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers &&
        calld->seen_path && calld->seen_authority) {
      /* do nothing */
    } else {
      if (!calld->seen_path) {
        gpr_log(GPR_ERROR, "Missing :path header");
      }
      if (!calld->seen_authority) {
        gpr_log(GPR_ERROR, "Missing :authority header");
      }
      if (!calld->seen_method) {
        gpr_log(GPR_ERROR, "Missing :method header");
      }
      if (!calld->seen_scheme) {
        gpr_log(GPR_ERROR, "Missing :scheme header");
      }
      if (!calld->seen_te_trailers) {
        gpr_log(GPR_ERROR, "Missing te trailers header");
      }
      /* Error this call out */
      success = 0;
      grpc_call_element_send_cancel(exec_ctx, elem);
    }
  }
  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
}
Example #10
0
static void server_on_recv(void *ptr, int success) {
  grpc_call_element *elem = ptr;
  call_data *calld = elem->call_data;
  channel_data *chand = elem->channel_data;
  int remove_res;

  if (success && !calld->got_initial_metadata) {
    size_t i;
    size_t nops = calld->recv_ops->nops;
    grpc_stream_op *ops = calld->recv_ops->ops;
    for (i = 0; i < nops; i++) {
      grpc_stream_op *op = &ops[i];
      if (op->type != GRPC_OP_METADATA) continue;
      grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
      if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
        calld->deadline = op->data.metadata.deadline;
      }
      calld->got_initial_metadata = 1;
      start_new_rpc(elem);
      break;
    }
  }

  switch (*calld->recv_state) {
    case GRPC_STREAM_OPEN:
      break;
    case GRPC_STREAM_SEND_CLOSED:
      break;
    case GRPC_STREAM_RECV_CLOSED:
      gpr_mu_lock(&chand->server->mu_call);
      if (calld->state == NOT_STARTED) {
        calld->state = ZOMBIED;
        grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
        grpc_iomgr_add_callback(&calld->kill_zombie_closure);
      }
      gpr_mu_unlock(&chand->server->mu_call);
      break;
    case GRPC_STREAM_CLOSED:
      gpr_mu_lock(&chand->server->mu_call);
      if (calld->state == NOT_STARTED) {
        calld->state = ZOMBIED;
        grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
        grpc_iomgr_add_callback(&calld->kill_zombie_closure);
      } else if (calld->state == PENDING) {
        call_list_remove(calld, PENDING_START);
        calld->state = ZOMBIED;
        grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
        grpc_iomgr_add_callback(&calld->kill_zombie_closure);
      }
      remove_res = call_list_remove(calld, ALL_CALLS);
      gpr_mu_unlock(&chand->server->mu_call);
      gpr_mu_lock(&chand->server->mu_global);
      if (remove_res) {
        decrement_call_count(chand);
      }
      gpr_mu_unlock(&chand->server->mu_global);
      break;
  }

  calld->on_done_recv(calld->recv_user_data, success);
}
Example #11
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);
  }
}
Example #12
0
static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, int success) {
  batch_control *bctl = bctlp;
  grpc_call *call = bctl->call;
  grpc_call *child_call;
  grpc_call *next_child_call;

  gpr_mu_lock(&call->mu);
  if (bctl->send_initial_metadata) {
    grpc_metadata_batch_destroy(
        &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
  }
  if (bctl->send_message) {
    call->sending_message = 0;
  }
  if (bctl->send_final_op) {
    grpc_metadata_batch_destroy(
        &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
  }
  if (bctl->recv_initial_metadata) {
    grpc_metadata_batch *md =
        &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
    grpc_metadata_batch_filter(md, recv_initial_filter, call);

    if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
            0 &&
        !call->is_client) {
      GPR_TIMER_BEGIN("set_deadline_alarm", 0);
      set_deadline_alarm(exec_ctx, call, md->deadline);
      GPR_TIMER_END("set_deadline_alarm", 0);
    }
  }
  if (bctl->recv_final_op) {
    grpc_metadata_batch *md =
        &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
    grpc_metadata_batch_filter(md, recv_trailing_filter, call);

    if (call->have_alarm) {
      grpc_timer_cancel(exec_ctx, &call->alarm);
    }
    /* propagate cancellation to any interested children */
    child_call = call->first_child;
    if (child_call != NULL) {
      do {
        next_child_call = child_call->sibling_next;
        if (child_call->cancellation_is_inherited) {
          GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
          grpc_call_cancel(child_call, NULL);
          GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
        }
        child_call = next_child_call;
      } while (child_call != call->first_child);
    }

    if (call->is_client) {
      get_final_status(call, set_status_value_directly,
                       call->final_op.client.status);
      get_final_details(call, call->final_op.client.status_details,
                        call->final_op.client.status_details_capacity);
    } else {
      get_final_status(call, set_cancelled_value,
                       call->final_op.server.cancelled);
    }

    success = 1;
  }
  bctl->success = success != 0;
  gpr_mu_unlock(&call->mu);
  if (gpr_unref(&bctl->steps_to_complete)) {
    post_batch_completion(exec_ctx, bctl);
  }
}
Example #13
0
void grpc_metadata_batch_clear(grpc_metadata_batch *batch) {
  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
  grpc_metadata_batch_filter(batch, no_metadata_for_you, NULL);
}
Example #14
0
static void server_on_recv(grpc_exec_ctx *exec_ctx, void *ptr, int success) {
  grpc_call_element *elem = ptr;
  call_data *calld = elem->call_data;
  gpr_timespec op_deadline;

  if (success && !calld->got_initial_metadata) {
    size_t i;
    size_t nops = calld->recv_ops->nops;
    grpc_stream_op *ops = calld->recv_ops->ops;
    for (i = 0; i < nops; i++) {
      grpc_stream_op *op = &ops[i];
      if (op->type != GRPC_OP_METADATA) continue;
      grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
      op_deadline = op->data.metadata.deadline;
      if (0 !=
          gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
        calld->deadline = op->data.metadata.deadline;
      }
      if (calld->host && calld->path) {
        calld->got_initial_metadata = 1;
        start_new_rpc(exec_ctx, elem);
      }
      break;
    }
  }

  switch (*calld->recv_state) {
    case GRPC_STREAM_OPEN:
      break;
    case GRPC_STREAM_SEND_CLOSED:
      break;
    case GRPC_STREAM_RECV_CLOSED:
      gpr_mu_lock(&calld->mu_state);
      if (calld->state == NOT_STARTED) {
        calld->state = ZOMBIED;
        gpr_mu_unlock(&calld->mu_state);
        grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
        grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, 1);
      } else {
        gpr_mu_unlock(&calld->mu_state);
      }
      break;
    case GRPC_STREAM_CLOSED:
      gpr_mu_lock(&calld->mu_state);
      if (calld->state == NOT_STARTED) {
        calld->state = ZOMBIED;
        gpr_mu_unlock(&calld->mu_state);
        grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
        grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, 1);
      } else if (calld->state == PENDING) {
        calld->state = ZOMBIED;
        gpr_mu_unlock(&calld->mu_state);
        /* zombied call will be destroyed when it's removed from the pending
           queue... later */
      } else {
        gpr_mu_unlock(&calld->mu_state);
      }
      break;
  }

  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
}