Merge branch 'oops-i-split-it-again' into tis-but-thy-name

pull/2303/head
Craig Tiller 10 years ago
commit 3b1847c528
  1. 12
      BUILD
  2. 8
      Makefile
  3. 6
      build.json
  4. 8
      gRPC.podspec
  5. 2
      include/grpc/support/slice_buffer.h
  6. 10
      src/core/channel/client_channel.c
  7. 17
      src/core/channel/http_client_filter.c
  8. 15
      src/core/channel/http_server_filter.c
  9. 4
      src/core/iomgr/iomgr.h
  10. 16
      src/core/support/slice_buffer.c
  11. 49
      src/core/surface/call.c
  12. 6
      src/core/surface/lame_client.c
  13. 12
      src/core/surface/server.c
  14. 2
      src/core/transport/chttp2/alpn.h
  15. 76
      src/core/transport/chttp2/bin_encoder.c
  16. 2
      src/core/transport/chttp2/bin_encoder.h
  17. 22
      src/core/transport/chttp2/frame.h
  18. 27
      src/core/transport/chttp2/frame_data.c
  19. 5
      src/core/transport/chttp2/frame_data.h
  20. 30
      src/core/transport/chttp2/frame_goaway.c
  21. 5
      src/core/transport/chttp2/frame_goaway.h
  22. 20
      src/core/transport/chttp2/frame_ping.c
  23. 5
      src/core/transport/chttp2/frame_ping.h
  24. 21
      src/core/transport/chttp2/frame_rst_stream.c
  25. 5
      src/core/transport/chttp2/frame_rst_stream.h
  26. 15
      src/core/transport/chttp2/frame_settings.c
  27. 5
      src/core/transport/chttp2/frame_settings.h
  28. 23
      src/core/transport/chttp2/frame_window_update.c
  29. 5
      src/core/transport/chttp2/frame_window_update.h
  30. 52
      src/core/transport/chttp2/hpack_parser.c
  31. 6
      src/core/transport/chttp2/hpack_parser.h
  32. 125
      src/core/transport/chttp2/hpack_table.c
  33. 2
      src/core/transport/chttp2/hpack_table.h
  34. 2
      src/core/transport/chttp2/http2_errors.h
  35. 323
      src/core/transport/chttp2/huffsyms.c
  36. 2
      src/core/transport/chttp2/huffsyms.h
  37. 177
      src/core/transport/chttp2/incoming_metadata.c
  38. 80
      src/core/transport/chttp2/incoming_metadata.h
  39. 652
      src/core/transport/chttp2/internal.h
  40. 813
      src/core/transport/chttp2/parsing.c
  41. 2
      src/core/transport/chttp2/status_conversion.h
  42. 2
      src/core/transport/chttp2/stream_encoder.h
  43. 353
      src/core/transport/chttp2/stream_lists.c
  44. 44
      src/core/transport/chttp2/stream_map.c
  45. 6
      src/core/transport/chttp2/stream_map.h
  46. 2
      src/core/transport/chttp2/timeout_encoding.h
  47. 25
      src/core/transport/chttp2/varint.h
  48. 215
      src/core/transport/chttp2/writing.c
  49. 2368
      src/core/transport/chttp2_transport.c
  50. 2
      src/core/transport/chttp2_transport.h
  51. 14
      src/core/transport/stream_op.c
  52. 2
      src/core/transport/stream_op.h
  53. 11
      src/core/transport/transport.c
  54. 16
      src/core/transport/transport.h
  55. 3
      src/core/transport/transport_impl.h
  56. 2
      test/core/end2end/tests/invoke_large_request.c
  57. 33
      tools/codegen/core/gen_hpack_tables.c
  58. 6
      tools/doxygen/Doxyfile.core.internal
  59. 10
      vsprojects/grpc/grpc.vcxproj
  60. 18
      vsprojects/grpc/grpc.vcxproj.filters
  61. 10
      vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
  62. 18
      vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters

12
BUILD

@ -227,6 +227,8 @@ cc_library(
"src/core/transport/chttp2/hpack_table.h",
"src/core/transport/chttp2/http2_errors.h",
"src/core/transport/chttp2/huffsyms.h",
"src/core/transport/chttp2/incoming_metadata.h",
"src/core/transport/chttp2/internal.h",
"src/core/transport/chttp2/status_conversion.h",
"src/core/transport/chttp2/stream_encoder.h",
"src/core/transport/chttp2/stream_map.h",
@ -352,11 +354,15 @@ cc_library(
"src/core/transport/chttp2/hpack_parser.c",
"src/core/transport/chttp2/hpack_table.c",
"src/core/transport/chttp2/huffsyms.c",
"src/core/transport/chttp2/incoming_metadata.c",
"src/core/transport/chttp2/parsing.c",
"src/core/transport/chttp2/status_conversion.c",
"src/core/transport/chttp2/stream_encoder.c",
"src/core/transport/chttp2/stream_lists.c",
"src/core/transport/chttp2/stream_map.c",
"src/core/transport/chttp2/timeout_encoding.c",
"src/core/transport/chttp2/varint.c",
"src/core/transport/chttp2/writing.c",
"src/core/transport/chttp2_transport.c",
"src/core/transport/metadata.c",
"src/core/transport/stream_op.c",
@ -469,6 +475,8 @@ cc_library(
"src/core/transport/chttp2/hpack_table.h",
"src/core/transport/chttp2/http2_errors.h",
"src/core/transport/chttp2/huffsyms.h",
"src/core/transport/chttp2/incoming_metadata.h",
"src/core/transport/chttp2/internal.h",
"src/core/transport/chttp2/status_conversion.h",
"src/core/transport/chttp2/stream_encoder.h",
"src/core/transport/chttp2/stream_map.h",
@ -572,11 +580,15 @@ cc_library(
"src/core/transport/chttp2/hpack_parser.c",
"src/core/transport/chttp2/hpack_table.c",
"src/core/transport/chttp2/huffsyms.c",
"src/core/transport/chttp2/incoming_metadata.c",
"src/core/transport/chttp2/parsing.c",
"src/core/transport/chttp2/status_conversion.c",
"src/core/transport/chttp2/stream_encoder.c",
"src/core/transport/chttp2/stream_lists.c",
"src/core/transport/chttp2/stream_map.c",
"src/core/transport/chttp2/timeout_encoding.c",
"src/core/transport/chttp2/varint.c",
"src/core/transport/chttp2/writing.c",
"src/core/transport/chttp2_transport.c",
"src/core/transport/metadata.c",
"src/core/transport/stream_op.c",

@ -3104,11 +3104,15 @@ LIBGRPC_SRC = \
src/core/transport/chttp2/hpack_parser.c \
src/core/transport/chttp2/hpack_table.c \
src/core/transport/chttp2/huffsyms.c \
src/core/transport/chttp2/incoming_metadata.c \
src/core/transport/chttp2/parsing.c \
src/core/transport/chttp2/status_conversion.c \
src/core/transport/chttp2/stream_encoder.c \
src/core/transport/chttp2/stream_lists.c \
src/core/transport/chttp2/stream_map.c \
src/core/transport/chttp2/timeout_encoding.c \
src/core/transport/chttp2/varint.c \
src/core/transport/chttp2/writing.c \
src/core/transport/chttp2_transport.c \
src/core/transport/metadata.c \
src/core/transport/stream_op.c \
@ -3358,11 +3362,15 @@ LIBGRPC_UNSECURE_SRC = \
src/core/transport/chttp2/hpack_parser.c \
src/core/transport/chttp2/hpack_table.c \
src/core/transport/chttp2/huffsyms.c \
src/core/transport/chttp2/incoming_metadata.c \
src/core/transport/chttp2/parsing.c \
src/core/transport/chttp2/status_conversion.c \
src/core/transport/chttp2/stream_encoder.c \
src/core/transport/chttp2/stream_lists.c \
src/core/transport/chttp2/stream_map.c \
src/core/transport/chttp2/timeout_encoding.c \
src/core/transport/chttp2/varint.c \
src/core/transport/chttp2/writing.c \
src/core/transport/chttp2_transport.c \
src/core/transport/metadata.c \
src/core/transport/stream_op.c \

@ -188,6 +188,8 @@
"src/core/transport/chttp2/hpack_table.h",
"src/core/transport/chttp2/http2_errors.h",
"src/core/transport/chttp2/huffsyms.h",
"src/core/transport/chttp2/incoming_metadata.h",
"src/core/transport/chttp2/internal.h",
"src/core/transport/chttp2/status_conversion.h",
"src/core/transport/chttp2/stream_encoder.h",
"src/core/transport/chttp2/stream_map.h",
@ -291,11 +293,15 @@
"src/core/transport/chttp2/hpack_parser.c",
"src/core/transport/chttp2/hpack_table.c",
"src/core/transport/chttp2/huffsyms.c",
"src/core/transport/chttp2/incoming_metadata.c",
"src/core/transport/chttp2/parsing.c",
"src/core/transport/chttp2/status_conversion.c",
"src/core/transport/chttp2/stream_encoder.c",
"src/core/transport/chttp2/stream_lists.c",
"src/core/transport/chttp2/stream_map.c",
"src/core/transport/chttp2/timeout_encoding.c",
"src/core/transport/chttp2/varint.c",
"src/core/transport/chttp2/writing.c",
"src/core/transport/chttp2_transport.c",
"src/core/transport/metadata.c",
"src/core/transport/stream_op.c",

@ -229,6 +229,8 @@ Pod::Spec.new do |s|
'src/core/transport/chttp2/hpack_table.h',
'src/core/transport/chttp2/http2_errors.h',
'src/core/transport/chttp2/huffsyms.h',
'src/core/transport/chttp2/incoming_metadata.h',
'src/core/transport/chttp2/internal.h',
'src/core/transport/chttp2/status_conversion.h',
'src/core/transport/chttp2/stream_encoder.h',
'src/core/transport/chttp2/stream_map.h',
@ -361,11 +363,15 @@ Pod::Spec.new do |s|
'src/core/transport/chttp2/hpack_parser.c',
'src/core/transport/chttp2/hpack_table.c',
'src/core/transport/chttp2/huffsyms.c',
'src/core/transport/chttp2/incoming_metadata.c',
'src/core/transport/chttp2/parsing.c',
'src/core/transport/chttp2/status_conversion.c',
'src/core/transport/chttp2/stream_encoder.c',
'src/core/transport/chttp2/stream_lists.c',
'src/core/transport/chttp2/stream_map.c',
'src/core/transport/chttp2/timeout_encoding.c',
'src/core/transport/chttp2/varint.c',
'src/core/transport/chttp2/writing.c',
'src/core/transport/chttp2_transport.c',
'src/core/transport/metadata.c',
'src/core/transport/stream_op.c',
@ -477,6 +483,8 @@ Pod::Spec.new do |s|
'src/core/transport/chttp2/hpack_table.h',
'src/core/transport/chttp2/http2_errors.h',
'src/core/transport/chttp2/huffsyms.h',
'src/core/transport/chttp2/incoming_metadata.h',
'src/core/transport/chttp2/internal.h',
'src/core/transport/chttp2/status_conversion.h',
'src/core/transport/chttp2/stream_encoder.h',
'src/core/transport/chttp2/stream_map.h',

@ -84,6 +84,8 @@ void gpr_slice_buffer_pop(gpr_slice_buffer *sb);
void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb);
/* swap the contents of two slice buffers */
void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b);
/* move all of the elements of src into dst */
void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst);
#ifdef __cplusplus
}

@ -159,7 +159,7 @@ static void handle_op_after_cancellation(grpc_call_element *elem,
channel_data *chand = elem->channel_data;
if (op->send_ops) {
grpc_stream_ops_unref_owned_objects(op->send_ops->ops, op->send_ops->nops);
op->on_done_send(op->send_user_data, 0);
op->on_done_send->cb(op->on_done_send->cb_arg, 0);
}
if (op->recv_ops) {
char status[GPR_LTOA_MIN_BUFSIZE];
@ -178,10 +178,10 @@ static void handle_op_after_cancellation(grpc_call_element *elem,
mdb.deadline = gpr_inf_future;
grpc_sopb_add_metadata(op->recv_ops, mdb);
*op->recv_state = GRPC_STREAM_CLOSED;
op->on_done_recv(op->recv_user_data, 1);
op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
}
if (op->on_consumed) {
op->on_consumed(op->on_consumed_user_data, 0);
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
}
}
@ -352,17 +352,15 @@ static void cc_start_transport_op(grpc_call_element *elem,
calld->s.waiting_op.send_ops = op->send_ops;
calld->s.waiting_op.is_last_send = op->is_last_send;
calld->s.waiting_op.on_done_send = op->on_done_send;
calld->s.waiting_op.send_user_data = op->send_user_data;
}
if (op->recv_ops) {
calld->s.waiting_op.recv_ops = op->recv_ops;
calld->s.waiting_op.recv_state = op->recv_state;
calld->s.waiting_op.on_done_recv = op->on_done_recv;
calld->s.waiting_op.recv_user_data = op->recv_user_data;
}
gpr_mu_unlock(&chand->mu);
if (op->on_consumed) {
op->on_consumed(op->on_consumed_user_data, 0);
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
}
}
break;

@ -43,8 +43,13 @@ typedef struct call_data {
int got_initial_metadata;
grpc_stream_op_buffer *recv_ops;
void (*on_done_recv)(void *user_data, int success);
void *recv_user_data;
/** Closure to call when finished with the hc_on_recv hook */
grpc_iomgr_closure *on_done_recv;
/** Receive closures are chained: we inject this closure as the on_done_recv
up-call on transport_op, and remember to call our on_done_recv member
after handling it. */
grpc_iomgr_closure hc_on_recv;
} call_data;
typedef struct channel_data {
@ -84,7 +89,7 @@ static void hc_on_recv(void *user_data, int success) {
grpc_metadata_batch_filter(&op->data.metadata, client_filter, elem);
}
}
calld->on_done_recv(calld->recv_user_data, success);
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
}
static void hc_mutate_op(grpc_call_element *elem,
@ -118,9 +123,7 @@ static void hc_mutate_op(grpc_call_element *elem,
/* substitute our callback for the higher callback */
calld->recv_ops = op->recv_ops;
calld->on_done_recv = op->on_done_recv;
calld->recv_user_data = op->recv_user_data;
op->on_done_recv = hc_on_recv;
op->recv_user_data = elem;
op->on_done_recv = &calld->hc_on_recv;
}
}
@ -155,6 +158,8 @@ static void init_call_elem(grpc_call_element *elem,
call_data *calld = elem->call_data;
calld->sent_initial_metadata = 0;
calld->got_initial_metadata = 0;
calld->on_done_recv = NULL;
grpc_iomgr_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
if (initial_op) hc_mutate_op(elem, initial_op);
}

@ -47,8 +47,12 @@ typedef struct call_data {
grpc_linked_mdelem status;
grpc_stream_op_buffer *recv_ops;
void (*on_done_recv)(void *user_data, int success);
void *recv_user_data;
/** Closure to call when finished with the hs_on_recv hook */
grpc_iomgr_closure *on_done_recv;
/** Receive closures are chained: we inject this closure as the on_done_recv
up-call on transport_op, and remember to call our on_done_recv member
after handling it. */
grpc_iomgr_closure hs_on_recv;
} call_data;
typedef struct channel_data {
@ -174,7 +178,7 @@ static void hs_on_recv(void *user_data, int success) {
}
}
}
calld->on_done_recv(calld->recv_user_data, success);
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
}
static void hs_mutate_op(grpc_call_element *elem,
@ -201,9 +205,7 @@ static void hs_mutate_op(grpc_call_element *elem,
/* substitute our callback for the higher callback */
calld->recv_ops = op->recv_ops;
calld->on_done_recv = op->on_done_recv;
calld->recv_user_data = op->recv_user_data;
op->on_done_recv = hs_on_recv;
op->recv_user_data = elem;
op->on_done_recv = &calld->hs_on_recv;
}
}
@ -239,6 +241,7 @@ static void init_call_elem(grpc_call_element *elem,
call_data *calld = elem->call_data;
/* initialize members */
memset(calld, 0, sizeof(*calld));
grpc_iomgr_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
if (initial_op) hs_mutate_op(elem, initial_op);
}

@ -73,4 +73,8 @@ void grpc_iomgr_shutdown(void);
* Can be called from within a callback or from anywhere else */
void grpc_iomgr_add_callback(grpc_iomgr_closure *closure);
/** As per grpc_iomgr_add_callback, with the ability to set the success
argument. */
void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success);
#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */

@ -190,3 +190,19 @@ void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) {
GPR_SWAP(gpr_slice *, a->slices, b->slices);
}
}
void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst) {
/* anything to move? */
if (src->count == 0) {
return;
}
/* anything in dst? */
if (dst->count == 0) {
gpr_slice_buffer_swap(src, dst);
return;
}
/* both buffers have data - copy, and reset src */
gpr_slice_buffer_addn(dst, src->slices, src->count);
src->count = 0;
src->length = 0;
}

