• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, grpc_slice slice,
49                                      int is_last);
50 
grpc_chttp2_perform_read(grpc_chttp2_transport * t,grpc_slice slice)51 grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
52                                      grpc_slice slice) {
53   uint8_t* beg = GRPC_SLICE_START_PTR(slice);
54   uint8_t* end = GRPC_SLICE_END_PTR(slice);
55   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 
init_frame_parser(grpc_chttp2_transport * t)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_http_trace.enabled()) {
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 
skip_parser(void * parser,grpc_chttp2_transport * t,grpc_chttp2_stream * s,grpc_slice slice,int is_last)314 static grpc_error* skip_parser(void* parser, grpc_chttp2_transport* t,
315                                grpc_chttp2_stream* s, grpc_slice slice,
316                                int is_last) {
317   return GRPC_ERROR_NONE;
318 }
319 
skip_header(void * tp,grpc_mdelem md)320 static void skip_header(void* tp, grpc_mdelem md) { GRPC_MDELEM_UNREF(md); }
321 
init_skip_frame_parser(grpc_chttp2_transport * t,int is_header)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 
grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport * t)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 
init_data_frame_parser(grpc_chttp2_transport * t)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   if (err == GRPC_ERROR_NONE) {
372     t->incoming_stream = s;
373     /* t->parser = grpc_chttp2_data_parser_parse;*/
374     t->parser = grpc_chttp2_data_parser_parse;
375     t->parser_data = &s->data_parser;
376     t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
377     return GRPC_ERROR_NONE;
378   } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, nullptr)) {
379     /* handle stream errors by closing the stream */
380     if (s != nullptr) {
381       grpc_chttp2_mark_stream_closed(t, s, true, false, err);
382     }
383     grpc_slice_buffer_add(
384         &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
385                                                 GRPC_HTTP2_PROTOCOL_ERROR,
386                                                 &s->stats.outgoing));
387     return init_skip_frame_parser(t, 0);
388   } else {
389     return err;
390   }
391 }
392 
free_timeout(void * p)393 static void free_timeout(void* p) { gpr_free(p); }
394 
on_initial_header(void * tp,grpc_mdelem md)395 static void on_initial_header(void* tp, grpc_mdelem md) {
396   GPR_TIMER_SCOPE("on_initial_header", 0);
397 
398   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
399   grpc_chttp2_stream* s = t->incoming_stream;
400   GPR_ASSERT(s != nullptr);
401 
402   if (grpc_http_trace.enabled()) {
403     char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
404     char* value =
405         grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
406     gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
407             t->is_client ? "CLI" : "SVR", key, value);
408     gpr_free(key);
409     gpr_free(value);
410   }
411 
412   if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
413       !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
414     /* TODO(ctiller): check for a status like " 0" */
415     s->seen_error = true;
416   }
417 
418   if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
419     grpc_millis* cached_timeout =
420         static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout));
421     grpc_millis timeout;
422     if (cached_timeout != nullptr) {
423       timeout = *cached_timeout;
424     } else {
425       if (GPR_UNLIKELY(
426               !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
427         char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
428         gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
429         gpr_free(val);
430         timeout = GRPC_MILLIS_INF_FUTURE;
431       }
432       if (GRPC_MDELEM_IS_INTERNED(md)) {
433         /* store the result */
434         cached_timeout =
435             static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis)));
436         *cached_timeout = timeout;
437         grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
438       }
439     }
440     if (timeout != GRPC_MILLIS_INF_FUTURE) {
441       grpc_chttp2_incoming_metadata_buffer_set_deadline(
442           &s->metadata_buffer[0], grpc_core::ExecCtx::Get()->Now() + timeout);
443     }
444     GRPC_MDELEM_UNREF(md);
445   } else {
446     const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
447     const size_t metadata_size_limit =
448         t->settings[GRPC_ACKED_SETTINGS]
449                    [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
450     if (new_size > metadata_size_limit) {
451       gpr_log(GPR_DEBUG,
452               "received initial metadata size exceeds limit (%" PRIuPTR
453               " vs. %" PRIuPTR ")",
454               new_size, metadata_size_limit);
455       grpc_chttp2_cancel_stream(
456           t, s,
457           grpc_error_set_int(
458               GRPC_ERROR_CREATE_FROM_STATIC_STRING(
459                   "received initial metadata size exceeds limit"),
460               GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
461       grpc_chttp2_parsing_become_skip_parser(t);
462       s->seen_error = true;
463       GRPC_MDELEM_UNREF(md);
464     } else {
465       grpc_error* error =
466           grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
467       if (error != GRPC_ERROR_NONE) {
468         grpc_chttp2_cancel_stream(t, s, error);
469         grpc_chttp2_parsing_become_skip_parser(t);
470         s->seen_error = true;
471         GRPC_MDELEM_UNREF(md);
472       }
473     }
474   }
475 }
476 
on_trailing_header(void * tp,grpc_mdelem md)477 static void on_trailing_header(void* tp, grpc_mdelem md) {
478   GPR_TIMER_SCOPE("on_trailing_header", 0);
479 
480   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
481   grpc_chttp2_stream* s = t->incoming_stream;
482   GPR_ASSERT(s != nullptr);
483 
484   if (grpc_http_trace.enabled()) {
485     char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
486     char* value =
487         grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
488     gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
489             t->is_client ? "CLI" : "SVR", key, value);
490     gpr_free(key);
491     gpr_free(value);
492   }
493 
494   if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
495       !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
496     /* TODO(ctiller): check for a status like " 0" */
497     s->seen_error = true;
498   }
499 
500   const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
501   const size_t metadata_size_limit =
502       t->settings[GRPC_ACKED_SETTINGS]
503                  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
504   if (new_size > metadata_size_limit) {
505     gpr_log(GPR_DEBUG,
506             "received trailing metadata size exceeds limit (%" PRIuPTR
507             " vs. %" PRIuPTR ")",
508             new_size, metadata_size_limit);
509     grpc_chttp2_cancel_stream(
510         t, s,
511         grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
512                                "received trailing metadata size exceeds limit"),
513                            GRPC_ERROR_INT_GRPC_STATUS,
514                            GRPC_STATUS_RESOURCE_EXHAUSTED));
515     grpc_chttp2_parsing_become_skip_parser(t);
516     s->seen_error = true;
517     GRPC_MDELEM_UNREF(md);
518   } else {
519     grpc_error* error =
520         grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md);
521     if (error != GRPC_ERROR_NONE) {
522       grpc_chttp2_cancel_stream(t, s, error);
523       grpc_chttp2_parsing_become_skip_parser(t);
524       s->seen_error = true;
525       GRPC_MDELEM_UNREF(md);
526     }
527   }
528 }
529 
init_header_frame_parser(grpc_chttp2_transport * t,int is_continuation)530 static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
531                                             int is_continuation) {
532   uint8_t is_eoh =
533       (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
534   grpc_chttp2_stream* s;
535 
536   /* TODO(ctiller): when to increment header_frames_received? */
537 
538   if (is_eoh) {
539     t->expect_continuation_stream_id = 0;
540   } else {
541     t->expect_continuation_stream_id = t->incoming_stream_id;
542   }
543 
544   if (!is_continuation) {
545     t->header_eof =
546         (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
547   }
548 
549   t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
550 
551   /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
552   s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
553   if (s == nullptr) {
554     if (GPR_UNLIKELY(is_continuation)) {
555       GRPC_CHTTP2_IF_TRACING(
556           gpr_log(GPR_ERROR,
557                   "grpc_chttp2_stream disbanded before CONTINUATION received"));
558       return init_skip_frame_parser(t, 1);
559     }
560     if (t->is_client) {
561       if (GPR_LIKELY((t->incoming_stream_id & 1) &&
562                      t->incoming_stream_id < t->next_stream_id)) {
563         /* this is an old (probably cancelled) grpc_chttp2_stream */
564       } else {
565         GRPC_CHTTP2_IF_TRACING(gpr_log(
566             GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client"));
567       }
568       grpc_error* err = init_skip_frame_parser(t, 1);
569       if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY) {
570         grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
571       }
572       return err;
573     } else if (GPR_UNLIKELY(t->last_new_stream_id >= t->incoming_stream_id)) {
574       GRPC_CHTTP2_IF_TRACING(gpr_log(
575           GPR_ERROR,
576           "ignoring out of order new grpc_chttp2_stream request on server; "
577           "last grpc_chttp2_stream "
578           "id=%d, new grpc_chttp2_stream id=%d",
579           t->last_new_stream_id, t->incoming_stream_id));
580       return init_skip_frame_parser(t, 1);
581     } else if (GPR_UNLIKELY((t->incoming_stream_id & 1) == 0)) {
582       GRPC_CHTTP2_IF_TRACING(gpr_log(
583           GPR_ERROR,
584           "ignoring grpc_chttp2_stream with non-client generated index %d",
585           t->incoming_stream_id));
586       return init_skip_frame_parser(t, 1);
587     } else if (GPR_UNLIKELY(
588                    grpc_chttp2_stream_map_size(&t->stream_map) >=
589                    t->settings[GRPC_ACKED_SETTINGS]
590                               [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS])) {
591       return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Max stream count exceeded");
592     }
593     t->last_new_stream_id = t->incoming_stream_id;
594     s = t->incoming_stream =
595         grpc_chttp2_parsing_accept_stream(t, t->incoming_stream_id);
596     if (GPR_UNLIKELY(s == nullptr)) {
597       GRPC_CHTTP2_IF_TRACING(
598           gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
599       return init_skip_frame_parser(t, 1);
600     }
601   } else {
602     t->incoming_stream = s;
603   }
604   GPR_ASSERT(s != nullptr);
605   s->stats.incoming.framing_bytes += 9;
606   if (GPR_UNLIKELY(s->read_closed)) {
607     GRPC_CHTTP2_IF_TRACING(gpr_log(
608         GPR_ERROR, "skipping already closed grpc_chttp2_stream header"));
609     t->incoming_stream = nullptr;
610     return init_skip_frame_parser(t, 1);
611   }
612   t->parser = grpc_chttp2_header_parser_parse;
613   t->parser_data = &t->hpack_parser;
614   switch (s->header_frames_received) {
615     case 0:
616       if (t->is_client && t->header_eof) {
617         GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing Trailers-Only"));
618         if (s->trailing_metadata_available != nullptr) {
619           *s->trailing_metadata_available = true;
620         }
621         t->hpack_parser.on_header = on_trailing_header;
622         s->received_trailing_metadata = true;
623       } else {
624         GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
625         t->hpack_parser.on_header = on_initial_header;
626       }
627       break;
628     case 1:
629       GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
630       t->hpack_parser.on_header = on_trailing_header;
631       s->received_trailing_metadata = true;
632       break;
633     case 2:
634       gpr_log(GPR_ERROR, "too many header frames received");
635       return init_skip_frame_parser(t, 1);
636   }
637   t->hpack_parser.on_header_user_data = t;
638   t->hpack_parser.is_boundary = is_eoh;
639   t->hpack_parser.is_eof = static_cast<uint8_t>(is_eoh ? t->header_eof : 0);
640   if (!is_continuation &&
641       (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
642     grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
643   }
644   return GRPC_ERROR_NONE;
645 }
646 
init_window_update_frame_parser(grpc_chttp2_transport * t)647 static grpc_error* init_window_update_frame_parser(grpc_chttp2_transport* t) {
648   grpc_error* err = grpc_chttp2_window_update_parser_begin_frame(
649       &t->simple.window_update, t->incoming_frame_size,
650       t->incoming_frame_flags);
651   if (err != GRPC_ERROR_NONE) return err;
652   if (t->incoming_stream_id != 0) {
653     grpc_chttp2_stream* s = t->incoming_stream =
654         grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
655     if (s == nullptr) {
656       return init_skip_frame_parser(t, 0);
657     }
658     s->stats.incoming.framing_bytes += 9;
659   }
660   t->parser = grpc_chttp2_window_update_parser_parse;
661   t->parser_data = &t->simple.window_update;
662   return GRPC_ERROR_NONE;
663 }
664 
init_ping_parser(grpc_chttp2_transport * t)665 static grpc_error* init_ping_parser(grpc_chttp2_transport* t) {
666   grpc_error* err = grpc_chttp2_ping_parser_begin_frame(
667       &t->simple.ping, t->incoming_frame_size, t->incoming_frame_flags);
668   if (err != GRPC_ERROR_NONE) return err;
669   t->parser = grpc_chttp2_ping_parser_parse;
670   t->parser_data = &t->simple.ping;
671   return GRPC_ERROR_NONE;
672 }
673 
init_rst_stream_parser(grpc_chttp2_transport * t)674 static grpc_error* init_rst_stream_parser(grpc_chttp2_transport* t) {
675   grpc_error* err = grpc_chttp2_rst_stream_parser_begin_frame(
676       &t->simple.rst_stream, t->incoming_frame_size, t->incoming_frame_flags);
677   if (err != GRPC_ERROR_NONE) return err;
678   grpc_chttp2_stream* s = t->incoming_stream =
679       grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
680   if (!t->incoming_stream) {
681     return init_skip_frame_parser(t, 0);
682   }
683   s->stats.incoming.framing_bytes += 9;
684   t->parser = grpc_chttp2_rst_stream_parser_parse;
685   t->parser_data = &t->simple.rst_stream;
686   return GRPC_ERROR_NONE;
687 }
688 
init_goaway_parser(grpc_chttp2_transport * t)689 static grpc_error* init_goaway_parser(grpc_chttp2_transport* t) {
690   grpc_error* err = grpc_chttp2_goaway_parser_begin_frame(
691       &t->goaway_parser, t->incoming_frame_size, t->incoming_frame_flags);
692   if (err != GRPC_ERROR_NONE) return err;
693   t->parser = grpc_chttp2_goaway_parser_parse;
694   t->parser_data = &t->goaway_parser;
695   return GRPC_ERROR_NONE;
696 }
697 
init_settings_frame_parser(grpc_chttp2_transport * t)698 static grpc_error* init_settings_frame_parser(grpc_chttp2_transport* t) {
699   if (t->incoming_stream_id != 0) {
700     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
701         "Settings frame received for grpc_chttp2_stream");
702   }
703 
704   grpc_error* err = grpc_chttp2_settings_parser_begin_frame(
705       &t->simple.settings, t->incoming_frame_size, t->incoming_frame_flags,
706       t->settings[GRPC_PEER_SETTINGS]);
707   if (err != GRPC_ERROR_NONE) {
708     return err;
709   }
710   if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
711     memcpy(t->settings[GRPC_ACKED_SETTINGS], t->settings[GRPC_SENT_SETTINGS],
712            GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
713     grpc_chttp2_hptbl_set_max_bytes(
714         &t->hpack_parser.table,
715         t->settings[GRPC_ACKED_SETTINGS]
716                    [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
717     t->sent_local_settings = 0;
718   }
719   t->parser = grpc_chttp2_settings_parser_parse;
720   t->parser_data = &t->simple.settings;
721   return GRPC_ERROR_NONE;
722 }
723 
parse_frame_slice(grpc_chttp2_transport * t,grpc_slice slice,int is_last)724 static grpc_error* parse_frame_slice(grpc_chttp2_transport* t, grpc_slice slice,
725                                      int is_last) {
726   grpc_chttp2_stream* s = t->incoming_stream;
727   grpc_error* err = t->parser(t->parser_data, t, s, slice, is_last);
728   if (GPR_LIKELY(err == GRPC_ERROR_NONE)) {
729     return err;
730   } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, nullptr)) {
731     if (grpc_http_trace.enabled()) {
732       const char* msg = grpc_error_string(err);
733       gpr_log(GPR_ERROR, "%s", msg);
734     }
735     grpc_chttp2_parsing_become_skip_parser(t);
736     if (s) {
737       s->forced_close_error = err;
738       grpc_slice_buffer_add(
739           &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
740                                                   GRPC_HTTP2_PROTOCOL_ERROR,
741                                                   &s->stats.outgoing));
742     } else {
743       GRPC_ERROR_UNREF(err);
744     }
745   }
746   return err;
747 }
748