Imported Upstream version 1.21.0
[platform/upstream/grpc.git] / src / core / ext / transport / chttp2 / transport / parsing.cc
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/ext/transport/chttp2/transport/internal.h"
22
23 #include <string.h>
24
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/string_util.h>
28
29 #include "src/core/lib/profiling/timers.h"
30 #include "src/core/lib/slice/slice_string_helpers.h"
31 #include "src/core/lib/transport/http2_errors.h"
32 #include "src/core/lib/transport/static_metadata.h"
33 #include "src/core/lib/transport/status_conversion.h"
34 #include "src/core/lib/transport/timeout_encoding.h"
35
36 static grpc_error* init_frame_parser(grpc_chttp2_transport* t);
37 static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
38                                             int is_continuation);
39 static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t);
40 static grpc_error* init_rst_stream_parser(grpc_chttp2_transport* t);
41 static grpc_error* init_settings_frame_parser(grpc_chttp2_transport* t);
42 static grpc_error* init_window_update_frame_parser(grpc_chttp2_transport* t);
43 static grpc_error* init_ping_parser(grpc_chttp2_transport* t);
44 static grpc_error* init_goaway_parser(grpc_chttp2_transport* t);
45 static grpc_error* init_skip_frame_parser(grpc_chttp2_transport* t,
46                                           int is_header);
47
48 static grpc_error* parse_frame_slice(grpc_chttp2_transport* t,
49                                      const grpc_slice& slice, int is_last);
50
51 grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
52                                      const grpc_slice& slice) {
53   const uint8_t* beg = GRPC_SLICE_START_PTR(slice);
54   const uint8_t* end = GRPC_SLICE_END_PTR(slice);
55   const uint8_t* cur = beg;
56   grpc_error* err;
57
58   if (cur == end) return GRPC_ERROR_NONE;
59
60   switch (t->deframe_state) {
61     case GRPC_DTS_CLIENT_PREFIX_0:
62     case GRPC_DTS_CLIENT_PREFIX_1:
63     case GRPC_DTS_CLIENT_PREFIX_2:
64     case GRPC_DTS_CLIENT_PREFIX_3:
65     case GRPC_DTS_CLIENT_PREFIX_4:
66     case GRPC_DTS_CLIENT_PREFIX_5:
67     case GRPC_DTS_CLIENT_PREFIX_6:
68     case GRPC_DTS_CLIENT_PREFIX_7:
69     case GRPC_DTS_CLIENT_PREFIX_8:
70     case GRPC_DTS_CLIENT_PREFIX_9:
71     case GRPC_DTS_CLIENT_PREFIX_10:
72     case GRPC_DTS_CLIENT_PREFIX_11:
73     case GRPC_DTS_CLIENT_PREFIX_12:
74     case GRPC_DTS_CLIENT_PREFIX_13:
75     case GRPC_DTS_CLIENT_PREFIX_14:
76     case GRPC_DTS_CLIENT_PREFIX_15:
77     case GRPC_DTS_CLIENT_PREFIX_16:
78     case GRPC_DTS_CLIENT_PREFIX_17:
79     case GRPC_DTS_CLIENT_PREFIX_18:
80     case GRPC_DTS_CLIENT_PREFIX_19:
81     case GRPC_DTS_CLIENT_PREFIX_20:
82     case GRPC_DTS_CLIENT_PREFIX_21:
83     case GRPC_DTS_CLIENT_PREFIX_22:
84     case GRPC_DTS_CLIENT_PREFIX_23:
85       while (cur != end && t->deframe_state != GRPC_DTS_FH_0) {
86         if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state]) {
87           char* msg;
88           gpr_asprintf(
89               &msg,
90               "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
91               "at byte %d",
92               GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state],
93               static_cast<int>(static_cast<uint8_t>(
94                   GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state])),
95               *cur, static_cast<int>(*cur), t->deframe_state);
96           err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
97           gpr_free(msg);
98           return err;
99         }
100         ++cur;
101         t->deframe_state = static_cast<grpc_chttp2_deframe_transport_state>(
102             1 + static_cast<int>(t->deframe_state));
103       }
104       if (cur == end) {
105         return GRPC_ERROR_NONE;
106       }
107     /* fallthrough */
108     dts_fh_0:
109     case GRPC_DTS_FH_0:
110       GPR_ASSERT(cur < end);
111       t->incoming_frame_size = (static_cast<uint32_t>(*cur)) << 16;
112       if (++cur == end) {
113         t->deframe_state = GRPC_DTS_FH_1;
114         return GRPC_ERROR_NONE;
115       }
116     /* fallthrough */
117     case GRPC_DTS_FH_1:
118       GPR_ASSERT(cur < end);
119       t->incoming_frame_size |= (static_cast<uint32_t>(*cur)) << 8;
120       if (++cur == end) {
121         t->deframe_state = GRPC_DTS_FH_2;
122         return GRPC_ERROR_NONE;
123       }
124     /* fallthrough */
125     case GRPC_DTS_FH_2:
126       GPR_ASSERT(cur < end);
127       t->incoming_frame_size |= *cur;
128       if (++cur == end) {
129         t->deframe_state = GRPC_DTS_FH_3;
130         return GRPC_ERROR_NONE;
131       }
132     /* fallthrough */
133     case GRPC_DTS_FH_3:
134       GPR_ASSERT(cur < end);
135       t->incoming_frame_type = *cur;
136       if (++cur == end) {
137         t->deframe_state = GRPC_DTS_FH_4;
138         return GRPC_ERROR_NONE;
139       }
140     /* fallthrough */
141     case GRPC_DTS_FH_4:
142       GPR_ASSERT(cur < end);
143       t->incoming_frame_flags = *cur;
144       if (++cur == end) {
145         t->deframe_state = GRPC_DTS_FH_5;
146         return GRPC_ERROR_NONE;
147       }
148     /* fallthrough */
149     case GRPC_DTS_FH_5:
150       GPR_ASSERT(cur < end);
151       t->incoming_stream_id = ((static_cast<uint32_t>(*cur)) & 0x7f) << 24;
152       if (++cur == end) {
153         t->deframe_state = GRPC_DTS_FH_6;
154         return GRPC_ERROR_NONE;
155       }
156     /* fallthrough */
157     case GRPC_DTS_FH_6:
158       GPR_ASSERT(cur < end);
159       t->incoming_stream_id |= (static_cast<uint32_t>(*cur)) << 16;
160       if (++cur == end) {
161         t->deframe_state = GRPC_DTS_FH_7;
162         return GRPC_ERROR_NONE;
163       }
164     /* fallthrough */
165     case GRPC_DTS_FH_7:
166       GPR_ASSERT(cur < end);
167       t->incoming_stream_id |= (static_cast<uint32_t>(*cur)) << 8;
168       if (++cur == end) {
169         t->deframe_state = GRPC_DTS_FH_8;
170         return GRPC_ERROR_NONE;
171       }
172     /* fallthrough */
173     case GRPC_DTS_FH_8:
174       GPR_ASSERT(cur < end);
175       t->incoming_stream_id |= (static_cast<uint32_t>(*cur));
176       t->deframe_state = GRPC_DTS_FRAME;
177       err = init_frame_parser(t);
178       if (err != GRPC_ERROR_NONE) {
179         return err;
180       }
181       if (t->incoming_frame_size == 0) {
182         err = parse_frame_slice(t, grpc_empty_slice(), 1);
183         if (err != GRPC_ERROR_NONE) {
184           return err;
185         }
186         t->incoming_stream = nullptr;
187         if (++cur == end) {
188           t->deframe_state = GRPC_DTS_FH_0;
189           return GRPC_ERROR_NONE;
190         }
191         goto dts_fh_0; /* loop */
192       } else if (t->flow_control->flow_control_enabled() &&
193                  t->incoming_frame_size >
194                      t->settings[GRPC_ACKED_SETTINGS]
195                                 [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]) {
196         char* msg;
197         gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d",
198                      t->incoming_frame_size,
199                      t->settings[GRPC_ACKED_SETTINGS]
200                                 [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]);
201         err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
202         gpr_free(msg);
203         return err;
204       }
205       if (++cur == end) {
206         return GRPC_ERROR_NONE;
207       }
208     /* fallthrough */
209     case GRPC_DTS_FRAME:
210       GPR_ASSERT(cur < end);
211       if (static_cast<uint32_t>(end - cur) == t->incoming_frame_size) {
212         err = parse_frame_slice(
213             t,
214             grpc_slice_sub_no_ref(slice, static_cast<size_t>(cur - beg),
215                                   static_cast<size_t>(end - beg)),
216             1);
217         if (err != GRPC_ERROR_NONE) {
218           return err;
219         }
220         t->deframe_state = GRPC_DTS_FH_0;
221         t->incoming_stream = nullptr;
222         return GRPC_ERROR_NONE;
223       } else if (static_cast<uint32_t>(end - cur) > t->incoming_frame_size) {
224         size_t cur_offset = static_cast<size_t>(cur - beg);
225         err = parse_frame_slice(
226             t,
227             grpc_slice_sub_no_ref(slice, cur_offset,
228                                   cur_offset + t->incoming_frame_size),
229             1);
230         if (err != GRPC_ERROR_NONE) {
231           return err;
232         }
233         cur += t->incoming_frame_size;
234         t->incoming_stream = nullptr;
235         goto dts_fh_0; /* loop */
236       } else {
237         err = parse_frame_slice(
238             t,
239             grpc_slice_sub_no_ref(slice, static_cast<size_t>(cur - beg),
240                                   static_cast<size_t>(end - beg)),
241             0);
242         if (err != GRPC_ERROR_NONE) {
243           return err;
244         }
245         t->incoming_frame_size -= static_cast<uint32_t>(end - cur);
246         return GRPC_ERROR_NONE;
247       }
248       GPR_UNREACHABLE_CODE(return nullptr);
249   }
250
251   GPR_UNREACHABLE_CODE(return nullptr);
252 }
253
254 static grpc_error* init_frame_parser(grpc_chttp2_transport* t) {
255   if (t->is_first_frame &&
256       t->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) {
257     char* msg;
258     gpr_asprintf(
259         &msg, "Expected SETTINGS frame as the first frame, got frame type %d",
260         t->incoming_frame_type);
261     grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
262     gpr_free(msg);
263     return err;
264   }
265   t->is_first_frame = false;
266   if (t->expect_continuation_stream_id != 0) {
267     if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) {
268       char* msg;
269       gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x",
270                    t->incoming_frame_type);
271       grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
272       gpr_free(msg);
273       return err;
274     }
275     if (t->expect_continuation_stream_id != t->incoming_stream_id) {
276       char* msg;
277       gpr_asprintf(
278           &msg,
279           "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
280           "grpc_chttp2_stream %08x",
281           t->expect_continuation_stream_id, t->incoming_stream_id);
282       grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
283       gpr_free(msg);
284       return err;
285     }
286     return init_header_frame_parser(t, 1);
287   }
288   switch (t->incoming_frame_type) {
289     case GRPC_CHTTP2_FRAME_DATA:
290       return init_data_frame_parser(t);
291     case GRPC_CHTTP2_FRAME_HEADER:
292       return init_header_frame_parser(t, 0);
293     case GRPC_CHTTP2_FRAME_CONTINUATION:
294       return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
295           "Unexpected CONTINUATION frame");
296     case GRPC_CHTTP2_FRAME_RST_STREAM:
297       return init_rst_stream_parser(t);
298     case GRPC_CHTTP2_FRAME_SETTINGS:
299       return init_settings_frame_parser(t);
300     case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
301       return init_window_update_frame_parser(t);
302     case GRPC_CHTTP2_FRAME_PING:
303       return init_ping_parser(t);
304     case GRPC_CHTTP2_FRAME_GOAWAY:
305       return init_goaway_parser(t);
306     default:
307       if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
308         gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type);
309       }
310       return init_skip_frame_parser(t, 0);
311   }
312 }
313
314 static grpc_error* skip_parser(void* parser, grpc_chttp2_transport* t,
315                                grpc_chttp2_stream* s, const grpc_slice& slice,
316                                int is_last) {
317   return GRPC_ERROR_NONE;
318 }
319
320 static void skip_header(void* tp, grpc_mdelem md) { GRPC_MDELEM_UNREF(md); }
321
322 static grpc_error* init_skip_frame_parser(grpc_chttp2_transport* t,
323                                           int is_header) {
324   if (is_header) {
325     uint8_t is_eoh = t->expect_continuation_stream_id != 0;
326     t->parser = grpc_chttp2_header_parser_parse;
327     t->parser_data = &t->hpack_parser;
328     t->hpack_parser.on_header = skip_header;
329     t->hpack_parser.on_header_user_data = nullptr;
330     t->hpack_parser.is_boundary = is_eoh;
331     t->hpack_parser.is_eof = static_cast<uint8_t>(is_eoh ? t->header_eof : 0);
332   } else {
333     t->parser = skip_parser;
334   }
335   return GRPC_ERROR_NONE;
336 }
337
338 void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t) {
339   init_skip_frame_parser(t, t->parser == grpc_chttp2_header_parser_parse);
340 }
341
342 static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t) {
343   grpc_chttp2_stream* s =
344       grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
345   grpc_error* err = GRPC_ERROR_NONE;
346   grpc_core::chttp2::FlowControlAction action;
347   if (s == nullptr) {
348     err = t->flow_control->RecvData(t->incoming_frame_size);
349     action = t->flow_control->MakeAction();
350   } else {
351     err = s->flow_control->RecvData(t->incoming_frame_size);
352     action = s->flow_control->MakeAction();
353   }
354   grpc_chttp2_act_on_flowctl_action(action, t, s);
355   if (err != GRPC_ERROR_NONE) {
356     goto error_handler;
357   }
358   if (s == nullptr) {
359     return init_skip_frame_parser(t, 0);
360   }
361   s->received_bytes += t->incoming_frame_size;
362   s->stats.incoming.framing_bytes += 9;
363   if (err == GRPC_ERROR_NONE && s->read_closed) {
364     return init_skip_frame_parser(t, 0);
365   }
366   if (err == GRPC_ERROR_NONE) {
367     err = grpc_chttp2_data_parser_begin_frame(
368         &s->data_parser, t->incoming_frame_flags, s->id, s);
369   }
370 error_handler:
371   intptr_t unused;
372   if (err == GRPC_ERROR_NONE) {
373     t->incoming_stream = s;
374     /* t->parser = grpc_chttp2_data_parser_parse;*/
375     t->parser = grpc_chttp2_data_parser_parse;
376     t->parser_data = &s->data_parser;
377     t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
378     return GRPC_ERROR_NONE;
379   } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, &unused)) {
380     /* handle stream errors by closing the stream */
381     if (s != nullptr) {
382       grpc_chttp2_mark_stream_closed(t, s, true, false, err);
383     }
384     grpc_slice_buffer_add(
385         &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
386                                                 GRPC_HTTP2_PROTOCOL_ERROR,
387                                                 &s->stats.outgoing));
388     return init_skip_frame_parser(t, 0);
389   } else {
390     return err;
391   }
392 }
393
394 static void free_timeout(void* p) { gpr_free(p); }
395
396 static void on_initial_header(void* tp, grpc_mdelem md) {
397   GPR_TIMER_SCOPE("on_initial_header", 0);
398
399   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
400   grpc_chttp2_stream* s = t->incoming_stream;
401   GPR_ASSERT(s != nullptr);
402
403   if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
404     char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
405     char* value =
406         grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
407     gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
408             t->is_client ? "CLI" : "SVR", key, value);
409     gpr_free(key);
410     gpr_free(value);
411   }
412
413   if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
414     // We don't use grpc_mdelem_eq here to avoid executing additional
415     // instructions. The reasoning is if the payload is not equal, we already
416     // know that the metadata elements are not equal because the md is
417     // confirmed to be static. If we had used grpc_mdelem_eq here, then if the
418     // payloads are not equal, grpc_mdelem_eq executes more instructions to
419     // determine if they're equal or not.
420     if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload ||
421         md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) {
422       s->seen_error = true;
423     }
424   } else {
425     if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
426         !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
427       /* TODO(ctiller): check for a status like " 0" */
428       s->seen_error = true;
429     }
430
431     if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
432       grpc_millis* cached_timeout = static_cast<grpc_millis*>(
433           grpc_mdelem_get_user_data(md, free_timeout));
434       grpc_millis timeout;
435       if (cached_timeout != nullptr) {
436         timeout = *cached_timeout;
437       } else {
438         if (GPR_UNLIKELY(
439                 !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
440           char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
441           gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
442           gpr_free(val);
443           timeout = GRPC_MILLIS_INF_FUTURE;
444         }
445         if (GRPC_MDELEM_IS_INTERNED(md)) {
446           /* store the result */
447           cached_timeout =
448               static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
449           *cached_timeout = timeout;
450           grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
451         }
452       }
453       if (timeout != GRPC_MILLIS_INF_FUTURE) {
454         grpc_chttp2_incoming_metadata_buffer_set_deadline(
455             &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
456       }
457       GRPC_MDELEM_UNREF(md);
458       return;
459     }
460   }
461
462   const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
463   const size_t metadata_size_limit =
464       t->settings[GRPC_ACKED_SETTINGS]
465                  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
466   if (new_size > metadata_size_limit) {
467     gpr_log(GPR_DEBUG,
468             "received initial metadata size exceeds limit (%" PRIuPTR
469             " vs. %" PRIuPTR ")",
470             new_size, metadata_size_limit);
471     grpc_chttp2_cancel_stream(
472         t, s,
473         grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
474                                "received initial metadata size exceeds limit"),
475                            GRPC_ERROR_INT_GRPC_STATUS,
476                            GRPC_STATUS_RESOURCE_EXHAUSTED));
477     grpc_chttp2_parsing_become_skip_parser(t);
478     s->seen_error = true;
479     GRPC_MDELEM_UNREF(md);
480   } else {
481     grpc_error* error =
482         grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
483     if (error != GRPC_ERROR_NONE) {
484       grpc_chttp2_cancel_stream(t, s, error);
485       grpc_chttp2_parsing_become_skip_parser(t);
486       s->seen_error = true;
487       GRPC_MDELEM_UNREF(md);
488     }
489   }
490 }
491
492 static void on_trailing_header(void* tp, grpc_mdelem md) {
493   GPR_TIMER_SCOPE("on_trailing_header", 0);
494
495   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
496   grpc_chttp2_stream* s = t->incoming_stream;
497   GPR_ASSERT(s != nullptr);
498
499   if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
500     char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
501     char* value =
502         grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
503     gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
504             t->is_client ? "CLI" : "SVR", key, value);
505     gpr_free(key);
506     gpr_free(value);
507   }
508
509   if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) {
510     // We don't use grpc_mdelem_eq here to avoid executing additional
511     // instructions. The reasoning is if the payload is not equal, we already
512     // know that the metadata elements are not equal because the md is
513     // confirmed to be static. If we had used grpc_mdelem_eq here, then if the
514     // payloads are not equal, grpc_mdelem_eq executes more instructions to
515     // determine if they're equal or not.
516     if (md.payload == GRPC_MDELEM_GRPC_STATUS_1.payload ||
517         md.payload == GRPC_MDELEM_GRPC_STATUS_2.payload) {
518       s->seen_error = true;
519     }
520   } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
521              !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
522     /* TODO(ctiller): check for a status like " 0" */
523     s->seen_error = true;
524   }
525
526   const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
527   const size_t metadata_size_limit =
528       t->settings[GRPC_ACKED_SETTINGS]
529                  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
530   if (new_size > metadata_size_limit) {
531     gpr_log(GPR_DEBUG,
532             "received trailing metadata size exceeds limit (%" PRIuPTR
533             " vs. %" PRIuPTR ")",
534             new_size, metadata_size_limit);
535     grpc_chttp2_cancel_stream(
536         t, s,
537         grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
538                                "received trailing metadata size exceeds limit"),
539                            GRPC_ERROR_INT_GRPC_STATUS,
540                            GRPC_STATUS_RESOURCE_EXHAUSTED));
541     grpc_chttp2_parsing_become_skip_parser(t);
542     s->seen_error = true;
543     GRPC_MDELEM_UNREF(md);
544   } else {
545     grpc_error* error =
546         grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md);
547     if (error != GRPC_ERROR_NONE) {
548       grpc_chttp2_cancel_stream(t, s, error);
549       grpc_chttp2_parsing_become_skip_parser(t);
550       s->seen_error = true;
551       GRPC_MDELEM_UNREF(md);
552     }
553   }
554 }
555
556 static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
557                                             int is_continuation) {
558   uint8_t is_eoh =
559       (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
560   grpc_chttp2_stream* s;
561
562   /* TODO(ctiller): when to increment header_frames_received? */
563
564   if (is_eoh) {
565     t->expect_continuation_stream_id = 0;
566   } else {
567     t->expect_continuation_stream_id = t->incoming_stream_id;
568   }
569
570   if (!is_continuation) {
571     t->header_eof =
572         (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
573   }
574
575   t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
576
577   /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
578   s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
579   if (s == nullptr) {
580     if (GPR_UNLIKELY(is_continuation)) {
581       GRPC_CHTTP2_IF_TRACING(
582           gpr_log(GPR_ERROR,
583                   "grpc_chttp2_stream disbanded before CONTINUATION received"));
584       return init_skip_frame_parser(t, 1);
585     }
586     if (t->is_client) {
587       if (GPR_LIKELY((t->incoming_stream_id & 1) &&
588                      t->incoming_stream_id < t->next_stream_id)) {
589         /* this is an old (probably cancelled) grpc_chttp2_stream */
590       } else {
591         GRPC_CHTTP2_IF_TRACING(gpr_log(
592             GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client"));
593       }
594       grpc_error* err = init_skip_frame_parser(t, 1);
595       if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY) {
596         grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
597       }
598       return err;
599     } else if (GPR_UNLIKELY(t->last_new_stream_id >= t->incoming_stream_id)) {
600       GRPC_CHTTP2_IF_TRACING(gpr_log(
601           GPR_ERROR,
602           "ignoring out of order new grpc_chttp2_stream request on server; "
603           "last grpc_chttp2_stream "
604           "id=%d, new grpc_chttp2_stream id=%d",
605           t->last_new_stream_id, t->incoming_stream_id));
606       return init_skip_frame_parser(t, 1);
607     } else if (GPR_UNLIKELY((t->incoming_stream_id & 1) == 0)) {
608       GRPC_CHTTP2_IF_TRACING(gpr_log(
609           GPR_ERROR,
610           "ignoring grpc_chttp2_stream with non-client generated index %d",
611           t->incoming_stream_id));
612       return init_skip_frame_parser(t, 1);
613     } else if (GPR_UNLIKELY(
614                    grpc_chttp2_stream_map_size(&t->stream_map) >=
615                    t->settings[GRPC_ACKED_SETTINGS]
616                               [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS])) {
617       return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Max stream count exceeded");
618     }
619     t->last_new_stream_id = t->incoming_stream_id;
620     s = t->incoming_stream =
621         grpc_chttp2_parsing_accept_stream(t, t->incoming_stream_id);
622     if (GPR_UNLIKELY(s == nullptr)) {
623       GRPC_CHTTP2_IF_TRACING(
624           gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
625       return init_skip_frame_parser(t, 1);
626     }
627     if (t->channelz_socket != nullptr) {
628       t->channelz_socket->RecordStreamStartedFromRemote();
629     }
630   } else {
631     t->incoming_stream = s;
632   }
633   GPR_ASSERT(s != nullptr);
634   s->stats.incoming.framing_bytes += 9;
635   if (GPR_UNLIKELY(s->read_closed)) {
636     GRPC_CHTTP2_IF_TRACING(gpr_log(
637         GPR_ERROR, "skipping already closed grpc_chttp2_stream header"));
638     t->incoming_stream = nullptr;
639     return init_skip_frame_parser(t, 1);
640   }
641   t->parser = grpc_chttp2_header_parser_parse;
642   t->parser_data = &t->hpack_parser;
643   if (t->header_eof) {
644     s->eos_received = true;
645   }
646   switch (s->header_frames_received) {
647     case 0:
648       if (t->is_client && t->header_eof) {
649         GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing Trailers-Only"));
650         if (s->trailing_metadata_available != nullptr) {
651           *s->trailing_metadata_available = true;
652         }
653         t->hpack_parser.on_header = on_trailing_header;
654         s->received_trailing_metadata = true;
655       } else {
656         GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
657         t->hpack_parser.on_header = on_initial_header;
658       }
659       break;
660     case 1:
661       GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
662       t->hpack_parser.on_header = on_trailing_header;
663       s->received_trailing_metadata = true;
664       break;
665     case 2:
666       gpr_log(GPR_ERROR, "too many header frames received");
667       return init_skip_frame_parser(t, 1);
668   }
669   t->hpack_parser.on_header_user_data = t;
670   t->hpack_parser.is_boundary = is_eoh;
671   t->hpack_parser.is_eof = static_cast<uint8_t>(is_eoh ? t->header_eof : 0);
672   if (!is_continuation &&
673       (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
674     grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
675   }
676   return GRPC_ERROR_NONE;
677 }
678
679 static grpc_error* init_window_update_frame_parser(grpc_chttp2_transport* t) {
680   grpc_error* err = grpc_chttp2_window_update_parser_begin_frame(
681       &t->simple.window_update, t->incoming_frame_size,
682       t->incoming_frame_flags);
683   if (err != GRPC_ERROR_NONE) return err;
684   if (t->incoming_stream_id != 0) {
685     grpc_chttp2_stream* s = t->incoming_stream =
686         grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
687     if (s == nullptr) {
688       return init_skip_frame_parser(t, 0);
689     }
690     s->stats.incoming.framing_bytes += 9;
691   }
692   t->parser = grpc_chttp2_window_update_parser_parse;
693   t->parser_data = &t->simple.window_update;
694   return GRPC_ERROR_NONE;
695 }
696
697 static grpc_error* init_ping_parser(grpc_chttp2_transport* t) {
698   grpc_error* err = grpc_chttp2_ping_parser_begin_frame(
699       &t->simple.ping, t->incoming_frame_size, t->incoming_frame_flags);
700   if (err != GRPC_ERROR_NONE) return err;
701   t->parser = grpc_chttp2_ping_parser_parse;
702   t->parser_data = &t->simple.ping;
703   return GRPC_ERROR_NONE;
704 }
705
706 static grpc_error* init_rst_stream_parser(grpc_chttp2_transport* t) {
707   grpc_error* err = grpc_chttp2_rst_stream_parser_begin_frame(
708       &t->simple.rst_stream, t->incoming_frame_size, t->incoming_frame_flags);
709   if (err != GRPC_ERROR_NONE) return err;
710   grpc_chttp2_stream* s = t->incoming_stream =
711       grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
712   if (!t->incoming_stream) {
713     return init_skip_frame_parser(t, 0);
714   }
715   s->stats.incoming.framing_bytes += 9;
716   t->parser = grpc_chttp2_rst_stream_parser_parse;
717   t->parser_data = &t->simple.rst_stream;
718   return GRPC_ERROR_NONE;
719 }
720
721 static grpc_error* init_goaway_parser(grpc_chttp2_transport* t) {
722   grpc_error* err = grpc_chttp2_goaway_parser_begin_frame(
723       &t->goaway_parser, t->incoming_frame_size, t->incoming_frame_flags);
724   if (err != GRPC_ERROR_NONE) return err;
725   t->parser = grpc_chttp2_goaway_parser_parse;
726   t->parser_data = &t->goaway_parser;
727   return GRPC_ERROR_NONE;
728 }
729
730 static grpc_error* init_settings_frame_parser(grpc_chttp2_transport* t) {
731   if (t->incoming_stream_id != 0) {
732     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
733         "Settings frame received for grpc_chttp2_stream");
734   }
735
736   grpc_error* err = grpc_chttp2_settings_parser_begin_frame(
737       &t->simple.settings, t->incoming_frame_size, t->incoming_frame_flags,
738       t->settings[GRPC_PEER_SETTINGS]);
739   if (err != GRPC_ERROR_NONE) {
740     return err;
741   }
742   if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
743     memcpy(t->settings[GRPC_ACKED_SETTINGS], t->settings[GRPC_SENT_SETTINGS],
744            GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
745     grpc_chttp2_hptbl_set_max_bytes(
746         &t->hpack_parser.table,
747         t->settings[GRPC_ACKED_SETTINGS]
748                    [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
749     t->sent_local_settings = 0;
750   }
751   t->parser = grpc_chttp2_settings_parser_parse;
752   t->parser_data = &t->simple.settings;
753   return GRPC_ERROR_NONE;
754 }
755
756 static grpc_error* parse_frame_slice(grpc_chttp2_transport* t,
757                                      const grpc_slice& slice, int is_last) {
758   grpc_chttp2_stream* s = t->incoming_stream;
759   grpc_error* err = t->parser(t->parser_data, t, s, slice, is_last);
760   intptr_t unused;
761   if (GPR_LIKELY(err == GRPC_ERROR_NONE)) {
762     return err;
763   } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, &unused)) {
764     if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
765       const char* msg = grpc_error_string(err);
766       gpr_log(GPR_ERROR, "%s", msg);
767     }
768     grpc_chttp2_parsing_become_skip_parser(t);
769     if (s) {
770       s->forced_close_error = err;
771       grpc_slice_buffer_add(
772           &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
773                                                   GRPC_HTTP2_PROTOCOL_ERROR,
774                                                   &s->stats.outgoing));
775     } else {
776       GRPC_ERROR_UNREF(err);
777     }
778   }
779   return err;
780 }