示例#1
0
文件: call.c 项目: caojiguang/grpc
grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
                            const void *server_transport_data,
                            grpc_mdelem **add_initial_metadata,
                            size_t add_initial_metadata_count,
                            gpr_timespec send_deadline) {
  size_t i;
  grpc_transport_op initial_op;
  grpc_transport_op *initial_op_ptr = NULL;
  grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
  grpc_call *call =
      gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
  memset(call, 0, sizeof(grpc_call));
  gpr_mu_init(&call->mu);
  call->channel = channel;
  call->cq = cq;
  call->is_client = server_transport_data == NULL;
  for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
    call->request_set[i] = REQSET_EMPTY;
  }
  if (call->is_client) {
    call->request_set[GRPC_IOREQ_SEND_TRAILING_METADATA] = REQSET_DONE;
    call->request_set[GRPC_IOREQ_SEND_STATUS] = REQSET_DONE;
  }
  GPR_ASSERT(add_initial_metadata_count < MAX_SEND_INITIAL_METADATA_COUNT);
  for (i = 0; i < add_initial_metadata_count; i++) {
    call->send_initial_metadata[i].md = add_initial_metadata[i];
  }
  call->send_initial_metadata_count = add_initial_metadata_count;
  call->send_deadline = send_deadline;
  grpc_channel_internal_ref(channel);
  call->metadata_context = grpc_channel_get_metadata_context(channel);
  grpc_sopb_init(&call->send_ops);
  grpc_sopb_init(&call->recv_ops);
  gpr_slice_buffer_init(&call->incoming_message);
  /* dropped in destroy */
  gpr_ref_init(&call->internal_refcount, 1);
  /* server hack: start reads immediately so we can get initial metadata.
     TODO(ctiller): figure out a cleaner solution */
  if (!call->is_client) {
    memset(&initial_op, 0, sizeof(initial_op));
    initial_op.recv_ops = &call->recv_ops;
    initial_op.recv_state = &call->recv_state;
    initial_op.on_done_recv = call_on_done_recv;
    initial_op.recv_user_data = call;
    initial_op.context = call->context;
    call->receiving = 1;
    GRPC_CALL_INTERNAL_REF(call, "receiving");
    initial_op_ptr = &initial_op;
  }
  grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr,
                       CALL_STACK_FROM_CALL(call));
  if (gpr_time_cmp(send_deadline, gpr_inf_future) != 0) {
    set_deadline_alarm(call, send_deadline);
  }
  return call;
}
示例#2
0
static void run_test(void (*test)(), const char *name) {
  gpr_log(GPR_INFO, "RUN TEST: %s", name);
  g_mdctx = grpc_mdctx_create_with_seed(0);
  grpc_chttp2_hpack_compressor_init(&g_compressor, g_mdctx);
  grpc_sopb_init(&g_sopb);
  test();
  grpc_chttp2_hpack_compressor_destroy(&g_compressor);
  grpc_mdctx_unref(g_mdctx);
  grpc_sopb_destroy(&g_sopb);
}
示例#3
0
static int init_stream(grpc_transport *gt, grpc_stream *gs,
                       const void *server_data,
                       grpc_transport_stream_op *initial_op) {
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;

  memset(s, 0, sizeof(*s));

  grpc_chttp2_incoming_metadata_buffer_init(&s->parsing.incoming_metadata);
  grpc_chttp2_incoming_metadata_buffer_init(&s->global.incoming_metadata);
  grpc_sopb_init(&s->writing.sopb);
  grpc_sopb_init(&s->global.incoming_sopb);
  grpc_chttp2_data_parser_init(&s->parsing.data_parser);

  REF_TRANSPORT(t, "stream");

  lock(t);
  grpc_chttp2_register_stream(t, s);
  if (server_data) {
    GPR_ASSERT(t->parsing_active);
    s->global.id = (gpr_uint32)(gpr_uintptr)server_data;
    s->global.outgoing_window =
        t->global.settings[GRPC_PEER_SETTINGS]
                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
    s->global.max_recv_bytes = 
        s->parsing.incoming_window = 
        s->global.incoming_window =
        t->global.settings[GRPC_SENT_SETTINGS]
                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
    *t->accepting_stream = s;
    grpc_chttp2_stream_map_add(&t->parsing_stream_map, s->global.id, s);
    s->global.in_stream_map = 1;
  }

  if (initial_op) perform_stream_op_locked(&t->global, &s->global, initial_op);
  unlock(t);

  return 0;
}
示例#4
0
/** Assembles a new grpc_stream_op_buffer with the compressed slices, modifying
 * the associated GRPC_OP_BEGIN_MESSAGE accordingly (new compressed length,
 * flags indicating compression is in effect) and replaces \a send_ops with it.
 * */
