Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include "src/core/transport/chttp2/internal.h"
35 :
36 : #include <string.h>
37 :
38 : #include <grpc/support/alloc.h>
39 : #include <grpc/support/log.h>
40 : #include <grpc/support/string_util.h>
41 :
42 : #include "src/core/profiling/timers.h"
43 : #include "src/core/transport/chttp2/http2_errors.h"
44 : #include "src/core/transport/chttp2/status_conversion.h"
45 : #include "src/core/transport/chttp2/timeout_encoding.h"
46 : #include "src/core/transport/static_metadata.h"
47 :
48 : static int init_frame_parser(grpc_exec_ctx *exec_ctx,
49 : grpc_chttp2_transport_parsing *transport_parsing);
50 : static int init_header_frame_parser(
51 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
52 : int is_continuation);
53 : static int init_data_frame_parser(
54 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
55 : static int init_rst_stream_parser(
56 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
57 : static int init_settings_frame_parser(
58 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
59 : static int init_window_update_frame_parser(
60 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
61 : static int init_ping_parser(grpc_exec_ctx *exec_ctx,
62 : grpc_chttp2_transport_parsing *transport_parsing);
63 : static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
64 : grpc_chttp2_transport_parsing *transport_parsing);
65 : static int init_skip_frame_parser(
66 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
67 : int is_header);
68 :
69 : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
70 : grpc_chttp2_transport_parsing *transport_parsing,
71 : gpr_slice slice, int is_last);
72 :
73 6516034 : void grpc_chttp2_prepare_to_read(
74 : grpc_chttp2_transport_global *transport_global,
75 : grpc_chttp2_transport_parsing *transport_parsing) {
76 : grpc_chttp2_stream_global *stream_global;
77 : grpc_chttp2_stream_parsing *stream_parsing;
78 :
79 : GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
80 :
81 6516034 : transport_parsing->next_stream_id = transport_global->next_stream_id;
82 6516034 : transport_parsing->last_sent_max_table_size =
83 : transport_global->settings[GRPC_SENT_SETTINGS]
84 6516034 : [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
85 :
86 : /* update the parsing view of incoming window */
87 15003088 : while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
88 : transport_global, transport_parsing, &stream_global, &stream_parsing)) {
89 1970902 : GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing,
90 : incoming_window, stream_global,
91 : unannounced_incoming_window_for_parse);
92 : }
93 :
94 : GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
95 6516027 : }
96 :
97 6516050 : void grpc_chttp2_publish_reads(
98 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
99 : grpc_chttp2_transport_parsing *transport_parsing) {
100 : grpc_chttp2_stream_global *stream_global;
101 : grpc_chttp2_stream_parsing *stream_parsing;
102 : int was_zero;
103 : int is_zero;
104 :
105 : /* transport_parsing->last_incoming_stream_id is used as
106 : last-grpc_chttp2_stream-id when
107 : sending GOAWAY frame.
108 : https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
109 : says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
110 : ID. So,
111 : since we don't have server pushed streams, client should send
112 : GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
113 6516050 : if (!transport_parsing->is_client) {
114 4338398 : transport_global->last_incoming_stream_id =
115 4338398 : transport_parsing->incoming_stream_id;
116 : }
117 :
118 : /* update global settings */
119 6516050 : if (transport_parsing->settings_updated) {
120 5552 : memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
121 5552 : transport_parsing->settings, sizeof(transport_parsing->settings));
122 5552 : transport_parsing->settings_updated = 0;
123 : }
124 :
125 : /* update settings based on ack if received */
126 6516050 : if (transport_parsing->settings_ack_received) {
127 5372 : memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
128 5372 : transport_global->settings[GRPC_SENT_SETTINGS],
129 : GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
130 5372 : transport_parsing->settings_ack_received = 0;
131 5372 : transport_global->sent_local_settings = 0;
132 : }
133 :
134 : /* move goaway to the global state if we received one (it will be
135 : published later */
136 6516050 : if (transport_parsing->goaway_received) {
137 284 : grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
138 284 : (gpr_uint32)transport_parsing->goaway_error,
139 : transport_parsing->goaway_text);
140 284 : transport_parsing->goaway_text = gpr_empty_slice();
141 284 : transport_parsing->goaway_received = 0;
142 : }
143 :
144 : /* propagate flow control tokens to global state */
145 6516050 : was_zero = transport_global->outgoing_window <= 0;
146 6516050 : GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
147 : transport_parsing, outgoing_window);
148 6516045 : is_zero = transport_global->outgoing_window <= 0;
149 6516045 : if (was_zero && !is_zero) {
150 11663 : while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
151 : &stream_global)) {
152 6 : grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
153 : }
154 : }
155 :
156 13032092 : if (transport_parsing->incoming_window <
157 6516046 : transport_global->connection_window_target * 3 / 4) {
158 12959 : gpr_int64 announce_bytes = transport_global->connection_window_target -
159 6436 : transport_parsing->incoming_window;
160 6523 : GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
161 : announce_incoming_window, announce_bytes);
162 6522 : GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
163 : incoming_window, announce_bytes);
164 : }
165 :
166 : /* for each stream that saw an update, fixup global state */
167 21748671 : while (grpc_chttp2_list_pop_parsing_seen_stream(
168 : transport_global, transport_parsing, &stream_global, &stream_parsing)) {
169 8718220 : if (stream_parsing->seen_error) {
170 523824 : stream_global->seen_error = 1;
171 523824 : grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
172 : }
173 :
174 : /* update outgoing flow control window */
175 8718389 : was_zero = stream_global->outgoing_window <= 0;
176 8718389 : GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
177 : outgoing_window, stream_parsing,
178 : outgoing_window);
179 8718544 : is_zero = stream_global->outgoing_window <= 0;
180 8718544 : if (was_zero && !is_zero) {
181 28567 : grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
182 : }
183 :
184 8718544 : stream_global->max_recv_bytes -= (gpr_uint32)GPR_MIN(
185 : stream_global->max_recv_bytes, stream_parsing->received_bytes);
186 8718544 : stream_parsing->received_bytes = 0;
187 :
188 : /* publish incoming stream ops */
189 8718544 : if (stream_global->incoming_frames.tail != NULL) {
190 64242 : stream_global->incoming_frames.tail->is_tail = 0;
191 : }
192 8718544 : if (stream_parsing->data_parser.incoming_frames.head != NULL) {
193 3954453 : grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
194 : }
195 17437532 : grpc_chttp2_incoming_frame_queue_merge(
196 8718766 : &stream_global->incoming_frames,
197 8718766 : &stream_parsing->data_parser.incoming_frames);
198 8719395 : if (stream_global->incoming_frames.tail != NULL) {
199 4016291 : stream_global->incoming_frames.tail->is_tail = 1;
200 : }
201 :
202 15717119 : if (!stream_global->published_initial_metadata &&
203 6997724 : stream_parsing->got_metadata_on_parse[0]) {
204 4441265 : stream_parsing->got_metadata_on_parse[0] = 0;
205 4441265 : stream_global->published_initial_metadata = 1;
206 4441265 : GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
207 : stream_parsing->metadata_buffer[0],
208 : stream_global->received_initial_metadata);
209 4441265 : grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
210 : }
211 17439722 : if (!stream_global->published_trailing_metadata &&
212 8720130 : stream_parsing->got_metadata_on_parse[1]) {
213 2271496 : stream_parsing->got_metadata_on_parse[1] = 0;
214 2271496 : stream_global->published_trailing_metadata = 1;
215 2271496 : GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
216 : stream_parsing->metadata_buffer[1],
217 : stream_global->received_trailing_metadata);
218 2271496 : grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
219 : }
220 :
221 8719158 : if (stream_parsing->saw_rst_stream) {
222 393 : if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
223 154 : grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
224 143 : (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
225 : char *status_details;
226 : gpr_slice slice_details;
227 154 : gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
228 154 : stream_parsing->rst_stream_reason);
229 154 : slice_details = gpr_slice_from_copied_string(status_details);
230 154 : gpr_free(status_details);
231 154 : grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
232 : status_code, &slice_details);
233 : }
234 393 : grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
235 : 1, 1);
236 : }
237 :
238 8719158 : if (stream_parsing->received_close) {
239 4440070 : grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
240 : 1, 0);
241 : }
242 : }
243 6515990 : }
244 :
245 18512073 : int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
246 : grpc_chttp2_transport_parsing *transport_parsing,
247 : gpr_slice slice) {
248 18512073 : gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
249 18512073 : gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
250 18511275 : gpr_uint8 *cur = beg;
251 :
252 18512073 : if (cur == end) return 1;
253 :
254 18512073 : switch (transport_parsing->deframe_state) {
255 : case GRPC_DTS_CLIENT_PREFIX_0:
256 : case GRPC_DTS_CLIENT_PREFIX_1:
257 : case GRPC_DTS_CLIENT_PREFIX_2:
258 : case GRPC_DTS_CLIENT_PREFIX_3:
259 : case GRPC_DTS_CLIENT_PREFIX_4:
260 : case GRPC_DTS_CLIENT_PREFIX_5:
261 : case GRPC_DTS_CLIENT_PREFIX_6:
262 : case GRPC_DTS_CLIENT_PREFIX_7:
263 : case GRPC_DTS_CLIENT_PREFIX_8:
264 : case GRPC_DTS_CLIENT_PREFIX_9:
265 : case GRPC_DTS_CLIENT_PREFIX_10:
266 : case GRPC_DTS_CLIENT_PREFIX_11:
267 : case GRPC_DTS_CLIENT_PREFIX_12:
268 : case GRPC_DTS_CLIENT_PREFIX_13:
269 : case GRPC_DTS_CLIENT_PREFIX_14:
270 : case GRPC_DTS_CLIENT_PREFIX_15:
271 : case GRPC_DTS_CLIENT_PREFIX_16:
272 : case GRPC_DTS_CLIENT_PREFIX_17:
273 : case GRPC_DTS_CLIENT_PREFIX_18:
274 : case GRPC_DTS_CLIENT_PREFIX_19:
275 : case GRPC_DTS_CLIENT_PREFIX_20:
276 : case GRPC_DTS_CLIENT_PREFIX_21:
277 : case GRPC_DTS_CLIENT_PREFIX_22:
278 : case GRPC_DTS_CLIENT_PREFIX_23:
279 82039 : while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
280 135264 : if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
281 67140 : ->deframe_state]) {
282 96 : gpr_log(GPR_INFO,
283 : "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
284 : "at byte %d",
285 24 : GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
286 24 : ->deframe_state],
287 24 : (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
288 24 : [transport_parsing->deframe_state],
289 48 : *cur, (int)*cur, transport_parsing->deframe_state);
290 24 : return 0;
291 : }
292 68100 : ++cur;
293 68100 : ++transport_parsing->deframe_state;
294 : }
295 6966 : if (cur == end) {
296 4320 : return 1;
297 : }
298 : /* fallthrough */
299 : dts_fh_0:
300 : case GRPC_DTS_FH_0:
301 11233057 : GPR_ASSERT(cur < end);
302 11233057 : transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
303 11233057 : if (++cur == end) {
304 211779 : transport_parsing->deframe_state = GRPC_DTS_FH_1;
305 211779 : return 1;
306 : }
307 : /* fallthrough */
308 : case GRPC_DTS_FH_1:
309 11234229 : GPR_ASSERT(cur < end);
310 11234229 : transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
311 11234229 : if (++cur == end) {
312 217856 : transport_parsing->deframe_state = GRPC_DTS_FH_2;
313 217856 : return 1;
314 : }
315 : /* fallthrough */
316 : case GRPC_DTS_FH_2:
317 11234272 : GPR_ASSERT(cur < end);
318 11234272 : transport_parsing->incoming_frame_size |= *cur;
319 11234272 : if (++cur == end) {
320 211953 : transport_parsing->deframe_state = GRPC_DTS_FH_3;
321 211953 : return 1;
322 : }
323 : /* fallthrough */
324 : case GRPC_DTS_FH_3:
325 11234325 : GPR_ASSERT(cur < end);
326 11234325 : transport_parsing->incoming_frame_type = *cur;
327 11234325 : if (++cur == end) {
328 211966 : transport_parsing->deframe_state = GRPC_DTS_FH_4;
329 211966 : return 1;
330 : }
331 : /* fallthrough */
332 : case GRPC_DTS_FH_4:
333 11235272 : GPR_ASSERT(cur < end);
334 11235272 : transport_parsing->incoming_frame_flags = *cur;
335 11235272 : if (++cur == end) {
336 211943 : transport_parsing->deframe_state = GRPC_DTS_FH_5;
337 211943 : return 1;
338 : }
339 : /* fallthrough */
340 : case GRPC_DTS_FH_5:
341 11234010 : GPR_ASSERT(cur < end);
342 11234010 : transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
343 11234010 : if (++cur == end) {
344 211776 : transport_parsing->deframe_state = GRPC_DTS_FH_6;
345 211776 : return 1;
346 : }
347 : /* fallthrough */
348 : case GRPC_DTS_FH_6:
349 11234027 : GPR_ASSERT(cur < end);
350 11234027 : transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
351 11234027 : if (++cur == end) {
352 211864 : transport_parsing->deframe_state = GRPC_DTS_FH_7;
353 211864 : return 1;
354 : }
355 : /* fallthrough */
356 : case GRPC_DTS_FH_7:
357 11233751 : GPR_ASSERT(cur < end);
358 11233751 : transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
359 11233751 : if (++cur == end) {
360 211905 : transport_parsing->deframe_state = GRPC_DTS_FH_8;
361 211905 : return 1;
362 : }
363 : /* fallthrough */
364 : case GRPC_DTS_FH_8:
365 11234736 : GPR_ASSERT(cur < end);
366 11234736 : transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
367 11234736 : transport_parsing->deframe_state = GRPC_DTS_FRAME;
368 11234736 : if (!init_frame_parser(exec_ctx, transport_parsing)) {
369 12 : return 0;
370 : }
371 11237195 : if (transport_parsing->incoming_stream_id) {
372 11219543 : transport_parsing->last_incoming_stream_id =
373 11218943 : transport_parsing->incoming_stream_id;
374 : }
375 11237195 : if (transport_parsing->incoming_frame_size == 0) {
376 528789 : if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
377 : 1)) {
378 0 : return 0;
379 : }
380 528790 : transport_parsing->incoming_stream = NULL;
381 528790 : if (++cur == end) {
382 527409 : transport_parsing->deframe_state = GRPC_DTS_FH_0;
383 527409 : return 1;
384 : }
385 1369 : goto dts_fh_0; /* loop */
386 : }
387 10708406 : if (++cur == end) {
388 159241 : return 1;
389 : }
390 : /* fallthrough */
391 : case GRPC_DTS_FRAME:
392 24868382 : GPR_ASSERT(cur < end);
393 24868382 : if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
394 3917126 : if (!parse_frame_slice(exec_ctx, transport_parsing,
395 1958563 : gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
396 1958563 : (size_t)(end - beg)),
397 : 1)) {
398 23 : return 0;
399 : }
400 1958546 : transport_parsing->deframe_state = GRPC_DTS_FH_0;
401 1958546 : transport_parsing->incoming_stream = NULL;
402 1958546 : return 1;
403 45818983 : } else if ((gpr_uint32)(end - cur) >
404 22909164 : transport_parsing->incoming_frame_size) {
405 8750802 : size_t cur_offset = (size_t)(cur - beg);
406 8750802 : if (!parse_frame_slice(
407 : exec_ctx, transport_parsing,
408 : gpr_slice_sub_no_ref(
409 : slice, cur_offset,
410 8750434 : cur_offset + transport_parsing->incoming_frame_size),
411 : 1)) {
412 0 : return 0;
413 : }
414 8745885 : cur += transport_parsing->incoming_frame_size;
415 8745885 : transport_parsing->incoming_stream = NULL;
416 8745885 : goto dts_fh_0; /* loop */
417 : } else {
418 28318034 : if (!parse_frame_slice(exec_ctx, transport_parsing,
419 14159017 : gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
420 14159017 : (size_t)(end - beg)),
421 : 0)) {
422 0 : return 0;
423 : }
424 14159017 : transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur);
425 14159017 : return 1;
426 : }
427 : GPR_UNREACHABLE_CODE(return 0);
428 : }
429 :
430 0 : GPR_UNREACHABLE_CODE(return 0);
431 0 : }
432 :
433 11240615 : static int init_frame_parser(grpc_exec_ctx *exec_ctx,
434 : grpc_chttp2_transport_parsing *transport_parsing) {
435 11240615 : if (transport_parsing->expect_continuation_stream_id != 0) {
436 115 : if (transport_parsing->incoming_frame_type !=
437 : GRPC_CHTTP2_FRAME_CONTINUATION) {
438 1 : gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
439 1 : transport_parsing->incoming_frame_type);
440 1 : return 0;
441 : }
442 228 : if (transport_parsing->expect_continuation_stream_id !=
443 114 : transport_parsing->incoming_stream_id) {
444 1 : gpr_log(GPR_ERROR,
445 : "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
446 : "grpc_chttp2_stream %08x",
447 : transport_parsing->expect_continuation_stream_id,
448 : transport_parsing->incoming_stream_id);
449 1 : return 0;
450 : }
451 113 : return init_header_frame_parser(exec_ctx, transport_parsing, 1);
452 : }
453 11240500 : switch (transport_parsing->incoming_frame_type) {
454 : case GRPC_CHTTP2_FRAME_DATA:
455 4488376 : return init_data_frame_parser(exec_ctx, transport_parsing);
456 : case GRPC_CHTTP2_FRAME_HEADER:
457 6705495 : return init_header_frame_parser(exec_ctx, transport_parsing, 0);
458 : case GRPC_CHTTP2_FRAME_CONTINUATION:
459 1 : gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
460 1 : return 0;
461 : case GRPC_CHTTP2_FRAME_RST_STREAM:
462 605 : return init_rst_stream_parser(exec_ctx, transport_parsing);
463 : case GRPC_CHTTP2_FRAME_SETTINGS:
464 10934 : return init_settings_frame_parser(exec_ctx, transport_parsing);
465 : case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
466 34804 : return init_window_update_frame_parser(exec_ctx, transport_parsing);
467 : case GRPC_CHTTP2_FRAME_PING:
468 0 : return init_ping_parser(exec_ctx, transport_parsing);
469 : case GRPC_CHTTP2_FRAME_GOAWAY:
470 284 : return init_goaway_parser(exec_ctx, transport_parsing);
471 : default:
472 1 : gpr_log(GPR_ERROR, "Unknown frame type %02x",
473 1 : transport_parsing->incoming_frame_type);
474 1 : return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
475 : }
476 : }
477 :
478 589 : static grpc_chttp2_parse_error skip_parser(
479 : grpc_exec_ctx *exec_ctx, void *parser,
480 : grpc_chttp2_transport_parsing *transport_parsing,
481 : grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
482 589 : return GRPC_CHTTP2_PARSE_OK;
483 : }
484 :
485 228 : static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
486 :
487 562 : static int init_skip_frame_parser(
488 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
489 : int is_header) {
490 562 : if (is_header) {
491 88 : gpr_uint8 is_eoh = transport_parsing->expect_continuation_stream_id != 0;
492 88 : transport_parsing->parser = grpc_chttp2_header_parser_parse;
493 88 : transport_parsing->parser_data = &transport_parsing->hpack_parser;
494 88 : transport_parsing->hpack_parser.on_header = skip_header;
495 88 : transport_parsing->hpack_parser.on_header_user_data = NULL;
496 88 : transport_parsing->hpack_parser.is_boundary = is_eoh;
497 88 : transport_parsing->hpack_parser.is_eof =
498 88 : (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
499 : } else {
500 484 : transport_parsing->parser = skip_parser;
501 : }
502 562 : return 1;
503 : }
504 :
505 35 : void grpc_chttp2_parsing_become_skip_parser(
506 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
507 35 : init_skip_frame_parser(
508 : exec_ctx, transport_parsing,
509 35 : transport_parsing->parser == grpc_chttp2_header_parser_parse);
510 35 : }
511 :
512 4490685 : static grpc_chttp2_parse_error update_incoming_window(
513 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
514 : grpc_chttp2_stream_parsing *stream_parsing) {
515 4490685 : gpr_uint32 incoming_frame_size = transport_parsing->incoming_frame_size;
516 4490685 : if (incoming_frame_size > transport_parsing->incoming_window) {
517 0 : gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
518 : transport_parsing->incoming_frame_size,
519 : transport_parsing->incoming_window);
520 0 : return GRPC_CHTTP2_CONNECTION_ERROR;
521 : }
522 :
523 4490685 : if (incoming_frame_size > stream_parsing->incoming_window) {
524 0 : gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
525 : transport_parsing->incoming_frame_size,
526 : stream_parsing->incoming_window);
527 0 : return GRPC_CHTTP2_CONNECTION_ERROR;
528 : }
529 :
530 4490685 : GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
531 : incoming_frame_size);
532 4490939 : GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing,
533 : incoming_window, incoming_frame_size);
534 4490939 : stream_parsing->received_bytes += incoming_frame_size;
535 :
536 4490939 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
537 :
538 4490556 : return GRPC_CHTTP2_PARSE_OK;
539 : }
540 :
541 4488492 : static int init_data_frame_parser(
542 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
543 4488492 : grpc_chttp2_stream_parsing *stream_parsing =
544 4488492 : grpc_chttp2_parsing_lookup_stream(transport_parsing,
545 : transport_parsing->incoming_stream_id);
546 4490915 : grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
547 4491238 : if (!stream_parsing || stream_parsing->received_close)
548 272 : return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
549 4490643 : if (err == GRPC_CHTTP2_PARSE_OK) {
550 4490961 : err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
551 : }
552 4490887 : if (err == GRPC_CHTTP2_PARSE_OK) {
553 4490869 : err = grpc_chttp2_data_parser_begin_frame(
554 4490869 : &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
555 : }
556 4490849 : switch (err) {
557 : case GRPC_CHTTP2_PARSE_OK:
558 4490848 : transport_parsing->incoming_stream = stream_parsing;
559 4490848 : transport_parsing->parser = grpc_chttp2_data_parser_parse;
560 4490848 : transport_parsing->parser_data = &stream_parsing->data_parser;
561 4490525 : return 1;
562 : case GRPC_CHTTP2_STREAM_ERROR:
563 1 : stream_parsing->received_close = 1;
564 1 : stream_parsing->saw_rst_stream = 1;
565 1 : stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
566 1 : gpr_slice_buffer_add(
567 : &transport_parsing->qbuf,
568 : grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
569 : GRPC_CHTTP2_PROTOCOL_ERROR));
570 1 : return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
571 : case GRPC_CHTTP2_CONNECTION_ERROR:
572 0 : return 0;
573 : }
574 0 : GPR_UNREACHABLE_CODE(return 0);
575 0 : }
576 :
577 1110 : static void free_timeout(void *p) { gpr_free(p); }
578 :
579 30986801 : static void on_initial_header(void *tp, grpc_mdelem *md) {
580 30985635 : grpc_chttp2_transport_parsing *transport_parsing = tp;
581 30986801 : grpc_chttp2_stream_parsing *stream_parsing =
582 : transport_parsing->incoming_stream;
583 :
584 : GPR_TIMER_BEGIN("on_initial_header", 0);
585 :
586 30986801 : GPR_ASSERT(stream_parsing);
587 :
588 30986801 : GRPC_CHTTP2_IF_TRACING(gpr_log(
589 : GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
590 : transport_parsing->is_client ? "CLI" : "SVR",
591 : grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
592 :
593 30983371 : if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
594 : /* TODO(ctiller): check for a status like " 0" */
595 5 : stream_parsing->seen_error = 1;
596 : }
597 :
598 30983371 : if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
599 1047992 : gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
600 1047992 : if (!cached_timeout) {
601 : /* not already parsed: parse it now, and store the result away */
602 1123 : cached_timeout = gpr_malloc(sizeof(gpr_timespec));
603 1123 : if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
604 : cached_timeout)) {
605 2 : gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
606 : grpc_mdstr_as_c_string(md->value));
607 2 : *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
608 : }
609 1123 : grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
610 : }
611 1047992 : grpc_chttp2_incoming_metadata_buffer_set_deadline(
612 : &stream_parsing->metadata_buffer[0],
613 : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
614 1047992 : GRPC_MDELEM_UNREF(md);
615 : } else {
616 29935379 : grpc_chttp2_incoming_metadata_buffer_add(
617 : &stream_parsing->metadata_buffer[0], md);
618 : }
619 :
620 30979907 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
621 :
622 : GPR_TIMER_END("on_initial_header", 0);
623 30981476 : }
624 :
625 2896653 : static void on_trailing_header(void *tp, grpc_mdelem *md) {
626 2896490 : grpc_chttp2_transport_parsing *transport_parsing = tp;
627 2896653 : grpc_chttp2_stream_parsing *stream_parsing =
628 : transport_parsing->incoming_stream;
629 :
630 : GPR_TIMER_BEGIN("on_trailing_header", 0);
631 :
632 2896653 : GPR_ASSERT(stream_parsing);
633 :
634 2896653 : GRPC_CHTTP2_IF_TRACING(gpr_log(
635 : GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", stream_parsing->id,
636 : transport_parsing->is_client ? "CLI" : "SVR",
637 : grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
638 :
639 2896653 : if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
640 : /* TODO(ctiller): check for a status like " 0" */
641 523274 : stream_parsing->seen_error = 1;
642 : }
643 :
644 2896653 : grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1],
645 : md);
646 :
647 2896521 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
648 :
649 : GPR_TIMER_END("on_trailing_header", 0);
650 2896466 : }
651 :
652 6706969 : static int init_header_frame_parser(
653 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
654 : int is_continuation) {
655 13413938 : gpr_uint8 is_eoh = (transport_parsing->incoming_frame_flags &
656 6706969 : GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
657 6706734 : int via_accept = 0;
658 : grpc_chttp2_stream_parsing *stream_parsing;
659 :
660 : /* TODO(ctiller): when to increment header_frames_received? */
661 :
662 6706969 : if (is_eoh) {
663 6706853 : transport_parsing->expect_continuation_stream_id = 0;
664 : } else {
665 116 : transport_parsing->expect_continuation_stream_id =
666 116 : transport_parsing->incoming_stream_id;
667 : }
668 :
669 6706969 : if (!is_continuation) {
670 13414376 : transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
671 6707188 : GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
672 : }
673 :
674 : /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
675 6706969 : stream_parsing = grpc_chttp2_parsing_lookup_stream(
676 : transport_parsing, transport_parsing->incoming_stream_id);
677 6714162 : if (stream_parsing == NULL) {
678 2171131 : if (is_continuation) {
679 0 : gpr_log(GPR_ERROR,
680 : "grpc_chttp2_stream disbanded before CONTINUATION received");
681 0 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
682 : }
683 2171131 : if (transport_parsing->is_client) {
684 102 : if ((transport_parsing->incoming_stream_id & 1) &&
685 50 : transport_parsing->incoming_stream_id <
686 51 : transport_parsing->next_stream_id) {
687 : /* this is an old (probably cancelled) grpc_chttp2_stream */
688 : } else {
689 0 : gpr_log(GPR_ERROR,
690 : "ignoring new grpc_chttp2_stream creation on client");
691 : }
692 51 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
693 4342160 : } else if (transport_parsing->last_incoming_stream_id >
694 2171080 : transport_parsing->incoming_stream_id) {
695 0 : gpr_log(GPR_ERROR,
696 : "ignoring out of order new grpc_chttp2_stream request on server; "
697 : "last grpc_chttp2_stream "
698 : "id=%d, new grpc_chttp2_stream id=%d",
699 : transport_parsing->last_incoming_stream_id,
700 : transport_parsing->incoming_stream_id);
701 0 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
702 2171080 : } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
703 2 : gpr_log(GPR_ERROR,
704 : "ignoring grpc_chttp2_stream with non-client generated index %d",
705 : transport_parsing->incoming_stream_id);
706 2 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
707 : }
708 2171096 : stream_parsing = transport_parsing->incoming_stream =
709 2171078 : grpc_chttp2_parsing_accept_stream(
710 : exec_ctx, transport_parsing, transport_parsing->incoming_stream_id);
711 2171096 : if (stream_parsing == NULL) {
712 0 : gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
713 0 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
714 : }
715 2171007 : via_accept = 1;
716 : } else {
717 4543031 : transport_parsing->incoming_stream = stream_parsing;
718 : }
719 6714127 : GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
720 6710928 : if (stream_parsing->received_close) {
721 0 : gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
722 0 : transport_parsing->incoming_stream = NULL;
723 0 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
724 : }
725 6710928 : transport_parsing->parser = grpc_chttp2_header_parser_parse;
726 6710928 : transport_parsing->parser_data = &transport_parsing->hpack_parser;
727 6710928 : switch (stream_parsing->header_frames_received) {
728 : case 0:
729 4441136 : transport_parsing->hpack_parser.on_header = on_initial_header;
730 4441136 : break;
731 : case 1:
732 2271558 : transport_parsing->hpack_parser.on_header = on_trailing_header;
733 2271558 : break;
734 : case 2:
735 1 : gpr_log(GPR_ERROR, "too many header frames received");
736 1 : return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
737 : }
738 6710927 : transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
739 6710927 : transport_parsing->hpack_parser.is_boundary = is_eoh;
740 6710927 : transport_parsing->hpack_parser.is_eof =
741 6710927 : (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
742 6710927 : if (!is_continuation && (transport_parsing->incoming_frame_flags &
743 : GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
744 10 : grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
745 : }
746 6710502 : return 1;
747 : }
748 :
749 34804 : static int init_window_update_frame_parser(
750 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
751 34804 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
752 : &transport_parsing->simple.window_update,
753 : transport_parsing->incoming_frame_size,
754 34804 : transport_parsing->incoming_frame_flags);
755 34796 : if (transport_parsing->incoming_stream_id) {
756 28866 : transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
757 : transport_parsing, transport_parsing->incoming_stream_id);
758 : }
759 34796 : transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
760 34796 : transport_parsing->parser_data = &transport_parsing->simple.window_update;
761 34796 : return ok;
762 : }
763 :
764 0 : static int init_ping_parser(grpc_exec_ctx *exec_ctx,
765 : grpc_chttp2_transport_parsing *transport_parsing) {
766 0 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
767 : &transport_parsing->simple.ping,
768 : transport_parsing->incoming_frame_size,
769 0 : transport_parsing->incoming_frame_flags);
770 0 : transport_parsing->parser = grpc_chttp2_ping_parser_parse;
771 0 : transport_parsing->parser_data = &transport_parsing->simple.ping;
772 0 : return ok;
773 : }
774 :
775 605 : static int init_rst_stream_parser(
776 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
777 605 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
778 : &transport_parsing->simple.rst_stream,
779 : transport_parsing->incoming_frame_size,
780 605 : transport_parsing->incoming_frame_flags);
781 605 : transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
782 : transport_parsing, transport_parsing->incoming_stream_id);
783 605 : if (!transport_parsing->incoming_stream) {
784 199 : return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
785 : }
786 397 : transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
787 397 : transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
788 386 : return ok;
789 : }
790 :
791 244 : static int init_goaway_parser(
792 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
793 284 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
794 : &transport_parsing->goaway_parser,
795 : transport_parsing->incoming_frame_size,
796 284 : transport_parsing->incoming_frame_flags);
797 284 : transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
798 284 : transport_parsing->parser_data = &transport_parsing->goaway_parser;
799 244 : return ok;
800 : }
801 :
802 10934 : static int init_settings_frame_parser(
803 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
804 : int ok;
805 :
806 10934 : if (transport_parsing->incoming_stream_id != 0) {
807 2 : gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
808 : transport_parsing->incoming_stream_id);
809 2 : return 0;
810 : }
811 :
812 10932 : ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
813 : &transport_parsing->simple.settings,
814 : transport_parsing->incoming_frame_size,
815 10932 : transport_parsing->incoming_frame_flags,
816 10932 : transport_parsing->settings);
817 10930 : if (!ok) {
818 7 : return 0;
819 : }
820 10923 : if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
821 5371 : transport_parsing->settings_ack_received = 1;
822 5371 : grpc_chttp2_hptbl_set_max_bytes(
823 : &transport_parsing->hpack_parser.table,
824 : transport_parsing->last_sent_max_table_size);
825 : }
826 10924 : transport_parsing->parser = grpc_chttp2_settings_parser_parse;
827 10924 : transport_parsing->parser_data = &transport_parsing->simple.settings;
828 10760 : return ok;
829 : }
830 :
831 : /*
832 : static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
833 : return window + window_update < MAX_WINDOW;
834 : }
835 : */
836 :
837 25395894 : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
838 : grpc_chttp2_transport_parsing *transport_parsing,
839 : gpr_slice slice, int is_last) {
840 25395894 : grpc_chttp2_stream_parsing *stream_parsing =
841 : transport_parsing->incoming_stream;
842 25395894 : switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
843 : transport_parsing, stream_parsing, slice,
844 : is_last)) {
845 : case GRPC_CHTTP2_PARSE_OK:
846 25396193 : if (stream_parsing) {
847 25372666 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
848 : stream_parsing);
849 : }
850 25391398 : return 1;
851 : case GRPC_CHTTP2_STREAM_ERROR:
852 1 : grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
853 1 : if (stream_parsing) {
854 1 : stream_parsing->saw_rst_stream = 1;
855 1 : stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
856 1 : gpr_slice_buffer_add(
857 : &transport_parsing->qbuf,
858 : grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
859 : GRPC_CHTTP2_PROTOCOL_ERROR));
860 : }
861 1 : return 1;
862 : case GRPC_CHTTP2_CONNECTION_ERROR:
863 23 : return 0;
864 : }
865 0 : GPR_UNREACHABLE_CODE(return 0);
866 0 : }
|