@ -150,6 +150,8 @@ struct grpc_call {
gpr_uint8 receiving;
/* are we currently completing requests */
gpr_uint8 completing;
/** has grpc_call_destroy been called */
gpr_uint8 destroy_called;
/* pairs with completed_requests */
gpr_uint8 num_completed_requests;
/* are we currently reading a message? */
@ -240,6 +242,9 @@ struct grpc_call {
gpr_uint32 incoming_message_length;
gpr_uint32 incoming_message_flags;
grpc_iomgr_closure destroy_closure;
grpc_iomgr_closure on_done_recv;
grpc_iomgr_closure on_done_send;
grpc_iomgr_closure on_done_bind;
};
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
@ -258,6 +263,7 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *metadata);
static void finish_read_ops(grpc_call *call);
static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status,
const char *description);
static void finished_loose_op(void *call, int success);
static void lock(grpc_call *call);
static void unlock(grpc_call *call);
@ -301,16 +307,18 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
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);
grpc_iomgr_closure_init(&call->on_done_recv, call_on_done_recv, call);
grpc_iomgr_closure_init(&call->on_done_send, call_on_done_send, call);
grpc_iomgr_closure_init(&call->on_done_bind, finished_loose_op, call);
/* dropped in destroy and when READ_STATE_STREAM_CLOSED received */
gpr_ref_init(&call->internal_refcount, 2);
/* 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.on_done_recv = &call->on_done_recv;
initial_op.context = call->context;
call->receiving = 1;
GRPC_CALL_INTERNAL_REF(call, "receiving");
@ -450,7 +458,8 @@ static int need_more_data(grpc_call *call) {
(is_op_live(call, GRPC_IOREQ_RECV_CLOSE) &&
grpc_bbq_empty(&call->incoming_queue)) ||
(call->write_state == WRITE_STATE_INITIAL && !call->is_client) ||
(call->cancel_with_status != GRPC_STATUS_OK);
(call->cancel_with_status != GRPC_STATUS_OK) ||
call->destroy_called;
}
static void unlock(grpc_call *call) {
@ -469,8 +478,7 @@ static void unlock(grpc_call *call) {
if (!call->receiving && need_more_data(call)) {
op.recv_ops = &call->recv_ops;
op.recv_state = &call->recv_state;
op.on_done_recv = call_on_done_recv;
op.recv_user_data = call;
op.on_done_recv = &call->on_done_recv;
call->receiving = 1;
GRPC_CALL_INTERNAL_REF(call, "receiving");
start_op = 1;
@ -797,6 +805,7 @@ static void call_on_done_recv(void *pc, int success) {
grpc_alarm_cancel(&call->alarm);
call->have_alarm = 0;
}
GRPC_CALL_INTERNAL_UNREF(call, "closed", 0);
}
finish_read_ops(call);
} else {
@ -940,8 +949,7 @@ static int fill_send_ops(grpc_call *call, grpc_transport_stream_op *op) {
break;
}
if (op->send_ops) {
op->on_done_send = call_on_done_send;
op->send_user_data = call;
op->on_done_send = &call->on_done_send;
}
return op->send_ops != NULL;
}
@ -1071,6 +1079,8 @@ grpc_call_error grpc_call_start_ioreq_and_call_back(
void grpc_call_destroy(grpc_call *c) {
int cancel;
lock(c);
GPR_ASSERT(!c->destroy_called);
c->destroy_called = 1;
if (c->have_alarm) {
grpc_alarm_cancel(&c->alarm);
c->have_alarm = 0;
@ -1115,14 +1125,31 @@ static void finished_loose_op(void *call, int success_ignored) {
GRPC_CALL_INTERNAL_UNREF(call, "loose-op", 0);
}
typedef struct {
grpc_call *call;
grpc_iomgr_closure closure;
} finished_loose_op_allocated_args;
static void finished_loose_op_allocated(void *alloc, int success) {
finished_loose_op_allocated_args *args = alloc;
finished_loose_op(args->call, success);
gpr_free(args);
}
static void execute_op(grpc_call *call, grpc_transport_stream_op *op) {
grpc_call_element *elem;
GPR_ASSERT(op->on_consumed == NULL);
if (op->cancel_with_status != GRPC_STATUS_OK || op->bind_pollset) {
GRPC_CALL_INTERNAL_REF(call, "loose-op");
op->on_consumed = finished_loose_op;
op->on_consumed_user_data = call;
if (op->bind_pollset) {
op->on_consumed = &call->on_done_bind;
} else {
finished_loose_op_allocated_args *args = gpr_malloc(sizeof(*args));
args->call = call;
grpc_iomgr_closure_init(&args->closure, finished_loose_op_allocated, args);
op->on_consumed = &args->closure;
}
}
elem = CALL_ELEM_FROM_CALL(call, 0);

@ -56,7 +56,7 @@ static void lame_start_transport_op(grpc_call_element *elem,
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
if (op->send_ops) {
grpc_stream_ops_unref_owned_objects(op->send_ops->ops, op->send_ops->nops);
op->on_done_send(op->send_user_data, 0);
op->on_done_send->cb(op->on_done_send->cb_arg, 0);
}
if (op->recv_ops) {
char tmp[GPR_LTOA_MIN_BUFSIZE];
@ -75,10 +75,10 @@ static void lame_start_transport_op(grpc_call_element *elem,
mdb.deadline = gpr_inf_future;
grpc_sopb_add_metadata(op->recv_ops, mdb);
*op->recv_state = GRPC_STREAM_CLOSED;
op->on_done_recv(op->recv_user_data, 1);
op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
}
if (op->on_consumed) {
op->on_consumed(op->on_consumed_user_data, 0);
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
}
}

@ -191,9 +191,9 @@ struct call_data {
grpc_stream_op_buffer *recv_ops;
grpc_stream_state *recv_state;
void (*on_done_recv)(void *user_data, int success);
void *recv_user_data;
grpc_iomgr_closure *on_done_recv;
grpc_iomgr_closure server_on_recv;
grpc_iomgr_closure kill_zombie_closure;
call_data **root[CALL_LIST_COUNT];
@ -523,7 +523,7 @@ static void server_on_recv(void *ptr, int success) {
break;
}
calld->on_done_recv(calld->recv_user_data, success);
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
}
static void server_mutate_op(grpc_call_element *elem,
@ -535,9 +535,7 @@ static void server_mutate_op(grpc_call_element *elem,
calld->recv_ops = op->recv_ops;
calld->recv_state = op->recv_state;
calld->on_done_recv = op->on_done_recv;
calld->recv_user_data = op->recv_user_data;
op->on_done_recv = server_on_recv;
op->recv_user_data = elem;
op->on_done_recv = &calld->server_on_recv;
}
}
@ -633,6 +631,8 @@ static void init_call_elem(grpc_call_element *elem,
calld->deadline = gpr_inf_future;
calld->call = grpc_call_from_top_element(elem);
grpc_iomgr_closure_init(&calld->server_on_recv, server_on_recv, elem);
gpr_mu_lock(&chand->server->mu_call);
call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
gpr_mu_unlock(&chand->server->mu_call);

@ -46,4 +46,4 @@ size_t grpc_chttp2_num_alpn_versions(void);
* grpc_chttp2_num_alpn_versions()) */
const char *grpc_chttp2_get_alpn_version_index(size_t i);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_ALPN_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_ALPN_H */

@ -46,70 +46,18 @@ typedef struct {
gpr_uint8 length;
} b64_huff_sym;
static const b64_huff_sym huff_alphabet[64] = {{0x21, 6},
{0x5d, 7},
{0x5e, 7},
{0x5f, 7},
{0x60, 7},
{0x61, 7},
{0x62, 7},
{0x63, 7},
{0x64, 7},
{0x65, 7},
{0x66, 7},
{0x67, 7},
{0x68, 7},
{0x69, 7},
{0x6a, 7},
{0x6b, 7},
{0x6c, 7},
{0x6d, 7},
{0x6e, 7},
{0x6f, 7},
{0x70, 7},
{0x71, 7},
{0x72, 7},
{0xfc, 8},
{0x73, 7},
{0xfd, 8},
{0x3, 5},
{0x23, 6},
{0x4, 5},
{0x24, 6},
{0x5, 5},
{0x25, 6},
{0x26, 6},
{0x27, 6},
{0x6, 5},
{0x74, 7},
{0x75, 7},
{0x28, 6},
{0x29, 6},
{0x2a, 6},
{0x7, 5},
{0x2b, 6},
{0x76, 7},
{0x2c, 6},
{0x8, 5},
{0x9, 5},
{0x2d, 6},
{0x77, 7},
{0x78, 7},
{0x79, 7},
{0x7a, 7},
{0x7b, 7},
{0x0, 5},
{0x1, 5},
{0x2, 5},
{0x19, 6},
{0x1a, 6},
{0x1b, 6},
{0x1c, 6},
{0x1d, 6},
{0x1e, 6},
{0x1f, 6},
{0x7fb, 11},
{0x18, 6}};
static const b64_huff_sym huff_alphabet[64] = {
{0x21, 6}, {0x5d, 7}, {0x5e, 7}, {0x5f, 7}, {0x60, 7}, {0x61, 7},
{0x62, 7}, {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, {0x67, 7},
{0x68, 7}, {0x69, 7}, {0x6a, 7}, {0x6b, 7}, {0x6c, 7}, {0x6d, 7},
{0x6e, 7}, {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, {0xfc, 8},
{0x73, 7}, {0xfd, 8}, {0x3, 5}, {0x23, 6}, {0x4, 5}, {0x24, 6},
{0x5, 5}, {0x25, 6}, {0x26, 6}, {0x27, 6}, {0x6, 5}, {0x74, 7},
{0x75, 7}, {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, {0x2b, 6},
{0x76, 7}, {0x2c, 6}, {0x8, 5}, {0x9, 5}, {0x2d, 6}, {0x77, 7},
{0x78, 7}, {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x0, 5}, {0x1, 5},
{0x2, 5}, {0x19, 6}, {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6},
{0x1e, 6}, {0x1f, 6}, {0x7fb, 11}, {0x18, 6}};
static const gpr_uint8 tail_xtra[3] = {0, 2, 3};

@ -53,4 +53,4 @@ gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input);
int grpc_is_binary_header(const char *key, size_t length);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_BIN_ENCODER_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_BIN_ENCODER_H */

@ -45,23 +45,9 @@ typedef enum {
GRPC_CHTTP2_CONNECTION_ERROR
} grpc_chttp2_parse_error;
typedef struct {
gpr_uint8 end_of_stream;
gpr_uint8 need_flush_reads;
gpr_uint8 metadata_boundary;
gpr_uint8 ack_settings;
gpr_uint8 send_ping_ack;
gpr_uint8 process_ping_reply;
gpr_uint8 goaway;
gpr_uint8 rst_stream;
gpr_int64 initial_window_update;
gpr_uint32 window_update;
gpr_uint32 goaway_last_stream_index;
gpr_uint32 goaway_error;
gpr_slice goaway_text;
gpr_uint32 rst_stream_reason;
} grpc_chttp2_parse_state;
/* defined in internal.h */
typedef struct grpc_chttp2_stream_parsing grpc_chttp2_stream_parsing;
typedef struct grpc_chttp2_transport_parsing grpc_chttp2_transport_parsing;
#define GRPC_CHTTP2_FRAME_DATA 0
#define GRPC_CHTTP2_FRAME_HEADER 1
@ -80,4 +66,4 @@ typedef struct {
#define GRPC_CHTTP2_DATA_FLAG_PADDED 8
#define GRPC_CHTTP2_FLAG_HAS_PRIORITY 0x20
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_H */

@ -35,6 +35,7 @@
#include <string.h>
#include "src/core/transport/chttp2/internal.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -69,16 +70,15 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
}
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last) {
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
grpc_chttp2_data_parser *p = parser;
if (is_last && p->is_last_frame) {
state->end_of_stream = 1;
state->need_flush_reads = 1;
stream_parsing->received_close = 1;
}
if (cur == end) {
@ -105,51 +105,52 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_1:
p->frame_size = ((gpr_uint32) * cur) << 24;
p->frame_size = ((gpr_uint32)*cur) << 24;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_2;
return GRPC_CHTTP2_PARSE_OK;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_2:
p->frame_size |= ((gpr_uint32) * cur) << 16;
p->frame_size |= ((gpr_uint32)*cur) << 16;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_3;
return GRPC_CHTTP2_PARSE_OK;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_3:
p->frame_size |= ((gpr_uint32) * cur) << 8;
p->frame_size |= ((gpr_uint32)*cur) << 8;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_4;
return GRPC_CHTTP2_PARSE_OK;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_4:
p->frame_size |= ((gpr_uint32) * cur);
p->frame_size |= ((gpr_uint32)*cur);
p->state = GRPC_CHTTP2_DATA_FRAME;
++cur;
state->need_flush_reads = 1;
grpc_sopb_add_begin_message(&p->incoming_sopb, p->frame_size, 0);
/* fallthrough */
case GRPC_CHTTP2_DATA_FRAME:
if (cur == end) {
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
return GRPC_CHTTP2_PARSE_OK;
} else if ((gpr_uint32)(end - cur) == p->frame_size) {
state->need_flush_reads = 1;
}
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
if ((gpr_uint32)(end - cur) == p->frame_size) {
grpc_sopb_add_slice(&p->incoming_sopb,
gpr_slice_sub(slice, cur - beg, end - beg));
p->state = GRPC_CHTTP2_DATA_FH_0;
return GRPC_CHTTP2_PARSE_OK;
} else if ((gpr_uint32)(end - cur) > p->frame_size) {
state->need_flush_reads = 1;
grpc_sopb_add_slice(
&p->incoming_sopb,
gpr_slice_sub(slice, cur - beg, cur + p->frame_size - beg));
cur += p->frame_size;
goto fh_0; /* loop */
} else {
state->need_flush_reads = 1;
grpc_sopb_add_slice(&p->incoming_sopb,
gpr_slice_sub(slice, cur - beg, end - beg));
p->frame_size -= (end - cur);

@ -72,9 +72,10 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
/* handle a slice of a data frame - is_last indicates the last slice of a
frame */
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last);
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
/* create a slice with an empty data frame and is_last set */
gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_DATA_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_DATA_H */

@ -32,6 +32,7 @@
*/
#include "src/core/transport/chttp2/frame_goaway.h"
#include "src/core/transport/chttp2/internal.h"
#include <string.h>
@ -62,8 +63,8 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
}
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last) {
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
@ -75,7 +76,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_LSI0;
return GRPC_CHTTP2_PARSE_OK;
}
p->last_stream_id = ((gpr_uint32) * cur) << 24;
p->last_stream_id = ((gpr_uint32)*cur) << 24;
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_LSI1:
@ -83,7 +84,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_LSI1;
return GRPC_CHTTP2_PARSE_OK;
}
p->last_stream_id |= ((gpr_uint32) * cur) << 16;
p->last_stream_id |= ((gpr_uint32)*cur) << 16;
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_LSI2:
@ -91,7 +92,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_LSI2;
return GRPC_CHTTP2_PARSE_OK;
}
p->last_stream_id |= ((gpr_uint32) * cur) << 8;
p->last_stream_id |= ((gpr_uint32)*cur) << 8;
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_LSI3:
@ -99,7 +100,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_LSI3;
return GRPC_CHTTP2_PARSE_OK;
}
p->last_stream_id |= ((gpr_uint32) * cur);
p->last_stream_id |= ((gpr_uint32)*cur);
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_ERR0:
@ -107,7 +108,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_ERR0;
return GRPC_CHTTP2_PARSE_OK;
}
p->error_code = ((gpr_uint32) * cur) << 24;
p->error_code = ((gpr_uint32)*cur) << 24;
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_ERR1:
@ -115,7 +116,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_ERR1;
return GRPC_CHTTP2_PARSE_OK;
}
p->error_code |= ((gpr_uint32) * cur) << 16;
p->error_code |= ((gpr_uint32)*cur) << 16;
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_ERR2:
@ -123,7 +124,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_ERR2;
return GRPC_CHTTP2_PARSE_OK;
}
p->error_code |= ((gpr_uint32) * cur) << 8;
p->error_code |= ((gpr_uint32)*cur) << 8;
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_ERR3:
@ -131,7 +132,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->state = GRPC_CHTTP2_GOAWAY_ERR3;
return GRPC_CHTTP2_PARSE_OK;
}
p->error_code |= ((gpr_uint32) * cur);
p->error_code |= ((gpr_uint32)*cur);
++cur;
/* fallthrough */
case GRPC_CHTTP2_GOAWAY_DEBUG:
@ -139,10 +140,11 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
p->debug_pos += end - cur;
p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
if (is_last) {
state->goaway = 1;
state->goaway_last_stream_index = p->last_stream_id;
state->goaway_error = p->error_code;
state->goaway_text =
transport_parsing->goaway_received = 1;
transport_parsing->goaway_last_stream_index = p->last_stream_id;
gpr_slice_unref(transport_parsing->goaway_text);
transport_parsing->goaway_error = p->error_code;
transport_parsing->goaway_text =
gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
p->debug_data = NULL;
}

@ -65,10 +65,11 @@ void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last);
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
void grpc_chttp2_goaway_append(gpr_uint32 last_stream_id, gpr_uint32 error_code,
gpr_slice debug_data,
gpr_slice_buffer *slice_buffer);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H */