static void finish_compressed_sopb(grpc_stream_op_buffer *send_ops,
                                   grpc_call_element *elem) {
  size_t i;
  call_data *calld = elem->call_data;
  int new_slices_added = 0; /* GPR_FALSE */
  grpc_metadata_batch metadata;
  grpc_stream_op_buffer new_send_ops;
  grpc_sopb_init(&new_send_ops);

  for (i = 0; i < send_ops->nops; i++) {
    grpc_stream_op *sop = &send_ops->ops[i];
    switch (sop->type) {
      case GRPC_OP_BEGIN_MESSAGE:
        GPR_ASSERT(calld->slices.length <= GPR_UINT32_MAX);
        grpc_sopb_add_begin_message(
            &new_send_ops, (gpr_uint32)calld->slices.length,
            sop->data.begin_message.flags | GRPC_WRITE_INTERNAL_COMPRESS);
        break;
      case GRPC_OP_SLICE:
        /* Once we reach the slices section of the original buffer, simply add
         * all the new (compressed) slices. We obviously want to do this only
         * once, hence the "new_slices_added" guard. */
        if (!new_slices_added) {
          size_t j;
          for (j = 0; j < calld->slices.count; ++j) {
            grpc_sopb_add_slice(&new_send_ops,
                                gpr_slice_ref(calld->slices.slices[j]));
          }
          new_slices_added = 1; /* GPR_TRUE */
        }
        break;
      case GRPC_OP_METADATA:
        /* move the metadata to the new buffer. */
        grpc_metadata_batch_move(&metadata, &sop->data.metadata);
        grpc_sopb_add_metadata(&new_send_ops, metadata);
        break;
      case GRPC_NO_OP:
        break;
    }
  }
  grpc_sopb_swap(send_ops, &new_send_ops);
  grpc_sopb_destroy(&new_send_ops);
}
示例#5
0
static void test_decode_random_headers_inner(int max_len) {
  int i;
  test_decode_random_header_state st;
  gpr_slice_buffer output;
  gpr_slice merged;
  grpc_stream_op_buffer encops;
  grpc_chttp2_hpack_parser parser;

  grpc_chttp2_hpack_parser_init(&parser, g_mdctx);
  grpc_sopb_init(&encops);

  gpr_log(GPR_INFO, "max_len = %d", max_len);

  for (i = 0; i < 10000; i++) {
    randstr(st.key, max_len);
    randstr(st.value, max_len);

    add_sopb_headers(1, st.key, st.value);
    gpr_slice_buffer_init(&output);
    GPR_ASSERT(0 ==
               grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, 0, &encops));
    grpc_chttp2_encode(encops.ops, encops.nops, 0, 0xdeadbeef, &g_compressor,
                       &output);
    encops.nops = 0;
    merged = grpc_slice_merge(output.slices, output.count);
    gpr_slice_buffer_destroy(&output);

    st.got_hdr = 0;
    parser.on_header = chk_hdr;
    parser.on_header_user_data = &st;
    grpc_chttp2_hpack_parser_parse(&parser, GPR_SLICE_START_PTR(merged) + 9,
                                   GPR_SLICE_END_PTR(merged));
    GPR_ASSERT(st.got_hdr);

    gpr_slice_unref(merged);
  }

  grpc_chttp2_hpack_parser_destroy(&parser);
  grpc_sopb_destroy(&encops);
}
示例#6
0
/* verify that the output generated by encoding the stream matches the
   hexstring passed in */
