|  | @@ -42,22 +42,28 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  | +#include <grpc/support/string_util.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | +static int init_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                             grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  |  static int init_header_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing, int is_continuation);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | +    int is_continuation);
 | 
	
		
			
				|  |  |  static int init_data_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  |  static int init_rst_stream_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  |  static int init_settings_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, 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);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | +static int init_ping_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                            grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | +static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                              grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  |  static int init_skip_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing, int is_header);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | +    int is_header);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |                               grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
	
		
			
				|  | @@ -74,23 +80,11 @@ void grpc_chttp2_prepare_to_read(
 | 
	
		
			
				|  |  |    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(
 | 
	
		
			
				|  |  | +  while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
 | 
	
		
			
				|  |  |        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;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing,
 | 
	
		
			
				|  |  | +                                 incoming_window, stream_global,
 | 
	
		
			
				|  |  | +                                 unannounced_incoming_window_for_parse);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
 | 
	
	
		
			
				|  | @@ -101,6 +95,8 @@ void grpc_chttp2_publish_reads(
 | 
	
		
			
				|  |  |      grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  |    grpc_chttp2_stream_global *stream_global;
 | 
	
		
			
				|  |  |    grpc_chttp2_stream_parsing *stream_parsing;
 | 
	
		
			
				|  |  | +  int was_zero;
 | 
	
		
			
				|  |  | +  int is_zero;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* transport_parsing->last_incoming_stream_id is used as
 | 
	
		
			
				|  |  |       last-grpc_chttp2_stream-id when
 | 
	
	
		
			
				|  | @@ -144,98 +140,102 @@ void grpc_chttp2_publish_reads(
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* 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;
 | 
	
		
			
				|  |  | +  was_zero = transport_global->outgoing_window <= 0;
 | 
	
		
			
				|  |  | +  GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
 | 
	
		
			
				|  |  | +                                  transport_parsing, outgoing_window);
 | 
	
		
			
				|  |  | +  is_zero = transport_global->outgoing_window <= 0;
 | 
	
		
			
				|  |  | +  if (was_zero && !is_zero) {
 | 
	
		
			
				|  |  | +    while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
 | 
	
		
			
				|  |  | +                                                     &stream_global)) {
 | 
	
		
			
				|  |  | +      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (transport_parsing->incoming_window <
 | 
	
		
			
				|  |  | +      transport_global->connection_window_target * 3 / 4) {
 | 
	
		
			
				|  |  | +    gpr_int64 announce_bytes = transport_global->connection_window_target -
 | 
	
		
			
				|  |  | +                               transport_parsing->incoming_window;
 | 
	
		
			
				|  |  | +    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
 | 
	
		
			
				|  |  | +                                      announce_incoming_window, announce_bytes);
 | 
	
		
			
				|  |  | +    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
 | 
	
		
			
				|  |  | +                                      incoming_window, announce_bytes);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* 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);
 | 
	
		
			
				|  |  | -      GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
 | 
	
		
			
				|  |  | -          "parsed", transport_parsing, stream_global, max_recv_bytes,
 | 
	
		
			
				|  |  | -          -(gpr_int64)stream_parsing->incoming_window_delta);
 | 
	
		
			
				|  |  | -      stream_global->incoming_window -= stream_parsing->incoming_window_delta;
 | 
	
		
			
				|  |  | -      GPR_ASSERT(stream_global->max_recv_bytes >=
 | 
	
		
			
				|  |  | -                 stream_parsing->incoming_window_delta);
 | 
	
		
			
				|  |  | -      stream_global->max_recv_bytes -= stream_parsing->incoming_window_delta;
 | 
	
		
			
				|  |  | -      stream_parsing->incoming_window_delta = 0;
 | 
	
		
			
				|  |  | -      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
 | 
	
		
			
				|  |  | +    if (stream_parsing->seen_error) {
 | 
	
		
			
				|  |  | +      stream_global->seen_error = 1;
 | 
	
		
			
				|  |  | +      grpc_chttp2_list_add_check_read_ops(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);
 | 
	
		
			
				|  |  | -      GPR_ASSERT(stream_parsing->outgoing_window_update <= GPR_UINT32_MAX);
 | 
	
		
			
				|  |  | -      stream_global->outgoing_window +=
 | 
	
		
			
				|  |  | -          (gpr_uint32)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);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +    was_zero = stream_global->outgoing_window <= 0;
 | 
	
		
			
				|  |  | +    GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
 | 
	
		
			
				|  |  | +                                 outgoing_window, stream_parsing,
 | 
	
		
			
				|  |  | +                                 outgoing_window);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    stream_global->max_recv_bytes -= (gpr_uint32)GPR_MIN(
 | 
	
		
			
				|  |  | +        stream_global->max_recv_bytes, stream_parsing->received_bytes);
 | 
	
		
			
				|  |  | +    stream_parsing->received_bytes = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* publish incoming stream ops */
 | 
	
		
			
				|  |  | +    if (stream_global->incoming_frames.tail != NULL) {
 | 
	
		
			
				|  |  | +      stream_global->incoming_frames.tail->is_tail = 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (stream_parsing->data_parser.incoming_frames.head != NULL) {
 | 
	
		
			
				|  |  | +      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    grpc_chttp2_incoming_frame_queue_merge(
 | 
	
		
			
				|  |  | +        &stream_global->incoming_frames,
 | 
	
		
			
				|  |  | +        &stream_parsing->data_parser.incoming_frames);
 | 
	
		
			
				|  |  | +    if (stream_global->incoming_frames.tail != NULL) {
 | 
	
		
			
				|  |  | +      stream_global->incoming_frames.tail->is_tail = 1;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!stream_global->published_initial_metadata &&
 | 
	
		
			
				|  |  | +        stream_parsing->got_metadata_on_parse[0]) {
 | 
	
		
			
				|  |  | +      stream_parsing->got_metadata_on_parse[0] = 0;
 | 
	
		
			
				|  |  | +      stream_global->published_initial_metadata = 1;
 | 
	
		
			
				|  |  | +      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
 | 
	
		
			
				|  |  | +               stream_parsing->metadata_buffer[0],
 | 
	
		
			
				|  |  | +               stream_global->received_initial_metadata);
 | 
	
		
			
				|  |  | +      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (!stream_global->published_trailing_metadata &&
 | 
	
		
			
				|  |  | +        stream_parsing->got_metadata_on_parse[1]) {
 | 
	
		
			
				|  |  | +      stream_parsing->got_metadata_on_parse[1] = 0;
 | 
	
		
			
				|  |  | +      stream_global->published_trailing_metadata = 1;
 | 
	
		
			
				|  |  | +      GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
 | 
	
		
			
				|  |  | +               stream_parsing->metadata_buffer[1],
 | 
	
		
			
				|  |  | +               stream_global->received_trailing_metadata);
 | 
	
		
			
				|  |  | +      grpc_chttp2_list_add_check_read_ops(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(
 | 
	
		
			
				|  |  | -          (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
 | 
	
		
			
				|  |  | -      if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
 | 
	
		
			
				|  |  | -        stream_global->published_cancelled = 1;
 | 
	
		
			
				|  |  | +      if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
 | 
	
		
			
				|  |  | +        grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
 | 
	
		
			
				|  |  | +            (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
 | 
	
		
			
				|  |  | +        char *status_details;
 | 
	
		
			
				|  |  | +        gpr_slice slice_details;
 | 
	
		
			
				|  |  | +        gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
 | 
	
		
			
				|  |  | +                     stream_parsing->rst_stream_reason);
 | 
	
		
			
				|  |  | +        slice_details = gpr_slice_from_copied_string(status_details);
 | 
	
		
			
				|  |  | +        gpr_free(status_details);
 | 
	
		
			
				|  |  | +        grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | +                                status_code, &slice_details);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      grpc_chttp2_list_add_read_write_state_changed(transport_global,
 | 
	
		
			
				|  |  | -                                                    stream_global);
 | 
	
		
			
				|  |  | +      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | +                                     1, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /* 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);
 | 
	
		
			
				|  |  | +    if (stream_parsing->received_close) {
 | 
	
		
			
				|  |  | +      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | +                                     1, 0);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -363,7 +363,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  |        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
 | 
	
		
			
				|  |  |        transport_parsing->deframe_state = GRPC_DTS_FRAME;
 | 
	
		
			
				|  |  | -      if (!init_frame_parser(transport_parsing)) {
 | 
	
		
			
				|  |  | +      if (!init_frame_parser(exec_ctx, transport_parsing)) {
 | 
	
		
			
				|  |  |          return 0;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        if (transport_parsing->incoming_stream_id) {
 | 
	
	
		
			
				|  | @@ -428,7 +428,8 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |    GPR_UNREACHABLE_CODE(return 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +static int init_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                             grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  |    if (transport_parsing->expect_continuation_stream_id != 0) {
 | 
	
		
			
				|  |  |      if (transport_parsing->incoming_frame_type !=
 | 
	
		
			
				|  |  |          GRPC_CHTTP2_FRAME_CONTINUATION) {
 | 
	
	
		
			
				|  | @@ -445,30 +446,30 @@ static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  |                transport_parsing->incoming_stream_id);
 | 
	
		
			
				|  |  |        return 0;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return init_header_frame_parser(transport_parsing, 1);
 | 
	
		
			
				|  |  | +    return init_header_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    switch (transport_parsing->incoming_frame_type) {
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_DATA:
 | 
	
		
			
				|  |  | -      return init_data_frame_parser(transport_parsing);
 | 
	
		
			
				|  |  | +      return init_data_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_HEADER:
 | 
	
		
			
				|  |  | -      return init_header_frame_parser(transport_parsing, 0);
 | 
	
		
			
				|  |  | +      return init_header_frame_parser(exec_ctx, 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);
 | 
	
		
			
				|  |  | +      return init_rst_stream_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_SETTINGS:
 | 
	
		
			
				|  |  | -      return init_settings_frame_parser(transport_parsing);
 | 
	
		
			
				|  |  | +      return init_settings_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
 | 
	
		
			
				|  |  | -      return init_window_update_frame_parser(transport_parsing);
 | 
	
		
			
				|  |  | +      return init_window_update_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_PING:
 | 
	
		
			
				|  |  | -      return init_ping_parser(transport_parsing);
 | 
	
		
			
				|  |  | +      return init_ping_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_GOAWAY:
 | 
	
		
			
				|  |  | -      return init_goaway_parser(transport_parsing);
 | 
	
		
			
				|  |  | +      return init_goaway_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |      default:
 | 
	
		
			
				|  |  |        gpr_log(GPR_ERROR, "Unknown frame type %02x",
 | 
	
		
			
				|  |  |                transport_parsing->incoming_frame_type);
 | 
	
		
			
				|  |  | -      return init_skip_frame_parser(transport_parsing, 0);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -482,7 +483,8 @@ static grpc_chttp2_parse_error skip_parser(
 | 
	
		
			
				|  |  |  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) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | +    int is_header) {
 | 
	
		
			
				|  |  |    if (is_header) {
 | 
	
		
			
				|  |  |      gpr_uint8 is_eoh = transport_parsing->expect_continuation_stream_id != 0;
 | 
	
		
			
				|  |  |      transport_parsing->parser = grpc_chttp2_header_parser_parse;
 | 
	
	
		
			
				|  | @@ -499,65 +501,51 @@ static int init_skip_frame_parser(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void grpc_chttp2_parsing_become_skip_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  |    init_skip_frame_parser(
 | 
	
		
			
				|  |  | -      transport_parsing,
 | 
	
		
			
				|  |  | +      exec_ctx, 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_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  |      grpc_chttp2_stream_parsing *stream_parsing) {
 | 
	
		
			
				|  |  | -  if (transport_parsing->incoming_frame_size >
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_window) {
 | 
	
		
			
				|  |  | +  gpr_uint32 incoming_frame_size = transport_parsing->incoming_frame_size;
 | 
	
		
			
				|  |  | +  if (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) {
 | 
	
		
			
				|  |  | +  if (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_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
 | 
	
		
			
				|  |  | +                                   incoming_frame_size);
 | 
	
		
			
				|  |  | +  GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing,
 | 
	
		
			
				|  |  | +                                incoming_window, incoming_frame_size);
 | 
	
		
			
				|  |  | +  stream_parsing->received_bytes += 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_exec_ctx *exec_ctx, 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);
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  |    if (err == GRPC_CHTTP2_PARSE_OK) {
 | 
	
		
			
				|  |  | -    err = update_incoming_window(transport_parsing, stream_parsing);
 | 
	
		
			
				|  |  | +    err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (err == GRPC_CHTTP2_PARSE_OK) {
 | 
	
		
			
				|  |  |      err = grpc_chttp2_data_parser_begin_frame(
 | 
	
	
		
			
				|  | @@ -577,7 +565,7 @@ static int init_data_frame_parser(
 | 
	
		
			
				|  |  |            &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);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_CONNECTION_ERROR:
 | 
	
		
			
				|  |  |        return 0;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -586,11 +574,13 @@ static int init_data_frame_parser(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void free_timeout(void *p) { gpr_free(p); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void on_header(void *tp, grpc_mdelem *md) {
 | 
	
		
			
				|  |  | +static void on_initial_header(void *tp, grpc_mdelem *md) {
 | 
	
		
			
				|  |  |    grpc_chttp2_transport_parsing *transport_parsing = tp;
 | 
	
		
			
				|  |  |    grpc_chttp2_stream_parsing *stream_parsing =
 | 
	
		
			
				|  |  |        transport_parsing->incoming_stream;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  GPR_TIMER_BEGIN("on_initial_header", 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    GPR_ASSERT(stream_parsing);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
	
		
			
				|  | @@ -598,6 +588,12 @@ static void on_header(void *tp, grpc_mdelem *md) {
 | 
	
		
			
				|  |  |        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->elem_grpc_status_ok->key &&
 | 
	
		
			
				|  |  | +      md != transport_parsing->elem_grpc_status_ok) {
 | 
	
		
			
				|  |  | +    /* TODO(ctiller): check for a status like " 0" */
 | 
	
		
			
				|  |  | +    stream_parsing->seen_error = 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    if (md->key == transport_parsing->str_grpc_timeout) {
 | 
	
		
			
				|  |  |      gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
 | 
	
		
			
				|  |  |      if (!cached_timeout) {
 | 
	
	
		
			
				|  | @@ -612,24 +608,57 @@ static void on_header(void *tp, grpc_mdelem *md) {
 | 
	
		
			
				|  |  |        grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      grpc_chttp2_incoming_metadata_buffer_set_deadline(
 | 
	
		
			
				|  |  | -        &stream_parsing->incoming_metadata,
 | 
	
		
			
				|  |  | +        &stream_parsing->metadata_buffer[0],
 | 
	
		
			
				|  |  |          gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
 | 
	
		
			
				|  |  |      GRPC_MDELEM_UNREF(md);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
 | 
	
		
			
				|  |  | -                                             md);
 | 
	
		
			
				|  |  | +    grpc_chttp2_incoming_metadata_buffer_add(
 | 
	
		
			
				|  |  | +        &stream_parsing->metadata_buffer[0], md);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  GPR_TIMER_END("on_initial_header", 0);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void on_trailing_header(void *tp, grpc_mdelem *md) {
 | 
	
		
			
				|  |  | +  grpc_chttp2_transport_parsing *transport_parsing = tp;
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream_parsing *stream_parsing =
 | 
	
		
			
				|  |  | +      transport_parsing->incoming_stream;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  GPR_TIMER_BEGIN("on_trailing_header", 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  GPR_ASSERT(stream_parsing);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
		
			
				|  |  | +      GPR_INFO, "HTTP:%d:TRL:%s: %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->elem_grpc_status_ok->key &&
 | 
	
		
			
				|  |  | +      md != transport_parsing->elem_grpc_status_ok) {
 | 
	
		
			
				|  |  | +    /* TODO(ctiller): check for a status like " 0" */
 | 
	
		
			
				|  |  | +    stream_parsing->seen_error = 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1],
 | 
	
		
			
				|  |  | +                                           md);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  GPR_TIMER_END("on_trailing_header", 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int init_header_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing, int is_continuation) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | +    int is_continuation) {
 | 
	
		
			
				|  |  |    gpr_uint8 is_eoh = (transport_parsing->incoming_frame_flags &
 | 
	
		
			
				|  |  |                        GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
 | 
	
		
			
				|  |  |    int via_accept = 0;
 | 
	
		
			
				|  |  |    grpc_chttp2_stream_parsing *stream_parsing;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  /* TODO(ctiller): when to increment header_frames_received? */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    if (is_eoh) {
 | 
	
		
			
				|  |  |      transport_parsing->expect_continuation_stream_id = 0;
 | 
	
		
			
				|  |  |    } else {
 | 
	
	
		
			
				|  | @@ -649,7 +678,7 @@ static int init_header_frame_parser(
 | 
	
		
			
				|  |  |      if (is_continuation) {
 | 
	
		
			
				|  |  |        gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  |                "grpc_chttp2_stream disbanded before CONTINUATION received");
 | 
	
		
			
				|  |  | -      return init_skip_frame_parser(transport_parsing, 1);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      if (transport_parsing->is_client) {
 | 
	
		
			
				|  |  |        if ((transport_parsing->incoming_stream_id & 1) &&
 | 
	
	
		
			
				|  | @@ -660,7 +689,7 @@ static int init_header_frame_parser(
 | 
	
		
			
				|  |  |          gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  |                  "ignoring new grpc_chttp2_stream creation on client");
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      return init_skip_frame_parser(transport_parsing, 1);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  |      } else if (transport_parsing->last_incoming_stream_id >
 | 
	
		
			
				|  |  |                 transport_parsing->incoming_stream_id) {
 | 
	
		
			
				|  |  |        gpr_log(GPR_ERROR,
 | 
	
	
		
			
				|  | @@ -669,19 +698,19 @@ static int init_header_frame_parser(
 | 
	
		
			
				|  |  |                "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);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, 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);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      stream_parsing = transport_parsing->incoming_stream =
 | 
	
		
			
				|  |  |          grpc_chttp2_parsing_accept_stream(
 | 
	
		
			
				|  |  | -            transport_parsing, transport_parsing->incoming_stream_id);
 | 
	
		
			
				|  |  | +            exec_ctx, 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);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      via_accept = 1;
 | 
	
		
			
				|  |  |    } else {
 | 
	
	
		
			
				|  | @@ -691,11 +720,21 @@ static int init_header_frame_parser(
 | 
	
		
			
				|  |  |    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);
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, 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;
 | 
	
		
			
				|  |  | +  switch (stream_parsing->header_frames_received) {
 | 
	
		
			
				|  |  | +    case 0:
 | 
	
		
			
				|  |  | +      transport_parsing->hpack_parser.on_header = on_initial_header;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case 1:
 | 
	
		
			
				|  |  | +      transport_parsing->hpack_parser.on_header = on_trailing_header;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case 2:
 | 
	
		
			
				|  |  | +      gpr_log(GPR_ERROR, "too many header frames received");
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
 | 
	
		
			
				|  |  |    transport_parsing->hpack_parser.is_boundary = is_eoh;
 | 
	
		
			
				|  |  |    transport_parsing->hpack_parser.is_eof =
 | 
	
	
		
			
				|  | @@ -708,7 +747,7 @@ static int init_header_frame_parser(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int init_window_update_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, 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,
 | 
	
	
		
			
				|  | @@ -722,7 +761,8 @@ static int init_window_update_frame_parser(
 | 
	
		
			
				|  |  |    return ok;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +static int init_ping_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                            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,
 | 
	
	
		
			
				|  | @@ -733,7 +773,7 @@ static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int init_rst_stream_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, 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,
 | 
	
	
		
			
				|  | @@ -741,7 +781,7 @@ static int init_rst_stream_parser(
 | 
	
		
			
				|  |  |    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);
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
 | 
	
		
			
				|  |  |    transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
 | 
	
	
		
			
				|  | @@ -749,7 +789,7 @@ static int init_rst_stream_parser(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int init_goaway_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, 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,
 | 
	
	
		
			
				|  | @@ -760,7 +800,7 @@ static int init_goaway_parser(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int init_settings_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  |    int ok;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (transport_parsing->incoming_stream_id != 0) {
 | 
	
	
		
			
				|  | @@ -806,7 +846,7 @@ static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        return 1;
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_STREAM_ERROR:
 | 
	
		
			
				|  |  | -      grpc_chttp2_parsing_become_skip_parser(transport_parsing);
 | 
	
		
			
				|  |  | +      grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  |        if (stream_parsing) {
 | 
	
		
			
				|  |  |          stream_parsing->saw_rst_stream = 1;
 | 
	
		
			
				|  |  |          stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
 |