LCOV - code coverage report
Current view: top level - src/core/transport/chttp2 - parsing.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 341 397 85.9 %
Date: 2015-10-10 Functions: 18 19 94.7 %

          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 "src/core/transport/chttp2/http2_errors.h"
      39             : #include "src/core/transport/chttp2/status_conversion.h"
      40             : #include "src/core/transport/chttp2/timeout_encoding.h"
      41             : 
      42             : #include <grpc/support/alloc.h>
      43             : #include <grpc/support/log.h>
      44             : 
      45             : static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing);
      46             : static int init_header_frame_parser(
      47             :     grpc_chttp2_transport_parsing *transport_parsing, int is_continuation);
      48             : static int init_data_frame_parser(
      49             :     grpc_chttp2_transport_parsing *transport_parsing);
      50             : static int init_rst_stream_parser(
      51             :     grpc_chttp2_transport_parsing *transport_parsing);
      52             : static int init_settings_frame_parser(
      53             :     grpc_chttp2_transport_parsing *transport_parsing);
      54             : static int init_window_update_frame_parser(
      55             :     grpc_chttp2_transport_parsing *transport_parsing);
      56             : static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing);
      57             : static int init_goaway_parser(grpc_chttp2_transport_parsing *transport_parsing);
      58             : static int init_skip_frame_parser(
      59             :     grpc_chttp2_transport_parsing *transport_parsing, int is_header);
      60             : 
      61             : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
      62             :                              grpc_chttp2_transport_parsing *transport_parsing,
      63             :                              gpr_slice slice, int is_last);
      64             : 
      65     2465955 : void grpc_chttp2_prepare_to_read(
      66             :     grpc_chttp2_transport_global *transport_global,
      67             :     grpc_chttp2_transport_parsing *transport_parsing) {
      68             :   grpc_chttp2_stream_global *stream_global;
      69             :   grpc_chttp2_stream_parsing *stream_parsing;
      70             : 
      71     2465955 :   transport_parsing->next_stream_id = transport_global->next_stream_id;
      72             : 
      73             :   /* update the parsing view of incoming window */
      74     2465955 :   if (transport_parsing->incoming_window != transport_global->incoming_window) {
      75        6305 :     GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
      76             :         "parse", transport_parsing, incoming_window,
      77             :         (gpr_int64)transport_global->incoming_window -
      78             :             (gpr_int64)transport_parsing->incoming_window);
      79        6305 :     transport_parsing->incoming_window = transport_global->incoming_window;
      80             :   }
      81     6652536 :   while (grpc_chttp2_list_pop_incoming_window_updated(
      82             :       transport_global, transport_parsing, &stream_global, &stream_parsing)) {
      83     1720624 :     stream_parsing->id = stream_global->id;
      84     1720624 :     if (stream_parsing->incoming_window != stream_global->incoming_window) {
      85     1720654 :       GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
      86             :           "parse", transport_parsing, stream_parsing, incoming_window,
      87             :           (gpr_int64)stream_global->incoming_window -
      88             :               (gpr_int64)stream_parsing->incoming_window);
      89     1720656 :       stream_parsing->incoming_window = stream_global->incoming_window;
      90             :     }
      91             :   }
      92     2465830 : }
      93             : 
      94     2466030 : void grpc_chttp2_publish_reads(
      95             :     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
      96             :     grpc_chttp2_transport_parsing *transport_parsing) {
      97             :   grpc_chttp2_stream_global *stream_global;
      98             :   grpc_chttp2_stream_parsing *stream_parsing;
      99             : 
     100             :   /* transport_parsing->last_incoming_stream_id is used as
     101             :      last-grpc_chttp2_stream-id when
     102             :      sending GOAWAY frame.
     103             :      https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
     104             :      says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
     105             :      ID.  So,
     106             :      since we don't have server pushed streams, client should send
     107             :      GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
     108     2466030 :   if (!transport_parsing->is_client) {
     109     1213144 :     transport_global->last_incoming_stream_id =
     110     1213144 :         transport_parsing->incoming_stream_id;
     111             :   }
     112             : 
     113             :   /* copy parsing qbuf to global qbuf */
     114     2466030 :   gpr_slice_buffer_move_into(&transport_parsing->qbuf, &transport_global->qbuf);
     115             : 
     116             :   /* update global settings */
     117     2466026 :   if (transport_parsing->settings_updated) {
     118        3681 :     memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
     119        3681 :            transport_parsing->settings, sizeof(transport_parsing->settings));
     120        3681 :     transport_parsing->settings_updated = 0;
     121             :   }
     122             : 
     123             :   /* update settings based on ack if received */
     124     2466026 :   if (transport_parsing->settings_ack_received) {
     125        3578 :     memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
     126        3578 :            transport_global->settings[GRPC_SENT_SETTINGS],
     127             :            GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
     128        3578 :     transport_parsing->settings_ack_received = 0;
     129             :   }
     130             : 
     131             :   /* move goaway to the global state if we received one (it will be
     132             :      published later */
     133     2466026 :   if (transport_parsing->goaway_received) {
     134         229 :     grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
     135         229 :                                     (gpr_uint32)transport_parsing->goaway_error,
     136             :                                     transport_parsing->goaway_text);
     137         229 :     transport_parsing->goaway_text = gpr_empty_slice();
     138         229 :     transport_parsing->goaway_received = 0;
     139             :   }
     140             : 
     141             :   /* propagate flow control tokens to global state */
     142     2466026 :   if (transport_parsing->outgoing_window_update) {
     143        4091 :     GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
     144             :         "parsed", transport_global, outgoing_window,
     145             :         transport_parsing->outgoing_window_update);
     146        4091 :     GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
     147             :         "parsed", transport_parsing, outgoing_window_update,
     148             :         -(gpr_int64)transport_parsing->outgoing_window_update);
     149        8182 :     transport_global->outgoing_window +=
     150        4091 :         transport_parsing->outgoing_window_update;
     151        4091 :     transport_parsing->outgoing_window_update = 0;
     152             :   }
     153             : 
     154     2466026 :   if (transport_parsing->incoming_window_delta) {
     155      966596 :     GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
     156             :         "parsed", transport_global, incoming_window,
     157             :         -(gpr_int64)transport_parsing->incoming_window_delta);
     158      966595 :     GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
     159             :         "parsed", transport_parsing, incoming_window_delta,
     160             :         -(gpr_int64)transport_parsing->incoming_window_delta);
     161     1933190 :     transport_global->incoming_window -=
     162      966595 :         transport_parsing->incoming_window_delta;
     163      966595 :     transport_parsing->incoming_window_delta = 0;
     164             :   }
     165             : 
     166             :   /* for each stream that saw an update, fixup global state */
     167     9445059 :   while (grpc_chttp2_list_pop_parsing_seen_stream(
     168             :       transport_global, transport_parsing, &stream_global, &stream_parsing)) {
     169             :     /* update incoming flow control window */
     170     4512407 :     if (stream_parsing->incoming_window_delta) {
     171     3015646 :       GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
     172             :           "parsed", transport_parsing, stream_global, incoming_window,
     173             :           -(gpr_int64)stream_parsing->incoming_window_delta);
     174     3015726 :       GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
     175             :           "parsed", transport_parsing, stream_parsing, incoming_window_delta,
     176             :           -(gpr_int64)stream_parsing->incoming_window_delta);
     177     3015726 :       GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
     178             :           "parsed", transport_parsing, stream_global, max_recv_bytes,
     179             :           -(gpr_int64)stream_parsing->incoming_window_delta);
     180     3015726 :       stream_global->incoming_window -= stream_parsing->incoming_window_delta;
     181     3015726 :       GPR_ASSERT(stream_global->max_recv_bytes >=
     182             :                  stream_parsing->incoming_window_delta);
     183     3015726 :       stream_global->max_recv_bytes -= stream_parsing->incoming_window_delta;
     184     3015726 :       stream_parsing->incoming_window_delta = 0;
     185     3015726 :       grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
     186             :     }
     187             : 
     188             :     /* update outgoing flow control window */
     189     4511468 :     if (stream_parsing->outgoing_window_update) {
     190     1591904 :       int was_zero = stream_global->outgoing_window <= 0;
     191             :       int is_zero;
     192     1591904 :       GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("parsed", transport_parsing,
     193             :                                        stream_global, outgoing_window,
     194             :                                        stream_parsing->outgoing_window_update);
     195     1591907 :       GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
     196             :           "parsed", transport_parsing, stream_parsing, outgoing_window_update,
     197             :           -(gpr_int64)stream_parsing->outgoing_window_update);
     198     1591907 :       GPR_ASSERT(stream_parsing->outgoing_window_update <= GPR_UINT32_MAX);
     199     3183814 :       stream_global->outgoing_window +=
     200     1591907 :           (gpr_uint32)stream_parsing->outgoing_window_update;
     201     1591907 :       stream_parsing->outgoing_window_update = 0;
     202     1591907 :       is_zero = stream_global->outgoing_window <= 0;
     203     1591907 :       if (was_zero && !is_zero) {
     204       13600 :         grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
     205             :       }
     206             :     }
     207             : 
     208             :     /* updating closed status */
     209     4511471 :     if (stream_parsing->received_close) {
     210     2881381 :       stream_global->read_closed = 1;
     211     2881381 :       grpc_chttp2_list_add_read_write_state_changed(transport_global,
     212             :                                                     stream_global);
     213             :     }
     214     4511510 :     if (stream_parsing->saw_rst_stream) {
     215        5728 :       stream_global->cancelled = 1;
     216       11456 :       stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(
     217        5728 :           (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
     218        5728 :       if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
     219         240 :         stream_global->published_cancelled = 1;
     220             :       }
     221        5728 :       grpc_chttp2_list_add_read_write_state_changed(transport_global,
     222             :                                                     stream_global);
     223             :     }
     224             : 
     225             :     /* publish incoming stream ops */
     226     4511510 :     if (stream_parsing->data_parser.incoming_sopb.nops > 0) {
     227    12122796 :       grpc_incoming_metadata_buffer_move_to_referencing_sopb(
     228     8081864 :           &stream_parsing->incoming_metadata, &stream_global->incoming_metadata,
     229     4040932 :           &stream_parsing->data_parser.incoming_sopb);
     230     4042111 :       grpc_sopb_move_to(&stream_parsing->data_parser.incoming_sopb,
     231     4042111 :                         &stream_global->incoming_sopb);
     232     4042470 :       grpc_chttp2_list_add_read_write_state_changed(transport_global,
     233             :                                                     stream_global);
     234             :     }
     235             :   }
     236     2466005 : }
     237             : 
     238     5626175 : int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
     239             :                              grpc_chttp2_transport_parsing *transport_parsing,
     240             :                              gpr_slice slice) {
     241     5626175 :   gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
     242     5626175 :   gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
     243     5626175 :   gpr_uint8 *cur = beg;
     244             : 
     245     5626175 :   if (cur == end) return 1;
     246             : 
     247     5626175 :   switch (transport_parsing->deframe_state) {
     248             :     case GRPC_DTS_CLIENT_PREFIX_0:
     249             :     case GRPC_DTS_CLIENT_PREFIX_1:
     250             :     case GRPC_DTS_CLIENT_PREFIX_2:
     251             :     case GRPC_DTS_CLIENT_PREFIX_3:
     252             :     case GRPC_DTS_CLIENT_PREFIX_4:
     253             :     case GRPC_DTS_CLIENT_PREFIX_5:
     254             :     case GRPC_DTS_CLIENT_PREFIX_6:
     255             :     case GRPC_DTS_CLIENT_PREFIX_7:
     256             :     case GRPC_DTS_CLIENT_PREFIX_8:
     257             :     case GRPC_DTS_CLIENT_PREFIX_9:
     258             :     case GRPC_DTS_CLIENT_PREFIX_10:
     259             :     case GRPC_DTS_CLIENT_PREFIX_11:
     260             :     case GRPC_DTS_CLIENT_PREFIX_12:
     261             :     case GRPC_DTS_CLIENT_PREFIX_13:
     262             :     case GRPC_DTS_CLIENT_PREFIX_14:
     263             :     case GRPC_DTS_CLIENT_PREFIX_15:
     264             :     case GRPC_DTS_CLIENT_PREFIX_16:
     265             :     case GRPC_DTS_CLIENT_PREFIX_17:
     266             :     case GRPC_DTS_CLIENT_PREFIX_18:
     267             :     case GRPC_DTS_CLIENT_PREFIX_19:
     268             :     case GRPC_DTS_CLIENT_PREFIX_20:
     269             :     case GRPC_DTS_CLIENT_PREFIX_21:
     270             :     case GRPC_DTS_CLIENT_PREFIX_22:
     271             :     case GRPC_DTS_CLIENT_PREFIX_23:
     272       53548 :       while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
     273       89688 :         if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
     274       44844 :                                                           ->deframe_state]) {
     275          96 :           gpr_log(GPR_INFO,
     276             :                   "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
     277             :                   "at byte %d",
     278          24 :                   GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
     279          24 :                                                         ->deframe_state],
     280          24 :                   (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
     281          24 :                       [transport_parsing->deframe_state],
     282          48 :                   *cur, (int)*cur, transport_parsing->deframe_state);
     283          24 :           return 0;
     284             :         }
     285       44820 :         ++cur;
     286       44820 :         ++transport_parsing->deframe_state;
     287             :       }
     288        4340 :       if (cur == end) {
     289        2592 :         return 1;
     290             :       }
     291             :     /* fallthrough */
     292             :     dts_fh_0:
     293             :     case GRPC_DTS_FH_0:
     294     9002524 :       GPR_ASSERT(cur < end);
     295     9002524 :       transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
     296     9002524 :       if (++cur == end) {
     297        4095 :         transport_parsing->deframe_state = GRPC_DTS_FH_1;
     298        4095 :         return 1;
     299             :       }
     300             :     /* fallthrough */
     301             :     case GRPC_DTS_FH_1:
     302     9002847 :       GPR_ASSERT(cur < end);
     303     9002847 :       transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
     304     9002847 :       if (++cur == end) {
     305        4302 :         transport_parsing->deframe_state = GRPC_DTS_FH_2;
     306        4302 :         return 1;
     307             :       }
     308             :     /* fallthrough */
     309             :     case GRPC_DTS_FH_2:
     310     9003031 :       GPR_ASSERT(cur < end);
     311     9003031 :       transport_parsing->incoming_frame_size |= *cur;
     312     9003031 :       if (++cur == end) {
     313        3643 :         transport_parsing->deframe_state = GRPC_DTS_FH_3;
     314        3643 :         return 1;
     315             :       }
     316             :     /* fallthrough */
     317             :     case GRPC_DTS_FH_3:
     318     9002896 :       GPR_ASSERT(cur < end);
     319     9002896 :       transport_parsing->incoming_frame_type = *cur;
     320     9002896 :       if (++cur == end) {
     321        3873 :         transport_parsing->deframe_state = GRPC_DTS_FH_4;
     322        3873 :         return 1;
     323             :       }
     324             :     /* fallthrough */
     325             :     case GRPC_DTS_FH_4:
     326     9002807 :       GPR_ASSERT(cur < end);
     327     9002807 :       transport_parsing->incoming_frame_flags = *cur;
     328     9002807 :       if (++cur == end) {
     329        3880 :         transport_parsing->deframe_state = GRPC_DTS_FH_5;
     330        3880 :         return 1;
     331             :       }
     332             :     /* fallthrough */
     333             :     case GRPC_DTS_FH_5:
     334     9003024 :       GPR_ASSERT(cur < end);
     335     9003024 :       transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
     336     9003024 :       if (++cur == end) {
     337        4105 :         transport_parsing->deframe_state = GRPC_DTS_FH_6;
     338        4105 :         return 1;
     339             :       }
     340             :     /* fallthrough */
     341             :     case GRPC_DTS_FH_6:
     342     9002560 :       GPR_ASSERT(cur < end);
     343     9002560 :       transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
     344     9002560 :       if (++cur == end) {
     345        3570 :         transport_parsing->deframe_state = GRPC_DTS_FH_7;
     346        3570 :         return 1;
     347             :       }
     348             :     /* fallthrough */
     349             :     case GRPC_DTS_FH_7:
     350     9002788 :       GPR_ASSERT(cur < end);
     351     9002788 :       transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
     352     9002788 :       if (++cur == end) {
     353        3737 :         transport_parsing->deframe_state = GRPC_DTS_FH_8;
     354        3737 :         return 1;
     355             :       }
     356             :     /* fallthrough */
     357             :     case GRPC_DTS_FH_8:
     358     9000722 :       GPR_ASSERT(cur < end);
     359     9000722 :       transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
     360     9000722 :       transport_parsing->deframe_state = GRPC_DTS_FRAME;
     361     9000722 :       if (!init_frame_parser(transport_parsing)) {
     362           7 :         return 0;
     363             :       }
     364     8995351 :       if (transport_parsing->incoming_stream_id) {
     365     8987103 :         transport_parsing->last_incoming_stream_id =
     366     8987103 :             transport_parsing->incoming_stream_id;
     367             :       }
     368     8995351 :       if (transport_parsing->incoming_frame_size == 0) {
     369        4087 :         if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
     370             :                                1)) {
     371           0 :           return 0;
     372             :         }
     373        4088 :         transport_parsing->incoming_stream = NULL;
     374        4088 :         if (++cur == end) {
     375        2743 :           transport_parsing->deframe_state = GRPC_DTS_FH_0;
     376        2743 :           return 1;
     377             :         }
     378        1345 :         goto dts_fh_0; /* loop */
     379             :       }
     380     8991264 :       if (++cur == end) {
     381        3471 :         return 1;
     382             :       }
     383             :     /* fallthrough */
     384             :     case GRPC_DTS_FRAME:
     385    13199253 :       GPR_ASSERT(cur < end);
     386    13199253 :       if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
     387     2760824 :         if (!parse_frame_slice(exec_ctx, transport_parsing,
     388     1380412 :                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
     389     1380412 :                                                     (size_t)(end - beg)),
     390             :                                1)) {
     391           0 :           return 0;
     392             :         }
     393     1380424 :         transport_parsing->deframe_state = GRPC_DTS_FH_0;
     394     1380424 :         transport_parsing->incoming_stream = NULL;
     395     1380424 :         return 1;
     396    23637682 :       } else if ((gpr_uint32)(end - cur) >
     397    11818841 :                  transport_parsing->incoming_frame_size) {
     398     7616517 :         size_t cur_offset = (size_t)(cur - beg);
     399     7616517 :         if (!parse_frame_slice(
     400             :                 exec_ctx, transport_parsing,
     401             :                 gpr_slice_sub_no_ref(
     402             :                     slice, cur_offset,
     403     7616517 :                     cur_offset + transport_parsing->incoming_frame_size),
     404             :                 1)) {
     405           0 :           return 0;
     406             :         }
     407     7618483 :         cur += transport_parsing->incoming_frame_size;
     408     7618483 :         transport_parsing->incoming_stream = NULL;
     409     7618483 :         goto dts_fh_0; /* loop */
     410             :       } else {
     411     8404648 :         if (!parse_frame_slice(exec_ctx, transport_parsing,
     412     4202324 :                                gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
     413     4202324 :                                                     (size_t)(end - beg)),
     414             :                                0)) {
     415           0 :           return 0;
     416             :         }
     417     4202324 :         transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur);
     418     4202324 :         return 1;
     419             :       }
     420             :       GPR_UNREACHABLE_CODE(return 0);
     421             :   }
     422             : 
     423           0 :   GPR_UNREACHABLE_CODE(return 0);
     424             : }
     425             : 
     426     9009243 : static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
     427     9009243 :   if (transport_parsing->expect_continuation_stream_id != 0) {
     428         104 :     if (transport_parsing->incoming_frame_type !=
     429             :         GRPC_CHTTP2_FRAME_CONTINUATION) {
     430           0 :       gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
     431           0 :               transport_parsing->incoming_frame_type);
     432           0 :       return 0;
     433             :     }
     434         208 :     if (transport_parsing->expect_continuation_stream_id !=
     435         104 :         transport_parsing->incoming_stream_id) {
     436           0 :       gpr_log(GPR_ERROR,
     437             :               "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
     438             :               "grpc_chttp2_stream %08x",
     439             :               transport_parsing->expect_continuation_stream_id,
     440             :               transport_parsing->incoming_stream_id);
     441           0 :       return 0;
     442             :     }
     443         104 :     return init_header_frame_parser(transport_parsing, 1);
     444             :   }
     445     9009139 :   switch (transport_parsing->incoming_frame_type) {
     446             :     case GRPC_CHTTP2_FRAME_DATA:
     447     3018251 :       return init_data_frame_parser(transport_parsing);
     448             :     case GRPC_CHTTP2_FRAME_HEADER:
     449     4102618 :       return init_header_frame_parser(transport_parsing, 0);
     450             :     case GRPC_CHTTP2_FRAME_CONTINUATION:
     451           0 :       gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
     452           0 :       return 0;
     453             :     case GRPC_CHTTP2_FRAME_RST_STREAM:
     454      278023 :       return init_rst_stream_parser(transport_parsing);
     455             :     case GRPC_CHTTP2_FRAME_SETTINGS:
     456        7262 :       return init_settings_frame_parser(transport_parsing);
     457             :     case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
     458     1602756 :       return init_window_update_frame_parser(transport_parsing);
     459             :     case GRPC_CHTTP2_FRAME_PING:
     460           0 :       return init_ping_parser(transport_parsing);
     461             :     case GRPC_CHTTP2_FRAME_GOAWAY:
     462         229 :       return init_goaway_parser(transport_parsing);
     463             :     default:
     464           0 :       gpr_log(GPR_ERROR, "Unknown frame type %02x",
     465           0 :               transport_parsing->incoming_frame_type);
     466           0 :       return init_skip_frame_parser(transport_parsing, 0);
     467             :   }
     468             : }
     469             : 
     470      274706 : static grpc_chttp2_parse_error skip_parser(
     471             :     grpc_exec_ctx *exec_ctx, void *parser,
     472             :     grpc_chttp2_transport_parsing *transport_parsing,
     473             :     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
     474      274706 :   return GRPC_CHTTP2_PARSE_OK;
     475             : }
     476             : 
     477         186 : static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
     478             : 
     479      272599 : static int init_skip_frame_parser(
     480             :     grpc_chttp2_transport_parsing *transport_parsing, int is_header) {
     481      272599 :   if (is_header) {
     482          42 :     gpr_uint8 is_eoh = transport_parsing->expect_continuation_stream_id != 0;
     483          42 :     transport_parsing->parser = grpc_chttp2_header_parser_parse;
     484          42 :     transport_parsing->parser_data = &transport_parsing->hpack_parser;
     485          42 :     transport_parsing->hpack_parser.on_header = skip_header;
     486          42 :     transport_parsing->hpack_parser.on_header_user_data = NULL;
     487          42 :     transport_parsing->hpack_parser.is_boundary = is_eoh;
     488          42 :     transport_parsing->hpack_parser.is_eof =
     489          42 :         (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
     490             :   } else {
     491      272557 :     transport_parsing->parser = skip_parser;
     492             :   }
     493      272599 :   return 1;
     494             : }
     495             : 
     496           9 : void grpc_chttp2_parsing_become_skip_parser(
     497             :     grpc_chttp2_transport_parsing *transport_parsing) {
     498           9 :   init_skip_frame_parser(
     499             :       transport_parsing,
     500           9 :       transport_parsing->parser == grpc_chttp2_header_parser_parse);
     501           9 : }
     502             : 
     503     3018587 : static grpc_chttp2_parse_error update_incoming_window(
     504             :     grpc_chttp2_transport_parsing *transport_parsing,
     505             :     grpc_chttp2_stream_parsing *stream_parsing) {
     506     6037174 :   if (transport_parsing->incoming_frame_size >
     507     3018587 :       transport_parsing->incoming_window) {
     508           0 :     gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
     509             :             transport_parsing->incoming_frame_size,
     510             :             transport_parsing->incoming_window);
     511           0 :     return GRPC_CHTTP2_CONNECTION_ERROR;
     512             :   }
     513             : 
     514     6037174 :   if (transport_parsing->incoming_frame_size >
     515     3018587 :       stream_parsing->incoming_window) {
     516           0 :     gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
     517             :             transport_parsing->incoming_frame_size,
     518             :             stream_parsing->incoming_window);
     519           0 :     return GRPC_CHTTP2_CONNECTION_ERROR;
     520             :   }
     521             : 
     522     3018587 :   GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
     523             :       "data", transport_parsing, incoming_window,
     524             :       -(gpr_int64)transport_parsing->incoming_frame_size);
     525     3018594 :   GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT("data", transport_parsing,
     526             :                                       incoming_window_delta,
     527             :                                       transport_parsing->incoming_frame_size);
     528     3018594 :   GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
     529             :       "data", transport_parsing, stream_parsing, incoming_window,
     530             :       -(gpr_int64)transport_parsing->incoming_frame_size);
     531     3018594 :   GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("data", transport_parsing, stream_parsing,
     532             :                                    incoming_window_delta,
     533             :                                    transport_parsing->incoming_frame_size);
     534             : 
     535     3018594 :   transport_parsing->incoming_window -= transport_parsing->incoming_frame_size;
     536     6037188 :   transport_parsing->incoming_window_delta +=
     537     3018594 :       transport_parsing->incoming_frame_size;
     538     3018594 :   stream_parsing->incoming_window -= transport_parsing->incoming_frame_size;
     539     6037188 :   stream_parsing->incoming_window_delta +=
     540     3018594 :       transport_parsing->incoming_frame_size;
     541     3018594 :   grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
     542             : 
     543     3018552 :   return GRPC_CHTTP2_PARSE_OK;
     544             : }
     545             : 
     546     3018387 : static int init_data_frame_parser(
     547             :     grpc_chttp2_transport_parsing *transport_parsing) {
     548     3018387 :   grpc_chttp2_stream_parsing *stream_parsing =
     549     3018387 :       grpc_chttp2_parsing_lookup_stream(transport_parsing,
     550             :                                         transport_parsing->incoming_stream_id);
     551     3018860 :   grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
     552     3018860 :   if (!stream_parsing || stream_parsing->received_close)
     553         258 :     return init_skip_frame_parser(transport_parsing, 0);
     554     3018602 :   if (err == GRPC_CHTTP2_PARSE_OK) {
     555     3018599 :     err = update_incoming_window(transport_parsing, stream_parsing);
     556             :   }
     557     3018534 :   if (err == GRPC_CHTTP2_PARSE_OK) {
     558     3018539 :     err = grpc_chttp2_data_parser_begin_frame(
     559     3018539 :         &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
     560             :   }
     561     3018510 :   switch (err) {
     562             :     case GRPC_CHTTP2_PARSE_OK:
     563     3018510 :       transport_parsing->incoming_stream = stream_parsing;
     564     3018510 :       transport_parsing->parser = grpc_chttp2_data_parser_parse;
     565     3018510 :       transport_parsing->parser_data = &stream_parsing->data_parser;
     566     3018510 :       return 1;
     567             :     case GRPC_CHTTP2_STREAM_ERROR:
     568           0 :       stream_parsing->received_close = 1;
     569           0 :       stream_parsing->saw_rst_stream = 1;
     570           0 :       stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
     571           0 :       gpr_slice_buffer_add(
     572             :           &transport_parsing->qbuf,
     573             :           grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
     574             :                                         GRPC_CHTTP2_PROTOCOL_ERROR));
     575           0 :       return init_skip_frame_parser(transport_parsing, 0);
     576             :     case GRPC_CHTTP2_CONNECTION_ERROR:
     577           0 :       return 0;
     578             :   }
     579           0 :   GPR_UNREACHABLE_CODE(return 0);
     580             : }
     581             : 
     582        3083 : static void free_timeout(void *p) { gpr_free(p); }
     583             : 
     584    18836607 : static void on_header(void *tp, grpc_mdelem *md) {
     585    18836607 :   grpc_chttp2_transport_parsing *transport_parsing = tp;
     586    18836607 :   grpc_chttp2_stream_parsing *stream_parsing =
     587             :       transport_parsing->incoming_stream;
     588             : 
     589    18836607 :   GPR_ASSERT(stream_parsing);
     590             : 
     591    18836607 :   GRPC_CHTTP2_IF_TRACING(gpr_log(
     592             :       GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
     593             :       transport_parsing->is_client ? "CLI" : "SVR",
     594             :       grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
     595             : 
     596    18836675 :   if (md->key == transport_parsing->str_grpc_timeout) {
     597        5187 :     gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
     598        5187 :     if (!cached_timeout) {
     599             :       /* not already parsed: parse it now, and store the result away */
     600        3083 :       cached_timeout = gpr_malloc(sizeof(gpr_timespec));
     601        3083 :       if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
     602             :                                       cached_timeout)) {
     603           0 :         gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
     604             :                 grpc_mdstr_as_c_string(md->value));
     605           0 :         *cached_timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
     606             :       }
     607        3083 :       grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
     608             :     }
     609        5187 :     grpc_chttp2_incoming_metadata_buffer_set_deadline(
     610             :         &stream_parsing->incoming_metadata,
     611             :         gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
     612        5187 :     GRPC_MDELEM_UNREF(md);
     613             :   } else {
     614    18831488 :     grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
     615             :                                              md);
     616             :   }
     617             : 
     618    18814600 :   grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
     619    18811831 : }
     620             : 
     621     4103524 : static int init_header_frame_parser(
     622             :     grpc_chttp2_transport_parsing *transport_parsing, int is_continuation) {
     623     8207048 :   gpr_uint8 is_eoh = (transport_parsing->incoming_frame_flags &
     624     4103524 :                       GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
     625     4103524 :   int via_accept = 0;
     626             :   grpc_chttp2_stream_parsing *stream_parsing;
     627             : 
     628     4103524 :   if (is_eoh) {
     629     4103420 :     transport_parsing->expect_continuation_stream_id = 0;
     630             :   } else {
     631         104 :     transport_parsing->expect_continuation_stream_id =
     632         104 :         transport_parsing->incoming_stream_id;
     633             :   }
     634             : 
     635     4103524 :   if (!is_continuation) {
     636     8207080 :     transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
     637     4103540 :                                      GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
     638             :   }
     639             : 
     640             :   /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
     641     4103524 :   stream_parsing = grpc_chttp2_parsing_lookup_stream(
     642             :       transport_parsing, transport_parsing->incoming_stream_id);
     643     4106891 :   if (stream_parsing == NULL) {
     644     1301816 :     if (is_continuation) {
     645           0 :       gpr_log(GPR_ERROR,
     646             :               "grpc_chttp2_stream disbanded before CONTINUATION received");
     647           0 :       return init_skip_frame_parser(transport_parsing, 1);
     648             :     }
     649     1301816 :     if (transport_parsing->is_client) {
     650          84 :       if ((transport_parsing->incoming_stream_id & 1) &&
     651          42 :           transport_parsing->incoming_stream_id <
     652          42 :               transport_parsing->next_stream_id) {
     653             :         /* this is an old (probably cancelled) grpc_chttp2_stream */
     654             :       } else {
     655           0 :         gpr_log(GPR_ERROR,
     656             :                 "ignoring new grpc_chttp2_stream creation on client");
     657             :       }
     658          42 :       return init_skip_frame_parser(transport_parsing, 1);
     659     2603548 :     } else if (transport_parsing->last_incoming_stream_id >
     660     1301774 :                transport_parsing->incoming_stream_id) {
     661           0 :       gpr_log(GPR_ERROR,
     662             :               "ignoring out of order new grpc_chttp2_stream request on server; "
     663             :               "last grpc_chttp2_stream "
     664             :               "id=%d, new grpc_chttp2_stream id=%d",
     665             :               transport_parsing->last_incoming_stream_id,
     666             :               transport_parsing->incoming_stream_id);
     667           0 :       return init_skip_frame_parser(transport_parsing, 1);
     668     1301774 :     } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
     669           0 :       gpr_log(GPR_ERROR,
     670             :               "ignoring grpc_chttp2_stream with non-client generated index %d",
     671             :               transport_parsing->incoming_stream_id);
     672           0 :       return init_skip_frame_parser(transport_parsing, 1);
     673             :     }
     674     1301757 :     stream_parsing = transport_parsing->incoming_stream =
     675     1301774 :         grpc_chttp2_parsing_accept_stream(
     676             :             transport_parsing, transport_parsing->incoming_stream_id);
     677     1301757 :     if (stream_parsing == NULL) {
     678           0 :       gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
     679           0 :       return init_skip_frame_parser(transport_parsing, 1);
     680             :     }
     681     1301757 :     via_accept = 1;
     682             :   } else {
     683     2805075 :     transport_parsing->incoming_stream = stream_parsing;
     684             :   }
     685     4106832 :   GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
     686     4104247 :   if (stream_parsing->received_close) {
     687           0 :     gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
     688           0 :     transport_parsing->incoming_stream = NULL;
     689           0 :     return init_skip_frame_parser(transport_parsing, 1);
     690             :   }
     691     4104247 :   transport_parsing->parser = grpc_chttp2_header_parser_parse;
     692     4104247 :   transport_parsing->parser_data = &transport_parsing->hpack_parser;
     693     4104247 :   transport_parsing->hpack_parser.on_header = on_header;
     694     4104247 :   transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
     695     4104247 :   transport_parsing->hpack_parser.is_boundary = is_eoh;
     696     4104247 :   transport_parsing->hpack_parser.is_eof =
     697     4104247 :       (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
     698     4104247 :   if (!is_continuation && (transport_parsing->incoming_frame_flags &
     699             :                            GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
     700           0 :     grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
     701             :   }
     702     4104298 :   return 1;
     703             : }
     704             : 
     705     1602879 : static int init_window_update_frame_parser(
     706             :     grpc_chttp2_transport_parsing *transport_parsing) {
     707     1602879 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
     708             :                                        &transport_parsing->simple.window_update,
     709             :                                        transport_parsing->incoming_frame_size,
     710     1602879 :                                        transport_parsing->incoming_frame_flags);
     711     1602862 :   if (transport_parsing->incoming_stream_id) {
     712     1598768 :     transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
     713             :         transport_parsing, transport_parsing->incoming_stream_id);
     714             :   }
     715     1602942 :   transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
     716     1602942 :   transport_parsing->parser_data = &transport_parsing->simple.window_update;
     717     1602942 :   return ok;
     718             : }
     719             : 
     720           0 : static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing) {
     721           0 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
     722             :                                        &transport_parsing->simple.ping,
     723             :                                        transport_parsing->incoming_frame_size,
     724           0 :                                        transport_parsing->incoming_frame_flags);
     725           0 :   transport_parsing->parser = grpc_chttp2_ping_parser_parse;
     726           0 :   transport_parsing->parser_data = &transport_parsing->simple.ping;
     727           0 :   return ok;
     728             : }
     729             : 
     730      278024 : static int init_rst_stream_parser(
     731             :     grpc_chttp2_transport_parsing *transport_parsing) {
     732      278024 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
     733             :                                        &transport_parsing->simple.rst_stream,
     734             :                                        transport_parsing->incoming_frame_size,
     735      278024 :                                        transport_parsing->incoming_frame_flags);
     736      278025 :   transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
     737             :       transport_parsing, transport_parsing->incoming_stream_id);
     738      278024 :   if (!transport_parsing->incoming_stream) {
     739      272291 :     return init_skip_frame_parser(transport_parsing, 0);
     740             :   }
     741        5733 :   transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
     742        5733 :   transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
     743        5733 :   return ok;
     744             : }
     745             : 
     746         229 : static int init_goaway_parser(
     747             :     grpc_chttp2_transport_parsing *transport_parsing) {
     748         229 :   int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
     749             :                                        &transport_parsing->goaway_parser,
     750             :                                        transport_parsing->incoming_frame_size,
     751         229 :                                        transport_parsing->incoming_frame_flags);
     752         229 :   transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
     753         229 :   transport_parsing->parser_data = &transport_parsing->goaway_parser;
     754         229 :   return ok;
     755             : }
     756             : 
     757        7261 : static int init_settings_frame_parser(
     758             :     grpc_chttp2_transport_parsing *transport_parsing) {
     759             :   int ok;
     760             : 
     761        7261 :   if (transport_parsing->incoming_stream_id != 0) {
     762           2 :     gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
     763             :             transport_parsing->incoming_stream_id);
     764           2 :     return 0;
     765             :   }
     766             : 
     767        7259 :   ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
     768             :                                    &transport_parsing->simple.settings,
     769             :                                    transport_parsing->incoming_frame_size,
     770        7259 :                                    transport_parsing->incoming_frame_flags,
     771        7259 :                                    transport_parsing->settings);
     772        7260 :   if (!ok) {
     773           5 :     return 0;
     774             :   }
     775        7255 :   if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
     776        3577 :     transport_parsing->settings_ack_received = 1;
     777             :   }
     778        7255 :   transport_parsing->parser = grpc_chttp2_settings_parser_parse;
     779        7255 :   transport_parsing->parser_data = &transport_parsing->simple.settings;
     780        7255 :   return ok;
     781             : }
     782             : 
     783             : /*
     784             : static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
     785             :   return window + window_update < MAX_WINDOW;
     786             : }
     787             : */
     788             : 
     789    13202600 : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
     790             :                              grpc_chttp2_transport_parsing *transport_parsing,
     791             :                              gpr_slice slice, int is_last) {
     792    13202600 :   grpc_chttp2_stream_parsing *stream_parsing =
     793             :       transport_parsing->incoming_stream;
     794    13202600 :   switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
     795             :                                     transport_parsing, stream_parsing, slice,
     796             :                                     is_last)) {
     797             :     case GRPC_CHTTP2_PARSE_OK:
     798    13200147 :       if (stream_parsing) {
     799    12912463 :         grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
     800             :                                                  stream_parsing);
     801             :       }
     802    13204240 :       return 1;
     803             :     case GRPC_CHTTP2_STREAM_ERROR:
     804           0 :       grpc_chttp2_parsing_become_skip_parser(transport_parsing);
     805           0 :       if (stream_parsing) {
     806           0 :         stream_parsing->saw_rst_stream = 1;
     807           0 :         stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
     808           0 :         gpr_slice_buffer_add(
     809             :             &transport_parsing->qbuf,
     810             :             grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
     811             :                                           GRPC_CHTTP2_PROTOCOL_ERROR));
     812             :       }
     813           0 :       return 1;
     814             :     case GRPC_CHTTP2_CONNECTION_ERROR:
     815           0 :       return 0;
     816             :   }
     817           0 :   GPR_UNREACHABLE_CODE(return 0);
     818             : }

Generated by: LCOV version 1.10