@ -32,9 +32,11 @@
*/
#include "src/core/transport/chttp2/frame_ping.h"
#include "src/core/transport/chttp2/internal.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
gpr_slice grpc_chttp2_ping_create(gpr_uint8 ack, gpr_uint8 *opaque_8bytes) {
@ -67,12 +69,13 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
}
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last) {
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
grpc_chttp2_ping_parser *p = parser;
grpc_chttp2_outstanding_ping *ping;
while (p->byte != 8 && cur != end) {
p->opaque_8bytes[p->byte] = *cur;
@ -83,9 +86,18 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
if (p->byte == 8) {
GPR_ASSERT(is_last);
if (p->is_ack) {
state->process_ping_reply = 1;
for (ping = transport_parsing->pings.next;
ping != &transport_parsing->pings; ping = ping->next) {
if (0 == memcmp(p->opaque_8bytes, ping->id, 8)) {
grpc_iomgr_add_delayed_callback(ping->on_recv, 1);
}
ping->next->prev = ping->prev;
ping->prev->next = ping->next;
gpr_free(ping);
}
} else {
state->send_ping_ack = 1;
gpr_slice_buffer_add(&transport_parsing->qbuf,
grpc_chttp2_ping_create(1, p->opaque_8bytes));
}
}

@ -48,6 +48,7 @@ gpr_slice grpc_chttp2_ping_create(gpr_uint8 ack, gpr_uint8 *opaque_8bytes);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_ping_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last);
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H */

@ -32,6 +32,7 @@
*/
#include "src/core/transport/chttp2/frame_rst_stream.h"
#include "src/core/transport/chttp2/internal.h"
#include <grpc/support/log.h>
@ -61,7 +62,8 @@ gpr_slice grpc_chttp2_rst_stream_create(gpr_uint32 id, gpr_uint32 code) {
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, gpr_uint32 length, gpr_uint8 flags) {
if (length != 4) {
gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length, flags);
gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length,
flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
}
parser->byte = 0;
@ -69,8 +71,8 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
}
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last) {
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
@ -84,12 +86,13 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
if (p->byte == 4) {
GPR_ASSERT(is_last);
state->rst_stream = 1;
state->rst_stream_reason =
(((gpr_uint32)p->reason_bytes[0]) << 24) |
(((gpr_uint32)p->reason_bytes[1]) << 16) |
(((gpr_uint32)p->reason_bytes[2]) << 8) |
(((gpr_uint32)p->reason_bytes[3]));
stream_parsing->received_close = 1;
stream_parsing->saw_rst_stream = 1;
stream_parsing->rst_stream_reason =
(((gpr_uint32)p->reason_bytes[0]) << 24) |
(((gpr_uint32)p->reason_bytes[1]) << 16) |
(((gpr_uint32)p->reason_bytes[2]) << 8) |
(((gpr_uint32)p->reason_bytes[3]));
}
return GRPC_CHTTP2_PARSE_OK;

@ -47,6 +47,7 @@ gpr_slice grpc_chttp2_rst_stream_create(gpr_uint32 stream_id, gpr_uint32 code);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last);
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H */

@ -32,6 +32,7 @@
*/
#include "src/core/transport/chttp2/frame_settings.h"
#include "src/core/transport/chttp2/internal.h"
#include <string.h>
@ -137,7 +138,8 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
}
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
void *p, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last) {
void *p, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_settings_parser *parser = p;
const gpr_uint8 *cur = GPR_SLICE_START_PTR(slice);
const gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
@ -152,9 +154,11 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_ID0;
if (is_last) {
transport_parsing->settings_updated = 1;
memcpy(parser->target_settings, parser->incoming_settings,
GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
state->ack_settings = 1;
gpr_slice_buffer_add(&transport_parsing->qbuf,
grpc_chttp2_settings_ack_create());
}
return GRPC_CHTTP2_PARSE_OK;
}
@ -220,15 +224,16 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
}
if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
parser->incoming_settings[parser->id] != parser->value) {
state->initial_window_update =
transport_parsing->initial_window_update =
(gpr_int64)parser->value -
parser->incoming_settings[parser->id];
gpr_log(GPR_DEBUG, "adding %d for initial_window change",
(int)state->initial_window_update);
(int)transport_parsing->initial_window_update);
}
parser->incoming_settings[parser->id] = parser->value;
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "CHTTP2: got setting %d = %d", parser->id,
gpr_log(GPR_DEBUG, "CHTTP2:%s: got setting %d = %d",
transport_parsing->is_client ? "CLI" : "SVR", parser->id,
parser->value);
}
} else {

@ -94,6 +94,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_settings_parser *parser, gpr_uint32 length, gpr_uint8 flags,
gpr_uint32 *settings);
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last);
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_SETTINGS_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_SETTINGS_H */

@ -32,6 +32,7 @@
*/
#include "src/core/transport/chttp2/frame_window_update.h"
#include "src/core/transport/chttp2/internal.h"
#include <grpc/support/log.h>
@ -73,15 +74,15 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
}
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last) {
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
grpc_chttp2_window_update_parser *p = parser;
while (p->byte != 4 && cur != end) {
p->amount |= ((gpr_uint32) * cur) << (8 * (3 - p->byte));
p->amount |= ((gpr_uint32)*cur) << (8 * (3 - p->byte));
cur++;
p->byte++;
}
@ -92,7 +93,21 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
return GRPC_CHTTP2_CONNECTION_ERROR;
}
GPR_ASSERT(is_last);
state->window_update = p->amount;
if (transport_parsing->incoming_stream_id) {
if (stream_parsing) {
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("update", transport_parsing,
stream_parsing, outgoing_window_update,
p->amount);
stream_parsing->outgoing_window_update += p->amount;
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
}
} else {
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT("update", transport_parsing,
outgoing_window_update, p->amount);
transport_parsing->outgoing_window_update += p->amount;
}
}
return GRPC_CHTTP2_PARSE_OK;

@ -50,6 +50,7 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_window_update_parser *parser, gpr_uint32 length,
gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
void *parser, grpc_chttp2_parse_state *state, gpr_slice slice, int is_last);
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H */

@ -32,6 +32,7 @@
*/
#include "src/core/transport/chttp2/hpack_parser.h"
#include "src/core/transport/chttp2/internal.h"
#include <stddef.h>
#include <string.h>
@ -149,10 +150,12 @@ typedef enum {
/* jump table of parse state functions -- order must match first_byte_type
above */
static const grpc_chttp2_hpack_parser_state first_byte_action[] = {
parse_indexed_field, parse_indexed_field_x, parse_lithdr_incidx,
parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx,
parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx,
parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size,
parse_indexed_field, parse_indexed_field_x,
parse_lithdr_incidx, parse_lithdr_incidx_x,
parse_lithdr_incidx_v, parse_lithdr_notidx,
parse_lithdr_notidx_x, parse_lithdr_notidx_v,
parse_lithdr_nvridx, parse_lithdr_nvridx_x,
parse_lithdr_nvridx_v, parse_max_tbl_size,
parse_max_tbl_size_x, parse_error};
/* indexes the first byte to a parse state function - generated by
@ -221,7 +224,8 @@ static const gpr_uint8 first_byte_lut[256] = {
INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD,
INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD_X, };
INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD, INDEXED_FIELD_X,
};
/* state table for huffman decoding: given a state, gives an index/16 into
next_sub_tbl. Taking that index and adding the value of the nibble being
@ -241,7 +245,8 @@ static const gpr_uint8 next_tbl[256] = {
38, 1, 1, 1, 1, 1, 1, 1, 15, 2, 2, 2, 2, 26, 3, 3, 39, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 7, 3, 3, 3, 40, 2,
41, 1, 1, 1, 42, 43, 1, 1, 44, 1, 1, 1, 1, 15, 2, 2, 2, 2, 2, 2,
3, 3, 3, 45, 46, 1, 1, 2, 2, 2, 35, 3, 3, 18, 47, 2, };
3, 3, 3, 45, 46, 1, 1, 2, 2, 2, 35, 3, 3, 18, 47, 2,
};
/* next state, based upon current state and the current nibble: see above.
generated by gen_hpack_tables.c */
static const gpr_int16 next_sub_tbl[48 * 16] = {
@ -296,7 +301,8 @@ static const gpr_int16 next_sub_tbl[48 * 16] = {
4, 8, 4, 8, 4, 8, 4, 8, 4, 8, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 255, };
0, 0, 255,
};
/* emission table: indexed like next_tbl, ultimately gives the byte to be
emitted, or -1 for no byte, or 256 for end of stream
@ -319,7 +325,8 @@ static const gpr_uint16 emit_tbl[256] = {
204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
219, 220, 221, 0, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
248, };
248,
};
/* generated by gen_hpack_tables.c */
static const gpr_int16 emit_sub_tbl[249 * 16] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@ -587,7 +594,8 @@ static const gpr_int16 emit_sub_tbl[249 * 16] = {
251, 251, 252, 252, 253, 253, 254, 254, 2, 3, 4, 5, 6, 7, 8,
11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27,
28, 29, 30, 31, 127, 220, 249, -1, 10, 10, 10, 10, 13, 13, 13,
13, 22, 22, 22, 22, 256, 256, 256, 256, };
13, 22, 22, 22, 22, 256, 256, 256, 256,
};
static const gpr_uint8 inverse_base64[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
@ -607,7 +615,8 @@ static const gpr_uint8 inverse_base64[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, };
255,
};
/* emission helpers */
static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
@ -945,7 +954,7 @@ static int parse_value1(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
return 1;
}
*p->parsing.value += (((gpr_uint32) * cur) & 0x7f) << 7;
*p->parsing.value += (((gpr_uint32)*cur) & 0x7f) << 7;
if ((*cur) & 0x80) {
return parse_value2(p, cur + 1, end);
@ -963,7 +972,7 @@ static int parse_value2(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
return 1;
}
*p->parsing.value += (((gpr_uint32) * cur) & 0x7f) << 14;
*p->parsing.value += (((gpr_uint32)*cur) & 0x7f) << 14;
if ((*cur) & 0x80) {
return parse_value3(p, cur + 1, end);
@ -981,7 +990,7 @@ static int parse_value3(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
return 1;
}
*p->parsing.value += (((gpr_uint32) * cur) & 0x7f) << 21;
*p->parsing.value += (((gpr_uint32)*cur) & 0x7f) << 21;
if ((*cur) & 0x80) {
return parse_value4(p, cur + 1, end);
@ -1369,8 +1378,8 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
}
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
void *hpack_parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last) {
void *hpack_parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_hpack_parser *parser = hpack_parser;
if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
GPR_SLICE_END_PTR(slice))) {
@ -1382,9 +1391,16 @@ grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
"end of header frame not aligned with a hpack record boundary");
return GRPC_CHTTP2_CONNECTION_ERROR;
}
state->metadata_boundary = parser->is_boundary;
state->end_of_stream = parser->is_eof;
state->need_flush_reads = parser->is_eof;
if (parser->is_boundary) {
grpc_chttp2_incoming_metadata_buffer_place_metadata_batch_into(
&stream_parsing->incoming_metadata,
&stream_parsing->data_parser.incoming_sopb);
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
}
if (parser->is_eof) {
stream_parsing->received_close = 1;
}
parser->on_header = on_header_not_set;
parser->on_header_user_data = NULL;
parser->is_boundary = 0xde;

@ -107,7 +107,7 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
the transport */
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
void *hpack_parser, grpc_chttp2_parse_state *state, gpr_slice slice,
int is_last);
void *hpack_parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H */

