LCOV - code coverage report
Current view: top level - core/transport/chttp2 - parsing.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 382 413 92.5 %
Date: 2015-12-10 22:15:08 Functions: 24 25 96.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright 2015, Google Inc.
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are
       8             :  * met:
       9             :  *
      10             :  *     * Redistributions of source code must retain the above copyright
      11             :  * notice, this list of conditions and the following disclaimer.
      12             :  *     * Redistributions in binary form must reproduce the above
      13             :  * copyright notice, this list of conditions and the following disclaimer
      14             :  * in the documentation and/or other materials provided with the
      15             :  * distribution.
      16             :  *     * Neither the name of Google Inc. nor the names of its
      17             :  * contributors may be used to endorse or promote products derived from
      18             :  * this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             :  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             :  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  *
      32             :  */
      33             : 
      34             : #include "src/core/transport/chttp2/internal.h"
      35             : 
      36             : #include <string.h>
      37             : 
      38             : #include <grpc/support/alloc.h>
      39             : #include <grpc/support/log.h>
      40             : #include <grpc/support/string_util.h>
      41             : 
      42             : #include "src/core/profiling/timers.h"
      43             : #include "src/core/transport/chttp2/http2_errors.h"
      44             : #include "src/core/transport/chttp2/status_conversion.h"
      45             : #include "src/core/transport/chttp2/timeout_encoding.h"
      46             : #include "src/core/transport/static_metadata.h"
      47             : 
      48             : static int init_frame_parser(grpc_exec_ctx *exec_ctx,
      49             :                              grpc_chttp2_transport_parsing *transport_parsing);
      50             : static int init_header_frame_parser(
      51             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
      52             :     int is_continuation);
      53             : static int init_data_frame_parser(
      54             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
      55             : static int init_rst_stream_parser(
      56             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
      57             : static int init_settings_frame_parser(
      58             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
      59             : static int init_window_update_frame_parser(
      60             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
      61             : static int init_ping_parser(grpc_exec_ctx *exec_ctx,
      62             :                             grpc_chttp2_transport_parsing *transport_parsing);
      63             : static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
      64             :                               grpc_chttp2_transport_parsing *transport_parsing);
      65             : static int init_skip_frame_parser(
      66             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
      67             :     int is_header);
      68             : 
      69             : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
      70             :                              grpc_chttp2_transport_parsing *transport_parsing,
      71             :                              gpr_slice slice, int is_last);
      72             : 
      73     6516034 : void grpc_chttp2_prepare_to_read(
      74             :     grpc_chttp2_transport_global *transport_global,
      75             :     grpc_chttp2_transport_parsing *transport_parsing) {
      76             :   grpc_chttp2_stream_global *stream_global;
      77             :   grpc_chttp2_stream_parsing *stream_parsing;
      78             : 
      79             :   GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
      80             : 
      81     6516034 :   transport_parsing->next_stream_id = transport_global->next_stream_id;
      82     6516034 :   transport_parsing->last_sent_max_table_size =
      83             :       transport_global->settings[GRPC_SENT_SETTINGS]
      84     6516034 :                                 [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
      85             : 
      86             :   /* update the parsing view of incoming window */
      87    15003088 :   while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
      88             :       transport_global, transport_parsing, &stream_global, &stream_parsing)) {
      89     1970902 :     GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing,
      90             :                                  incoming_window, stream_global,
      91             :                                  unannounced_incoming_window_for_parse);
      92             :   }
      93             : 
      94             :   GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
      95     6516027 : }
      96             : 
      97     6516050 : void grpc_chttp2_publish_reads(
      98             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
      99             :     grpc_chttp2_transport_parsing *transport_parsing) {
     100             :   grpc_chttp2_stream_global *stream_global;
     101             :   grpc_chttp2_stream_parsing *stream_parsing;
     102             :   int was_zero;
     103             :   int is_zero;
     104             : 
     105             :   /* transport_parsing->last_incoming_stream_id is used as
     106             :      last-grpc_chttp2_stream-id when
     107             :      sending GOAWAY frame.
     108             :      https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
     109             :      says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
     110             :      ID.  So,
     111             :      since we don't have server pushed streams, client should send
     112             :      GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
     113     6516050 :   if (!transport_parsing->is_client) {
     114     4338398 :     transport_global->last_incoming_stream_id =
     115     4338398 :         transport_parsing->incoming_stream_id;
     116             :   }
     117             : 
     118             :   /* update global settings */
     119     6516050 :   if (transport_parsing->settings_updated) {
     120        5552 :     memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
     121        5552 :            transport_parsing->settings, sizeof(transport_parsing->settings));
     122        5552 :     transport_parsing->settings_updated = 0;
     123             :   }
     124             : 
     125             :   /* update settings based on ack if received */
     126     6516050 :   if (transport_parsing->settings_ack_received) {
     127        5372 :     memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
     128        5372 :            transport_global->settings[GRPC_SENT_SETTINGS],
     129             :            GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
     130        5372 :     transport_parsing->settings_ack_received = 0;
     131        5372 :     transport_global->sent_local_settings = 0;
     132             :   }
     133             : 
     134             :   /* move goaway to the global state if we received one (it will be
     135             :      published later */
     136     6516050 :   if (transport_parsing->goaway_received) {
     137         284 :     grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
     138         284 :                                     (gpr_uint32)transport_parsing->goaway_error,
     139             :                                     transport_parsing->goaway_text);
     140         284 :     transport_parsing->goaway_text = gpr_empty_slice();
     141         284 :     transport_parsing->goaway_received = 0;
     142             :   }
     143             : 
     144             :   /* propagate flow control tokens to global state */
     145     6516050 :   was_zero = transport_global->outgoing_window <= 0;
     146     6516050 :   GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
     147             :                                   transport_parsing, outgoing_window);
     148     6516045 :   is_zero = transport_global->outgoing_window <= 0;
     149     6516045 :   if (was_zero && !is_zero) {
     150       11663 :     while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
     151             :                                                      &stream_global)) {
     152           6 :       grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
     153             :     }
     154             :   }
     155             : 
     156    13032092 :   if (transport_parsing->incoming_window <
     157     6516046 :       transport_global->connection_window_target * 3 / 4) {
     158       12959 :     gpr_int64 announce_bytes = transport_global->connection_window_target -
     159        6436 :                                transport_parsing->incoming_window;
     160        6523 :     GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
     161             :                                       announce_incoming_window, announce_bytes);
     162        6522 :     GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
     163             :                                       incoming_window, announce_bytes);
     164             :   }
     165             : 
     166             :   /* for each stream that saw an update, fixup global state */
     167    21748671 :   while (grpc_chttp2_list_pop_parsing_seen_stream(
     168             :       transport_global, transport_parsing, &stream_global, &stream_parsing)) {
     169     8718220 :     if (stream_parsing->seen_error) {
     170      523824 :       stream_global->seen_error = 1;
     171      523824 :       grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
     172             :     }
     173             : 
     174             :     /* update outgoing flow control window */
     175     8718389 :     was_zero = stream_global->outgoing_window <= 0;
     176     8718389 :     GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
     177             :                                  outgoing_window, stream_parsing,
     178             :                                  outgoing_window);
     179     8718544 :     is_zero = stream_global->outgoing_window <= 0;
     180     8718544 :     if (was_zero && !is_zero) {
     181       28567 :       grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
     182             :     }
     183             : 
     184     8718544 :     stream_global->max_recv_bytes -= (gpr_uint32)GPR_MIN(
     185             :         stream_global->max_recv_bytes, stream_parsing->received_bytes);
     186     8718544 :     stream_parsing->received_bytes = 0;
     187             : 
     188             :     /* publish incoming stream ops */
     189     8718544 :     if (stream_global->incoming_frames.tail != NULL) {
     190       64242 :       stream_global->incoming_frames.tail->is_tail = 0;
     191             :     }
     192     8718544 :     if (stream_parsing->data_parser.incoming_frames.head != NULL) {
     193     3954453 :       grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
     194             :     }
     195    17437532 :     grpc_chttp2_incoming_frame_queue_merge(
     196     8718766 :         &stream_global->incoming_frames,
     197     8718766 :         &stream_parsing->data_parser.incoming_frames);
     198     8719395 :     if (stream_global->incoming_frames.tail != NULL) {
     199     4016291 :       stream_global->incoming_frames.tail->is_tail = 1;
     200             :     }
     201             : 
     202    15717119 :     if (!stream_global->published_initial_metadata &&
     203     6997724 :         stream_parsing->got_metadata_on_parse[0]) {
     204     4441265 :       stream_parsing->got_metadata_on_parse[0] = 0;
     205     4441265 :       stream_global->published_initial_metadata = 1;
     206     4441265 :       GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
     207             :                stream_parsing->metadata_buffer[0],
     208             :                stream_global->received_initial_metadata);
     209     4441265 :       grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
     210             :     }
     211    17439722 :     if (!stream_global->published_trailing_metadata &&
     212     8720130 :         stream_parsing->got_metadata_on_parse[1]) {
     213     2271496 :       stream_parsing->got_metadata_on_parse[1] = 0;
     214     2271496 :       stream_global->published_trailing_metadata = 1;
     215     2271496 :       GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
     216             :                stream_parsing->metadata_buffer[1],
     217             :                stream_global->received_trailing_metadata);
     218     2271496 :       grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
     219             :     }
     220             : 
     221     8719158 :     if (stream_parsing->saw_rst_stream) {
     222         393 :       if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
     223         154 :         grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
     224         143 :             (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
     225             :         char *status_details;
     226             :         gpr_slice slice_details;
     227         154 :         gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
     228         154 :                      stream_parsing->rst_stream_reason);
     229         154 :         slice_details = gpr_slice_from_copied_string(status_details);
     230         154 :         gpr_free(status_details);
     231         154 :         grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
     232             :                                 status_code, &slice_details);
     233             :       }
     234         393 :       grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
     235             :                                      1, 1);
     236             :     }
     237             : 
     238     8719158 :     if (stream_parsing->received_close) {
     239     4440070 :       grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
     240             :                                      1, 0);
     241             :     }
     242             :   }
     243     6515990 : }
     244             : 
     245    18512073 : int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
     246             :                              grpc_chttp2_transport_parsing *transport_parsing,
     247             :                              gpr_slice slice) {
     248    18512073 :   gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
     249    18512073 :   gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
     250    18511275 :   gpr_uint8 *cur = beg;
     251             : 
     252    18512073 :   if (cur == end) return 1;
     253             : 
     254    18512073 :   switch (transport_parsing->deframe_state) {
     255             :     case GRPC_DTS_CLIENT_PREFIX_0:
     256             :     case GRPC_DTS_CLIENT_PREFIX_1:
     257             :     case GRPC_DTS_CLIENT_PREFIX_2:
     258             :     case GRPC_DTS_CLIENT_PREFIX_3:
     259             :     case GRPC_DTS_CLIENT_PREFIX_4:
     260             :     case GRPC_DTS_CLIENT_PREFIX_5:
     261             :     case GRPC_DTS_CLIENT_PREFIX_6:
     262             :     case GRPC_DTS_CLIENT_PREFIX_7:
     263             :     case GRPC_DTS_CLIENT_PREFIX_8:
     264             :     case GRPC_DTS_CLIENT_PREFIX_9:
     265             :     case GRPC_DTS_CLIENT_PREFIX_10:
     266             :     case GRPC_DTS_CLIENT_PREFIX_11:
     267             :     case GRPC_DTS_CLIENT_PREFIX_12:
     268             :     case GRPC_DTS_CLIENT_PREFIX_13:
     269             :     case GRPC_DTS_CLIENT_PREFIX_14:
     270             :     case GRPC_DTS_CLIENT_PREFIX_15:
     271             :     case GRPC_DTS_CLIENT_PREFIX_16:
     272             :     case GRPC_DTS_CLIENT_PREFIX_17:
     273             :     case GRPC_DTS_CLIENT_PREFIX_18:
     274             :     case GRPC_DTS_CLIENT_PREFIX_19:
     275             :     case GRPC_DTS_CLIENT_PREFIX_20:
     276             :     case GRPC_DTS_CLIENT_PREFIX_21:
     277             :     case GRPC_DTS_CLIENT_PREFIX_22:
     278             :     case GRPC_DTS_CLIENT_PREFIX_23:
     279       82039 :       while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
     280      135264 :         if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
     281       67140 :                                                           ->deframe_state]) {
     282          96 :           gpr_log(GPR_INFO,
     283             :                   "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
     284             :                   "at byte %d",
     285          24 :                   GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
     286          24 :                                                         ->deframe_state],
     287          24 :                   (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
     288          24 :                       [transport_parsing->deframe_state],
     289          48 :                   *cur, (int)*cur, transport_parsing->deframe_state);
     290          24 :           return 0;
     291             :         }
     292       68100 :         ++cur;
     293       68100 :         ++transport_parsing->deframe_state;
     294             :       }
     295        6966 :       if (cur == end) {
     296        4320 :         return 1;
     297             :       }
     298             :     /* fallthrough */
     299             :     dts_fh_0:
     300             :     case GRPC_DTS_FH_0:
     301    11233057 :       GPR_ASSERT(cur < end);
     302    11233057 :       transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
     303    11233057 :       if (++cur == end) {
     304      211779 :         transport_parsing->deframe_state = GRPC_DTS_FH_1;
     305      211779 :         return 1;
     306             :       }
     307             :     /* fallthrough */
     308             :     case GRPC_DTS_FH_1:
     309    11234229 :       GPR_ASSERT(cur < end);
     310    11234229 :       transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
     311    11234229 :       if (++cur == end) {
     312      217856 :         transport_parsing->deframe_state = GRPC_DTS_FH_2;
     313      217856 :         return 1;
     314             :       }
     315             :     /* fallthrough */
     316             :     case GRPC_DTS_FH_2:
     317    11234272 :       GPR_ASSERT(cur < end);
     318    11234272 :       transport_parsing->incoming_frame_size |= *cur;
     319    11234272 :       if (++cur == end) {
     320      211953 :         transport_parsing->deframe_state = GRPC_DTS_FH_3;
     321      211953 :         return 1;
     322             :       }
     323             :     /* fallthrough */
     324             :     case GRPC_DTS_FH_3:
     325    11234325 :       GPR_ASSERT(cur < end);
     326    11234325 :       transport_parsing->incoming_frame_type = *cur;
     327    11234325 :       if (++cur == end) {
     328      211966 :         transport_parsing->deframe_state = GRPC_DTS_FH_4;
     329      211966 :         return 1;
     330             :       }
     331             :     /* fallthrough */
     332             :     case GRPC_DTS_FH_4:
     333    11235272 :       GPR_ASSERT(cur < end);
     334    11235272 :       transport_parsing->incoming_frame_flags = *cur;
     335    11235272 :       if (++cur == end) {
     336      211943 :         transport_parsing->deframe_state = GRPC_DTS_FH_5;
     337      211943 :         return 1;
     338             :       }
     339             :     /* fallthrough */
     340             :     case GRPC_DTS_FH_5:
     341    11234010 :       GPR_ASSERT(cur < end);
     342    11234010 :       transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
     343    11234010 :       if (++cur == end) {
     344      211776 :         transport_parsing->deframe_state = GRPC_DTS_FH_6;
     345      211776 :         return 1;
     346             :       }
     347             :     /* fallthrough */
     348             :     case GRPC_DTS_FH_6:
     349    11234027 :       GPR_ASSERT(cur < end);
     350    11234027 :       transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
     351    11234027 :       if (++cur == end) {
     352      211864 :         transport_parsing->deframe_state = GRPC_DTS_FH_7;
     353      211864 :         return 1;
     354             :       }
     355             :     /* fallthrough */
     356             :     case GRPC_DTS_FH_7:
     357    11233751 :       GPR_ASSERT(cur < end);
     358    11233751 :       transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
     359    11233751 :       if (++cur == end) {
     360      211905 :         transport_parsing->deframe_state = GRPC_DTS_FH_8;
     361      211905 :         return 1;
     362             :       }
     363             :     /* fallthrough */
     364             :     case GRPC_DTS_FH_8:
     365    11234736 :       GPR_ASSERT(cur < end);
     366    11234736 :       transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
     367    11234736 :       transport_parsing->deframe_state = GRPC_DTS_FRAME;
     368    11234736 :       if (!init_frame_parser(exec_ctx, transport_parsing)) {
     369          12 :         return 0;
     370             :       }
     371    11237195 :       if (transport_parsing->incoming_stream_id) {
     372    11219543 :         transport_parsing->last_incoming_stream_id =
     373    11218943 :             transport_parsing->incoming_stream_id;
     374             :       }
     375    11237195 :       if (transport_parsing->incoming_frame_size == 0) {
     376      528789 :         if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
     377             :                                1)) {
     378           0 :           return 0;
     379             :         }
     380      528790 :         transport_parsing->incoming_stream = NULL;
     381      528790 :         if (++cur == end) {
     382      527409 :           transport_parsing->deframe_state = GRPC_DTS_FH_0;
     383      527409 :           return 1;
     384             :         }
     385        1369 :         goto dts_fh_0; /* loop */
     386             :       }
     387    10708406 :       if (++cur == end) {
     388      159241 :         return 1;
     389             :       }
     390             :     /* fallthrough */
     391             :     case GRPC_DTS_FRAME:
     392    24868382 :       GPR_ASSERT(cur < end);
     393    24868382 :       if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
     394     3917126 :         if (!parse_frame_slice(exec_ctx, transport_parsing,
     395     1958563 :                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
     396     1958563 :                                                     (size_t)(end - beg)),
     397             :                                1)) {
     398          23 :           return 0;
     399             :         }
     400     1958546 :         transport_parsing->deframe_state = GRPC_DTS_FH_0;
     401     1958546 :         transport_parsing->incoming_stream = NULL;
     402     1958546 :         return 1;
     403    45818983 :       } else if ((gpr_uint32)(end - cur) >
     404    22909164 :                  transport_parsing->incoming_frame_size) {
     405     8750802 :         size_t cur_offset = (size_t)(cur - beg);
     406     8750802 :         if (!parse_frame_slice(
     407             :                 exec_ctx, transport_parsing,
     408             :                 gpr_slice_sub_no_ref(
     409             :                     slice, cur_offset,
     410     8750434 :                     cur_offset + transport_parsing->incoming_frame_size),
     411             :                 1)) {
     412           0 :           return 0;
     413             :         }
     414     8745885 :         cur += transport_parsing->incoming_frame_size;
     415     8745885 :         transport_parsing->incoming_stream = NULL;
     416     8745885 :         goto dts_fh_0; /* loop */
     417             :       } else {
     418    28318034 :         if (!parse_frame_slice(exec_ctx, transport_parsing,
     419    14159017 :                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
     420    14159017 :                                                     (size_t)(end - beg)),
     421             :                                0)) {
     422           0 :           return 0;
     423             :         }
     424    14159017 :         transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur);
     425    14159017 :         return 1;
     426             :       }
     427             :       GPR_UNREACHABLE_CODE(return 0);
     428             :   }
     429             : 
     430           0 :   GPR_UNREACHABLE_CODE(return 0);
     431           0 : }
     432             : 
     433    11240615 : static int init_frame_parser(grpc_exec_ctx *exec_ctx,
     434             :                              grpc_chttp2_transport_parsing *transport_parsing) {
     435    11240615 :   if (transport_parsing->expect_continuation_stream_id != 0) {
     436         115 :     if (transport_parsing->incoming_frame_type !=
     437             :         GRPC_CHTTP2_FRAME_CONTINUATION) {
     438           1 :       gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
     439           1 :               transport_parsing->incoming_frame_type);
     440           1 :       return 0;
     441             :     }
     442         228 :     if (transport_parsing->expect_continuation_stream_id !=
     443         114 :         transport_parsing->incoming_stream_id) {
     444           1 :       gpr_log(GPR_ERROR,
     445             :               "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
     446             :               "grpc_chttp2_stream %08x",
     447             :               transport_parsing->expect_continuation_stream_id,
     448             :               transport_parsing->incoming_stream_id);
     449           1 :       return 0;
     450             :     }
     451         113 :     return init_header_frame_parser(exec_ctx, transport_parsing, 1);
     452             :   }
     453    11240500 :   switch (transport_parsing->incoming_frame_type) {
     454             :     case GRPC_CHTTP2_FRAME_DATA:
     455     4488376 :       return init_data_frame_parser(exec_ctx, transport_parsing);
     456             :     case GRPC_CHTTP2_FRAME_HEADER:
     457     6705495 :       return init_header_frame_parser(exec_ctx, transport_parsing, 0);
     458             :     case GRPC_CHTTP2_FRAME_CONTINUATION:
     459           1 :       gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
     460           1 :       return 0;
     461             :     case GRPC_CHTTP2_FRAME_RST_STREAM:
     462         605 :       return init_rst_stream_parser(exec_ctx, transport_parsing);
     463             :     case GRPC_CHTTP2_FRAME_SETTINGS:
     464       10934 :       return init_settings_frame_parser(exec_ctx, transport_parsing);
     465             :     case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
     466       34804 :       return init_window_update_frame_parser(exec_ctx, transport_parsing);
     467             :     case GRPC_CHTTP2_FRAME_PING:
     468           0 :       return init_ping_parser(exec_ctx, transport_parsing);
     469             :     case GRPC_CHTTP2_FRAME_GOAWAY:
     470         284 :       return init_goaway_parser(exec_ctx, transport_parsing);
     471             :     default:
     472           1 :       gpr_log(GPR_ERROR, "Unknown frame type %02x",
     473           1 :               transport_parsing->incoming_frame_type);
     474           1 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
     475             :   }
     476             : }
     477             : 
     478         589 : static grpc_chttp2_parse_error skip_parser(
     479             :     grpc_exec_ctx *exec_ctx, void *parser,
     480             :     grpc_chttp2_transport_parsing *transport_parsing,
     481             :     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
     482         589 :   return GRPC_CHTTP2_PARSE_OK;
     483             : }
     484             : 
     485         228 : static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
     486             : 
     487         562 : static int init_skip_frame_parser(
     488             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     489             :     int is_header) {
     490         562 :   if (is_header) {
     491          88 :     gpr_uint8 is_eoh = transport_parsing->expect_continuation_stream_id != 0;
     492          88 :     transport_parsing->parser = grpc_chttp2_header_parser_parse;
     493          88 :     transport_parsing->parser_data = &transport_parsing->hpack_parser;
     494          88 :     transport_parsing->hpack_parser.on_header = skip_header;
     495          88 :     transport_parsing->hpack_parser.on_header_user_data = NULL;
     496          88 :     transport_parsing->hpack_parser.is_boundary = is_eoh;
     497          88 :     transport_parsing->hpack_parser.is_eof =
     498          88 :         (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
     499             :   } else {
     500         484 :     transport_parsing->parser = skip_parser;
     501             :   }
     502         562 :   return 1;
     503             : }
     504             : 
     505          35 : void grpc_chttp2_parsing_become_skip_parser(
     506             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
     507          35 :   init_skip_frame_parser(
     508             :       exec_ctx, transport_parsing,
     509          35 :       transport_parsing->parser == grpc_chttp2_header_parser_parse);
     510          35 : }
     511             : 
     512     4490685 : static grpc_chttp2_parse_error update_incoming_window(
     513             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     514             :     grpc_chttp2_stream_parsing *stream_parsing) {
     515     4490685 :   gpr_uint32 incoming_frame_size = transport_parsing->incoming_frame_size;
     516     4490685 :   if (incoming_frame_size > transport_parsing->incoming_window) {
     517           0 :     gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
     518             :             transport_parsing->incoming_frame_size,
     519             :             transport_parsing->incoming_window);
     520           0 :     return GRPC_CHTTP2_CONNECTION_ERROR;
     521             :   }
     522             : 
     523     4490685 :   if (incoming_frame_size > stream_parsing->incoming_window) {
     524           0 :     gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
     525             :             transport_parsing->incoming_frame_size,
     526             :             stream_parsing->incoming_window);
     527           0 :     return GRPC_CHTTP2_CONNECTION_ERROR;
     528             :   }
     529             : 
     530     4490685 :   GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
     531             :                                    incoming_frame_size);
     532     4490939 :   GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing,
     533             :                                 incoming_window, incoming_frame_size);
     534     4490939 :   stream_parsing->received_bytes += incoming_frame_size;
     535             : 
     536     4490939 :   grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
     537             : 
     538     4490556 :   return GRPC_CHTTP2_PARSE_OK;
     539             : }
     540             : 
     541     4488492 : static int init_data_frame_parser(
     542             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
     543     4488492 :   grpc_chttp2_stream_parsing *stream_parsing =
     544     4488492 :       grpc_chttp2_parsing_lookup_stream(transport_parsing,
     545             :                                         transport_parsing->incoming_stream_id);
     546     4490915 :   grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
     547     4491238 :   if (!stream_parsing || stream_parsing->received_close)
     548         272 :     return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
     549     4490643 :   if (err == GRPC_CHTTP2_PARSE_OK) {
     550     4490961 :     err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
     551             :   }
     552     4490887 :   if (err == GRPC_CHTTP2_PARSE_OK) {
     553     4490869 :     err = grpc_chttp2_data_parser_begin_frame(
     554     4490869 :         &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
     555             :   }
     556     4490849 :   switch (err) {
     557             :     case GRPC_CHTTP2_PARSE_OK:
     558     4490848 :       transport_parsing->incoming_stream = stream_parsing;
     559     4490848 :       transport_parsing->parser = grpc_chttp2_data_parser_parse;
     560     4490848 :       transport_parsing->parser_data = &stream_parsing->data_parser;
     561     4490525 :       return 1;
     562             :     case GRPC_CHTTP2_STREAM_ERROR:
     563           1 :       stream_parsing->received_close = 1;
     564           1 :       stream_parsing->saw_rst_stream = 1;
     565           1 :       stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
     566           1 :       gpr_slice_buffer_add(
     567             :           &transport_parsing->qbuf,
     568             :           grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
     569             :                                         GRPC_CHTTP2_PROTOCOL_ERROR));
     570           1 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
     571             :     case GRPC_CHTTP2_CONNECTION_ERROR:
     572           0 :       return 0;
     573             :   }
     574           0 :   GPR_UNREACHABLE_CODE(return 0);
     575           0 : }
     576             : 
     577        1110 : static void free_timeout(void *p) { gpr_free(p); }
     578             : 
     579    30986801 : static void on_initial_header(void *tp, grpc_mdelem *md) {
     580    30985635 :   grpc_chttp2_transport_parsing *transport_parsing = tp;
     581    30986801 :   grpc_chttp2_stream_parsing *stream_parsing =
     582             :       transport_parsing->incoming_stream;
     583             : 
     584             :   GPR_TIMER_BEGIN("on_initial_header", 0);
     585             : 
     586    30986801 :   GPR_ASSERT(stream_parsing);
     587             : 
     588    30986801 :   GRPC_CHTTP2_IF_TRACING(gpr_log(
     589             :       GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
     590             :       transport_parsing->is_client ? "CLI" : "SVR",
     591             :       grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
     592             : 
     593    30983371 :   if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
     594             :     /* TODO(ctiller): check for a status like " 0" */
     595           5 :     stream_parsing->seen_error = 1;
     596             :   }
     597             : 
     598    30983371 :   if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
     599     1047992 :     gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
     600     1047992 :     if (!cached_timeout) {
     601             :       /* not already parsed: parse it now, and store the result away */
     602        1123 :       cached_timeout = gpr_malloc(sizeof(gpr_timespec));
     603        1123 :       if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
     604             :                                       cached_timeout)) {
     605           2 :         gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
     606             :                 grpc_mdstr_as_c_string(md->value));
     607           2 :         *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
     608             :       }
     609        1123 :       grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
     610             :     }
     611     1047992 :     grpc_chttp2_incoming_metadata_buffer_set_deadline(
     612             :         &stream_parsing->metadata_buffer[0],
     613             :         gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
     614     1047992 :     GRPC_MDELEM_UNREF(md);
     615             :   } else {
     616    29935379 :     grpc_chttp2_incoming_metadata_buffer_add(
     617             :         &stream_parsing->metadata_buffer[0], md);
     618             :   }
     619             : 
     620    30979907 :   grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
     621             : 
     622             :   GPR_TIMER_END("on_initial_header", 0);
     623    30981476 : }
     624             : 
     625     2896653 : static void on_trailing_header(void *tp, grpc_mdelem *md) {
     626     2896490 :   grpc_chttp2_transport_parsing *transport_parsing = tp;
     627     2896653 :   grpc_chttp2_stream_parsing *stream_parsing =
     628             :       transport_parsing->incoming_stream;
     629             : 
     630             :   GPR_TIMER_BEGIN("on_trailing_header", 0);
     631             : 
     632     2896653 :   GPR_ASSERT(stream_parsing);
     633             : 
     634     2896653 :   GRPC_CHTTP2_IF_TRACING(gpr_log(
     635             :       GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", stream_parsing->id,
     636             :       transport_parsing->is_client ? "CLI" : "SVR",
     637             :       grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
     638             : 
     639     2896653 :   if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
     640             :     /* TODO(ctiller): check for a status like " 0" */
     641      523274 :     stream_parsing->seen_error = 1;
     642             :   }
     643             : 
     644     2896653 :   grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1],
     645             :                                            md);
     646             : 
     647     2896521 :   grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
     648             : 
     649             :   GPR_TIMER_END("on_trailing_header", 0);
     650     2896466 : }
     651             : 
     652     6706969 : static int init_header_frame_parser(
     653             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
     654             :     int is_continuation) {
     655    13413938 :   gpr_uint8 is_eoh = (transport_parsing->incoming_frame_flags &
     656     6706969 :                       GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
     657     6706734 :   int via_accept = 0;
     658             :   grpc_chttp2_stream_parsing *stream_parsing;
     659             : 
     660             :   /* TODO(ctiller): when to increment header_frames_received? */
     661             : 
     662     6706969 :   if (is_eoh) {
     663     6706853 :     transport_parsing->expect_continuation_stream_id = 0;
     664             :   } else {
     665         116 :     transport_parsing->expect_continuation_stream_id =
     666         116 :         transport_parsing->incoming_stream_id;
     667             :   }
     668             : 
     669     6706969 :   if (!is_continuation) {
     670    13414376 :     transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
     671     6707188 :                                      GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
     672             :   }
     673             : 
     674             :   /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
     675     6706969 :   stream_parsing = grpc_chttp2_parsing_lookup_stream(
     676             :       transport_parsing, transport_parsing->incoming_stream_id);
     677     6714162 :   if (stream_parsing == NULL) {
     678     2171131 :     if (is_continuation) {
     679           0 :       gpr_log(GPR_ERROR,
     680             :               "grpc_chttp2_stream disbanded before CONTINUATION received");
     681           0 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     682             :     }
     683     2171131 :     if (transport_parsing->is_client) {
     684         102 :       if ((transport_parsing->incoming_stream_id & 1) &&
     685          50 :           transport_parsing->incoming_stream_id <
     686          51 :               transport_parsing->next_stream_id) {
     687             :         /* this is an old (probably cancelled) grpc_chttp2_stream */
     688             :       } else {
     689           0 :         gpr_log(GPR_ERROR,
     690             :                 "ignoring new grpc_chttp2_stream creation on client");
     691             :       }
     692          51 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     693     4342160 :     } else if (transport_parsing->last_incoming_stream_id >
     694     2171080 :                transport_parsing->incoming_stream_id) {
     695           0 :       gpr_log(GPR_ERROR,
     696             :               "ignoring out of order new grpc_chttp2_stream request on server; "
     697             :               "last grpc_chttp2_stream "
     698             :               "id=%d, new grpc_chttp2_stream id=%d",
     699             :               transport_parsing->last_incoming_stream_id,
     700             :               transport_parsing->incoming_stream_id);
     701           0 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     702     2171080 :     } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
     703           2 :       gpr_log(GPR_ERROR,
     704             :               "ignoring grpc_chttp2_stream with non-client generated index %d",
     705             :               transport_parsing->incoming_stream_id);
     706           2 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     707             :     }
     708     2171096 :     stream_parsing = transport_parsing->incoming_stream =
     709     2171078 :         grpc_chttp2_parsing_accept_stream(
     710             :             exec_ctx, transport_parsing, transport_parsing->incoming_stream_id);
     711     2171096 :     if (stream_parsing == NULL) {
     712           0 :       gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
     713           0 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     714             :     }
     715     2171007 :     via_accept = 1;
     716             :   } else {
     717     4543031 :     transport_parsing->incoming_stream = stream_parsing;
     718             :   }
     719     6714127 :   GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
     720     6710928 :   if (stream_parsing->received_close) {
     721           0 :     gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
     722           0 :     transport_parsing->incoming_stream = NULL;
     723           0 :     return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     724             :   }
     725     6710928 :   transport_parsing->parser = grpc_chttp2_header_parser_parse;
     726     6710928 :   transport_parsing->parser_data = &transport_parsing->hpack_parser;
     727     6710928 :   switch (stream_parsing->header_frames_received) {
     728             :     case 0:
     729     4441136 :       transport_parsing->hpack_parser.on_header = on_initial_header;
     730     4441136 :       break;
     731             :     case 1:
     732     2271558 :       transport_parsing->hpack_parser.on_header = on_trailing_header;
     733     2271558 :       break;
     734             :     case 2:
     735           1 :       gpr_log(GPR_ERROR, "too many header frames received");
     736           1 :       return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
     737             :   }
     738     6710927 :   transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
     739     6710927 :   transport_parsing->hpack_parser.is_boundary = is_eoh;
     740     6710927 :   transport_parsing->hpack_parser.is_eof =
     741     6710927 :       (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
     742     6710927 :   if (!is_continuation && (transport_parsing->incoming_frame_flags &
     743             :                            GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
     744          10 :     grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
     745             :   }
     746     6710502 :   return 1;
     747             : }
     748             : 
     749       34804 : static int init_window_update_frame_parser(
     750             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
     751       34804 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
     752             :                                        &transport_parsing->simple.window_update,
     753             :                                        transport_parsing->incoming_frame_size,
     754       34804 :                                        transport_parsing->incoming_frame_flags);
     755       34796 :   if (transport_parsing->incoming_stream_id) {
     756       28866 :     transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
     757             :         transport_parsing, transport_parsing->incoming_stream_id);
     758             :   }
     759       34796 :   transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
     760       34796 :   transport_parsing->parser_data = &transport_parsing->simple.window_update;
     761       34796 :   return ok;
     762             : }
     763             : 
     764           0 : static int init_ping_parser(grpc_exec_ctx *exec_ctx,
     765             :                             grpc_chttp2_transport_parsing *transport_parsing) {
     766           0 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
     767             :                                        &transport_parsing->simple.ping,
     768             :                                        transport_parsing->incoming_frame_size,
     769           0 :                                        transport_parsing->incoming_frame_flags);
     770           0 :   transport_parsing->parser = grpc_chttp2_ping_parser_parse;
     771           0 :   transport_parsing->parser_data = &transport_parsing->simple.ping;
     772           0 :   return ok;
     773             : }
     774             : 
     775         605 : static int init_rst_stream_parser(
     776             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
     777         605 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
     778             :                                        &transport_parsing->simple.rst_stream,
     779             :                                        transport_parsing->incoming_frame_size,
     780         605 :                                        transport_parsing->incoming_frame_flags);
     781         605 :   transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
     782             :       transport_parsing, transport_parsing->incoming_stream_id);
     783         605 :   if (!transport_parsing->incoming_stream) {
     784         199 :     return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
     785             :   }
     786         397 :   transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
     787         397 :   transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
     788         386 :   return ok;
     789             : }
     790             : 
     791         244 : static int init_goaway_parser(
     792             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
     793         284 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
     794             :                                        &transport_parsing->goaway_parser,
     795             :                                        transport_parsing->incoming_frame_size,
     796         284 :                                        transport_parsing->incoming_frame_flags);
     797         284 :   transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
     798         284 :   transport_parsing->parser_data = &transport_parsing->goaway_parser;
     799         244 :   return ok;
     800             : }
     801             : 
     802       10934 : static int init_settings_frame_parser(
     803             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
     804             :   int ok;
     805             : 
     806       10934 :   if (transport_parsing->incoming_stream_id != 0) {
     807           2 :     gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
     808             :             transport_parsing->incoming_stream_id);
     809           2 :     return 0;
     810             :   }
     811             : 
     812       10932 :   ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
     813             :                                    &transport_parsing->simple.settings,
     814             :                                    transport_parsing->incoming_frame_size,
     815       10932 :                                    transport_parsing->incoming_frame_flags,
     816       10932 :                                    transport_parsing->settings);
     817       10930 :   if (!ok) {
     818           7 :     return 0;
     819             :   }
     820       10923 :   if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
     821        5371 :     transport_parsing->settings_ack_received = 1;
     822        5371 :     grpc_chttp2_hptbl_set_max_bytes(
     823             :         &transport_parsing->hpack_parser.table,
     824             :         transport_parsing->last_sent_max_table_size);
     825             :   }
     826       10924 :   transport_parsing->parser = grpc_chttp2_settings_parser_parse;
     827       10924 :   transport_parsing->parser_data = &transport_parsing->simple.settings;
     828       10760 :   return ok;
     829             : }
     830             : 
     831             : /*
     832             : static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
     833             :   return window + window_update < MAX_WINDOW;
     834             : }
     835             : */
     836             : 
     837    25395894 : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
     838             :                              grpc_chttp2_transport_parsing *transport_parsing,
     839             :                              gpr_slice slice, int is_last) {
     840    25395894 :   grpc_chttp2_stream_parsing *stream_parsing =
     841             :       transport_parsing->incoming_stream;
     842    25395894 :   switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
     843             :                                     transport_parsing, stream_parsing, slice,
     844             :                                     is_last)) {
     845             :     case GRPC_CHTTP2_PARSE_OK:
     846    25396193 :       if (stream_parsing) {
     847    25372666 :         grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
     848             :                                                  stream_parsing);
     849             :       }
     850    25391398 :       return 1;
     851             :     case GRPC_CHTTP2_STREAM_ERROR:
     852           1 :       grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
     853           1 :       if (stream_parsing) {
     854           1 :         stream_parsing->saw_rst_stream = 1;
     855           1 :         stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
     856           1 :         gpr_slice_buffer_add(
     857             :             &transport_parsing->qbuf,
     858             :             grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
     859             :                                           GRPC_CHTTP2_PROTOCOL_ERROR));
     860             :       }
     861           1 :       return 1;
     862             :     case GRPC_CHTTP2_CONNECTION_ERROR:
     863          23 :       return 0;
     864             :   }
     865           0 :   GPR_UNREACHABLE_CODE(return 0);
     866           0 : }

Generated by: LCOV version 1.11