static void verify_sopb(size_t window_available, int eof,
                        size_t expect_window_used, const char *expected) {
  gpr_slice_buffer output;
  grpc_stream_op_buffer encops;
  gpr_slice merged;
  gpr_slice expect = parse_hexstring(expected);
  gpr_slice_buffer_init(&output);
  grpc_sopb_init(&encops);
  GPR_ASSERT(expect_window_used ==
             grpc_chttp2_preencode(g_sopb.ops, &g_sopb.nops, window_available,
                                   &encops));
  grpc_chttp2_encode(encops.ops, encops.nops, eof, 0xdeadbeef, &g_compressor,
                     &output);
  encops.nops = 0;
  merged = grpc_slice_merge(output.slices, output.count);
  gpr_slice_buffer_destroy(&output);
  grpc_sopb_destroy(&encops);

  if (0 != gpr_slice_cmp(merged, expect)) {
    char *expect_str =
        gpr_hexdump((char *)GPR_SLICE_START_PTR(expect),
                    GPR_SLICE_LENGTH(expect), GPR_HEXDUMP_PLAINTEXT);
    char *got_str =
        gpr_hexdump((char *)GPR_SLICE_START_PTR(merged),
                    GPR_SLICE_LENGTH(merged), GPR_HEXDUMP_PLAINTEXT);
    gpr_log(GPR_ERROR, "mismatched output for %s", expected);
    gpr_log(GPR_ERROR, "EXPECT: %s", expect_str);
    gpr_log(GPR_ERROR, "GOT:    %s", got_str);
    gpr_free(expect_str);
    gpr_free(got_str);
    g_failure = 1;
  }

  gpr_slice_unref(merged);
  gpr_slice_unref(expect);
}
示例#7
0
grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
    grpc_chttp2_data_parser *parser) {
  parser->state = GRPC_CHTTP2_DATA_FH_0;
  grpc_sopb_init(&parser->incoming_sopb);
  return GRPC_CHTTP2_PARSE_OK;
}
示例#8
0
int main(int argc, char **argv) {
  /* some basic test data */
  gpr_slice test_slice_1 = gpr_slice_malloc(1);
  gpr_slice test_slice_2 = gpr_slice_malloc(2);
  gpr_slice test_slice_3 = gpr_slice_malloc(3);
  gpr_slice test_slice_4 = gpr_slice_malloc(4);
  unsigned i;

  grpc_stream_op_buffer buf;
  grpc_stream_op_buffer buf2;

  grpc_test_init(argc, argv);
  /* initialize one of our buffers */
  grpc_sopb_init(&buf);
  /* it should start out empty */
  GPR_ASSERT(buf.nops == 0);

  /* add some data to the buffer */
  grpc_sopb_add_begin_message(&buf, 1, 2);
  grpc_sopb_add_slice(&buf, test_slice_1);
  grpc_sopb_add_slice(&buf, test_slice_2);
  grpc_sopb_add_slice(&buf, test_slice_3);
  grpc_sopb_add_slice(&buf, test_slice_4);
  grpc_sopb_add_no_op(&buf);

  /* verify that the data went in ok */
  GPR_ASSERT(buf.nops == 6);
  GPR_ASSERT(buf.ops[0].type == GRPC_OP_BEGIN_MESSAGE);
  GPR_ASSERT(buf.ops[0].data.begin_message.length == 1);
  GPR_ASSERT(buf.ops[0].data.begin_message.flags == 2);
  GPR_ASSERT(buf.ops[1].type == GRPC_OP_SLICE);
  assert_slices_equal(buf.ops[1].data.slice, test_slice_1);
  GPR_ASSERT(buf.ops[2].type == GRPC_OP_SLICE);
  assert_slices_equal(buf.ops[2].data.slice, test_slice_2);
  GPR_ASSERT(buf.ops[3].type == GRPC_OP_SLICE);
  assert_slices_equal(buf.ops[3].data.slice, test_slice_3);
  GPR_ASSERT(buf.ops[4].type == GRPC_OP_SLICE);
  assert_slices_equal(buf.ops[4].data.slice, test_slice_4);
  GPR_ASSERT(buf.ops[5].type == GRPC_NO_OP);

  /* initialize the second buffer */
  grpc_sopb_init(&buf2);
  /* add a no-op, and then the original buffer */
  grpc_sopb_add_no_op(&buf2);
  grpc_sopb_append(&buf2, buf.ops, buf.nops);
  /* should be one element bigger than the original */
  GPR_ASSERT(buf2.nops == buf.nops + 1);
  GPR_ASSERT(buf2.ops[0].type == GRPC_NO_OP);
  /* and the tail should be the same */
  for (i = 0; i < buf.nops; i++) {
    GPR_ASSERT(buf2.ops[i + 1].type == buf.ops[i].type);
  }

  /* destroy the buffers */
  grpc_sopb_destroy(&buf);
  grpc_sopb_destroy(&buf2);

  gpr_slice_unref(test_slice_1);
  gpr_slice_unref(test_slice_2);
  gpr_slice_unref(test_slice_3);
  gpr_slice_unref(test_slice_4);

  return 0;
}