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