@ -43,68 +43,69 @@ static struct {
const char *key;
const char *value;
} static_table[] = {
/* 0: */ {NULL, NULL},
/* 1: */ {":authority", ""},
/* 2: */ {":method", "GET"},
/* 3: */ {":method", "POST"},
/* 4: */ {":path", "/"},
/* 5: */ {":path", "/index.html"},
/* 6: */ {":scheme", "http"},
/* 7: */ {":scheme", "https"},
/* 8: */ {":status", "200"},
/* 9: */ {":status", "204"},
/* 10: */ {":status", "206"},
/* 11: */ {":status", "304"},
/* 12: */ {":status", "400"},
/* 13: */ {":status", "404"},
/* 14: */ {":status", "500"},
/* 15: */ {"accept-charset", ""},
/* 16: */ {"accept-encoding", "gzip, deflate"},
/* 17: */ {"accept-language", ""},
/* 18: */ {"accept-ranges", ""},
/* 19: */ {"accept", ""},
/* 20: */ {"access-control-allow-origin", ""},
/* 21: */ {"age", ""},
/* 22: */ {"allow", ""},
/* 23: */ {"authorization", ""},
/* 24: */ {"cache-control", ""},
/* 25: */ {"content-disposition", ""},
/* 26: */ {"content-encoding", ""},
/* 27: */ {"content-language", ""},
/* 28: */ {"content-length", ""},
/* 29: */ {"content-location", ""},
/* 30: */ {"content-range", ""},
/* 31: */ {"content-type", ""},
/* 32: */ {"cookie", ""},
/* 33: */ {"date", ""},
/* 34: */ {"etag", ""},
/* 35: */ {"expect", ""},
/* 36: */ {"expires", ""},
/* 37: */ {"from", ""},
/* 38: */ {"host", ""},
/* 39: */ {"if-match", ""},
/* 40: */ {"if-modified-since", ""},
/* 41: */ {"if-none-match", ""},
/* 42: */ {"if-range", ""},
/* 43: */ {"if-unmodified-since", ""},
/* 44: */ {"last-modified", ""},
/* 45: */ {"link", ""},
/* 46: */ {"location", ""},
/* 47: */ {"max-forwards", ""},
/* 48: */ {"proxy-authenticate", ""},
/* 49: */ {"proxy-authorization", ""},
/* 50: */ {"range", ""},
/* 51: */ {"referer", ""},
/* 52: */ {"refresh", ""},
/* 53: */ {"retry-after", ""},
/* 54: */ {"server", ""},
/* 55: */ {"set-cookie", ""},
/* 56: */ {"strict-transport-security", ""},
/* 57: */ {"transfer-encoding", ""},
/* 58: */ {"user-agent", ""},
/* 59: */ {"vary", ""},
/* 60: */ {"via", ""},
/* 61: */ {"www-authenticate", ""}, };
/* 0: */ {NULL, NULL},
/* 1: */ {":authority", ""},
/* 2: */ {":method", "GET"},
/* 3: */ {":method", "POST"},
/* 4: */ {":path", "/"},
/* 5: */ {":path", "/index.html"},
/* 6: */ {":scheme", "http"},
/* 7: */ {":scheme", "https"},
/* 8: */ {":status", "200"},
/* 9: */ {":status", "204"},
/* 10: */ {":status", "206"},
/* 11: */ {":status", "304"},
/* 12: */ {":status", "400"},
/* 13: */ {":status", "404"},
/* 14: */ {":status", "500"},
/* 15: */ {"accept-charset", ""},
/* 16: */ {"accept-encoding", "gzip, deflate"},
/* 17: */ {"accept-language", ""},
/* 18: */ {"accept-ranges", ""},
/* 19: */ {"accept", ""},
/* 20: */ {"access-control-allow-origin", ""},
/* 21: */ {"age", ""},
/* 22: */ {"allow", ""},
/* 23: */ {"authorization", ""},
/* 24: */ {"cache-control", ""},
/* 25: */ {"content-disposition", ""},
/* 26: */ {"content-encoding", ""},
/* 27: */ {"content-language", ""},
/* 28: */ {"content-length", ""},
/* 29: */ {"content-location", ""},
/* 30: */ {"content-range", ""},
/* 31: */ {"content-type", ""},
/* 32: */ {"cookie", ""},
/* 33: */ {"date", ""},
/* 34: */ {"etag", ""},
/* 35: */ {"expect", ""},
/* 36: */ {"expires", ""},
/* 37: */ {"from", ""},
/* 38: */ {"host", ""},
/* 39: */ {"if-match", ""},
/* 40: */ {"if-modified-since", ""},
/* 41: */ {"if-none-match", ""},
/* 42: */ {"if-range", ""},
/* 43: */ {"if-unmodified-since", ""},
/* 44: */ {"last-modified", ""},
/* 45: */ {"link", ""},
/* 46: */ {"location", ""},
/* 47: */ {"max-forwards", ""},
/* 48: */ {"proxy-authenticate", ""},
/* 49: */ {"proxy-authorization", ""},
/* 50: */ {"range", ""},
/* 51: */ {"referer", ""},
/* 52: */ {"refresh", ""},
/* 53: */ {"retry-after", ""},
/* 54: */ {"server", ""},
/* 55: */ {"set-cookie", ""},
/* 56: */ {"strict-transport-security", ""},
/* 57: */ {"transfer-encoding", ""},
/* 58: */ {"user-agent", ""},
/* 59: */ {"vary", ""},
/* 60: */ {"via", ""},
/* 61: */ {"www-authenticate", ""},
};
void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx) {
size_t i;

@ -94,4 +94,4 @@ typedef struct {
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
const grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HPACK_TABLE_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HPACK_TABLE_H */

@ -53,4 +53,4 @@ typedef enum {
GRPC_CHTTP2__ERROR_DO_NOT_USE = -1
} grpc_chttp2_error_code;
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HTTP2_ERRORS_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HTTP2_ERRORS_H */

@ -37,260 +37,69 @@
command:
:%s/.* \([0-9a-f]\+\) \[ *\([0-9]\+\)\]/{0x\1, \2},/g */
const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS] = {
{0x1ff8, 13},
{0x7fffd8, 23},
{0xfffffe2, 28},
{0xfffffe3, 28},
{0xfffffe4, 28},
{0xfffffe5, 28},
{0xfffffe6, 28},
{0xfffffe7, 28},
{0xfffffe8, 28},
{0xffffea, 24},
{0x3ffffffc, 30},
{0xfffffe9, 28},
{0xfffffea, 28},
{0x3ffffffd, 30},
{0xfffffeb, 28},
{0xfffffec, 28},
{0xfffffed, 28},
{0xfffffee, 28},
{0xfffffef, 28},
{0xffffff0, 28},
{0xffffff1, 28},
{0xffffff2, 28},
{0x3ffffffe, 30},
{0xffffff3, 28},
{0xffffff4, 28},
{0xffffff5, 28},
{0xffffff6, 28},
{0xffffff7, 28},
{0xffffff8, 28},
{0xffffff9, 28},
{0xffffffa, 28},
{0xffffffb, 28},
{0x14, 6},
{0x3f8, 10},
{0x3f9, 10},
{0xffa, 12},
{0x1ff9, 13},
{0x15, 6},
{0xf8, 8},
{0x7fa, 11},
{0x3fa, 10},
{0x3fb, 10},
{0xf9, 8},
{0x7fb, 11},
{0xfa, 8},
{0x16, 6},
{0x17, 6},
{0x18, 6},
{0x0, 5},
{0x1, 5},
{0x2, 5},
{0x19, 6},
{0x1a, 6},
{0x1b, 6},
{0x1c, 6},
{0x1d, 6},
{0x1e, 6},
{0x1f, 6},
{0x5c, 7},
{0xfb, 8},
{0x7ffc, 15},
{0x20, 6},
{0xffb, 12},
{0x3fc, 10},
{0x1ffa, 13},
{0x21, 6},
{0x5d, 7},
{0x5e, 7},
{0x5f, 7},
{0x60, 7},
{0x61, 7},
{0x62, 7},
{0x63, 7},
{0x64, 7},
{0x65, 7},
{0x66, 7},
{0x67, 7},
{0x68, 7},
{0x69, 7},
{0x6a, 7},
{0x6b, 7},
{0x6c, 7},
{0x6d, 7},
{0x6e, 7},
{0x6f, 7},
{0x70, 7},
{0x71, 7},
{0x72, 7},
{0xfc, 8},
{0x73, 7},
{0xfd, 8},
{0x1ffb, 13},
{0x7fff0, 19},
{0x1ffc, 13},
{0x3ffc, 14},
{0x22, 6},
{0x7ffd, 15},
{0x3, 5},
{0x23, 6},
{0x4, 5},
{0x24, 6},
{0x5, 5},
{0x25, 6},
{0x26, 6},
{0x27, 6},
{0x6, 5},
{0x74, 7},
{0x75, 7},
{0x28, 6},
{0x29, 6},
{0x2a, 6},
{0x7, 5},
{0x2b, 6},
{0x76, 7},
{0x2c, 6},
{0x8, 5},
{0x9, 5},
{0x2d, 6},
{0x77, 7},
{0x78, 7},
{0x79, 7},
{0x7a, 7},
{0x7b, 7},
{0x7ffe, 15},
{0x7fc, 11},
{0x3ffd, 14},
{0x1ffd, 13},
{0xffffffc, 28},
{0xfffe6, 20},
{0x3fffd2, 22},
{0xfffe7, 20},
{0xfffe8, 20},
{0x3fffd3, 22},
{0x3fffd4, 22},
{0x3fffd5, 22},
{0x7fffd9, 23},
{0x3fffd6, 22},
{0x7fffda, 23},
{0x7fffdb, 23},
{0x7fffdc, 23},
{0x7fffdd, 23},
{0x7fffde, 23},
{0xffffeb, 24},
{0x7fffdf, 23},
{0xffffec, 24},
{0xffffed, 24},
{0x3fffd7, 22},
{0x7fffe0, 23},
{0xffffee, 24},
{0x7fffe1, 23},
{0x7fffe2, 23},
{0x7fffe3, 23},
{0x7fffe4, 23},
{0x1fffdc, 21},
{0x3fffd8, 22},
{0x7fffe5, 23},
{0x3fffd9, 22},
{0x7fffe6, 23},
{0x7fffe7, 23},
{0xffffef, 24},
{0x3fffda, 22},
{0x1fffdd, 21},
{0xfffe9, 20},
{0x3fffdb, 22},
{0x3fffdc, 22},
{0x7fffe8, 23},
{0x7fffe9, 23},
{0x1fffde, 21},
{0x7fffea, 23},
{0x3fffdd, 22},
{0x3fffde, 22},
{0xfffff0, 24},
{0x1fffdf, 21},
{0x3fffdf, 22},
{0x7fffeb, 23},
{0x7fffec, 23},
{0x1fffe0, 21},
{0x1fffe1, 21},
{0x3fffe0, 22},
{0x1fffe2, 21},
{0x7fffed, 23},
{0x3fffe1, 22},
{0x7fffee, 23},
{0x7fffef, 23},
{0xfffea, 20},
{0x3fffe2, 22},
{0x3fffe3, 22},
{0x3fffe4, 22},
{0x7ffff0, 23},
{0x3fffe5, 22},
{0x3fffe6, 22},
{0x7ffff1, 23},
{0x3ffffe0, 26},
{0x3ffffe1, 26},
{0xfffeb, 20},
{0x7fff1, 19},
{0x3fffe7, 22},
{0x7ffff2, 23},
{0x3fffe8, 22},
{0x1ffffec, 25},
{0x3ffffe2, 26},
{0x3ffffe3, 26},
{0x3ffffe4, 26},
{0x7ffffde, 27},
{0x7ffffdf, 27},
{0x3ffffe5, 26},
{0xfffff1, 24},
{0x1ffffed, 25},
{0x7fff2, 19},
{0x1fffe3, 21},
{0x3ffffe6, 26},
{0x7ffffe0, 27},
{0x7ffffe1, 27},
{0x3ffffe7, 26},
{0x7ffffe2, 27},
{0xfffff2, 24},
{0x1fffe4, 21},
{0x1fffe5, 21},
{0x3ffffe8, 26},
{0x3ffffe9, 26},
{0xffffffd, 28},
{0x7ffffe3, 27},
{0x7ffffe4, 27},
{0x7ffffe5, 27},
{0xfffec, 20},
{0xfffff3, 24},
{0xfffed, 20},
{0x1fffe6, 21},
{0x3fffe9, 22},
{0x1fffe7, 21},
{0x1fffe8, 21},
{0x7ffff3, 23},
{0x3fffea, 22},
{0x3fffeb, 22},
{0x1ffffee, 25},
{0x1ffffef, 25},
{0xfffff4, 24},
{0xfffff5, 24},
{0x3ffffea, 26},
{0x7ffff4, 23},
{0x3ffffeb, 26},
{0x7ffffe6, 27},
{0x3ffffec, 26},
{0x3ffffed, 26},
{0x7ffffe7, 27},
{0x7ffffe8, 27},
{0x7ffffe9, 27},
{0x7ffffea, 27},
{0x7ffffeb, 27},
{0xffffffe, 28},
{0x7ffffec, 27},
{0x7ffffed, 27},
{0x7ffffee, 27},
{0x7ffffef, 27},
{0x7fffff0, 27},
{0x3ffffee, 26},
{0x3fffffff, 30}, };
{0x1ff8, 13}, {0x7fffd8, 23}, {0xfffffe2, 28}, {0xfffffe3, 28},
{0xfffffe4, 28}, {0xfffffe5, 28}, {0xfffffe6, 28}, {0xfffffe7, 28},
{0xfffffe8, 28}, {0xffffea, 24}, {0x3ffffffc, 30}, {0xfffffe9, 28},
{0xfffffea, 28}, {0x3ffffffd, 30}, {0xfffffeb, 28}, {0xfffffec, 28},
{0xfffffed, 28}, {0xfffffee, 28}, {0xfffffef, 28}, {0xffffff0, 28},
{0xffffff1, 28}, {0xffffff2, 28}, {0x3ffffffe, 30}, {0xffffff3, 28},
{0xffffff4, 28}, {0xffffff5, 28}, {0xffffff6, 28}, {0xffffff7, 28},
{0xffffff8, 28}, {0xffffff9, 28}, {0xffffffa, 28}, {0xffffffb, 28},
{0x14, 6}, {0x3f8, 10}, {0x3f9, 10}, {0xffa, 12},
{0x1ff9, 13}, {0x15, 6}, {0xf8, 8}, {0x7fa, 11},
{0x3fa, 10}, {0x3fb, 10}, {0xf9, 8}, {0x7fb, 11},
{0xfa, 8}, {0x16, 6}, {0x17, 6}, {0x18, 6},
{0x0, 5}, {0x1, 5}, {0x2, 5}, {0x19, 6},
{0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6},
{0x1e, 6}, {0x1f, 6}, {0x5c, 7}, {0xfb, 8},
{0x7ffc, 15}, {0x20, 6}, {0xffb, 12}, {0x3fc, 10},
{0x1ffa, 13}, {0x21, 6}, {0x5d, 7}, {0x5e, 7},
{0x5f, 7}, {0x60, 7}, {0x61, 7}, {0x62, 7},
{0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7},
{0x67, 7}, {0x68, 7}, {0x69, 7}, {0x6a, 7},
{0x6b, 7}, {0x6c, 7}, {0x6d, 7}, {0x6e, 7},
{0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7},
{0xfc, 8}, {0x73, 7}, {0xfd, 8}, {0x1ffb, 13},
{0x7fff0, 19}, {0x1ffc, 13}, {0x3ffc, 14}, {0x22, 6},
{0x7ffd, 15}, {0x3, 5}, {0x23, 6}, {0x4, 5},
{0x24, 6}, {0x5, 5}, {0x25, 6}, {0x26, 6},
{0x27, 6}, {0x6, 5}, {0x74, 7}, {0x75, 7},
{0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5},
{0x2b, 6}, {0x76, 7}, {0x2c, 6}, {0x8, 5},
{0x9, 5}, {0x2d, 6}, {0x77, 7}, {0x78, 7},
{0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x7ffe, 15},
{0x7fc, 11}, {0x3ffd, 14}, {0x1ffd, 13}, {0xffffffc, 28},
{0xfffe6, 20}, {0x3fffd2, 22}, {0xfffe7, 20}, {0xfffe8, 20},
{0x3fffd3, 22}, {0x3fffd4, 22}, {0x3fffd5, 22}, {0x7fffd9, 23},
{0x3fffd6, 22}, {0x7fffda, 23}, {0x7fffdb, 23}, {0x7fffdc, 23},
{0x7fffdd, 23}, {0x7fffde, 23}, {0xffffeb, 24}, {0x7fffdf, 23},
{0xffffec, 24}, {0xffffed, 24}, {0x3fffd7, 22}, {0x7fffe0, 23},
{0xffffee, 24}, {0x7fffe1, 23}, {0x7fffe2, 23}, {0x7fffe3, 23},
{0x7fffe4, 23}, {0x1fffdc, 21}, {0x3fffd8, 22}, {0x7fffe5, 23},
{0x3fffd9, 22}, {0x7fffe6, 23}, {0x7fffe7, 23}, {0xffffef, 24},
{0x3fffda, 22}, {0x1fffdd, 21}, {0xfffe9, 20}, {0x3fffdb, 22},
{0x3fffdc, 22}, {0x7fffe8, 23}, {0x7fffe9, 23}, {0x1fffde, 21},
{0x7fffea, 23}, {0x3fffdd, 22}, {0x3fffde, 22}, {0xfffff0, 24},
{0x1fffdf, 21}, {0x3fffdf, 22}, {0x7fffeb, 23}, {0x7fffec, 23},
{0x1fffe0, 21}, {0x1fffe1, 21}, {0x3fffe0, 22}, {0x1fffe2, 21},
{0x7fffed, 23}, {0x3fffe1, 22}, {0x7fffee, 23}, {0x7fffef, 23},
{0xfffea, 20}, {0x3fffe2, 22}, {0x3fffe3, 22}, {0x3fffe4, 22},
{0x7ffff0, 23}, {0x3fffe5, 22}, {0x3fffe6, 22}, {0x7ffff1, 23},
{0x3ffffe0, 26}, {0x3ffffe1, 26}, {0xfffeb, 20}, {0x7fff1, 19},
{0x3fffe7, 22}, {0x7ffff2, 23}, {0x3fffe8, 22}, {0x1ffffec, 25},
{0x3ffffe2, 26}, {0x3ffffe3, 26}, {0x3ffffe4, 26}, {0x7ffffde, 27},
{0x7ffffdf, 27}, {0x3ffffe5, 26}, {0xfffff1, 24}, {0x1ffffed, 25},
{0x7fff2, 19}, {0x1fffe3, 21}, {0x3ffffe6, 26}, {0x7ffffe0, 27},
{0x7ffffe1, 27}, {0x3ffffe7, 26}, {0x7ffffe2, 27}, {0xfffff2, 24},
{0x1fffe4, 21}, {0x1fffe5, 21}, {0x3ffffe8, 26}, {0x3ffffe9, 26},
{0xffffffd, 28}, {0x7ffffe3, 27}, {0x7ffffe4, 27}, {0x7ffffe5, 27},
{0xfffec, 20}, {0xfffff3, 24}, {0xfffed, 20}, {0x1fffe6, 21},
{0x3fffe9, 22}, {0x1fffe7, 21}, {0x1fffe8, 21}, {0x7ffff3, 23},
{0x3fffea, 22}, {0x3fffeb, 22}, {0x1ffffee, 25}, {0x1ffffef, 25},
{0xfffff4, 24}, {0xfffff5, 24}, {0x3ffffea, 26}, {0x7ffff4, 23},
{0x3ffffeb, 26}, {0x7ffffe6, 27}, {0x3ffffec, 26}, {0x3ffffed, 26},
{0x7ffffe7, 27}, {0x7ffffe8, 27}, {0x7ffffe9, 27}, {0x7ffffea, 27},
{0x7ffffeb, 27}, {0xffffffe, 28}, {0x7ffffec, 27}, {0x7ffffed, 27},
{0x7ffffee, 27}, {0x7ffffef, 27}, {0x7fffff0, 27}, {0x3ffffee, 26},
{0x3fffffff, 30},
};

@ -45,4 +45,4 @@ typedef struct {
extern const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS];
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HUFFSYMS_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HUFFSYMS_H */

@ -0,0 +1,177 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/chttp2/incoming_metadata.h"
#include <string.h>
#include "src/core/transport/chttp2/internal.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
void grpc_chttp2_incoming_metadata_buffer_init(
grpc_chttp2_incoming_metadata_buffer *buffer) {
buffer->deadline = gpr_inf_future;
}
void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_chttp2_incoming_metadata_buffer *buffer) {
gpr_free(buffer->elems);
}
void grpc_chttp2_incoming_metadata_buffer_add(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) {
if (buffer->capacity == buffer->count) {
buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
buffer->elems =
gpr_realloc(buffer->elems, sizeof(*buffer->elems) * buffer->capacity);
}
buffer->elems[buffer->count++].md = elem;
}
void grpc_chttp2_incoming_metadata_buffer_set_deadline(
grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
buffer->deadline = deadline;
}
void grpc_chttp2_incoming_metadata_live_op_buffer_end(
grpc_chttp2_incoming_metadata_live_op_buffer *buffer) {
gpr_free(buffer->elems);
buffer->elems = NULL;
}
void grpc_chttp2_incoming_metadata_buffer_place_metadata_batch_into(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_stream_op_buffer *sopb) {
grpc_metadata_batch b;
b.list.head = NULL;
/* Store away the last element of the list, so that in patch_metadata_ops
we can reconstitute the list.
We can't do list building here as later incoming metadata may reallocate
the underlying array. */
b.list.tail = (void *)(gpr_intptr)buffer->count;
b.garbage.head = b.garbage.tail = NULL;
b.deadline = buffer->deadline;
buffer->deadline = gpr_inf_future;
grpc_sopb_add_metadata(sopb, b);
}
void grpc_chttp2_incoming_metadata_buffer_swap(
grpc_chttp2_incoming_metadata_buffer *a,
grpc_chttp2_incoming_metadata_buffer *b) {
GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, *a, *b);
}
void grpc_incoming_metadata_buffer_move_to_referencing_sopb(
grpc_chttp2_incoming_metadata_buffer *src,
grpc_chttp2_incoming_metadata_buffer *dst, grpc_stream_op_buffer *sopb) {
size_t delta;
size_t i;
dst->deadline = gpr_time_min(src->deadline, dst->deadline);
if (src->count == 0) {
return;
}
if (dst->count == 0) {
grpc_chttp2_incoming_metadata_buffer_swap(src, dst);
return;
}
delta = dst->count;
if (dst->capacity < src->count + dst->count) {
dst->capacity = GPR_MAX(dst->capacity * 2, src->count + dst->count);
dst->elems = gpr_realloc(dst->elems, dst->capacity * sizeof(*dst->elems));
}
memcpy(dst->elems + dst->count, src->elems, src->count * sizeof(*src->elems));
dst->count += src->count;
for (i = 0; i < sopb->nops; i++) {
if (sopb->ops[i].type != GRPC_OP_METADATA) continue;
sopb->ops[i].data.metadata.list.tail =
(void *)(delta + (gpr_intptr)sopb->ops[i].data.metadata.list.tail);
}
}
void grpc_chttp2_incoming_metadata_buffer_postprocess_sopb_and_begin_live_op(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_stream_op_buffer *sopb,
grpc_chttp2_incoming_metadata_live_op_buffer *live_op_buffer) {
grpc_stream_op *ops = sopb->ops;
size_t nops = sopb->nops;
size_t i;
size_t j;
size_t mdidx = 0;
size_t last_mdidx;
int found_metadata = 0;
/* rework the array of metadata into a linked list, making use
of the breadcrumbs we left in metadata batches during
add_metadata_batch */
for (i = 0; i < nops; i++) {
grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA) continue;
found_metadata = 1;
/* we left a breadcrumb indicating where the end of this list is,
and since we add sequentially, we know from the end of the last
segment where this segment begins */
last_mdidx = (size_t)(gpr_intptr)(op->data.metadata.list.tail);
GPR_ASSERT(last_mdidx > mdidx);
GPR_ASSERT(last_mdidx <= buffer->count);
/* turn the array into a doubly linked list */
op->data.metadata.list.head = &buffer->elems[mdidx];
op->data.metadata.list.tail = &buffer->elems[last_mdidx - 1];
for (j = mdidx + 1; j < last_mdidx; j++) {
buffer->elems[j].prev = &buffer->elems[j - 1];
buffer->elems[j - 1].next = &buffer->elems[j];
}
buffer->elems[mdidx].prev = NULL;
buffer->elems[last_mdidx - 1].next = NULL;
/* track where we're up to */
mdidx = last_mdidx;
}
if (found_metadata) {
live_op_buffer->elems = buffer->elems;
if (mdidx != buffer->count) {
/* we have a partially read metadata batch still in incoming_metadata */
size_t new_count = buffer->count - mdidx;
size_t copy_bytes = sizeof(*buffer->elems) * new_count;
GPR_ASSERT(mdidx < buffer->count);
buffer->elems = gpr_malloc(copy_bytes);
memcpy(live_op_buffer->elems + mdidx, buffer->elems, copy_bytes);
buffer->count = buffer->capacity = new_count;
} else {
buffer->elems = NULL;
buffer->count = 0;
buffer->capacity = 0;
}
}
}

