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