3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <grpc/support/port_platform.h>
21 #include "src/core/ext/transport/chttp2/transport/internal.h"
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/string_util.h>
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"
36 static grpc_error* init_frame_parser(grpc_chttp2_transport* t);
37 static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
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,
48 static grpc_error* parse_frame_slice(grpc_chttp2_transport* t,
49 const grpc_slice& slice, int is_last);
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;
58 if (cur == end) return GRPC_ERROR_NONE;
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]) {
90 "Connect string mismatch: expected '%c' (%d) got '%c' (%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);
101 t->deframe_state = static_cast<grpc_chttp2_deframe_transport_state>(
102 1 + static_cast<int>(t->deframe_state));
105 return GRPC_ERROR_NONE;
110 GPR_ASSERT(cur < end);
111 t->incoming_frame_size = (static_cast<uint32_t>(*cur)) << 16;
113 t->deframe_state = GRPC_DTS_FH_1;
114 return GRPC_ERROR_NONE;
118 GPR_ASSERT(cur < end);
119 t->incoming_frame_size |= (static_cast<uint32_t>(*cur)) << 8;
121 t->deframe_state = GRPC_DTS_FH_2;
122 return GRPC_ERROR_NONE;
126 GPR_ASSERT(cur < end);
127 t->incoming_frame_size |= *cur;
129 t->deframe_state = GRPC_DTS_FH_3;
130 return GRPC_ERROR_NONE;
134 GPR_ASSERT(cur < end);
135 t->incoming_frame_type = *cur;
137 t->deframe_state = GRPC_DTS_FH_4;
138 return GRPC_ERROR_NONE;
142 GPR_ASSERT(cur < end);
143 t->incoming_frame_flags = *cur;
145 t->deframe_state = GRPC_DTS_FH_5;
146 return GRPC_ERROR_NONE;
150 GPR_ASSERT(cur < end);
151 t->incoming_stream_id = ((static_cast<uint32_t>(*cur)) & 0x7f) << 24;
153 t->deframe_state = GRPC_DTS_FH_6;
154 return GRPC_ERROR_NONE;
158 GPR_ASSERT(cur < end);
159 t->incoming_stream_id |= (static_cast<uint32_t>(*cur)) << 16;
161 t->deframe_state = GRPC_DTS_FH_7;
162 return GRPC_ERROR_NONE;
166 GPR_ASSERT(cur < end);
167 t->incoming_stream_id |= (static_cast<uint32_t>(*cur)) << 8;
169 t->deframe_state = GRPC_DTS_FH_8;
170 return GRPC_ERROR_NONE;
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) {
181 if (t->incoming_frame_size == 0) {
182 err = parse_frame_slice(t, grpc_empty_slice(), 1);
183 if (err != GRPC_ERROR_NONE) {
186 t->incoming_stream = nullptr;
188 t->deframe_state = GRPC_DTS_FH_0;
189 return GRPC_ERROR_NONE;
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]) {
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);
206 return GRPC_ERROR_NONE;
210 GPR_ASSERT(cur < end);
211 if (static_cast<uint32_t>(end - cur) == t->incoming_frame_size) {
212 err = parse_frame_slice(
214 grpc_slice_sub_no_ref(slice, static_cast<size_t>(cur - beg),
215 static_cast<size_t>(end - beg)),
217 if (err != GRPC_ERROR_NONE) {
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(
227 grpc_slice_sub_no_ref(slice, cur_offset,
228 cur_offset + t->incoming_frame_size),
230 if (err != GRPC_ERROR_NONE) {
233 cur += t->incoming_frame_size;
234 t->incoming_stream = nullptr;
235 goto dts_fh_0; /* loop */
237 err = parse_frame_slice(
239 grpc_slice_sub_no_ref(slice, static_cast<size_t>(cur - beg),
240 static_cast<size_t>(end - beg)),
242 if (err != GRPC_ERROR_NONE) {
245 t->incoming_frame_size -= static_cast<uint32_t>(end - cur);
246 return GRPC_ERROR_NONE;
248 GPR_UNREACHABLE_CODE(return nullptr);
251 GPR_UNREACHABLE_CODE(return nullptr);
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) {
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);
265 t->is_first_frame = false;
266 if (t->expect_continuation_stream_id != 0) {
267 if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) {
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);
275 if (t->expect_continuation_stream_id != t->incoming_stream_id) {
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);
286 return init_header_frame_parser(t, 1);
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);
307 if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
308 gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type);
310 return init_skip_frame_parser(t, 0);
314 static grpc_error* skip_parser(void* parser, grpc_chttp2_transport* t,
315 grpc_chttp2_stream* s, const grpc_slice& slice,
317 return GRPC_ERROR_NONE;
320 static void skip_header(void* tp, grpc_mdelem md) { GRPC_MDELEM_UNREF(md); }
322 static grpc_error* init_skip_frame_parser(grpc_chttp2_transport* t,
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);
333 t->parser = skip_parser;
335 return GRPC_ERROR_NONE;
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);
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;
348 err = t->flow_control->RecvData(t->incoming_frame_size);
349 action = t->flow_control->MakeAction();
351 err = s->flow_control->RecvData(t->incoming_frame_size);
352 action = s->flow_control->MakeAction();
354 grpc_chttp2_act_on_flowctl_action(action, t, s);
355 if (err != GRPC_ERROR_NONE) {
359 return init_skip_frame_parser(t, 0);
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);
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);
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 */
382 grpc_chttp2_mark_stream_closed(t, s, true, false, err);
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);
394 static void free_timeout(void* p) { gpr_free(p); }
396 static void on_initial_header(void* tp, grpc_mdelem md) {
397 GPR_TIMER_SCOPE("on_initial_header", 0);
399 grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
400 grpc_chttp2_stream* s = t->incoming_stream;
401 GPR_ASSERT(s != nullptr);
403 if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
404 char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
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);
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;
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;
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));
435 if (cached_timeout != nullptr) {
436 timeout = *cached_timeout;
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);
443 timeout = GRPC_MILLIS_INF_FUTURE;
445 if (GRPC_MDELEM_IS_INTERNED(md)) {
446 /* store the result */
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);
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);
457 GRPC_MDELEM_UNREF(md);
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) {
468 "received initial metadata size exceeds limit (%" PRIuPTR
469 " vs. %" PRIuPTR ")",
470 new_size, metadata_size_limit);
471 grpc_chttp2_cancel_stream(
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);
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);
492 static void on_trailing_header(void* tp, grpc_mdelem md) {
493 GPR_TIMER_SCOPE("on_trailing_header", 0);
495 grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
496 grpc_chttp2_stream* s = t->incoming_stream;
497 GPR_ASSERT(s != nullptr);
499 if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
500 char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
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);
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;
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;
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) {
532 "received trailing metadata size exceeds limit (%" PRIuPTR
533 " vs. %" PRIuPTR ")",
534 new_size, metadata_size_limit);
535 grpc_chttp2_cancel_stream(
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);
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);
556 static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
557 int is_continuation) {
559 (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
560 grpc_chttp2_stream* s;
562 /* TODO(ctiller): when to increment header_frames_received? */
565 t->expect_continuation_stream_id = 0;
567 t->expect_continuation_stream_id = t->incoming_stream_id;
570 if (!is_continuation) {
572 (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
575 t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
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);
580 if (GPR_UNLIKELY(is_continuation)) {
581 GRPC_CHTTP2_IF_TRACING(
583 "grpc_chttp2_stream disbanded before CONTINUATION received"));
584 return init_skip_frame_parser(t, 1);
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 */
591 GRPC_CHTTP2_IF_TRACING(gpr_log(
592 GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client"));
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);
599 } else if (GPR_UNLIKELY(t->last_new_stream_id >= t->incoming_stream_id)) {
600 GRPC_CHTTP2_IF_TRACING(gpr_log(
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(
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");
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);
627 if (t->channelz_socket != nullptr) {
628 t->channelz_socket->RecordStreamStartedFromRemote();
631 t->incoming_stream = s;
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);
641 t->parser = grpc_chttp2_header_parser_parse;
642 t->parser_data = &t->hpack_parser;
644 s->eos_received = true;
646 switch (s->header_frames_received) {
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;
653 t->hpack_parser.on_header = on_trailing_header;
654 s->received_trailing_metadata = true;
656 GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
657 t->hpack_parser.on_header = on_initial_header;
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;
666 gpr_log(GPR_ERROR, "too many header frames received");
667 return init_skip_frame_parser(t, 1);
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);
676 return GRPC_ERROR_NONE;
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);
688 return init_skip_frame_parser(t, 0);
690 s->stats.incoming.framing_bytes += 9;
692 t->parser = grpc_chttp2_window_update_parser_parse;
693 t->parser_data = &t->simple.window_update;
694 return GRPC_ERROR_NONE;
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;
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);
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;
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;
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");
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) {
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;
751 t->parser = grpc_chttp2_settings_parser_parse;
752 t->parser_data = &t->simple.settings;
753 return GRPC_ERROR_NONE;
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);
761 if (GPR_LIKELY(err == GRPC_ERROR_NONE)) {
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);
768 grpc_chttp2_parsing_become_skip_parser(t);
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));
776 GRPC_ERROR_UNREF(err);