@ -0,0 +1,80 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_CORE_CHTTP2_INCOMING_METADATA_H
#define GRPC_INTERNAL_CORE_CHTTP2_INCOMING_METADATA_H
#include "src/core/transport/transport.h"
typedef struct {
grpc_linked_mdelem *elems;
size_t count;
size_t capacity;
gpr_timespec deadline;
} grpc_chttp2_incoming_metadata_buffer;
typedef struct {
grpc_linked_mdelem *elems;
} grpc_chttp2_incoming_metadata_live_op_buffer;
/** assumes everything initially zeroed */
void grpc_chttp2_incoming_metadata_buffer_init(
grpc_chttp2_incoming_metadata_buffer *buffer);
void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_chttp2_incoming_metadata_buffer *buffer);
void grpc_chttp2_incoming_metadata_buffer_reset(
grpc_chttp2_incoming_metadata_buffer *buffer);
void grpc_chttp2_incoming_metadata_buffer_add(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem);
void grpc_chttp2_incoming_metadata_buffer_set_deadline(
grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline);
/** extend sopb with a metadata batch; this must be post-processed by
grpc_chttp2_incoming_metadata_buffer_postprocess_sopb before being handed
out of the transport */
void grpc_chttp2_incoming_metadata_buffer_place_metadata_batch_into(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_stream_op_buffer *sopb);
void grpc_incoming_metadata_buffer_move_to_referencing_sopb(
grpc_chttp2_incoming_metadata_buffer *src,
grpc_chttp2_incoming_metadata_buffer *dst, grpc_stream_op_buffer *sopb);
void grpc_chttp2_incoming_metadata_buffer_postprocess_sopb_and_begin_live_op(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_stream_op_buffer *sopb,
grpc_chttp2_incoming_metadata_live_op_buffer *live_op_buffer);
void grpc_chttp2_incoming_metadata_live_op_buffer_end(
grpc_chttp2_incoming_metadata_live_op_buffer *live_op_buffer);
#endif /* GRPC_INTERNAL_CORE_CHTTP2_INCOMING_METADATA_H */

@ -0,0 +1,652 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_CORE_CHTTP2_INTERNAL_H
#define GRPC_INTERNAL_CORE_CHTTP2_INTERNAL_H
#include "src/core/transport/transport_impl.h"
#include "src/core/iomgr/endpoint.h"
#include "src/core/transport/chttp2/frame.h"
#include "src/core/transport/chttp2/frame_data.h"
#include "src/core/transport/chttp2/frame_goaway.h"
#include "src/core/transport/chttp2/frame_ping.h"
#include "src/core/transport/chttp2/frame_rst_stream.h"
#include "src/core/transport/chttp2/frame_settings.h"
#include "src/core/transport/chttp2/frame_window_update.h"
#include "src/core/transport/chttp2/hpack_parser.h"
#include "src/core/transport/chttp2/incoming_metadata.h"
#include "src/core/transport/chttp2/stream_encoder.h"
#include "src/core/transport/chttp2/stream_map.h"
typedef struct grpc_chttp2_transport grpc_chttp2_transport;
typedef struct grpc_chttp2_stream grpc_chttp2_stream;
/* streams are kept in various linked lists depending on what things need to
happen to them... this enum labels each list */
typedef enum {
GRPC_CHTTP2_LIST_ALL_STREAMS,
GRPC_CHTTP2_LIST_READ_WRITE_STATE_CHANGED,
GRPC_CHTTP2_LIST_WRITABLE,
GRPC_CHTTP2_LIST_WRITING,
GRPC_CHTTP2_LIST_WRITTEN,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE,
GRPC_CHTTP2_LIST_PARSING_SEEN,
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED,
/** streams that are waiting to start because there are too many concurrent
streams on the connection */
GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
STREAM_LIST_COUNT /* must be last */
} grpc_chttp2_stream_list_id;
/* deframer state for the overall http2 stream of bytes */
typedef enum {
/* prefix: one entry per http2 connection prefix byte */
DTS_CLIENT_PREFIX_0 = 0,
DTS_CLIENT_PREFIX_1,
DTS_CLIENT_PREFIX_2,
DTS_CLIENT_PREFIX_3,
DTS_CLIENT_PREFIX_4,
DTS_CLIENT_PREFIX_5,
DTS_CLIENT_PREFIX_6,
DTS_CLIENT_PREFIX_7,
DTS_CLIENT_PREFIX_8,
DTS_CLIENT_PREFIX_9,
DTS_CLIENT_PREFIX_10,
DTS_CLIENT_PREFIX_11,
DTS_CLIENT_PREFIX_12,
DTS_CLIENT_PREFIX_13,
DTS_CLIENT_PREFIX_14,
DTS_CLIENT_PREFIX_15,
DTS_CLIENT_PREFIX_16,
DTS_CLIENT_PREFIX_17,
DTS_CLIENT_PREFIX_18,
DTS_CLIENT_PREFIX_19,
DTS_CLIENT_PREFIX_20,
DTS_CLIENT_PREFIX_21,
DTS_CLIENT_PREFIX_22,
DTS_CLIENT_PREFIX_23,
/* frame header byte 0... */
/* must follow from the prefix states */
DTS_FH_0,
DTS_FH_1,
DTS_FH_2,
DTS_FH_3,
DTS_FH_4,
DTS_FH_5,
DTS_FH_6,
DTS_FH_7,
/* ... frame header byte 8 */
DTS_FH_8,
/* inside a http2 frame */
DTS_FRAME
} grpc_chttp2_deframe_transport_state;
typedef enum {
WRITE_STATE_OPEN,
WRITE_STATE_QUEUED_CLOSE,
WRITE_STATE_SENT_CLOSE
} grpc_chttp2_write_state;
typedef enum {
DONT_SEND_CLOSED = 0,
SEND_CLOSED,
SEND_CLOSED_WITH_RST_STREAM
} grpc_chttp2_send_closed;
typedef struct {
grpc_chttp2_stream *head;
grpc_chttp2_stream *tail;
} grpc_chttp2_stream_list;
typedef struct {
grpc_chttp2_stream *next;
grpc_chttp2_stream *prev;
} grpc_chttp2_stream_link;
typedef enum {
GRPC_CHTTP2_ERROR_STATE_NONE,
GRPC_CHTTP2_ERROR_STATE_SEEN,
GRPC_CHTTP2_ERROR_STATE_NOTIFIED
} grpc_chttp2_error_state;
/* We keep several sets of connection wide parameters */
typedef enum {
/* The settings our peer has asked for (and we have acked) */
PEER_SETTINGS = 0,
/* The settings we'd like to have */
LOCAL_SETTINGS,
/* The settings we've published to our peer */
SENT_SETTINGS,
/* The settings the peer has acked */
ACKED_SETTINGS,
NUM_SETTING_SETS
} grpc_chttp2_setting_set;
/* Outstanding ping request data */
typedef struct grpc_chttp2_outstanding_ping {
gpr_uint8 id[8];
grpc_iomgr_closure *on_recv;
struct grpc_chttp2_outstanding_ping *next;
struct grpc_chttp2_outstanding_ping *prev;
} grpc_chttp2_outstanding_ping;
typedef struct {
/** data to write next write */
gpr_slice_buffer qbuf;
/** queued callbacks */
grpc_iomgr_closure *pending_closures;
/** window available for us to send to peer */
gpr_uint32 outgoing_window;
/** window available for peer to send to us - updated after parse */
gpr_uint32 incoming_window;
/** how much window would we like to have for incoming_window */
gpr_uint32 connection_window_target;
/** is this transport a client? */
gpr_uint8 is_client;
/** are the local settings dirty and need to be sent? */
gpr_uint8 dirtied_local_settings;
/** have local settings been sent? */
gpr_uint8 sent_local_settings;
/** bitmask of setting indexes to send out */
gpr_uint32 force_send_settings;
/** settings values */
gpr_uint32 settings[NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
/** has there been a connection level error, and have we notified
anyone about it? */
grpc_chttp2_error_state error_state;
/** what is the next stream id to be allocated by this peer?
copied to next_stream_id in parsing when parsing commences */
gpr_uint32 next_stream_id;
/** last received stream id */
gpr_uint32 last_incoming_stream_id;
/** pings awaiting responses */
grpc_chttp2_outstanding_ping pings;
/** next payload for an outgoing ping */
gpr_uint64 ping_counter;
/** concurrent stream count: updated when not parsing,
so this is a strict over-estimation on the client */
gpr_uint32 concurrent_stream_count;
/** is there a goaway available? (boolean) */
grpc_chttp2_error_state goaway_state;
/** what is the debug text of the goaway? */
gpr_slice goaway_text;
/** what is the status code of the goaway? */
grpc_status_code goaway_error;
} grpc_chttp2_transport_global;
typedef struct {
/** data to write now */
gpr_slice_buffer outbuf;
/** hpack encoding */
grpc_chttp2_hpack_compressor hpack_compressor;
/** is this a client? */
gpr_uint8 is_client;
} grpc_chttp2_transport_writing;
struct grpc_chttp2_transport_parsing {
/** is this transport a client? (boolean) */
gpr_uint8 is_client;
/** were settings updated? */
gpr_uint8 settings_updated;
/** was a settings ack received? */
gpr_uint8 settings_ack_received;
/** was a goaway frame received? */
gpr_uint8 goaway_received;
/** initial window change */
gpr_int64 initial_window_update;
/** data to write later - after parsing */
gpr_slice_buffer qbuf;
/* metadata object cache */
grpc_mdstr *str_grpc_timeout;
/** parser for headers */
grpc_chttp2_hpack_parser hpack_parser;
/** simple one shot parsers */
union {
grpc_chttp2_window_update_parser window_update;
grpc_chttp2_settings_parser settings;
grpc_chttp2_ping_parser ping;
grpc_chttp2_rst_stream_parser rst_stream;
} simple;
/** parser for goaway frames */
grpc_chttp2_goaway_parser goaway_parser;
/** window available for peer to send to us */
gpr_uint32 incoming_window;
gpr_uint32 incoming_window_delta;
/** next stream id available at the time of beginning parsing */
gpr_uint32 next_stream_id;
gpr_uint32 last_incoming_stream_id;
/* deframing */
grpc_chttp2_deframe_transport_state deframe_state;
gpr_uint8 incoming_frame_type;
gpr_uint8 incoming_frame_flags;
gpr_uint8 header_eof;
gpr_uint32 expect_continuation_stream_id;
gpr_uint32 incoming_frame_size;
gpr_uint32 incoming_stream_id;
/* active parser */
void *parser_data;
grpc_chttp2_stream_parsing *incoming_stream;
grpc_chttp2_parse_error (*parser)(
void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
/* received settings */
gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
/* goaway data */
grpc_status_code goaway_error;
gpr_uint32 goaway_last_stream_index;
gpr_slice goaway_text;
gpr_uint64 outgoing_window_update;
/** pings awaiting responses */
grpc_chttp2_outstanding_ping pings;
};
struct grpc_chttp2_transport {
grpc_transport base; /* must be first */
grpc_endpoint *ep;
grpc_mdctx *metadata_context;
gpr_refcount refs;
gpr_mu mu;
/** is the transport destroying itself? */
gpr_uint8 destroying;
/** has the upper layer closed the transport? */
gpr_uint8 closed;
/** is a thread currently writing */
gpr_uint8 writing_active;
/** is a thread currently parsing */
gpr_uint8 parsing_active;
/** is there a read request to the endpoint outstanding? */
gpr_uint8 endpoint_reading;
/** various lists of streams */
grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
/** global state for reading/writing */
grpc_chttp2_transport_global global;
/** state only accessible by the chain of execution that
set writing_active=1 */
grpc_chttp2_transport_writing writing;
/** state only accessible by the chain of execution that
set parsing_active=1 */
grpc_chttp2_transport_parsing parsing;
/** maps stream id to grpc_chttp2_stream objects;
owned by the parsing thread when parsing */
grpc_chttp2_stream_map parsing_stream_map;
/** streams created by the client (possibly during parsing);
merged with parsing_stream_map during unlock when no
parsing is occurring */
grpc_chttp2_stream_map new_stream_map;
/** closure to execute writing */
grpc_iomgr_closure writing_action;
/** closure to start reading from the endpoint */
grpc_iomgr_closure reading_action;
/** address to place a newly accepted stream - set and unset by
grpc_chttp2_parsing_accept_stream; used by init_stream to
publish the accepted server stream */
grpc_chttp2_stream **accepting_stream;
struct {
/** is a thread currently performing channel callbacks */
gpr_uint8 executing;
/** transport channel-level callback */
const grpc_transport_callbacks *cb;
/** user data for cb calls */
void *cb_user_data;
/** closure for notifying transport closure */
grpc_iomgr_closure notify_closed;
} channel_callback;
#if 0
/* basic state management - what are we doing at the moment? */
gpr_uint8 reading;
/** are we calling back any grpc_transport_stream_op completion events */
gpr_uint8 calling_back_ops;
gpr_uint8 destroying;
gpr_uint8 closed;
/* stream indexing */
gpr_uint32 next_stream_id;
/* window management */
gpr_uint32 outgoing_window_update;
/* state for a stream that's not yet been created */
grpc_stream_op_buffer new_stream_sopb;
/* stream ops that need to be destroyed, but outside of the lock */
grpc_stream_op_buffer nuke_later_sopb;
/* pings */
gpr_int64 ping_counter;
grpc_chttp2_stream **accepting_stream;
#endif
};
typedef struct {
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
gpr_uint32 id;
grpc_iomgr_closure *send_done_closure;
grpc_iomgr_closure *recv_done_closure;
/** window available for us to send to peer */
gpr_int64 outgoing_window;
/** window available for peer to send to us - updated after parse */
gpr_uint32 incoming_window;
/** stream ops the transport user would like to send */
grpc_stream_op_buffer *outgoing_sopb;
/** when the application requests writes be closed, the write_closed is
'queued'; when the close is flow controlled into the send path, we are
'sending' it; when the write has been performed it is 'sent' */
grpc_chttp2_write_state write_state;
/** is this stream closed (boolean) */
gpr_uint8 read_closed;
/** has this stream been cancelled? (boolean) */
gpr_uint8 cancelled;
grpc_status_code cancelled_status;
/** have we told the upper layer that this stream is cancelled? */
gpr_uint8 published_cancelled;
/** is this stream in the stream map? (boolean) */
gpr_uint8 in_stream_map;
/** stream state already published to the upper layer */
grpc_stream_state published_state;
/** address to publish next stream state to */
grpc_stream_state *publish_state;
/** pointer to sop buffer to fill in with new stream ops */
grpc_stream_op_buffer *publish_sopb;
grpc_stream_op_buffer incoming_sopb;
/** incoming metadata */
grpc_chttp2_incoming_metadata_buffer incoming_metadata;
grpc_chttp2_incoming_metadata_live_op_buffer outstanding_metadata;
} grpc_chttp2_stream_global;
typedef struct {
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
gpr_uint32 id;
/** sops that have passed flow control to be written */
grpc_stream_op_buffer sopb;
/** how strongly should we indicate closure with the next write */
grpc_chttp2_send_closed send_closed;
} grpc_chttp2_stream_writing;
struct grpc_chttp2_stream_parsing {
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
gpr_uint32 id;
/** has this stream received a close */
gpr_uint8 received_close;
/** saw a rst_stream */
gpr_uint8 saw_rst_stream;
/** incoming_window has been reduced by this much during parsing */
gpr_uint32 incoming_window_delta;
/** window available for peer to send to us */
gpr_uint32 incoming_window;
/** parsing state for data frames */
grpc_chttp2_data_parser data_parser;
/** reason give to rst_stream */
gpr_uint32 rst_stream_reason;
/* amount of window given */
gpr_uint64 outgoing_window_update;
/** incoming metadata */
grpc_chttp2_incoming_metadata_buffer incoming_metadata;
/*
grpc_linked_mdelem *incoming_metadata;
size_t incoming_metadata_count;
size_t incoming_metadata_capacity;
grpc_linked_mdelem *old_incoming_metadata;
gpr_timespec incoming_deadline;
*/
};
struct grpc_chttp2_stream {
grpc_chttp2_stream_global global;
grpc_chttp2_stream_writing writing;
grpc_chttp2_stream_parsing parsing;
grpc_chttp2_stream_link links[STREAM_LIST_COUNT];
gpr_uint8 included[STREAM_LIST_COUNT];
#if 0
gpr_uint32 outgoing_window_update;
gpr_uint8 cancelled;
grpc_stream_state callback_state;
grpc_stream_op_buffer callback_sopb;
#endif
};
/** Transport writing call flow:
chttp2_transport.c calls grpc_chttp2_unlocking_check_writes to see if writes
are required;
if they are, chttp2_transport.c calls grpc_chttp2_perform_writes to do the
writes.
Once writes have been completed (meaning another write could potentially be
started),
grpc_chttp2_terminate_writing is called. This will call
grpc_chttp2_cleanup_writing, at which
point the write phase is complete. */
/** Someone is unlocking the transport mutex: check to see if writes
are required, and schedule them if so */
int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_writing *writing);
void grpc_chttp2_perform_writes(
grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
void grpc_chttp2_terminate_writing(
grpc_chttp2_transport_writing *transport_writing, int success);
void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_writing *writing);
void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
/** Process one slice of incoming data */
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice);
void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
/** Get a writable stream
\return non-zero if there was a stream available */
void grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_add_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_parsing **stream_parsing);
void grpc_chttp2_list_remove_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing);
int grpc_chttp2_list_have_writing_streams(
grpc_chttp2_transport_writing *transport_writing);
int grpc_chttp2_list_pop_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_add_written_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing);
int grpc_chttp2_list_pop_written_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global);
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_parsing_seen_stream(
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing);
int grpc_chttp2_list_pop_parsing_seen_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_parsing **stream_parsing);
void grpc_chttp2_list_add_waiting_for_concurrency(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_waiting_for_concurrency(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global);
void grpc_chttp2_list_add_closed_waiting_for_parsing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_closed_waiting_for_parsing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global);
void grpc_chttp2_list_add_read_write_state_changed(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_read_write_state_changed(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global);
/** schedule a closure to run without the transport lock taken */
void grpc_chttp2_schedule_closure(
grpc_chttp2_transport_global *transport_global, grpc_iomgr_closure *closure,
int success);
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id);
void grpc_chttp2_add_incoming_goaway(
grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
gpr_slice goaway_text);
void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
void grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
void grpc_chttp2_for_all_streams(
grpc_chttp2_transport_global *transport_global, void *user_data,
void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
grpc_chttp2_stream_global *stream_global));
void grpc_chttp2_parsing_become_skip_parser(
grpc_chttp2_transport_parsing *transport_parsing);
#define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
#define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \
(sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1)
extern int grpc_http_trace;
extern int grpc_flowctl_trace;
#define IF_TRACING(stmt) \
if (!(grpc_http_trace)) \
; \
else \
stmt
#define GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(reason, transport, context, var, \
delta) \
if (!(grpc_flowctl_trace)) { \
} else { \
grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
transport->is_client, context->id, context->var, \
delta); \
}
#define GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(reason, context, var, delta) \
if (!(grpc_flowctl_trace)) { \
} else { \
grpc_chttp2_flowctl_trace(__FILE__, __LINE__, reason, #context, #var, \
context->is_client, 0, context->var, delta); \
}
void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
const char *context, const char *var,
int is_client, gpr_uint32 stream_id,
gpr_int64 current_value, gpr_int64 delta);
#endif

