|  | @@ -45,223 +45,34 @@
 | 
	
		
			
				|  |  |  #include "src/core/lib/transport/static_metadata.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/transport/timeout_encoding.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define TRANSPORT_FROM_PARSING(tp)                                        \
 | 
	
		
			
				|  |  | -  ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
 | 
	
		
			
				|  |  | -                                                   parsing)))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static grpc_error *init_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_header_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    int is_continuation);
 | 
	
		
			
				|  |  | -static grpc_error *init_data_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_rst_stream_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_settings_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_window_update_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_ping_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_goaway_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
 | 
	
		
			
				|  |  | -static grpc_error *init_skip_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    int is_header);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static grpc_error *parse_frame_slice(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, 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;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  transport_parsing->next_stream_id = transport_global->next_stream_id;
 | 
	
		
			
				|  |  | -  memcpy(transport_parsing->last_sent_settings,
 | 
	
		
			
				|  |  | -         transport_global->settings[GRPC_SENT_SETTINGS],
 | 
	
		
			
				|  |  | -         sizeof(transport_parsing->last_sent_settings));
 | 
	
		
			
				|  |  | -  transport_parsing->max_frame_size =
 | 
	
		
			
				|  |  | -      transport_global->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | -                                [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* update the parsing view of incoming window */
 | 
	
		
			
				|  |  | -  while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
 | 
	
		
			
				|  |  | -      transport_global, transport_parsing, &stream_global, &stream_parsing)) {
 | 
	
		
			
				|  |  | -    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);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void grpc_chttp2_publish_reads(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
 | 
	
		
			
				|  |  | -    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
 | 
	
		
			
				|  |  | -     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->last_incoming_stream_id;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* update global settings */
 | 
	
		
			
				|  |  | -  if (transport_parsing->settings_updated) {
 | 
	
		
			
				|  |  | -    memcpy(transport_global->settings[GRPC_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[GRPC_ACKED_SETTINGS],
 | 
	
		
			
				|  |  | -           transport_global->settings[GRPC_SENT_SETTINGS],
 | 
	
		
			
				|  |  | -           GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
 | 
	
		
			
				|  |  | -    transport_parsing->settings_ack_received = 0;
 | 
	
		
			
				|  |  | -    transport_global->sent_local_settings = 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(exec_ctx, transport_global,
 | 
	
		
			
				|  |  | -                                    (uint32_t)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 */
 | 
	
		
			
				|  |  | -  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) {
 | 
	
		
			
				|  |  | -    grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
 | 
	
		
			
				|  |  | -                               "new_global_flow_control");
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (transport_parsing->incoming_window <
 | 
	
		
			
				|  |  | -      transport_global->connection_window_target * 3 / 4) {
 | 
	
		
			
				|  |  | -    int64_t 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);
 | 
	
		
			
				|  |  | -    grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
 | 
	
		
			
				|  |  | -                               "global incoming window");
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* 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)) {
 | 
	
		
			
				|  |  | -    if (stream_parsing->seen_error) {
 | 
	
		
			
				|  |  | -      stream_global->seen_error = true;
 | 
	
		
			
				|  |  | -      stream_global->exceeded_metadata_size =
 | 
	
		
			
				|  |  | -          stream_parsing->exceeded_metadata_size;
 | 
	
		
			
				|  |  | -      grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /* flush stats to global stream state */
 | 
	
		
			
				|  |  | -    grpc_transport_move_stats(&stream_parsing->stats, &stream_global->stats);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /* update outgoing flow control window */
 | 
	
		
			
				|  |  | -    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_become_writable(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | -                                  false, "stream.read_flow_control");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    stream_global->max_recv_bytes -= (uint32_t)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->forced_close_error != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -      intptr_t reason;
 | 
	
		
			
				|  |  | -      bool has_reason = grpc_error_get_int(stream_parsing->forced_close_error,
 | 
	
		
			
				|  |  | -                                           GRPC_ERROR_INT_HTTP2_ERROR, &reason);
 | 
	
		
			
				|  |  | -      if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) {
 | 
	
		
			
				|  |  | -        grpc_status_code status_code =
 | 
	
		
			
				|  |  | -            has_reason
 | 
	
		
			
				|  |  | -                ? grpc_chttp2_http2_error_to_grpc_status(
 | 
	
		
			
				|  |  | -                      (grpc_chttp2_error_code)reason, stream_global->deadline)
 | 
	
		
			
				|  |  | -                : GRPC_STATUS_INTERNAL;
 | 
	
		
			
				|  |  | -        const char *status_details =
 | 
	
		
			
				|  |  | -            grpc_error_string(stream_parsing->forced_close_error);
 | 
	
		
			
				|  |  | -        gpr_slice slice_details = gpr_slice_from_copied_string(status_details);
 | 
	
		
			
				|  |  | -        grpc_error_free_string(status_details);
 | 
	
		
			
				|  |  | -        grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | -                                status_code, &slice_details);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | -                                     1, 1, stream_parsing->forced_close_error);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (stream_parsing->received_close) {
 | 
	
		
			
				|  |  | -      grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
 | 
	
		
			
				|  |  | -                                     1, 0, GRPC_ERROR_NONE);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -grpc_error *grpc_chttp2_perform_read(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    gpr_slice slice) {
 | 
	
		
			
				|  |  | +static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                     grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                            grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  | +                                            int is_continuation);
 | 
	
		
			
				|  |  | +static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_rst_stream_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_settings_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                              grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_window_update_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                                   grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_ping_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                    grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_goaway_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                      grpc_chttp2_transport *t);
 | 
	
		
			
				|  |  | +static grpc_error *init_skip_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  | +                                          int is_header);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                     grpc_chttp2_transport *t, gpr_slice slice,
 | 
	
		
			
				|  |  | +                                     int is_last);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                     grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  | +                                     gpr_slice slice) {
 | 
	
		
			
				|  |  |    uint8_t *beg = GPR_SLICE_START_PTR(slice);
 | 
	
		
			
				|  |  |    uint8_t *end = GPR_SLICE_END_PTR(slice);
 | 
	
		
			
				|  |  |    uint8_t *cur = beg;
 | 
	
	
		
			
				|  | @@ -269,7 +80,7 @@ grpc_error *grpc_chttp2_perform_read(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (cur == end) return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  switch (transport_parsing->deframe_state) {
 | 
	
		
			
				|  |  | +  switch (t->deframe_state) {
 | 
	
		
			
				|  |  |      case GRPC_DTS_CLIENT_PREFIX_0:
 | 
	
		
			
				|  |  |      case GRPC_DTS_CLIENT_PREFIX_1:
 | 
	
		
			
				|  |  |      case GRPC_DTS_CLIENT_PREFIX_2:
 | 
	
	
		
			
				|  | @@ -294,25 +105,22 @@ grpc_error *grpc_chttp2_perform_read(
 | 
	
		
			
				|  |  |      case GRPC_DTS_CLIENT_PREFIX_21:
 | 
	
		
			
				|  |  |      case GRPC_DTS_CLIENT_PREFIX_22:
 | 
	
		
			
				|  |  |      case GRPC_DTS_CLIENT_PREFIX_23:
 | 
	
		
			
				|  |  | -      while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
 | 
	
		
			
				|  |  | -        if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
 | 
	
		
			
				|  |  | -                                                          ->deframe_state]) {
 | 
	
		
			
				|  |  | +      while (cur != end && t->deframe_state != GRPC_DTS_FH_0) {
 | 
	
		
			
				|  |  | +        if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state]) {
 | 
	
		
			
				|  |  |            char *msg;
 | 
	
		
			
				|  |  |            gpr_asprintf(
 | 
	
		
			
				|  |  |                &msg,
 | 
	
		
			
				|  |  |                "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
 | 
	
		
			
				|  |  |                "at byte %d",
 | 
	
		
			
				|  |  | -              GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
 | 
	
		
			
				|  |  | -                                                    ->deframe_state],
 | 
	
		
			
				|  |  | -              (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
 | 
	
		
			
				|  |  | -                  [transport_parsing->deframe_state],
 | 
	
		
			
				|  |  | -              *cur, (int)*cur, transport_parsing->deframe_state);
 | 
	
		
			
				|  |  | +              GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state],
 | 
	
		
			
				|  |  | +              (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state],
 | 
	
		
			
				|  |  | +              *cur, (int)*cur, t->deframe_state);
 | 
	
		
			
				|  |  |            err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |            gpr_free(msg);
 | 
	
		
			
				|  |  |            return err;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          ++cur;
 | 
	
		
			
				|  |  | -        ++transport_parsing->deframe_state;
 | 
	
		
			
				|  |  | +        ++t->deframe_state;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        if (cur == end) {
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
	
		
			
				|  | @@ -321,100 +129,95 @@ grpc_error *grpc_chttp2_perform_read(
 | 
	
		
			
				|  |  |      dts_fh_0:
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_0:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
 | 
	
		
			
				|  |  | +      t->incoming_frame_size = ((uint32_t)*cur) << 16;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_1;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_1;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_1:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
 | 
	
		
			
				|  |  | +      t->incoming_frame_size |= ((uint32_t)*cur) << 8;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_2;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_2;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_2:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_size |= *cur;
 | 
	
		
			
				|  |  | +      t->incoming_frame_size |= *cur;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_3;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_3;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_3:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_type = *cur;
 | 
	
		
			
				|  |  | +      t->incoming_frame_type = *cur;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_4;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_4;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_4:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_flags = *cur;
 | 
	
		
			
				|  |  | +      t->incoming_frame_flags = *cur;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_5;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_5;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_5:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
 | 
	
		
			
				|  |  | +      t->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_6;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_6;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_6:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
 | 
	
		
			
				|  |  | +      t->incoming_stream_id |= ((uint32_t)*cur) << 16;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_7;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_7;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_7:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
 | 
	
		
			
				|  |  | +      t->incoming_stream_id |= ((uint32_t)*cur) << 8;
 | 
	
		
			
				|  |  |        if (++cur == end) {
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_8;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_8;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FH_8:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
 | 
	
		
			
				|  |  | -      transport_parsing->deframe_state = GRPC_DTS_FRAME;
 | 
	
		
			
				|  |  | -      err = init_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      t->incoming_stream_id |= ((uint32_t)*cur);
 | 
	
		
			
				|  |  | +      t->deframe_state = GRPC_DTS_FRAME;
 | 
	
		
			
				|  |  | +      err = init_frame_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |        if (err != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |          return err;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      if (transport_parsing->incoming_stream_id != 0 &&
 | 
	
		
			
				|  |  | -          transport_parsing->incoming_stream_id >
 | 
	
		
			
				|  |  | -              transport_parsing->last_incoming_stream_id) {
 | 
	
		
			
				|  |  | -        transport_parsing->last_incoming_stream_id =
 | 
	
		
			
				|  |  | -            transport_parsing->incoming_stream_id;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      if (transport_parsing->incoming_frame_size == 0) {
 | 
	
		
			
				|  |  | -        err = parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
 | 
	
		
			
				|  |  | -                                1);
 | 
	
		
			
				|  |  | +      if (t->incoming_frame_size == 0) {
 | 
	
		
			
				|  |  | +        err = parse_frame_slice(exec_ctx, t, gpr_empty_slice(), 1);
 | 
	
		
			
				|  |  |          if (err != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |            return err;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_stream = NULL;
 | 
	
		
			
				|  |  | +        t->incoming_stream = NULL;
 | 
	
		
			
				|  |  |          if (++cur == end) {
 | 
	
		
			
				|  |  | -          transport_parsing->deframe_state = GRPC_DTS_FH_0;
 | 
	
		
			
				|  |  | +          t->deframe_state = GRPC_DTS_FH_0;
 | 
	
		
			
				|  |  |            return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          goto dts_fh_0; /* loop */
 | 
	
		
			
				|  |  | -      } else if (transport_parsing->incoming_frame_size >
 | 
	
		
			
				|  |  | -                 transport_parsing->max_frame_size) {
 | 
	
		
			
				|  |  | +      } else if (t->incoming_frame_size >
 | 
	
		
			
				|  |  | +                 t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | +                            [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]) {
 | 
	
		
			
				|  |  |          char *msg;
 | 
	
		
			
				|  |  |          gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d",
 | 
	
		
			
				|  |  | -                     transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -                     transport_parsing->max_frame_size);
 | 
	
		
			
				|  |  | +                     t->incoming_frame_size,
 | 
	
		
			
				|  |  | +                     t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | +                                [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]);
 | 
	
		
			
				|  |  |          err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |          gpr_free(msg);
 | 
	
		
			
				|  |  |          return err;
 | 
	
	
		
			
				|  | @@ -425,41 +228,39 @@ grpc_error *grpc_chttp2_perform_read(
 | 
	
		
			
				|  |  |      /* fallthrough */
 | 
	
		
			
				|  |  |      case GRPC_DTS_FRAME:
 | 
	
		
			
				|  |  |        GPR_ASSERT(cur < end);
 | 
	
		
			
				|  |  | -      if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
 | 
	
		
			
				|  |  | -        err = parse_frame_slice(exec_ctx, transport_parsing,
 | 
	
		
			
				|  |  | +      if ((uint32_t)(end - cur) == t->incoming_frame_size) {
 | 
	
		
			
				|  |  | +        err = parse_frame_slice(exec_ctx, t,
 | 
	
		
			
				|  |  |                                  gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
 | 
	
		
			
				|  |  |                                                       (size_t)(end - beg)),
 | 
	
		
			
				|  |  |                                  1);
 | 
	
		
			
				|  |  |          if (err != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |            return err;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        transport_parsing->deframe_state = GRPC_DTS_FH_0;
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_stream = NULL;
 | 
	
		
			
				|  |  | +        t->deframe_state = GRPC_DTS_FH_0;
 | 
	
		
			
				|  |  | +        t->incoming_stream = NULL;
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | -      } else if ((uint32_t)(end - cur) >
 | 
	
		
			
				|  |  | -                 transport_parsing->incoming_frame_size) {
 | 
	
		
			
				|  |  | +      } else if ((uint32_t)(end - cur) > t->incoming_frame_size) {
 | 
	
		
			
				|  |  |          size_t cur_offset = (size_t)(cur - beg);
 | 
	
		
			
				|  |  |          err = parse_frame_slice(
 | 
	
		
			
				|  |  | -            exec_ctx, transport_parsing,
 | 
	
		
			
				|  |  | -            gpr_slice_sub_no_ref(
 | 
	
		
			
				|  |  | -                slice, cur_offset,
 | 
	
		
			
				|  |  | -                cur_offset + transport_parsing->incoming_frame_size),
 | 
	
		
			
				|  |  | +            exec_ctx, t,
 | 
	
		
			
				|  |  | +            gpr_slice_sub_no_ref(slice, cur_offset,
 | 
	
		
			
				|  |  | +                                 cur_offset + t->incoming_frame_size),
 | 
	
		
			
				|  |  |              1);
 | 
	
		
			
				|  |  |          if (err != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |            return err;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        cur += transport_parsing->incoming_frame_size;
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_stream = NULL;
 | 
	
		
			
				|  |  | +        cur += t->incoming_frame_size;
 | 
	
		
			
				|  |  | +        t->incoming_stream = NULL;
 | 
	
		
			
				|  |  |          goto dts_fh_0; /* loop */
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  | -        err = parse_frame_slice(exec_ctx, transport_parsing,
 | 
	
		
			
				|  |  | +        err = parse_frame_slice(exec_ctx, t,
 | 
	
		
			
				|  |  |                                  gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
 | 
	
		
			
				|  |  |                                                       (size_t)(end - beg)),
 | 
	
		
			
				|  |  |                                  0);
 | 
	
		
			
				|  |  |          if (err != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |            return err;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
 | 
	
		
			
				|  |  | +        t->incoming_frame_size -= (uint32_t)(end - cur);
 | 
	
		
			
				|  |  |          return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        GPR_UNREACHABLE_CODE(return 0);
 | 
	
	
		
			
				|  | @@ -468,175 +269,164 @@ grpc_error *grpc_chttp2_perform_read(
 | 
	
		
			
				|  |  |    GPR_UNREACHABLE_CODE(return 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | -  if (transport_parsing->is_first_frame &&
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) {
 | 
	
		
			
				|  |  | +static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                     grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  | +  if (t->is_first_frame &&
 | 
	
		
			
				|  |  | +      t->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) {
 | 
	
		
			
				|  |  |      char *msg;
 | 
	
		
			
				|  |  |      gpr_asprintf(
 | 
	
		
			
				|  |  |          &msg, "Expected SETTINGS frame as the first frame, got frame type %d",
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_frame_type);
 | 
	
		
			
				|  |  | +        t->incoming_frame_type);
 | 
	
		
			
				|  |  |      grpc_error *err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |      gpr_free(msg);
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  transport_parsing->is_first_frame = false;
 | 
	
		
			
				|  |  | -  if (transport_parsing->expect_continuation_stream_id != 0) {
 | 
	
		
			
				|  |  | -    if (transport_parsing->incoming_frame_type !=
 | 
	
		
			
				|  |  | -        GRPC_CHTTP2_FRAME_CONTINUATION) {
 | 
	
		
			
				|  |  | +  t->is_first_frame = false;
 | 
	
		
			
				|  |  | +  if (t->expect_continuation_stream_id != 0) {
 | 
	
		
			
				|  |  | +    if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) {
 | 
	
		
			
				|  |  |        char *msg;
 | 
	
		
			
				|  |  |        gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x",
 | 
	
		
			
				|  |  | -                   transport_parsing->incoming_frame_type);
 | 
	
		
			
				|  |  | +                   t->incoming_frame_type);
 | 
	
		
			
				|  |  |        grpc_error *err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |        gpr_free(msg);
 | 
	
		
			
				|  |  |        return err;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if (transport_parsing->expect_continuation_stream_id !=
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_stream_id) {
 | 
	
		
			
				|  |  | +    if (t->expect_continuation_stream_id != t->incoming_stream_id) {
 | 
	
		
			
				|  |  |        char *msg;
 | 
	
		
			
				|  |  |        gpr_asprintf(
 | 
	
		
			
				|  |  |            &msg,
 | 
	
		
			
				|  |  |            "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
 | 
	
		
			
				|  |  |            "grpc_chttp2_stream %08x",
 | 
	
		
			
				|  |  | -          transport_parsing->expect_continuation_stream_id,
 | 
	
		
			
				|  |  | -          transport_parsing->incoming_stream_id);
 | 
	
		
			
				|  |  | +          t->expect_continuation_stream_id, t->incoming_stream_id);
 | 
	
		
			
				|  |  |        grpc_error *err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |        gpr_free(msg);
 | 
	
		
			
				|  |  |        return err;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return init_header_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  | +    return init_header_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  switch (transport_parsing->incoming_frame_type) {
 | 
	
		
			
				|  |  | +  switch (t->incoming_frame_type) {
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_DATA:
 | 
	
		
			
				|  |  | -      return init_data_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      return init_data_frame_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_HEADER:
 | 
	
		
			
				|  |  | -      return init_header_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | +      return init_header_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_CONTINUATION:
 | 
	
		
			
				|  |  |        return GRPC_ERROR_CREATE("Unexpected CONTINUATION frame");
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_RST_STREAM:
 | 
	
		
			
				|  |  | -      return init_rst_stream_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      return init_rst_stream_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_SETTINGS:
 | 
	
		
			
				|  |  | -      return init_settings_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      return init_settings_frame_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
 | 
	
		
			
				|  |  | -      return init_window_update_frame_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      return init_window_update_frame_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_PING:
 | 
	
		
			
				|  |  | -      return init_ping_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      return init_ping_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |      case GRPC_CHTTP2_FRAME_GOAWAY:
 | 
	
		
			
				|  |  | -      return init_goaway_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | +      return init_goaway_parser(exec_ctx, t);
 | 
	
		
			
				|  |  |      default:
 | 
	
		
			
				|  |  |        if (grpc_http_trace) {
 | 
	
		
			
				|  |  | -        gpr_log(GPR_ERROR, "Unknown frame type %02x",
 | 
	
		
			
				|  |  | -                transport_parsing->incoming_frame_type);
 | 
	
		
			
				|  |  | +        gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static grpc_error *skip_parser(grpc_exec_ctx *exec_ctx, void *parser,
 | 
	
		
			
				|  |  | -                               grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -                               grpc_chttp2_stream_parsing *stream_parsing,
 | 
	
		
			
				|  |  | +                               grpc_chttp2_transport *t, grpc_chttp2_stream *s,
 | 
	
		
			
				|  |  |                                 gpr_slice slice, int is_last) {
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
 | 
	
		
			
				|  |  | +static void skip_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem *md) {
 | 
	
		
			
				|  |  | +  GRPC_MDELEM_UNREF(md);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_skip_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    int is_header) {
 | 
	
		
			
				|  |  | +static grpc_error *init_skip_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  | +                                          int is_header) {
 | 
	
		
			
				|  |  |    if (is_header) {
 | 
	
		
			
				|  |  | -    uint8_t 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 =
 | 
	
		
			
				|  |  | -        (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
 | 
	
		
			
				|  |  | +    uint8_t is_eoh = t->expect_continuation_stream_id != 0;
 | 
	
		
			
				|  |  | +    t->parser = grpc_chttp2_header_parser_parse;
 | 
	
		
			
				|  |  | +    t->parser_data = &t->hpack_parser;
 | 
	
		
			
				|  |  | +    t->hpack_parser.on_header = skip_header;
 | 
	
		
			
				|  |  | +    t->hpack_parser.on_header_user_data = NULL;
 | 
	
		
			
				|  |  | +    t->hpack_parser.is_boundary = is_eoh;
 | 
	
		
			
				|  |  | +    t->hpack_parser.is_eof = (uint8_t)(is_eoh ? t->header_eof : 0);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    transport_parsing->parser = skip_parser;
 | 
	
		
			
				|  |  | +    t->parser = skip_parser;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void grpc_chttp2_parsing_become_skip_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | -  init_skip_frame_parser(
 | 
	
		
			
				|  |  | -      exec_ctx, transport_parsing,
 | 
	
		
			
				|  |  | -      transport_parsing->parser == grpc_chttp2_header_parser_parse);
 | 
	
		
			
				|  |  | +void grpc_chttp2_parsing_become_skip_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                            grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  | +  init_skip_frame_parser(exec_ctx, t,
 | 
	
		
			
				|  |  | +                         t->parser == grpc_chttp2_header_parser_parse);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *update_incoming_window(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    grpc_chttp2_stream_parsing *stream_parsing) {
 | 
	
		
			
				|  |  | -  uint32_t incoming_frame_size = transport_parsing->incoming_frame_size;
 | 
	
		
			
				|  |  | -  if (incoming_frame_size > transport_parsing->incoming_window) {
 | 
	
		
			
				|  |  | +static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_stream *s) {
 | 
	
		
			
				|  |  | +  uint32_t incoming_frame_size = t->incoming_frame_size;
 | 
	
		
			
				|  |  | +  if (incoming_frame_size > t->incoming_window) {
 | 
	
		
			
				|  |  |      char *msg;
 | 
	
		
			
				|  |  |      gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
 | 
	
		
			
				|  |  | -                 transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -                 transport_parsing->incoming_window);
 | 
	
		
			
				|  |  | +                 t->incoming_frame_size, t->incoming_window);
 | 
	
		
			
				|  |  |      grpc_error *err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |      gpr_free(msg);
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (incoming_frame_size > stream_parsing->incoming_window) {
 | 
	
		
			
				|  |  | +  if (incoming_frame_size > s->incoming_window) {
 | 
	
		
			
				|  |  |      char *msg;
 | 
	
		
			
				|  |  |      gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
 | 
	
		
			
				|  |  | -                 transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -                 stream_parsing->incoming_window);
 | 
	
		
			
				|  |  | +                 t->incoming_frame_size, s->incoming_window);
 | 
	
		
			
				|  |  |      grpc_error *err = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |      gpr_free(msg);
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
 | 
	
		
			
				|  |  | +  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, 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);
 | 
	
		
			
				|  |  | +  GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window,
 | 
	
		
			
				|  |  | +                                incoming_frame_size);
 | 
	
		
			
				|  |  | +  s->received_bytes += incoming_frame_size;
 | 
	
		
			
				|  |  | +  s->max_recv_bytes -=
 | 
	
		
			
				|  |  | +      (uint32_t)GPR_MIN(s->max_recv_bytes, incoming_frame_size);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_data_frame_parser(
 | 
	
		
			
				|  |  | -    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);
 | 
	
		
			
				|  |  | +static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream *s =
 | 
	
		
			
				|  |  | +      grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
 | 
	
		
			
				|  |  |    grpc_error *err = GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | -  if (stream_parsing == NULL) {
 | 
	
		
			
				|  |  | -    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | +  if (s == NULL) {
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  stream_parsing->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | -  if (stream_parsing->received_close) {
 | 
	
		
			
				|  |  | -    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | +  s->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | +  if (s->read_closed) {
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (err == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -    err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
 | 
	
		
			
				|  |  | +    err = update_incoming_window(exec_ctx, t, s);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (err == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -    err = grpc_chttp2_data_parser_begin_frame(
 | 
	
		
			
				|  |  | -        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags,
 | 
	
		
			
				|  |  | -        stream_parsing->id);
 | 
	
		
			
				|  |  | +    err = grpc_chttp2_data_parser_begin_frame(&s->data_parser,
 | 
	
		
			
				|  |  | +                                              t->incoming_frame_flags, s->id);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (err == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -    transport_parsing->incoming_stream = stream_parsing;
 | 
	
		
			
				|  |  | -    transport_parsing->parser = grpc_chttp2_data_parser_parse;
 | 
	
		
			
				|  |  | -    transport_parsing->parser_data = &stream_parsing->data_parser;
 | 
	
		
			
				|  |  | +    t->incoming_stream = s;
 | 
	
		
			
				|  |  | +    t->parser = grpc_chttp2_data_parser_parse;
 | 
	
		
			
				|  |  | +    t->parser_data = &s->data_parser;
 | 
	
		
			
				|  |  |      return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |    } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
 | 
	
		
			
				|  |  |      /* handle stream errors by closing the stream */
 | 
	
		
			
				|  |  | -    stream_parsing->received_close = 1;
 | 
	
		
			
				|  |  | -    stream_parsing->forced_close_error = err;
 | 
	
		
			
				|  |  | +    grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, err);
 | 
	
		
			
				|  |  |      gpr_slice_buffer_add(
 | 
	
		
			
				|  |  | -        &transport_parsing->qbuf,
 | 
	
		
			
				|  |  | -        grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
 | 
	
		
			
				|  |  | -                                      GRPC_CHTTP2_PROTOCOL_ERROR,
 | 
	
		
			
				|  |  | -                                      &stream_parsing->stats.outgoing));
 | 
	
		
			
				|  |  | -    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | +        &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
 | 
	
		
			
				|  |  | +                                                GRPC_CHTTP2_PROTOCOL_ERROR,
 | 
	
		
			
				|  |  | +                                                &s->stats.outgoing));
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -644,23 +434,22 @@ static grpc_error *init_data_frame_parser(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void free_timeout(void *p) { gpr_free(p); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -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;
 | 
	
		
			
				|  |  | +static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
 | 
	
		
			
				|  |  | +                              grpc_mdelem *md) {
 | 
	
		
			
				|  |  | +  grpc_chttp2_transport *t = tp;
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream *s = t->incoming_stream;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GPR_TIMER_BEGIN("on_initial_header", 0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  GPR_ASSERT(stream_parsing);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(s != NULL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
		
			
				|  |  | -      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
 | 
	
		
			
				|  |  | -      transport_parsing->is_client ? "CLI" : "SVR",
 | 
	
		
			
				|  |  | +      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR",
 | 
	
		
			
				|  |  |        grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
 | 
	
		
			
				|  |  |      /* TODO(ctiller): check for a status like " 0" */
 | 
	
		
			
				|  |  | -    stream_parsing->seen_error = true;
 | 
	
		
			
				|  |  | +    s->seen_error = true;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
 | 
	
	
		
			
				|  | @@ -677,306 +466,273 @@ static void on_initial_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->metadata_buffer[0],
 | 
	
		
			
				|  |  | +        &s->metadata_buffer[0],
 | 
	
		
			
				|  |  |          gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
 | 
	
		
			
				|  |  |      GRPC_MDELEM_UNREF(md);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    const size_t new_size =
 | 
	
		
			
				|  |  | -        stream_parsing->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
 | 
	
		
			
				|  |  | -    grpc_chttp2_transport_global *transport_global =
 | 
	
		
			
				|  |  | -        &TRANSPORT_FROM_PARSING(transport_parsing)->global;
 | 
	
		
			
				|  |  | +    const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
 | 
	
		
			
				|  |  |      const size_t metadata_size_limit =
 | 
	
		
			
				|  |  | -        transport_global->settings[GRPC_LOCAL_SETTINGS]
 | 
	
		
			
				|  |  | -                                  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
 | 
	
		
			
				|  |  | +        t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | +                   [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
 | 
	
		
			
				|  |  |      if (new_size > metadata_size_limit) {
 | 
	
		
			
				|  |  | -      if (!stream_parsing->exceeded_metadata_size) {
 | 
	
		
			
				|  |  | -        gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | -                "received initial metadata size exceeds limit (%" PRIuPTR
 | 
	
		
			
				|  |  | -                " vs. %" PRIuPTR ")",
 | 
	
		
			
				|  |  | -                new_size, metadata_size_limit);
 | 
	
		
			
				|  |  | -        stream_parsing->seen_error = true;
 | 
	
		
			
				|  |  | -        stream_parsing->exceeded_metadata_size = true;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +      gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | +              "received initial metadata size exceeds limit (%" PRIuPTR
 | 
	
		
			
				|  |  | +              " vs. %" PRIuPTR ")",
 | 
	
		
			
				|  |  | +              new_size, metadata_size_limit);
 | 
	
		
			
				|  |  | +      grpc_chttp2_cancel_stream(
 | 
	
		
			
				|  |  | +          exec_ctx, t, s,
 | 
	
		
			
				|  |  | +          grpc_error_set_int(
 | 
	
		
			
				|  |  | +              GRPC_ERROR_CREATE("received initial metadata size exceeds limit"),
 | 
	
		
			
				|  |  | +              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
 | 
	
		
			
				|  |  | +      grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
 | 
	
		
			
				|  |  | +      s->seen_error = true;
 | 
	
		
			
				|  |  |        GRPC_MDELEM_UNREF(md);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -      grpc_chttp2_incoming_metadata_buffer_add(
 | 
	
		
			
				|  |  | -          &stream_parsing->metadata_buffer[0], md);
 | 
	
		
			
				|  |  | +      grpc_chttp2_incoming_metadata_buffer_add(&s->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;
 | 
	
		
			
				|  |  | +static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
 | 
	
		
			
				|  |  | +                               grpc_mdelem *md) {
 | 
	
		
			
				|  |  | +  grpc_chttp2_transport *t = tp;
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream *s = t->incoming_stream;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GPR_TIMER_BEGIN("on_trailing_header", 0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  GPR_ASSERT(stream_parsing);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(s != NULL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
		
			
				|  |  | -      GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", stream_parsing->id,
 | 
	
		
			
				|  |  | -      transport_parsing->is_client ? "CLI" : "SVR",
 | 
	
		
			
				|  |  | +      GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR",
 | 
	
		
			
				|  |  |        grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
 | 
	
		
			
				|  |  |      /* TODO(ctiller): check for a status like " 0" */
 | 
	
		
			
				|  |  | -    stream_parsing->seen_error = true;
 | 
	
		
			
				|  |  | +    s->seen_error = true;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  const size_t new_size =
 | 
	
		
			
				|  |  | -      stream_parsing->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
 | 
	
		
			
				|  |  | -  grpc_chttp2_transport_global *transport_global =
 | 
	
		
			
				|  |  | -      &TRANSPORT_FROM_PARSING(transport_parsing)->global;
 | 
	
		
			
				|  |  | +  const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
 | 
	
		
			
				|  |  |    const size_t metadata_size_limit =
 | 
	
		
			
				|  |  | -      transport_global->settings[GRPC_LOCAL_SETTINGS]
 | 
	
		
			
				|  |  | -                                [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
 | 
	
		
			
				|  |  | +      t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | +                 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
 | 
	
		
			
				|  |  |    if (new_size > metadata_size_limit) {
 | 
	
		
			
				|  |  | -    if (!stream_parsing->exceeded_metadata_size) {
 | 
	
		
			
				|  |  | -      gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | -              "received trailing metadata size exceeds limit (%" PRIuPTR
 | 
	
		
			
				|  |  | -              " vs. %" PRIuPTR ")",
 | 
	
		
			
				|  |  | -              new_size, metadata_size_limit);
 | 
	
		
			
				|  |  | -      stream_parsing->seen_error = true;
 | 
	
		
			
				|  |  | -      stream_parsing->exceeded_metadata_size = true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | +            "received trailing metadata size exceeds limit (%" PRIuPTR
 | 
	
		
			
				|  |  | +            " vs. %" PRIuPTR ")",
 | 
	
		
			
				|  |  | +            new_size, metadata_size_limit);
 | 
	
		
			
				|  |  | +    grpc_chttp2_cancel_stream(
 | 
	
		
			
				|  |  | +        exec_ctx, t, s,
 | 
	
		
			
				|  |  | +        grpc_error_set_int(
 | 
	
		
			
				|  |  | +            GRPC_ERROR_CREATE("received trailing metadata size exceeds limit"),
 | 
	
		
			
				|  |  | +            GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
 | 
	
		
			
				|  |  | +    grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
 | 
	
		
			
				|  |  | +    s->seen_error = true;
 | 
	
		
			
				|  |  |      GRPC_MDELEM_UNREF(md);
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    grpc_chttp2_incoming_metadata_buffer_add(
 | 
	
		
			
				|  |  | -        &stream_parsing->metadata_buffer[1], md);
 | 
	
		
			
				|  |  | +    grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    GPR_TIMER_END("on_trailing_header", 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_header_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    int is_continuation) {
 | 
	
		
			
				|  |  | -  uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
 | 
	
		
			
				|  |  | -                    GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
 | 
	
		
			
				|  |  | -  int via_accept = 0;
 | 
	
		
			
				|  |  | -  grpc_chttp2_stream_parsing *stream_parsing;
 | 
	
		
			
				|  |  | +static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                            grpc_chttp2_transport *t,
 | 
	
		
			
				|  |  | +                                            int is_continuation) {
 | 
	
		
			
				|  |  | +  uint8_t is_eoh =
 | 
	
		
			
				|  |  | +      (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream *s;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* TODO(ctiller): when to increment header_frames_received? */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (is_eoh) {
 | 
	
		
			
				|  |  | -    transport_parsing->expect_continuation_stream_id = 0;
 | 
	
		
			
				|  |  | +    t->expect_continuation_stream_id = 0;
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    transport_parsing->expect_continuation_stream_id =
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_stream_id;
 | 
	
		
			
				|  |  | +    t->expect_continuation_stream_id = t->incoming_stream_id;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (!is_continuation) {
 | 
	
		
			
				|  |  | -    transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
 | 
	
		
			
				|  |  | -                                     GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
 | 
	
		
			
				|  |  | +    t->header_eof =
 | 
	
		
			
				|  |  | +        (t->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) {
 | 
	
		
			
				|  |  | +  s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
 | 
	
		
			
				|  |  | +  if (s == NULL) {
 | 
	
		
			
				|  |  |      if (is_continuation) {
 | 
	
		
			
				|  |  | -      gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  | -              "grpc_chttp2_stream disbanded before CONTINUATION received");
 | 
	
		
			
				|  |  | -      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  | +      GRPC_CHTTP2_IF_TRACING(
 | 
	
		
			
				|  |  | +          gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  | +                  "grpc_chttp2_stream disbanded before CONTINUATION received"));
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if (transport_parsing->is_client) {
 | 
	
		
			
				|  |  | -      if ((transport_parsing->incoming_stream_id & 1) &&
 | 
	
		
			
				|  |  | -          transport_parsing->incoming_stream_id <
 | 
	
		
			
				|  |  | -              transport_parsing->next_stream_id) {
 | 
	
		
			
				|  |  | +    if (t->is_client) {
 | 
	
		
			
				|  |  | +      if ((t->incoming_stream_id & 1) &&
 | 
	
		
			
				|  |  | +          t->incoming_stream_id < t->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");
 | 
	
		
			
				|  |  | +        GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
		
			
				|  |  | +            GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client"));
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      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,
 | 
	
		
			
				|  |  | -              "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(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(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  | +    } else if (t->last_new_stream_id >= t->incoming_stream_id) {
 | 
	
		
			
				|  |  | +      GRPC_CHTTP2_IF_TRACING(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",
 | 
	
		
			
				|  |  | +          t->last_new_stream_id, t->incoming_stream_id));
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  | +    } else if ((t->incoming_stream_id & 1) == 0) {
 | 
	
		
			
				|  |  | +      GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
		
			
				|  |  | +          GPR_ERROR,
 | 
	
		
			
				|  |  | +          "ignoring grpc_chttp2_stream with non-client generated index %d",
 | 
	
		
			
				|  |  | +          t->incoming_stream_id));
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    stream_parsing = transport_parsing->incoming_stream =
 | 
	
		
			
				|  |  | -        grpc_chttp2_parsing_accept_stream(
 | 
	
		
			
				|  |  | -            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(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  | +    t->last_new_stream_id = t->incoming_stream_id;
 | 
	
		
			
				|  |  | +    s = t->incoming_stream =
 | 
	
		
			
				|  |  | +        grpc_chttp2_parsing_accept_stream(exec_ctx, t, t->incoming_stream_id);
 | 
	
		
			
				|  |  | +    if (s == NULL) {
 | 
	
		
			
				|  |  | +      GRPC_CHTTP2_IF_TRACING(
 | 
	
		
			
				|  |  | +          gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    via_accept = 1;
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    transport_parsing->incoming_stream = stream_parsing;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
 | 
	
		
			
				|  |  | -  stream_parsing->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | -  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(exec_ctx, transport_parsing, 1);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  transport_parsing->parser = grpc_chttp2_header_parser_parse;
 | 
	
		
			
				|  |  | -  transport_parsing->parser_data = &transport_parsing->hpack_parser;
 | 
	
		
			
				|  |  | -  switch (stream_parsing->header_frames_received) {
 | 
	
		
			
				|  |  | +    t->incoming_stream = s;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  GPR_ASSERT(s != NULL);
 | 
	
		
			
				|  |  | +  s->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | +  if (s->read_closed) {
 | 
	
		
			
				|  |  | +    GRPC_CHTTP2_IF_TRACING(gpr_log(
 | 
	
		
			
				|  |  | +        GPR_ERROR, "skipping already closed grpc_chttp2_stream header"));
 | 
	
		
			
				|  |  | +    t->incoming_stream = NULL;
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, t, 1);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  t->parser = grpc_chttp2_header_parser_parse;
 | 
	
		
			
				|  |  | +  t->parser_data = &t->hpack_parser;
 | 
	
		
			
				|  |  | +  switch (s->header_frames_received) {
 | 
	
		
			
				|  |  |      case 0:
 | 
	
		
			
				|  |  | -      transport_parsing->hpack_parser.on_header = on_initial_header;
 | 
	
		
			
				|  |  | +      t->hpack_parser.on_header = on_initial_header;
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      case 1:
 | 
	
		
			
				|  |  | -      transport_parsing->hpack_parser.on_header = on_trailing_header;
 | 
	
		
			
				|  |  | +      t->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);
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 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 =
 | 
	
		
			
				|  |  | -      (uint8_t)(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);
 | 
	
		
			
				|  |  | +  t->hpack_parser.on_header_user_data = t;
 | 
	
		
			
				|  |  | +  t->hpack_parser.is_boundary = is_eoh;
 | 
	
		
			
				|  |  | +  t->hpack_parser.is_eof = (uint8_t)(is_eoh ? t->header_eof : 0);
 | 
	
		
			
				|  |  | +  if (!is_continuation &&
 | 
	
		
			
				|  |  | +      (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
 | 
	
		
			
				|  |  | +    grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_window_update_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +static grpc_error *init_window_update_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                                   grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  |    grpc_error *err = grpc_chttp2_window_update_parser_begin_frame(
 | 
	
		
			
				|  |  | -      &transport_parsing->simple.window_update,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_flags);
 | 
	
		
			
				|  |  | +      &t->simple.window_update, t->incoming_frame_size,
 | 
	
		
			
				|  |  | +      t->incoming_frame_flags);
 | 
	
		
			
				|  |  |    if (err != GRPC_ERROR_NONE) return err;
 | 
	
		
			
				|  |  | -  if (transport_parsing->incoming_stream_id != 0) {
 | 
	
		
			
				|  |  | -    grpc_chttp2_stream_parsing *stream_parsing =
 | 
	
		
			
				|  |  | -        transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
 | 
	
		
			
				|  |  | -            transport_parsing, transport_parsing->incoming_stream_id);
 | 
	
		
			
				|  |  | -    if (stream_parsing == NULL) {
 | 
	
		
			
				|  |  | -      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | +  if (t->incoming_stream_id != 0) {
 | 
	
		
			
				|  |  | +    grpc_chttp2_stream *s = t->incoming_stream =
 | 
	
		
			
				|  |  | +        grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
 | 
	
		
			
				|  |  | +    if (s == NULL) {
 | 
	
		
			
				|  |  | +      return init_skip_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    stream_parsing->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | +    s->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
 | 
	
		
			
				|  |  | -  transport_parsing->parser_data = &transport_parsing->simple.window_update;
 | 
	
		
			
				|  |  | +  t->parser = grpc_chttp2_window_update_parser_parse;
 | 
	
		
			
				|  |  | +  t->parser_data = &t->simple.window_update;
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_ping_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +static grpc_error *init_ping_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                    grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  |    grpc_error *err = grpc_chttp2_ping_parser_begin_frame(
 | 
	
		
			
				|  |  | -      &transport_parsing->simple.ping, transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_flags);
 | 
	
		
			
				|  |  | +      &t->simple.ping, t->incoming_frame_size, t->incoming_frame_flags);
 | 
	
		
			
				|  |  |    if (err != GRPC_ERROR_NONE) return err;
 | 
	
		
			
				|  |  | -  transport_parsing->parser = grpc_chttp2_ping_parser_parse;
 | 
	
		
			
				|  |  | -  transport_parsing->parser_data = &transport_parsing->simple.ping;
 | 
	
		
			
				|  |  | +  t->parser = grpc_chttp2_ping_parser_parse;
 | 
	
		
			
				|  |  | +  t->parser_data = &t->simple.ping;
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_rst_stream_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +static grpc_error *init_rst_stream_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                          grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  |    grpc_error *err = grpc_chttp2_rst_stream_parser_begin_frame(
 | 
	
		
			
				|  |  | -      &transport_parsing->simple.rst_stream,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_flags);
 | 
	
		
			
				|  |  | +      &t->simple.rst_stream, t->incoming_frame_size, t->incoming_frame_flags);
 | 
	
		
			
				|  |  |    if (err != GRPC_ERROR_NONE) return err;
 | 
	
		
			
				|  |  | -  grpc_chttp2_stream_parsing *stream_parsing =
 | 
	
		
			
				|  |  | -      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(exec_ctx, transport_parsing, 0);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  stream_parsing->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | -  transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
 | 
	
		
			
				|  |  | -  transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream *s = t->incoming_stream =
 | 
	
		
			
				|  |  | +      grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
 | 
	
		
			
				|  |  | +  if (!t->incoming_stream) {
 | 
	
		
			
				|  |  | +    return init_skip_frame_parser(exec_ctx, t, 0);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  s->stats.incoming.framing_bytes += 9;
 | 
	
		
			
				|  |  | +  t->parser = grpc_chttp2_rst_stream_parser_parse;
 | 
	
		
			
				|  |  | +  t->parser_data = &t->simple.rst_stream;
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_goaway_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | +static grpc_error *init_goaway_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                      grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  |    grpc_error *err = grpc_chttp2_goaway_parser_begin_frame(
 | 
	
		
			
				|  |  | -      &transport_parsing->goaway_parser, transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_flags);
 | 
	
		
			
				|  |  | +      &t->goaway_parser, t->incoming_frame_size, t->incoming_frame_flags);
 | 
	
		
			
				|  |  |    if (err != GRPC_ERROR_NONE) return err;
 | 
	
		
			
				|  |  | -  transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
 | 
	
		
			
				|  |  | -  transport_parsing->parser_data = &transport_parsing->goaway_parser;
 | 
	
		
			
				|  |  | +  t->parser = grpc_chttp2_goaway_parser_parse;
 | 
	
		
			
				|  |  | +  t->parser_data = &t->goaway_parser;
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static grpc_error *init_settings_frame_parser(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
 | 
	
		
			
				|  |  | -  if (transport_parsing->incoming_stream_id != 0) {
 | 
	
		
			
				|  |  | +static grpc_error *init_settings_frame_parser(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                              grpc_chttp2_transport *t) {
 | 
	
		
			
				|  |  | +  if (t->incoming_stream_id != 0) {
 | 
	
		
			
				|  |  |      return GRPC_ERROR_CREATE("Settings frame received for grpc_chttp2_stream");
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    grpc_error *err = grpc_chttp2_settings_parser_begin_frame(
 | 
	
		
			
				|  |  | -      &transport_parsing->simple.settings,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_size,
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_frame_flags, transport_parsing->settings);
 | 
	
		
			
				|  |  | +      &t->simple.settings, t->incoming_frame_size, t->incoming_frame_flags,
 | 
	
		
			
				|  |  | +      t->settings[GRPC_PEER_SETTINGS]);
 | 
	
		
			
				|  |  |    if (err != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |      return err;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
 | 
	
		
			
				|  |  | -    transport_parsing->settings_ack_received = 1;
 | 
	
		
			
				|  |  | +  if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
 | 
	
		
			
				|  |  | +    memcpy(t->settings[GRPC_ACKED_SETTINGS], t->settings[GRPC_SENT_SETTINGS],
 | 
	
		
			
				|  |  | +           GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
 | 
	
		
			
				|  |  |      grpc_chttp2_hptbl_set_max_bytes(
 | 
	
		
			
				|  |  | -        &transport_parsing->hpack_parser.table,
 | 
	
		
			
				|  |  | -        transport_parsing
 | 
	
		
			
				|  |  | -            ->last_sent_settings[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
 | 
	
		
			
				|  |  | -    transport_parsing->max_frame_size =
 | 
	
		
			
				|  |  | -        transport_parsing
 | 
	
		
			
				|  |  | -            ->last_sent_settings[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
 | 
	
		
			
				|  |  | +        &t->hpack_parser.table,
 | 
	
		
			
				|  |  | +        t->settings[GRPC_ACKED_SETTINGS]
 | 
	
		
			
				|  |  | +                   [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
 | 
	
		
			
				|  |  | +    t->sent_local_settings = 0;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  transport_parsing->parser = grpc_chttp2_settings_parser_parse;
 | 
	
		
			
				|  |  | -  transport_parsing->parser_data = &transport_parsing->simple.settings;
 | 
	
		
			
				|  |  | +  t->parser = grpc_chttp2_settings_parser_parse;
 | 
	
		
			
				|  |  | +  t->parser_data = &t->simple.settings;
 | 
	
		
			
				|  |  |    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*
 | 
	
		
			
				|  |  | -static int is_window_update_legal(int64_t window_update, int64_t window) {
 | 
	
		
			
				|  |  | -  return window + window_update < MAX_WINDOW;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static grpc_error *parse_frame_slice(
 | 
	
		
			
				|  |  | -    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
 | 
	
		
			
				|  |  | -    gpr_slice slice, int is_last) {
 | 
	
		
			
				|  |  | -  grpc_chttp2_stream_parsing *stream_parsing =
 | 
	
		
			
				|  |  | -      transport_parsing->incoming_stream;
 | 
	
		
			
				|  |  | -  grpc_error *err = transport_parsing->parser(
 | 
	
		
			
				|  |  | -      exec_ctx, transport_parsing->parser_data, transport_parsing,
 | 
	
		
			
				|  |  | -      stream_parsing, slice, is_last);
 | 
	
		
			
				|  |  | +static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  | +                                     grpc_chttp2_transport *t, gpr_slice slice,
 | 
	
		
			
				|  |  | +                                     int is_last) {
 | 
	
		
			
				|  |  | +  grpc_chttp2_stream *s = t->incoming_stream;
 | 
	
		
			
				|  |  | +  grpc_error *err = t->parser(exec_ctx, t->parser_data, t, s, slice, is_last);
 | 
	
		
			
				|  |  |    if (err == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -    if (stream_parsing) {
 | 
	
		
			
				|  |  | -      grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
 | 
	
		
			
				|  |  | -                                               stream_parsing);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return GRPC_ERROR_NONE;
 | 
	
		
			
				|  |  | +    return err;
 | 
	
		
			
				|  |  |    } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
 | 
	
		
			
				|  |  |      if (grpc_http_trace) {
 | 
	
		
			
				|  |  |        const char *msg = grpc_error_string(err);
 | 
	
		
			
				|  |  |        gpr_log(GPR_ERROR, "%s", msg);
 | 
	
		
			
				|  |  |        grpc_error_free_string(msg);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
 | 
	
		
			
				|  |  | -    if (stream_parsing) {
 | 
	
		
			
				|  |  | -      stream_parsing->forced_close_error = err;
 | 
	
		
			
				|  |  | +    grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
 | 
	
		
			
				|  |  | +    if (s) {
 | 
	
		
			
				|  |  | +      s->forced_close_error = err;
 | 
	
		
			
				|  |  |        gpr_slice_buffer_add(
 | 
	
		
			
				|  |  | -          &transport_parsing->qbuf,
 | 
	
		
			
				|  |  | -          grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
 | 
	
		
			
				|  |  | -                                        GRPC_CHTTP2_PROTOCOL_ERROR,
 | 
	
		
			
				|  |  | -                                        &stream_parsing->stats.outgoing));
 | 
	
		
			
				|  |  | +          &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
 | 
	
		
			
				|  |  | +                                                  GRPC_CHTTP2_PROTOCOL_ERROR,
 | 
	
		
			
				|  |  | +                                                  &s->stats.outgoing));
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |        GRPC_ERROR_UNREF(err);
 | 
	
		
			
				|  |  |      }
 |