static void destroy_call(void *call, int ignored_success) { size_t i; grpc_call *c = call; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); gpr_mu_destroy(&c->mu); for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (c->status[i].details) { grpc_mdstr_unref(c->status[i].details); } } for (i = 0; i < c->owned_metadata_count; i++) { grpc_mdelem_unref(c->owned_metadata[i]); } gpr_free(c->owned_metadata); for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) { gpr_free(c->buffered_metadata[i].metadata); } for (i = 0; i < c->send_initial_metadata_count; i++) { grpc_mdelem_unref(c->send_initial_metadata[i].md); } for (i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (c->destroy_context[i]) { c->destroy_context[i](c->context[i]); } } grpc_sopb_destroy(&c->send_ops); grpc_sopb_destroy(&c->recv_ops); grpc_bbq_destroy(&c->incoming_queue); gpr_slice_buffer_destroy(&c->incoming_message); gpr_free(c); }
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; int i; gpr_mu_lock(&t->mu); GPR_ASSERT(s->global.published_state == GRPC_STREAM_CLOSED || s->global.id == 0); GPR_ASSERT(!s->global.in_stream_map); if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) { close_transport_locked(exec_ctx, t); } if (!t->parsing_active && s->global.id) { GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map, s->global.id) == NULL); } grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global); grpc_chttp2_list_remove_writable_stream(&t->global, &s->global); gpr_mu_unlock(&t->mu); for (i = 0; i < STREAM_LIST_COUNT; i++) { if (s->included[i]) { gpr_log(GPR_ERROR, "%s stream %d still included in list %d", t->global.is_client ? "client" : "server", s->global.id, i); abort(); } } GPR_ASSERT(s->global.outgoing_sopb == NULL); GPR_ASSERT(s->global.publish_sopb == NULL); grpc_sopb_destroy(&s->writing.sopb); grpc_sopb_destroy(&s->global.incoming_sopb); grpc_chttp2_data_parser_destroy(&s->parsing.data_parser); grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.incoming_metadata); grpc_chttp2_incoming_metadata_buffer_destroy(&s->global.incoming_metadata); grpc_chttp2_incoming_metadata_live_op_buffer_end( &s->global.outstanding_metadata); UNREF_TRANSPORT(exec_ctx, t, "stream"); }
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); }
static void destroy_stream(grpc_transport *gt, grpc_stream *gs) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; int i; gpr_mu_lock(&t->mu); GPR_ASSERT(s->global.published_state == GRPC_STREAM_CLOSED || s->global.id == 0); GPR_ASSERT(!s->global.in_stream_map); grpc_chttp2_unregister_stream(t, s); if (!t->parsing_active && s->global.id) { GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map, s->global.id) == NULL); } grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global); grpc_chttp2_list_remove_writable_window_update_stream(&t->global, &s->global); gpr_mu_unlock(&t->mu); for (i = 0; i < STREAM_LIST_COUNT; i++) { GPR_ASSERT(!s->included[i]); } GPR_ASSERT(s->global.outgoing_sopb == NULL); GPR_ASSERT(s->global.publish_sopb == NULL); grpc_sopb_destroy(&s->writing.sopb); grpc_sopb_destroy(&s->global.incoming_sopb); grpc_chttp2_data_parser_destroy(&s->parsing.data_parser); grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.incoming_metadata); grpc_chttp2_incoming_metadata_buffer_destroy(&s->global.incoming_metadata); grpc_chttp2_incoming_metadata_live_op_buffer_end( &s->global.outstanding_metadata); UNREF_TRANSPORT(t, "stream"); }
/** 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); }
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); }
/* 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); }
void grpc_chttp2_data_parser_destroy(grpc_chttp2_data_parser *parser) { grpc_sopb_destroy(&parser->incoming_sopb); }
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; }