@ -0,0 +1,813 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/chttp2/internal.h"
#include <string.h>
#include "src/core/transport/chttp2/http2_errors.h"
#include "src/core/transport/chttp2/status_conversion.h"
#include "src/core/transport/chttp2/timeout_encoding.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing);
static int init_header_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_continuation);
static int init_data_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing);
static int init_rst_stream_parser(
grpc_chttp2_transport_parsing *transport_parsing);
static int init_settings_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing);
static int init_window_update_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing);
static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing);
static int init_goaway_parser(grpc_chttp2_transport_parsing *transport_parsing);
static int init_skip_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_header);
static int parse_frame_slice(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last);
void grpc_chttp2_prepare_to_read(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing) {
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_parsing *stream_parsing;
transport_parsing->next_stream_id = transport_global->next_stream_id;
/* update the parsing view of incoming window */
if (transport_parsing->incoming_window != transport_global->incoming_window) {
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"parse", transport_parsing, incoming_window,
(gpr_int64)transport_global->incoming_window -
(gpr_int64)transport_parsing->incoming_window);
transport_parsing->incoming_window = transport_global->incoming_window;
}
while (grpc_chttp2_list_pop_incoming_window_updated(
transport_global, transport_parsing, &stream_global, &stream_parsing)) {
stream_parsing->id = stream_global->id;
if (stream_parsing->incoming_window != stream_global->incoming_window) {
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
"parse", transport_parsing, stream_parsing, incoming_window,
(gpr_int64)stream_global->incoming_window -
(gpr_int64)stream_parsing->incoming_window);
stream_parsing->incoming_window = stream_global->incoming_window;
}
}
}
void grpc_chttp2_publish_reads(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing) {
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_parsing *stream_parsing;
/* transport_parsing->last_incoming_stream_id is used as
last-grpc_chttp2_stream-id when
sending GOAWAY frame.
https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
ID. So,
since we don't have server pushed streams, client should send
GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
if (!transport_parsing->is_client) {
transport_global->last_incoming_stream_id =
transport_parsing->incoming_stream_id;
}
/* TODO(ctiller): re-implement */
GPR_ASSERT(transport_parsing->initial_window_update == 0);
/* copy parsing qbuf to global qbuf */
gpr_slice_buffer_move_into(&transport_parsing->qbuf, &transport_global->qbuf);
/* update global settings */
if (transport_parsing->settings_updated) {
memcpy(transport_global->settings[PEER_SETTINGS],
transport_parsing->settings, sizeof(transport_parsing->settings));
transport_parsing->settings_updated = 0;
}
/* update settings based on ack if received */
if (transport_parsing->settings_ack_received) {
memcpy(transport_global->settings[ACKED_SETTINGS],
transport_global->settings[SENT_SETTINGS],
GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
transport_parsing->settings_ack_received = 0;
}
/* move goaway to the global state if we received one (it will be
published later */
if (transport_parsing->goaway_received) {
grpc_chttp2_add_incoming_goaway(transport_global,
transport_parsing->goaway_error,
transport_parsing->goaway_text);
transport_parsing->goaway_text = gpr_empty_slice();
transport_parsing->goaway_received = 0;
}
/* propagate flow control tokens to global state */
if (transport_parsing->outgoing_window_update) {
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"parsed", transport_global, outgoing_window,
transport_parsing->outgoing_window_update);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"parsed", transport_parsing, outgoing_window_update,
-(gpr_int64)transport_parsing->outgoing_window_update);
transport_global->outgoing_window +=
transport_parsing->outgoing_window_update;
transport_parsing->outgoing_window_update = 0;
}
if (transport_parsing->incoming_window_delta) {
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"parsed", transport_global, incoming_window,
-(gpr_int64)transport_parsing->incoming_window_delta);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"parsed", transport_parsing, incoming_window_delta,
-(gpr_int64)transport_parsing->incoming_window_delta);
transport_global->incoming_window -=
transport_parsing->incoming_window_delta;
transport_parsing->incoming_window_delta = 0;
}
/* for each stream that saw an update, fixup global state */
while (grpc_chttp2_list_pop_parsing_seen_stream(
transport_global, transport_parsing, &stream_global, &stream_parsing)) {
/* update incoming flow control window */
if (stream_parsing->incoming_window_delta) {
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
"parsed", transport_parsing, stream_global, incoming_window,
-(gpr_int64)stream_parsing->incoming_window_delta);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
"parsed", transport_parsing, stream_parsing, incoming_window_delta,
-(gpr_int64)stream_parsing->incoming_window_delta);
stream_global->incoming_window -= stream_parsing->incoming_window_delta;
stream_parsing->incoming_window_delta = 0;
grpc_chttp2_list_add_writable_window_update_stream(transport_global,
stream_global);
}
/* update outgoing flow control window */
if (stream_parsing->outgoing_window_update) {
int was_zero = stream_global->outgoing_window <= 0;
int is_zero;
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("parsed", transport_parsing,
stream_global, outgoing_window,
stream_parsing->outgoing_window_update);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
"parsed", transport_parsing, stream_parsing, outgoing_window_update,
-(gpr_int64)stream_parsing->outgoing_window_update);
stream_global->outgoing_window += stream_parsing->outgoing_window_update;
stream_parsing->outgoing_window_update = 0;
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
}
/* updating closed status */
if (stream_parsing->received_close) {
stream_global->read_closed = 1;
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
if (stream_parsing->saw_rst_stream) {
stream_global->cancelled = 1;
stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(stream_parsing->rst_stream_reason);
if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
stream_global->published_cancelled = 1;
}
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
/* publish incoming stream ops */
if (stream_parsing->data_parser.incoming_sopb.nops > 0) {
grpc_incoming_metadata_buffer_move_to_referencing_sopb(
&stream_parsing->incoming_metadata, &stream_global->incoming_metadata,
&stream_parsing->data_parser.incoming_sopb);
grpc_sopb_move_to(&stream_parsing->data_parser.incoming_sopb,
&stream_global->incoming_sopb);
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
}
}
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice) {
gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
if (cur == end) return 1;
switch (transport_parsing->deframe_state) {
case DTS_CLIENT_PREFIX_0:
case DTS_CLIENT_PREFIX_1:
case DTS_CLIENT_PREFIX_2:
case DTS_CLIENT_PREFIX_3:
case DTS_CLIENT_PREFIX_4:
case DTS_CLIENT_PREFIX_5:
case DTS_CLIENT_PREFIX_6:
case DTS_CLIENT_PREFIX_7:
case DTS_CLIENT_PREFIX_8:
case DTS_CLIENT_PREFIX_9:
case DTS_CLIENT_PREFIX_10:
case DTS_CLIENT_PREFIX_11:
case DTS_CLIENT_PREFIX_12:
case DTS_CLIENT_PREFIX_13:
case DTS_CLIENT_PREFIX_14:
case DTS_CLIENT_PREFIX_15:
case DTS_CLIENT_PREFIX_16:
case DTS_CLIENT_PREFIX_17:
case DTS_CLIENT_PREFIX_18:
case DTS_CLIENT_PREFIX_19:
case DTS_CLIENT_PREFIX_20:
case DTS_CLIENT_PREFIX_21:
case DTS_CLIENT_PREFIX_22:
case DTS_CLIENT_PREFIX_23:
while (cur != end && transport_parsing->deframe_state != DTS_FH_0) {
if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
->deframe_state]) {
gpr_log(GPR_ERROR,
"Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
"at byte %d",
GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
->deframe_state],
(int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
[transport_parsing->deframe_state],
*cur, (int)*cur, transport_parsing->deframe_state);
return 0;
}
++cur;
++transport_parsing->deframe_state;
}
if (cur == end) {
return 1;
}
/* fallthrough */
dts_fh_0:
case DTS_FH_0:
GPR_ASSERT(cur < end);
transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_1;
return 1;
}
/* fallthrough */
case DTS_FH_1:
GPR_ASSERT(cur < end);
transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_2;
return 1;
}
/* fallthrough */
case DTS_FH_2:
GPR_ASSERT(cur < end);
transport_parsing->incoming_frame_size |= *cur;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_3;
return 1;
}
/* fallthrough */
case DTS_FH_3:
GPR_ASSERT(cur < end);
transport_parsing->incoming_frame_type = *cur;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_4;
return 1;
}
/* fallthrough */
case DTS_FH_4:
GPR_ASSERT(cur < end);
transport_parsing->incoming_frame_flags = *cur;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_5;
return 1;
}
/* fallthrough */
case DTS_FH_5:
GPR_ASSERT(cur < end);
transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_6;
return 1;
}
/* fallthrough */
case DTS_FH_6:
GPR_ASSERT(cur < end);
transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_7;
return 1;
}
/* fallthrough */
case DTS_FH_7:
GPR_ASSERT(cur < end);
transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_8;
return 1;
}
/* fallthrough */
case DTS_FH_8:
GPR_ASSERT(cur < end);
transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
transport_parsing->deframe_state = DTS_FRAME;
if (!init_frame_parser(transport_parsing)) {
return 0;
}
if (transport_parsing->incoming_stream_id) {
transport_parsing->last_incoming_stream_id =
transport_parsing->incoming_stream_id;
}
if (transport_parsing->incoming_frame_size == 0) {
if (!parse_frame_slice(transport_parsing, gpr_empty_slice(), 1)) {
return 0;
}
transport_parsing->incoming_stream = NULL;
if (++cur == end) {
transport_parsing->deframe_state = DTS_FH_0;
return 1;
}
goto dts_fh_0; /* loop */
}
if (++cur == end) {
return 1;
}
/* fallthrough */
case DTS_FRAME:
GPR_ASSERT(cur < end);
if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
if (!parse_frame_slice(
transport_parsing,
gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 1)) {
return 0;
}
transport_parsing->deframe_state = DTS_FH_0;
transport_parsing->incoming_stream = NULL;
return 1;
} else if ((gpr_uint32)(end - cur) >
transport_parsing->incoming_frame_size) {
if (!parse_frame_slice(
transport_parsing,
gpr_slice_sub_no_ref(
slice, cur - beg,
cur + transport_parsing->incoming_frame_size - beg),
1)) {
return 0;
}
cur += transport_parsing->incoming_frame_size;
transport_parsing->incoming_stream = NULL;
goto dts_fh_0; /* loop */
} else {
if (!parse_frame_slice(
transport_parsing,
gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 0)) {
return 0;
}
transport_parsing->incoming_frame_size -= (end - cur);
return 1;
}
gpr_log(GPR_ERROR, "should never reach here");
abort();
}
gpr_log(GPR_ERROR, "should never reach here");
abort();
return 0;
}
static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
if (transport_parsing->expect_continuation_stream_id != 0) {
if (transport_parsing->incoming_frame_type !=
GRPC_CHTTP2_FRAME_CONTINUATION) {
gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
transport_parsing->incoming_frame_type);
return 0;
}
if (transport_parsing->expect_continuation_stream_id !=
transport_parsing->incoming_stream_id) {
gpr_log(GPR_ERROR,
"Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
"grpc_chttp2_stream %08x",
transport_parsing->expect_continuation_stream_id,
transport_parsing->incoming_stream_id);
return 0;
}
return init_header_frame_parser(transport_parsing, 1);
}
switch (transport_parsing->incoming_frame_type) {
case GRPC_CHTTP2_FRAME_DATA:
return init_data_frame_parser(transport_parsing);
case GRPC_CHTTP2_FRAME_HEADER:
return init_header_frame_parser(transport_parsing, 0);
case GRPC_CHTTP2_FRAME_CONTINUATION:
gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
return 0;
case GRPC_CHTTP2_FRAME_RST_STREAM:
return init_rst_stream_parser(transport_parsing);
case GRPC_CHTTP2_FRAME_SETTINGS:
return init_settings_frame_parser(transport_parsing);
case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
return init_window_update_frame_parser(transport_parsing);
case GRPC_CHTTP2_FRAME_PING:
return init_ping_parser(transport_parsing);
case GRPC_CHTTP2_FRAME_GOAWAY:
return init_goaway_parser(transport_parsing);
default:
gpr_log(GPR_ERROR, "Unknown frame type %02x",
transport_parsing->incoming_frame_type);
return init_skip_frame_parser(transport_parsing, 0);
}
}
static grpc_chttp2_parse_error skip_parser(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
return GRPC_CHTTP2_PARSE_OK;
}
static void skip_header(void *tp, grpc_mdelem *md) { grpc_mdelem_unref(md); }
static int init_skip_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_header) {
if (is_header) {
int is_eoh = transport_parsing->expect_continuation_stream_id != 0;
transport_parsing->parser = grpc_chttp2_header_parser_parse;
transport_parsing->parser_data = &transport_parsing->hpack_parser;
transport_parsing->hpack_parser.on_header = skip_header;
transport_parsing->hpack_parser.on_header_user_data = NULL;
transport_parsing->hpack_parser.is_boundary = is_eoh;
transport_parsing->hpack_parser.is_eof =
is_eoh ? transport_parsing->header_eof : 0;
} else {
transport_parsing->parser = skip_parser;
}
return 1;
}
void grpc_chttp2_parsing_become_skip_parser(
grpc_chttp2_transport_parsing *transport_parsing) {
init_skip_frame_parser(
transport_parsing,
transport_parsing->parser == grpc_chttp2_header_parser_parse);
}
static grpc_chttp2_parse_error update_incoming_window(
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing) {
if (transport_parsing->incoming_frame_size >
transport_parsing->incoming_window) {
gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
transport_parsing->incoming_frame_size,
transport_parsing->incoming_window);
return GRPC_CHTTP2_CONNECTION_ERROR;
}
if (transport_parsing->incoming_frame_size >
stream_parsing->incoming_window) {
gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
transport_parsing->incoming_frame_size,
stream_parsing->incoming_window);
return GRPC_CHTTP2_CONNECTION_ERROR;
}
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"data", transport_parsing, incoming_window,
-(gpr_int64)transport_parsing->incoming_frame_size);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT("data", transport_parsing,
incoming_window_delta,
transport_parsing->incoming_frame_size);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
"data", transport_parsing, stream_parsing, incoming_window,
-(gpr_int64)transport_parsing->incoming_frame_size);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("data", transport_parsing, stream_parsing,
incoming_window_delta,
transport_parsing->incoming_frame_size);
transport_parsing->incoming_window -= transport_parsing->incoming_frame_size;
transport_parsing->incoming_window_delta +=
transport_parsing->incoming_frame_size;
stream_parsing->incoming_window -= transport_parsing->incoming_frame_size;
stream_parsing->incoming_window_delta +=
transport_parsing->incoming_frame_size;
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
return GRPC_CHTTP2_PARSE_OK;
}
static int init_data_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing) {
grpc_chttp2_stream_parsing *stream_parsing =
grpc_chttp2_parsing_lookup_stream(transport_parsing,
transport_parsing->incoming_stream_id);
grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
if (!stream_parsing || stream_parsing->received_close)
return init_skip_frame_parser(transport_parsing, 0);
if (err == GRPC_CHTTP2_PARSE_OK) {
err = update_incoming_window(transport_parsing, stream_parsing);
}
if (err == GRPC_CHTTP2_PARSE_OK) {
err = grpc_chttp2_data_parser_begin_frame(
&stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
}
switch (err) {
case GRPC_CHTTP2_PARSE_OK:
transport_parsing->incoming_stream = stream_parsing;
transport_parsing->parser = grpc_chttp2_data_parser_parse;
transport_parsing->parser_data = &stream_parsing->data_parser;
return 1;
case GRPC_CHTTP2_STREAM_ERROR:
stream_parsing->received_close = 1;
stream_parsing->saw_rst_stream = 1;
stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
gpr_slice_buffer_add(
&transport_parsing->qbuf,
grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR));
return init_skip_frame_parser(transport_parsing, 0);
case GRPC_CHTTP2_CONNECTION_ERROR:
return 0;
}
gpr_log(GPR_ERROR, "should never reach here");
abort();
return 0;
}
static void free_timeout(void *p) { gpr_free(p); }
static void on_header(void *tp, grpc_mdelem *md) {
grpc_chttp2_transport_parsing *transport_parsing = tp;
grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream;
GPR_ASSERT(stream_parsing);
IF_TRACING(gpr_log(GPR_INFO, "HTTP:%d:HDR: %s: %s", stream_parsing->id,
transport_parsing->is_client ? "CLI" : "SVR",
grpc_mdstr_as_c_string(md->key),
grpc_mdstr_as_c_string(md->value)));
if (md->key == transport_parsing->str_grpc_timeout) {
gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
if (!cached_timeout) {
/* not already parsed: parse it now, and store the result away */
cached_timeout = gpr_malloc(sizeof(gpr_timespec));
if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
cached_timeout)) {
gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
grpc_mdstr_as_c_string(md->value));
*cached_timeout = gpr_inf_future;
}
grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
}
grpc_chttp2_incoming_metadata_buffer_set_deadline(
&stream_parsing->incoming_metadata,
gpr_time_add(gpr_now(), *cached_timeout));
grpc_mdelem_unref(md);
} else {
grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
md);
}
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
}
static int init_header_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_continuation) {
int is_eoh = (transport_parsing->incoming_frame_flags &
GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
int via_accept = 0;
grpc_chttp2_stream_parsing *stream_parsing;
if (is_eoh) {
transport_parsing->expect_continuation_stream_id = 0;
} else {
transport_parsing->expect_continuation_stream_id =
transport_parsing->incoming_stream_id;
}
if (!is_continuation) {
transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
}
/* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
stream_parsing = grpc_chttp2_parsing_lookup_stream(
transport_parsing, transport_parsing->incoming_stream_id);
if (stream_parsing == NULL) {
if (is_continuation) {
gpr_log(GPR_ERROR,
"grpc_chttp2_stream disbanded before CONTINUATION received");
return init_skip_frame_parser(transport_parsing, 1);
}
if (transport_parsing->is_client) {
if ((transport_parsing->incoming_stream_id & 1) &&
transport_parsing->incoming_stream_id <
transport_parsing->next_stream_id) {
/* this is an old (probably cancelled) grpc_chttp2_stream */
} else {
gpr_log(GPR_ERROR,
"ignoring new grpc_chttp2_stream creation on client");
}
return init_skip_frame_parser(transport_parsing, 1);
} else if (transport_parsing->last_incoming_stream_id >
transport_parsing->incoming_stream_id) {
gpr_log(GPR_ERROR,
"ignoring out of order new grpc_chttp2_stream request on server; "
"last grpc_chttp2_stream "
"id=%d, new grpc_chttp2_stream id=%d",
transport_parsing->last_incoming_stream_id,
transport_parsing->incoming_stream_id);
return init_skip_frame_parser(transport_parsing, 1);
} else if ((transport_parsing->incoming_stream_id & 1) == 0) {
gpr_log(GPR_ERROR,
"ignoring grpc_chttp2_stream with non-client generated index %d",
transport_parsing->incoming_stream_id);
return init_skip_frame_parser(transport_parsing, 1);
}
stream_parsing = transport_parsing->incoming_stream =
grpc_chttp2_parsing_accept_stream(
transport_parsing, transport_parsing->incoming_stream_id);
if (stream_parsing == NULL) {
gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
return init_skip_frame_parser(transport_parsing, 1);
}
via_accept = 1;
} else {
transport_parsing->incoming_stream = stream_parsing;
}
GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
if (stream_parsing->received_close) {
gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
transport_parsing->incoming_stream = NULL;
return init_skip_frame_parser(transport_parsing, 1);
}
transport_parsing->parser = grpc_chttp2_header_parser_parse;
transport_parsing->parser_data = &transport_parsing->hpack_parser;
transport_parsing->hpack_parser.on_header = on_header;
transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
transport_parsing->hpack_parser.is_boundary = is_eoh;
transport_parsing->hpack_parser.is_eof =
is_eoh ? transport_parsing->header_eof : 0;
if (!is_continuation && (transport_parsing->incoming_frame_flags &
GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
}
return 1;
}
static int init_window_update_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
&transport_parsing->simple.window_update,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
if (transport_parsing->incoming_stream_id) {
transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
transport_parsing, transport_parsing->incoming_stream_id);
}
transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.window_update;
return ok;
}
static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
&transport_parsing->simple.ping,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
transport_parsing->parser = grpc_chttp2_ping_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.ping;
return ok;
}
static int init_rst_stream_parser(
grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
&transport_parsing->simple.rst_stream,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
transport_parsing, transport_parsing->incoming_stream_id);
if (!transport_parsing->incoming_stream) {
return init_skip_frame_parser(transport_parsing, 0);
}
transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
return ok;
}
static int init_goaway_parser(
grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
&transport_parsing->goaway_parser,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
transport_parsing->parser_data = &transport_parsing->goaway_parser;
return ok;
}
static int init_settings_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing) {
int ok;
if (transport_parsing->incoming_stream_id != 0) {
gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
transport_parsing->incoming_stream_id);
return 0;
}
ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
&transport_parsing->simple.settings,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags,
transport_parsing->settings);
if (!ok) {
return 0;
}
if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
transport_parsing->settings_ack_received = 1;
}
transport_parsing->parser = grpc_chttp2_settings_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.settings;
return ok;
}
/*
static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
return window + window_update < MAX_WINDOW;
}
*/
static int parse_frame_slice(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream;
switch (transport_parsing->parser(transport_parsing->parser_data,
transport_parsing, stream_parsing, slice,
is_last)) {
case GRPC_CHTTP2_PARSE_OK:
if (stream_parsing) {
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
}
return 1;
case GRPC_CHTTP2_STREAM_ERROR:
grpc_chttp2_parsing_become_skip_parser(transport_parsing);
if (stream_parsing) {
stream_parsing->saw_rst_stream = 1;
stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
gpr_slice_buffer_add(
&transport_parsing->qbuf,
grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR));
}
return 1;
case GRPC_CHTTP2_CONNECTION_ERROR:
return 0;
}
gpr_log(GPR_ERROR, "should never reach here");
abort();
return 0;
}

@ -47,4 +47,4 @@ grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status);
int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_STATUS_CONVERSION_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_STATUS_CONVERSION_H */

@ -90,4 +90,4 @@ void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof,
grpc_chttp2_hpack_compressor *compressor,
gpr_slice_buffer *output);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_STREAM_ENCODER_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_STREAM_ENCODER_H */

@ -0,0 +1,353 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/chttp2/internal.h"
#include <grpc/support/log.h>
#define TRANSPORT_FROM_GLOBAL(tg) \
((grpc_chttp2_transport *)((char *)(tg)-offsetof(grpc_chttp2_transport, \
global)))
#define STREAM_FROM_GLOBAL(sg) \
((grpc_chttp2_stream *)((char *)(sg)-offsetof(grpc_chttp2_stream, global)))
#define TRANSPORT_FROM_WRITING(tw) \
((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
writing)))
#define STREAM_FROM_WRITING(sw) \
((grpc_chttp2_stream *)((char *)(sw)-offsetof(grpc_chttp2_stream, writing)))
#define TRANSPORT_FROM_PARSING(tp) \
((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
parsing)))
#define STREAM_FROM_PARSING(sp) \
((grpc_chttp2_stream *)((char *)(sp)-offsetof(grpc_chttp2_stream, parsing)))
/* core list management */
static int stream_list_empty(grpc_chttp2_transport *t,
grpc_chttp2_stream_list_id id) {
return t->lists[id].head == NULL;
}
static int stream_list_pop(grpc_chttp2_transport *t,
grpc_chttp2_stream **stream,
grpc_chttp2_stream_list_id id) {
grpc_chttp2_stream *s = t->lists[id].head;
if (s) {
grpc_chttp2_stream *new_head = s->links[id].next;
GPR_ASSERT(s->included[id]);
if (new_head) {
t->lists[id].head = new_head;
new_head->links[id].prev = NULL;
} else {
t->lists[id].head = NULL;
t->lists[id].tail = NULL;
}
s->included[id] = 0;
}
*stream = s;
return s != 0;
}
static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
GPR_ASSERT(s->included[id]);
s->included[id] = 0;
if (s->links[id].prev) {
s->links[id].prev->links[id].next = s->links[id].next;
} else {
GPR_ASSERT(t->lists[id].head == s);
t->lists[id].head = s->links[id].next;
}
if (s->links[id].next) {
s->links[id].next->links[id].prev = s->links[id].prev;
} else {
t->lists[id].tail = s->links[id].prev;
}
}
static void stream_list_maybe_remove(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
if (s->included[id]) {
stream_list_remove(t, s, id);
}
}
static void stream_list_add_tail(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
grpc_chttp2_stream *old_tail;
GPR_ASSERT(!s->included[id]);
old_tail = t->lists[id].tail;
s->links[id].next = NULL;
s->links[id].prev = old_tail;
if (old_tail) {
old_tail->links[id].next = s;
} else {
s->links[id].prev = NULL;
t->lists[id].head = s;
}
t->lists[id].tail = s;
s->included[id] = 1;
}
static void stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
if (s->included[id]) {
return;
}
stream_list_add_tail(t, s, id);
}
/* wrappers for specializations */
void grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_WRITABLE);
*stream_global = &stream->global;
*stream_writing = &stream->writing;
return r;
}
void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) {
stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
STREAM_FROM_WRITING(stream_writing),
GRPC_CHTTP2_LIST_WRITING);
}
int grpc_chttp2_list_have_writing_streams(
grpc_chttp2_transport_writing *transport_writing) {
return !stream_list_empty(TRANSPORT_FROM_WRITING(transport_writing),
GRPC_CHTTP2_LIST_WRITING);
}
int grpc_chttp2_list_pop_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing **stream_writing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
GRPC_CHTTP2_LIST_WRITING);
*stream_writing = &stream->writing;
return r;
}
void grpc_chttp2_list_add_written_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) {
stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
STREAM_FROM_WRITING(stream_writing),
GRPC_CHTTP2_LIST_WRITTEN);
}
int grpc_chttp2_list_pop_written_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream,
GRPC_CHTTP2_LIST_WRITTEN);
*stream_global = &stream->global;
*stream_writing = &stream->writing;
return r;
}
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
}
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
*stream_global = &stream->global;
return r;
}
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global), STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
}
void grpc_chttp2_list_add_parsing_seen_stream(
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing) {
stream_list_add(TRANSPORT_FROM_PARSING(transport_parsing),
STREAM_FROM_PARSING(stream_parsing),
GRPC_CHTTP2_LIST_PARSING_SEEN);
}
int grpc_chttp2_list_pop_parsing_seen_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_parsing **stream_parsing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_PARSING(transport_parsing), &stream,
GRPC_CHTTP2_LIST_PARSING_SEEN);
*stream_global = &stream->global;
*stream_parsing = &stream->parsing;
return r;
}
void grpc_chttp2_list_add_waiting_for_concurrency(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
}
int grpc_chttp2_list_pop_waiting_for_concurrency(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
*stream_global = &stream->global;
return r;
}
void grpc_chttp2_list_add_closed_waiting_for_parsing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
}
int grpc_chttp2_list_pop_closed_waiting_for_parsing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING);
*stream_global = &stream->global;
return r;
}
void grpc_chttp2_list_add_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED);
}
int grpc_chttp2_list_pop_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_parsing **stream_parsing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED);
*stream_global = &stream->global;
*stream_parsing = &stream->parsing;
return r;
}
void grpc_chttp2_list_remove_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED);
}
void grpc_chttp2_list_add_read_write_state_changed(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_READ_WRITE_STATE_CHANGED);
}
int grpc_chttp2_list_pop_read_write_state_changed(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_READ_WRITE_STATE_CHANGED);
*stream_global = &stream->global;
return r;
}
void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
stream_list_add_tail(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
}
void grpc_chttp2_unregister_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
stream_list_remove(t, s, GRPC_CHTTP2_LIST_ALL_STREAMS);
}
void grpc_chttp2_for_all_streams(
grpc_chttp2_transport_global *transport_global, void *user_data,
void (*cb)(grpc_chttp2_transport_global *transport_global, void *user_data,
grpc_chttp2_stream_global *stream_global)) {
grpc_chttp2_stream *s;
for (s = TRANSPORT_FROM_GLOBAL(transport_global)
->lists[GRPC_CHTTP2_LIST_ALL_STREAMS]
.head;
s; s = s->links[GRPC_CHTTP2_LIST_ALL_STREAMS].next) {
cb(transport_global, user_data, &s->global);
}
}

@ -32,8 +32,12 @@
*/
#include "src/core/transport/chttp2/stream_map.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map,
size_t initial_capacity) {
@ -92,6 +96,41 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, gpr_uint32 key,
map->count = count + 1;
}
void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src,
grpc_chttp2_stream_map *dst) {
/* if src is empty we dont need to do anything */
if (src->count == src->free) {
return;
}
/* if dst is empty we simply need to swap */
if (dst->count == dst->free) {
GPR_SWAP(grpc_chttp2_stream_map, *src, *dst);
return;
}
/* the first element of src must be greater than the last of dst...
* however the maps may need compacting for this property to hold */
if (src->keys[0] <= dst->keys[dst->count - 1]) {
src->count = compact(src->keys, src->values, src->count);
src->free = 0;
dst->count = compact(dst->keys, dst->values, dst->count);
dst->free = 0;
}
GPR_ASSERT(src->keys[0] > dst->keys[dst->count - 1]);
/* if dst doesn't have capacity, resize */
if (dst->count + src->count > dst->capacity) {
dst->capacity = GPR_MAX(dst->capacity * 3 / 2, dst->count + src->count);
dst->keys = gpr_realloc(dst->keys, dst->capacity * sizeof(gpr_uint32));
dst->values = gpr_realloc(dst->values, dst->capacity * sizeof(void *));
}
memcpy(dst->keys + dst->count, src->keys, src->count * sizeof(gpr_uint32));
memcpy(dst->values + dst->count, src->values,
src->count * sizeof(void*));
dst->count += src->count;
dst->free += src->free;
src->count = 0;
src->free = 0;
}
static void **find(grpc_chttp2_stream_map *map, gpr_uint32 key) {
size_t min_idx = 0;
size_t max_idx = map->count;
@ -127,6 +166,11 @@ void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map,
out = *pvalue;
*pvalue = NULL;
map->free += (out != NULL);
/* recognize complete emptyness and ensure we can skip
* defragmentation later */
if (map->free == map->count) {
map->free = map->count = 0;
}
}
return out;
}

@ -66,6 +66,10 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, gpr_uint32 key,
void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map,
gpr_uint32 key);
/* Move all elements of src into dst */
void grpc_chttp2_stream_map_move_into(grpc_chttp2_stream_map *src,
grpc_chttp2_stream_map *dst);
/* Return an existing key, or NULL if it does not exist */
void *grpc_chttp2_stream_map_find(grpc_chttp2_stream_map *map, gpr_uint32 key);
@ -78,4 +82,4 @@ void grpc_chttp2_stream_map_for_each(grpc_chttp2_stream_map *map,
void *value),
void *user_data);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_STREAM_MAP_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_STREAM_MAP_H */

@ -44,4 +44,4 @@
void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer);
int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TIMEOUT_ENCODING_H */

@ -56,19 +56,18 @@ void grpc_chttp2_hpack_write_varint_tail(gpr_uint32 tail_value,
((n) < GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits) \
? 1 \
: grpc_chttp2_hpack_varint_length( \
(n) - GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits)))
(n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits)))
#define GRPC_CHTTP2_WRITE_VARINT(n, prefix_bits, prefix_or, target, length) \
do { \
gpr_uint8* tgt = target; \
if ((length) == 1) { \
(tgt)[0] = (prefix_or) | (n); \
} else { \
(tgt)[0] = (prefix_or) | GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits); \
grpc_chttp2_hpack_write_varint_tail( \
(n) - GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits), (tgt) + 1, \
(length) - 1); \
} \
#define GRPC_CHTTP2_WRITE_VARINT(n, prefix_bits, prefix_or, target, length) \
do { \
gpr_uint8* tgt = target; \
if ((length) == 1) { \
(tgt)[0] = (prefix_or) | (n); \
} else { \
(tgt)[0] = (prefix_or) | GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits); \
grpc_chttp2_hpack_write_varint_tail( \
(n)-GRPC_CHTTP2_MAX_IN_PREFIX(prefix_bits), (tgt) + 1, (length)-1); \
} \
} while (0)
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_VARINT_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_VARINT_H */

@ -0,0 +1,215 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/transport/chttp2/internal.h"
#include "src/core/transport/chttp2/http2_errors.h"
#include <grpc/support/log.h>
static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing);
static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status);
int grpc_chttp2_unlocking_check_writes(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_writing *stream_writing;
gpr_uint32 window_delta;
/* simple writes are queued to qbuf, and flushed here */
gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf);
GPR_ASSERT(transport_global->qbuf.count == 0);
if (transport_global->dirtied_local_settings &&
!transport_global->sent_local_settings) {
gpr_slice_buffer_add(
&transport_writing->outbuf,
grpc_chttp2_settings_create(transport_global->settings[SENT_SETTINGS],
transport_global->settings[LOCAL_SETTINGS],
transport_global->force_send_settings,
GRPC_CHTTP2_NUM_SETTINGS));
transport_global->force_send_settings = 0;
transport_global->dirtied_local_settings = 0;
transport_global->sent_local_settings = 1;
}
/* for each grpc_chttp2_stream that's become writable, frame it's data
(according to
available window sizes) and add to the output buffer */
while (transport_global->outgoing_window &&
grpc_chttp2_list_pop_writable_stream(transport_global,
transport_writing, &stream_global,
&stream_writing) &&
stream_global->outgoing_window > 0) {
stream_writing->id = stream_global->id;
window_delta = grpc_chttp2_preencode(
stream_global->outgoing_sopb->ops, &stream_global->outgoing_sopb->nops,
GPR_MIN(transport_global->outgoing_window,
stream_global->outgoing_window),
&stream_writing->sopb);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"write", transport_global, outgoing_window, -(gpr_int64)window_delta);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
outgoing_window, -(gpr_int64)window_delta);
transport_global->outgoing_window -= window_delta;
stream_global->outgoing_window -= window_delta;
if (stream_global->write_state == WRITE_STATE_QUEUED_CLOSE &&
stream_global->outgoing_sopb->nops == 0) {
if (!transport_global->is_client && !stream_global->read_closed) {
stream_writing->send_closed = SEND_CLOSED_WITH_RST_STREAM;
} else {
stream_writing->send_closed = SEND_CLOSED;
}
}
if (stream_writing->sopb.nops > 0 ||
stream_writing->send_closed != DONT_SEND_CLOSED) {
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
}
/* we should either exhaust window or have no ops left, but not both */
if (stream_global->outgoing_sopb->nops == 0) {
stream_global->outgoing_sopb = NULL;
grpc_chttp2_schedule_closure(transport_global,
stream_global->send_done_closure, 1);
} else if (stream_global->outgoing_window > 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
}
/* for each grpc_chttp2_stream that wants to update its window, add that
* window here */
while (grpc_chttp2_list_pop_writable_window_update_stream(transport_global,
&stream_global)) {
window_delta =
transport_global->settings[LOCAL_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
stream_global->incoming_window;
if (!stream_global->read_closed && window_delta > 0) {
gpr_slice_buffer_add(
&transport_writing->outbuf,
grpc_chttp2_window_update_create(stream_global->id, window_delta));
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
incoming_window, window_delta);
stream_global->incoming_window += window_delta;
grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global);
}
}
/* if the grpc_chttp2_transport is ready to send a window update, do so here
* also */
if (transport_global->incoming_window <
transport_global->connection_window_target * 3 / 4) {
window_delta = transport_global->connection_window_target -
transport_global->incoming_window;
gpr_slice_buffer_add(&transport_writing->outbuf,
grpc_chttp2_window_update_create(0, window_delta));
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT("write", transport_global,
incoming_window, window_delta);
transport_global->incoming_window += window_delta;
}
return transport_writing->outbuf.count > 0 ||
grpc_chttp2_list_have_writing_streams(transport_writing);
}
void grpc_chttp2_perform_writes(
grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint) {
GPR_ASSERT(transport_writing->outbuf.count > 0 ||
grpc_chttp2_list_have_writing_streams(transport_writing));
finalize_outbuf(transport_writing);
GPR_ASSERT(transport_writing->outbuf.count > 0);
GPR_ASSERT(endpoint);
switch (grpc_endpoint_write(endpoint, transport_writing->outbuf.slices,
transport_writing->outbuf.count, finish_write_cb,
transport_writing)) {
case GRPC_ENDPOINT_WRITE_DONE:
grpc_chttp2_terminate_writing(transport_writing, 1);
break;
case GRPC_ENDPOINT_WRITE_ERROR:
grpc_chttp2_terminate_writing(transport_writing, 0);
break;
case GRPC_ENDPOINT_WRITE_PENDING:
break;
}
}
static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_stream_writing *stream_writing;
while (
grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
grpc_chttp2_encode(stream_writing->sopb.ops, stream_writing->sopb.nops,
stream_writing->send_closed != DONT_SEND_CLOSED,
stream_writing->id, &transport_writing->hpack_compressor,
&transport_writing->outbuf);
stream_writing->sopb.nops = 0;
if (stream_writing->send_closed == SEND_CLOSED_WITH_RST_STREAM) {
gpr_slice_buffer_add(&transport_writing->outbuf,
grpc_chttp2_rst_stream_create(stream_writing->id,
GRPC_CHTTP2_NO_ERROR));
}
grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
}
}
static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status) {
grpc_chttp2_transport_writing *transport_writing = tw;
grpc_chttp2_terminate_writing(transport_writing,
write_status == GRPC_ENDPOINT_CB_OK);
}
void grpc_chttp2_cleanup_writing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_stream_writing *stream_writing;
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_written_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
if (stream_writing->send_closed != DONT_SEND_CLOSED) {
stream_global->write_state = WRITE_STATE_SENT_CLOSE;
if (!transport_global->is_client) {
stream_global->read_closed = 1;
}
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
}
transport_writing->outbuf.count = 0;
transport_writing->outbuf.length = 0;
}

File diff suppressed because it is too large Load Diff

@ -47,4 +47,4 @@ void grpc_create_chttp2_transport(grpc_transport_setup_callback setup,
size_t nslices, grpc_mdctx *metadata_context,
int is_client);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TRANSPORT_H */
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TRANSPORT_H */

@ -65,7 +65,7 @@ void grpc_sopb_swap(grpc_stream_op_buffer *a, grpc_stream_op_buffer *b) {
if (a->ops == a->inlined_ops) {
if (b->ops == b->inlined_ops) {
/* swap contents of inlined buffer */
gpr_slice temp[GRPC_SOPB_INLINE_ELEMENTS];
grpc_stream_op temp[GRPC_SOPB_INLINE_ELEMENTS];
memcpy(temp, a->ops, b->nops * sizeof(grpc_stream_op));
memcpy(a->ops, b->ops, a->nops * sizeof(grpc_stream_op));
memcpy(b->ops, temp, b->nops * sizeof(grpc_stream_op));
@ -163,6 +163,18 @@ void grpc_sopb_append(grpc_stream_op_buffer *sopb, grpc_stream_op *ops,
sopb->nops = new_nops;
}
void grpc_sopb_move_to(grpc_stream_op_buffer *src, grpc_stream_op_buffer *dst) {
if (src->nops == 0) {
return;
}
if (dst->nops == 0) {
grpc_sopb_swap(src, dst);
return;
}
grpc_sopb_append(dst, src->ops, src->nops);
src->nops = 0;
}
static void assert_valid_list(grpc_mdelem_list *list) {
#ifndef NDEBUG
grpc_linked_mdelem *l;

@ -199,6 +199,8 @@ void grpc_sopb_add_slice(grpc_stream_op_buffer *sopb, gpr_slice slice);
void grpc_sopb_append(grpc_stream_op_buffer *sopb, grpc_stream_op *ops,
size_t nops);
void grpc_sopb_move_to(grpc_stream_op_buffer *src, grpc_stream_op_buffer *dst);
char *grpc_sopb_string(grpc_stream_op_buffer *sopb);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_STREAM_OP_H */

@ -73,9 +73,8 @@ void grpc_transport_destroy_stream(grpc_transport *transport,
transport->vtable->destroy_stream(transport, stream);
}
void grpc_transport_ping(grpc_transport *transport, void (*cb)(void *user_data),
void *user_data) {
transport->vtable->ping(transport, cb, user_data);
void grpc_transport_ping(grpc_transport *transport, grpc_iomgr_closure *cb) {
transport->vtable->ping(transport, cb);
}
void grpc_transport_setup_cancel(grpc_transport_setup *setup) {
@ -99,13 +98,13 @@ void grpc_transport_setup_del_interested_party(grpc_transport_setup *setup,
void grpc_transport_stream_op_finish_with_failure(
grpc_transport_stream_op *op) {
if (op->send_ops) {
op->on_done_send(op->send_user_data, 0);
op->on_done_send->cb(op->on_done_send->cb_arg, 0);
}
if (op->recv_ops) {
op->on_done_recv(op->recv_user_data, 0);
op->on_done_recv->cb(op->on_done_recv->cb_arg, 0);
}
if (op->on_consumed) {
op->on_consumed(op->on_consumed_user_data, 0);
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
}
}

@ -64,18 +64,15 @@ typedef enum grpc_stream_state {
/* Transport op: a set of operations to perform on a transport */
typedef struct grpc_transport_stream_op {
void (*on_consumed)(void *user_data, int success);
void *on_consumed_user_data;
grpc_iomgr_closure *on_consumed;
grpc_stream_op_buffer *send_ops;
int is_last_send;
void (*on_done_send)(void *user_data, int success);
void *send_user_data;
grpc_iomgr_closure *on_done_send;
grpc_stream_op_buffer *recv_ops;
grpc_stream_state *recv_state;
void (*on_done_recv)(void *user_data, int success);
void *recv_user_data;
grpc_iomgr_closure *on_done_recv;
grpc_pollset *bind_pollset;
@ -167,11 +164,8 @@ void grpc_transport_perform_op(grpc_transport *transport, grpc_stream *stream,
/* Send a ping on a transport
Calls cb with user data when a response is received.
cb *MAY* be called with arbitrary transport level locks held. It is not safe
to call into the transport during cb. */
void grpc_transport_ping(grpc_transport *transport, void (*cb)(void *user_data),
void *user_data);
Calls cb with user data when a response is received. */
void grpc_transport_ping(grpc_transport *transport, grpc_iomgr_closure *cb);
/* Advise peer of pending connection termination. */
void grpc_transport_goaway(grpc_transport *transport, grpc_status_code status,

@ -64,8 +64,7 @@ typedef struct grpc_transport_vtable {
void (*close)(grpc_transport *self);
/* implementation of grpc_transport_ping */
void (*ping)(grpc_transport *self, void (*cb)(void *user_data),
void *user_data);
void (*ping)(grpc_transport *self, grpc_iomgr_closure *cb);
/* implementation of grpc_transport_destroy */
void (*destroy)(grpc_transport *self);

@ -97,7 +97,7 @@ static void end_test(grpc_end2end_test_fixture *f) {
static gpr_slice large_slice(void) {
gpr_slice slice = gpr_slice_malloc(1000000);
memset(GPR_SLICE_START_PTR(slice), 0xab, GPR_SLICE_LENGTH(slice));
memset(GPR_SLICE_START_PTR(slice), 'x', GPR_SLICE_LENGTH(slice));
return slice;
}

@ -55,19 +55,15 @@ typedef struct {
unsigned char index;
} spec;
static const spec fields[] = {{"INDEXED_FIELD", 0X80, 1, 1},
{"INDEXED_FIELD_X", 0X80, 1, 2},
{"LITHDR_INCIDX", 0X40, 2, 1},
{"LITHDR_INCIDX_X", 0X40, 2, 2},
{"LITHDR_INCIDX_V", 0X40, 2, 0},
{"LITHDR_NOTIDX", 0X00, 4, 1},
{"LITHDR_NOTIDX_X", 0X00, 4, 2},
{"LITHDR_NOTIDX_V", 0X00, 4, 0},
{"LITHDR_NVRIDX", 0X10, 4, 1},
{"LITHDR_NVRIDX_X", 0X10, 4, 2},
{"LITHDR_NVRIDX_V", 0X10, 4, 0},
{"MAX_TBL_SIZE", 0X20, 3, 1},
{"MAX_TBL_SIZE_X", 0X20, 3, 2}, };
static const spec fields[] = {
{"INDEXED_FIELD", 0X80, 1, 1}, {"INDEXED_FIELD_X", 0X80, 1, 2},
{"LITHDR_INCIDX", 0X40, 2, 1}, {"LITHDR_INCIDX_X", 0X40, 2, 2},
{"LITHDR_INCIDX_V", 0X40, 2, 0}, {"LITHDR_NOTIDX", 0X00, 4, 1},
{"LITHDR_NOTIDX_X", 0X00, 4, 2}, {"LITHDR_NOTIDX_V", 0X00, 4, 0},
{"LITHDR_NVRIDX", 0X10, 4, 1}, {"LITHDR_NVRIDX_X", 0X10, 4, 2},
{"LITHDR_NVRIDX_V", 0X10, 4, 0}, {"MAX_TBL_SIZE", 0X20, 3, 1},
{"MAX_TBL_SIZE_X", 0X20, 3, 2},
};
static const int num_fields = sizeof(fields) / sizeof(*fields);
@ -129,13 +125,9 @@ static void generate_first_byte_lut(void) {
#define MAXHUFFSTATES 1024
/* represents a set of symbols as an array of booleans indicating inclusion */
typedef struct {
char included[GRPC_CHTTP2_NUM_HUFFSYMS];
} symset;
typedef struct { char included[GRPC_CHTTP2_NUM_HUFFSYMS]; } symset;
/* represents a lookup table indexed by a nibble */
typedef struct {
int values[16];
} nibblelut;
typedef struct { int values[16]; } nibblelut;
/* returns a symset that includes all possible symbols */
static symset symset_all(void) {
@ -268,8 +260,7 @@ static void build_dec_tbl(int state, int nibble, int nibbits, unsigned bitofs,
/* recurse down for this bit */
build_dec_tbl(state, (nibble << 1) | bit, nibbits + 1, bitofs + 1, emit,
nextsyms);
next:
;
next:;
}
}

@ -864,6 +864,8 @@ src/core/transport/chttp2/hpack_parser.h \
src/core/transport/chttp2/hpack_table.h \
src/core/transport/chttp2/http2_errors.h \
src/core/transport/chttp2/huffsyms.h \
src/core/transport/chttp2/incoming_metadata.h \
src/core/transport/chttp2/internal.h \
src/core/transport/chttp2/status_conversion.h \
src/core/transport/chttp2/stream_encoder.h \
src/core/transport/chttp2/stream_map.h \
@ -989,11 +991,15 @@ src/core/transport/chttp2/frame_window_update.c \
src/core/transport/chttp2/hpack_parser.c \
src/core/transport/chttp2/hpack_table.c \
src/core/transport/chttp2/huffsyms.c \
src/core/transport/chttp2/incoming_metadata.c \
src/core/transport/chttp2/parsing.c \
src/core/transport/chttp2/status_conversion.c \
src/core/transport/chttp2/stream_encoder.c \
src/core/transport/chttp2/stream_lists.c \
src/core/transport/chttp2/stream_map.c \
src/core/transport/chttp2/timeout_encoding.c \
src/core/transport/chttp2/varint.c \
src/core/transport/chttp2/writing.c \
src/core/transport/chttp2_transport.c \
src/core/transport/metadata.c \
src/core/transport/stream_op.c \

@ -253,6 +253,8 @@
<ClInclude Include="..\..\src\core\transport\chttp2\hpack_table.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\http2_errors.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\huffsyms.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\incoming_metadata.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\internal.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\status_conversion.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\stream_encoder.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\stream_map.h" />
@ -494,16 +496,24 @@
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\huffsyms.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\incoming_metadata.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\parsing.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\status_conversion.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_encoder.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_lists.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_map.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\timeout_encoding.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\varint.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\writing.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2_transport.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\metadata.c">

@ -343,12 +343,21 @@
<ClCompile Include="..\..\src\core\transport\chttp2\huffsyms.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\incoming_metadata.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\parsing.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\status_conversion.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_encoder.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_lists.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_map.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
@ -358,6 +367,9 @@
<ClCompile Include="..\..\src\core\transport\chttp2\varint.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\writing.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2_transport.c">
<Filter>src\core\transport</Filter>
</ClCompile>
@ -695,6 +707,12 @@
<ClInclude Include="..\..\src\core\transport\chttp2\huffsyms.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\transport\chttp2\incoming_metadata.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\transport\chttp2\internal.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\transport\chttp2\status_conversion.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>

@ -235,6 +235,8 @@
<ClInclude Include="..\..\src\core\transport\chttp2\hpack_table.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\http2_errors.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\huffsyms.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\incoming_metadata.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\internal.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\status_conversion.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\stream_encoder.h" />
<ClInclude Include="..\..\src\core\transport\chttp2\stream_map.h" />
@ -432,16 +434,24 @@
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\huffsyms.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\incoming_metadata.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\parsing.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\status_conversion.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_encoder.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_lists.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_map.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\timeout_encoding.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\varint.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\writing.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2_transport.c">
</ClCompile>
<ClCompile Include="..\..\src\core\transport\metadata.c">

@ -277,12 +277,21 @@
<ClCompile Include="..\..\src\core\transport\chttp2\huffsyms.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\incoming_metadata.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\parsing.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\status_conversion.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_encoder.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_lists.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\stream_map.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
@ -292,6 +301,9 @@
<ClCompile Include="..\..\src\core\transport\chttp2\varint.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2\writing.c">
<Filter>src\core\transport\chttp2</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\transport\chttp2_transport.c">
<Filter>src\core\transport</Filter>
</ClCompile>
@ -578,6 +590,12 @@
<ClInclude Include="..\..\src\core\transport\chttp2\huffsyms.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\transport\chttp2\incoming_metadata.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\transport\chttp2\internal.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\transport\chttp2\status_conversion.h">
<Filter>src\core\transport\chttp2</Filter>
</ClInclude>

Loading…
Cancel
Save