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 "src/core/transport/chttp2/http2_errors.h"
39 : #include "src/core/transport/chttp2/status_conversion.h"
40 : #include "src/core/transport/chttp2/timeout_encoding.h"
41 :
42 : #include <grpc/support/alloc.h>
43 : #include <grpc/support/log.h>
44 :
45 : static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing);
46 : static int init_header_frame_parser(
47 : grpc_chttp2_transport_parsing *transport_parsing, int is_continuation);
48 : static int init_data_frame_parser(
49 : grpc_chttp2_transport_parsing *transport_parsing);
50 : static int init_rst_stream_parser(
51 : grpc_chttp2_transport_parsing *transport_parsing);
52 : static int init_settings_frame_parser(
53 : grpc_chttp2_transport_parsing *transport_parsing);
54 : static int init_window_update_frame_parser(
55 : grpc_chttp2_transport_parsing *transport_parsing);
56 : static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing);
57 : static int init_goaway_parser(grpc_chttp2_transport_parsing *transport_parsing);
58 : static int init_skip_frame_parser(
59 : grpc_chttp2_transport_parsing *transport_parsing, int is_header);
60 :
61 : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
62 : grpc_chttp2_transport_parsing *transport_parsing,
63 : gpr_slice slice, int is_last);
64 :
65 2465955 : void grpc_chttp2_prepare_to_read(
66 : grpc_chttp2_transport_global *transport_global,
67 : grpc_chttp2_transport_parsing *transport_parsing) {
68 : grpc_chttp2_stream_global *stream_global;
69 : grpc_chttp2_stream_parsing *stream_parsing;
70 :
71 2465955 : transport_parsing->next_stream_id = transport_global->next_stream_id;
72 :
73 : /* update the parsing view of incoming window */
74 2465955 : if (transport_parsing->incoming_window != transport_global->incoming_window) {
75 6305 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
76 : "parse", transport_parsing, incoming_window,
77 : (gpr_int64)transport_global->incoming_window -
78 : (gpr_int64)transport_parsing->incoming_window);
79 6305 : transport_parsing->incoming_window = transport_global->incoming_window;
80 : }
81 6652536 : while (grpc_chttp2_list_pop_incoming_window_updated(
82 : transport_global, transport_parsing, &stream_global, &stream_parsing)) {
83 1720624 : stream_parsing->id = stream_global->id;
84 1720624 : if (stream_parsing->incoming_window != stream_global->incoming_window) {
85 1720654 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
86 : "parse", transport_parsing, stream_parsing, incoming_window,
87 : (gpr_int64)stream_global->incoming_window -
88 : (gpr_int64)stream_parsing->incoming_window);
89 1720656 : stream_parsing->incoming_window = stream_global->incoming_window;
90 : }
91 : }
92 2465830 : }
93 :
94 2466030 : void grpc_chttp2_publish_reads(
95 : grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
96 : grpc_chttp2_transport_parsing *transport_parsing) {
97 : grpc_chttp2_stream_global *stream_global;
98 : grpc_chttp2_stream_parsing *stream_parsing;
99 :
100 : /* transport_parsing->last_incoming_stream_id is used as
101 : last-grpc_chttp2_stream-id when
102 : sending GOAWAY frame.
103 : https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
104 : says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
105 : ID. So,
106 : since we don't have server pushed streams, client should send
107 : GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
108 2466030 : if (!transport_parsing->is_client) {
109 1213144 : transport_global->last_incoming_stream_id =
110 1213144 : transport_parsing->incoming_stream_id;
111 : }
112 :
113 : /* copy parsing qbuf to global qbuf */
114 2466030 : gpr_slice_buffer_move_into(&transport_parsing->qbuf, &transport_global->qbuf);
115 :
116 : /* update global settings */
117 2466026 : if (transport_parsing->settings_updated) {
118 3681 : memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
119 3681 : transport_parsing->settings, sizeof(transport_parsing->settings));
120 3681 : transport_parsing->settings_updated = 0;
121 : }
122 :
123 : /* update settings based on ack if received */
124 2466026 : if (transport_parsing->settings_ack_received) {
125 3578 : memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
126 3578 : transport_global->settings[GRPC_SENT_SETTINGS],
127 : GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
128 3578 : transport_parsing->settings_ack_received = 0;
129 : }
130 :
131 : /* move goaway to the global state if we received one (it will be
132 : published later */
133 2466026 : if (transport_parsing->goaway_received) {
134 229 : grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
135 229 : (gpr_uint32)transport_parsing->goaway_error,
136 : transport_parsing->goaway_text);
137 229 : transport_parsing->goaway_text = gpr_empty_slice();
138 229 : transport_parsing->goaway_received = 0;
139 : }
140 :
141 : /* propagate flow control tokens to global state */
142 2466026 : if (transport_parsing->outgoing_window_update) {
143 4091 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
144 : "parsed", transport_global, outgoing_window,
145 : transport_parsing->outgoing_window_update);
146 4091 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
147 : "parsed", transport_parsing, outgoing_window_update,
148 : -(gpr_int64)transport_parsing->outgoing_window_update);
149 8182 : transport_global->outgoing_window +=
150 4091 : transport_parsing->outgoing_window_update;
151 4091 : transport_parsing->outgoing_window_update = 0;
152 : }
153 :
154 2466026 : if (transport_parsing->incoming_window_delta) {
155 966596 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
156 : "parsed", transport_global, incoming_window,
157 : -(gpr_int64)transport_parsing->incoming_window_delta);
158 966595 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
159 : "parsed", transport_parsing, incoming_window_delta,
160 : -(gpr_int64)transport_parsing->incoming_window_delta);
161 1933190 : transport_global->incoming_window -=
162 966595 : transport_parsing->incoming_window_delta;
163 966595 : transport_parsing->incoming_window_delta = 0;
164 : }
165 :
166 : /* for each stream that saw an update, fixup global state */
167 9445059 : while (grpc_chttp2_list_pop_parsing_seen_stream(
168 : transport_global, transport_parsing, &stream_global, &stream_parsing)) {
169 : /* update incoming flow control window */
170 4512407 : if (stream_parsing->incoming_window_delta) {
171 3015646 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
172 : "parsed", transport_parsing, stream_global, incoming_window,
173 : -(gpr_int64)stream_parsing->incoming_window_delta);
174 3015726 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
175 : "parsed", transport_parsing, stream_parsing, incoming_window_delta,
176 : -(gpr_int64)stream_parsing->incoming_window_delta);
177 3015726 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
178 : "parsed", transport_parsing, stream_global, max_recv_bytes,
179 : -(gpr_int64)stream_parsing->incoming_window_delta);
180 3015726 : stream_global->incoming_window -= stream_parsing->incoming_window_delta;
181 3015726 : GPR_ASSERT(stream_global->max_recv_bytes >=
182 : stream_parsing->incoming_window_delta);
183 3015726 : stream_global->max_recv_bytes -= stream_parsing->incoming_window_delta;
184 3015726 : stream_parsing->incoming_window_delta = 0;
185 3015726 : grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
186 : }
187 :
188 : /* update outgoing flow control window */
189 4511468 : if (stream_parsing->outgoing_window_update) {
190 1591904 : int was_zero = stream_global->outgoing_window <= 0;
191 : int is_zero;
192 1591904 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("parsed", transport_parsing,
193 : stream_global, outgoing_window,
194 : stream_parsing->outgoing_window_update);
195 1591907 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
196 : "parsed", transport_parsing, stream_parsing, outgoing_window_update,
197 : -(gpr_int64)stream_parsing->outgoing_window_update);
198 1591907 : GPR_ASSERT(stream_parsing->outgoing_window_update <= GPR_UINT32_MAX);
199 3183814 : stream_global->outgoing_window +=
200 1591907 : (gpr_uint32)stream_parsing->outgoing_window_update;
201 1591907 : stream_parsing->outgoing_window_update = 0;
202 1591907 : is_zero = stream_global->outgoing_window <= 0;
203 1591907 : if (was_zero && !is_zero) {
204 13600 : grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
205 : }
206 : }
207 :
208 : /* updating closed status */
209 4511471 : if (stream_parsing->received_close) {
210 2881381 : stream_global->read_closed = 1;
211 2881381 : grpc_chttp2_list_add_read_write_state_changed(transport_global,
212 : stream_global);
213 : }
214 4511510 : if (stream_parsing->saw_rst_stream) {
215 5728 : stream_global->cancelled = 1;
216 11456 : stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(
217 5728 : (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
218 5728 : if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
219 240 : stream_global->published_cancelled = 1;
220 : }
221 5728 : grpc_chttp2_list_add_read_write_state_changed(transport_global,
222 : stream_global);
223 : }
224 :
225 : /* publish incoming stream ops */
226 4511510 : if (stream_parsing->data_parser.incoming_sopb.nops > 0) {
227 12122796 : grpc_incoming_metadata_buffer_move_to_referencing_sopb(
228 8081864 : &stream_parsing->incoming_metadata, &stream_global->incoming_metadata,
229 4040932 : &stream_parsing->data_parser.incoming_sopb);
230 4042111 : grpc_sopb_move_to(&stream_parsing->data_parser.incoming_sopb,
231 4042111 : &stream_global->incoming_sopb);
232 4042470 : grpc_chttp2_list_add_read_write_state_changed(transport_global,
233 : stream_global);
234 : }
235 : }
236 2466005 : }
237 :
238 5626175 : int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
239 : grpc_chttp2_transport_parsing *transport_parsing,
240 : gpr_slice slice) {
241 5626175 : gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
242 5626175 : gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
243 5626175 : gpr_uint8 *cur = beg;
244 :
245 5626175 : if (cur == end) return 1;
246 :
247 5626175 : switch (transport_parsing->deframe_state) {
248 : case GRPC_DTS_CLIENT_PREFIX_0:
249 : case GRPC_DTS_CLIENT_PREFIX_1:
250 : case GRPC_DTS_CLIENT_PREFIX_2:
251 : case GRPC_DTS_CLIENT_PREFIX_3:
252 : case GRPC_DTS_CLIENT_PREFIX_4:
253 : case GRPC_DTS_CLIENT_PREFIX_5:
254 : case GRPC_DTS_CLIENT_PREFIX_6:
255 : case GRPC_DTS_CLIENT_PREFIX_7:
256 : case GRPC_DTS_CLIENT_PREFIX_8:
257 : case GRPC_DTS_CLIENT_PREFIX_9:
258 : case GRPC_DTS_CLIENT_PREFIX_10:
259 : case GRPC_DTS_CLIENT_PREFIX_11:
260 : case GRPC_DTS_CLIENT_PREFIX_12:
261 : case GRPC_DTS_CLIENT_PREFIX_13:
262 : case GRPC_DTS_CLIENT_PREFIX_14:
263 : case GRPC_DTS_CLIENT_PREFIX_15:
264 : case GRPC_DTS_CLIENT_PREFIX_16:
265 : case GRPC_DTS_CLIENT_PREFIX_17:
266 : case GRPC_DTS_CLIENT_PREFIX_18:
267 : case GRPC_DTS_CLIENT_PREFIX_19:
268 : case GRPC_DTS_CLIENT_PREFIX_20:
269 : case GRPC_DTS_CLIENT_PREFIX_21:
270 : case GRPC_DTS_CLIENT_PREFIX_22:
271 : case GRPC_DTS_CLIENT_PREFIX_23:
272 53548 : while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
273 89688 : if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
274 44844 : ->deframe_state]) {
275 96 : gpr_log(GPR_INFO,
276 : "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
277 : "at byte %d",
278 24 : GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
279 24 : ->deframe_state],
280 24 : (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
281 24 : [transport_parsing->deframe_state],
282 48 : *cur, (int)*cur, transport_parsing->deframe_state);
283 24 : return 0;
284 : }
285 44820 : ++cur;
286 44820 : ++transport_parsing->deframe_state;
287 : }
288 4340 : if (cur == end) {
289 2592 : return 1;
290 : }
291 : /* fallthrough */
292 : dts_fh_0:
293 : case GRPC_DTS_FH_0:
294 9002524 : GPR_ASSERT(cur < end);
295 9002524 : transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
296 9002524 : if (++cur == end) {
297 4095 : transport_parsing->deframe_state = GRPC_DTS_FH_1;
298 4095 : return 1;
299 : }
300 : /* fallthrough */
301 : case GRPC_DTS_FH_1:
302 9002847 : GPR_ASSERT(cur < end);
303 9002847 : transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
304 9002847 : if (++cur == end) {
305 4302 : transport_parsing->deframe_state = GRPC_DTS_FH_2;
306 4302 : return 1;
307 : }
308 : /* fallthrough */
309 : case GRPC_DTS_FH_2:
310 9003031 : GPR_ASSERT(cur < end);
311 9003031 : transport_parsing->incoming_frame_size |= *cur;
312 9003031 : if (++cur == end) {
313 3643 : transport_parsing->deframe_state = GRPC_DTS_FH_3;
314 3643 : return 1;
315 : }
316 : /* fallthrough */
317 : case GRPC_DTS_FH_3:
318 9002896 : GPR_ASSERT(cur < end);
319 9002896 : transport_parsing->incoming_frame_type = *cur;
320 9002896 : if (++cur == end) {
321 3873 : transport_parsing->deframe_state = GRPC_DTS_FH_4;
322 3873 : return 1;
323 : }
324 : /* fallthrough */
325 : case GRPC_DTS_FH_4:
326 9002807 : GPR_ASSERT(cur < end);
327 9002807 : transport_parsing->incoming_frame_flags = *cur;
328 9002807 : if (++cur == end) {
329 3880 : transport_parsing->deframe_state = GRPC_DTS_FH_5;
330 3880 : return 1;
331 : }
332 : /* fallthrough */
333 : case GRPC_DTS_FH_5:
334 9003024 : GPR_ASSERT(cur < end);
335 9003024 : transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
336 9003024 : if (++cur == end) {
337 4105 : transport_parsing->deframe_state = GRPC_DTS_FH_6;
338 4105 : return 1;
339 : }
340 : /* fallthrough */
341 : case GRPC_DTS_FH_6:
342 9002560 : GPR_ASSERT(cur < end);
343 9002560 : transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
344 9002560 : if (++cur == end) {
345 3570 : transport_parsing->deframe_state = GRPC_DTS_FH_7;
346 3570 : return 1;
347 : }
348 : /* fallthrough */
349 : case GRPC_DTS_FH_7:
350 9002788 : GPR_ASSERT(cur < end);
351 9002788 : transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
352 9002788 : if (++cur == end) {
353 3737 : transport_parsing->deframe_state = GRPC_DTS_FH_8;
354 3737 : return 1;
355 : }
356 : /* fallthrough */
357 : case GRPC_DTS_FH_8:
358 9000722 : GPR_ASSERT(cur < end);
359 9000722 : transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
360 9000722 : transport_parsing->deframe_state = GRPC_DTS_FRAME;
361 9000722 : if (!init_frame_parser(transport_parsing)) {
362 7 : return 0;
363 : }
364 8995351 : if (transport_parsing->incoming_stream_id) {
365 8987103 : transport_parsing->last_incoming_stream_id =
366 8987103 : transport_parsing->incoming_stream_id;
367 : }
368 8995351 : if (transport_parsing->incoming_frame_size == 0) {
369 4087 : if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
370 : 1)) {
371 0 : return 0;
372 : }
373 4088 : transport_parsing->incoming_stream = NULL;
374 4088 : if (++cur == end) {
375 2743 : transport_parsing->deframe_state = GRPC_DTS_FH_0;
376 2743 : return 1;
377 : }
378 1345 : goto dts_fh_0; /* loop */
379 : }
380 8991264 : if (++cur == end) {
381 3471 : return 1;
382 : }
383 : /* fallthrough */
384 : case GRPC_DTS_FRAME:
385 13199253 : GPR_ASSERT(cur < end);
386 13199253 : if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
387 2760824 : if (!parse_frame_slice(exec_ctx, transport_parsing,
388 1380412 : gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
389 1380412 : (size_t)(end - beg)),
390 : 1)) {
391 0 : return 0;
392 : }
393 1380424 : transport_parsing->deframe_state = GRPC_DTS_FH_0;
394 1380424 : transport_parsing->incoming_stream = NULL;
395 1380424 : return 1;
396 23637682 : } else if ((gpr_uint32)(end - cur) >
397 11818841 : transport_parsing->incoming_frame_size) {
398 7616517 : size_t cur_offset = (size_t)(cur - beg);
399 7616517 : if (!parse_frame_slice(
400 : exec_ctx, transport_parsing,
401 : gpr_slice_sub_no_ref(
402 : slice, cur_offset,
403 7616517 : cur_offset + transport_parsing->incoming_frame_size),
404 : 1)) {
405 0 : return 0;
406 : }
407 7618483 : cur += transport_parsing->incoming_frame_size;
408 7618483 : transport_parsing->incoming_stream = NULL;
409 7618483 : goto dts_fh_0; /* loop */
410 : } else {
411 8404648 : if (!parse_frame_slice(exec_ctx, transport_parsing,
412 4202324 : gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
413 4202324 : (size_t)(end - beg)),
414 : 0)) {
415 0 : return 0;
416 : }
417 4202324 : transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur);
418 4202324 : return 1;
419 : }
420 : GPR_UNREACHABLE_CODE(return 0);
421 : }
422 :
423 0 : GPR_UNREACHABLE_CODE(return 0);
424 : }
425 :
426 9009243 : static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
427 9009243 : if (transport_parsing->expect_continuation_stream_id != 0) {
428 104 : if (transport_parsing->incoming_frame_type !=
429 : GRPC_CHTTP2_FRAME_CONTINUATION) {
430 0 : gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
431 0 : transport_parsing->incoming_frame_type);
432 0 : return 0;
433 : }
434 208 : if (transport_parsing->expect_continuation_stream_id !=
435 104 : transport_parsing->incoming_stream_id) {
436 0 : gpr_log(GPR_ERROR,
437 : "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
438 : "grpc_chttp2_stream %08x",
439 : transport_parsing->expect_continuation_stream_id,
440 : transport_parsing->incoming_stream_id);
441 0 : return 0;
442 : }
443 104 : return init_header_frame_parser(transport_parsing, 1);
444 : }
445 9009139 : switch (transport_parsing->incoming_frame_type) {
446 : case GRPC_CHTTP2_FRAME_DATA:
447 3018251 : return init_data_frame_parser(transport_parsing);
448 : case GRPC_CHTTP2_FRAME_HEADER:
449 4102618 : return init_header_frame_parser(transport_parsing, 0);
450 : case GRPC_CHTTP2_FRAME_CONTINUATION:
451 0 : gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
452 0 : return 0;
453 : case GRPC_CHTTP2_FRAME_RST_STREAM:
454 278023 : return init_rst_stream_parser(transport_parsing);
455 : case GRPC_CHTTP2_FRAME_SETTINGS:
456 7262 : return init_settings_frame_parser(transport_parsing);
457 : case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
458 1602756 : return init_window_update_frame_parser(transport_parsing);
459 : case GRPC_CHTTP2_FRAME_PING:
460 0 : return init_ping_parser(transport_parsing);
461 : case GRPC_CHTTP2_FRAME_GOAWAY:
462 229 : return init_goaway_parser(transport_parsing);
463 : default:
464 0 : gpr_log(GPR_ERROR, "Unknown frame type %02x",
465 0 : transport_parsing->incoming_frame_type);
466 0 : return init_skip_frame_parser(transport_parsing, 0);
467 : }
468 : }
469 :
470 274706 : static grpc_chttp2_parse_error skip_parser(
471 : grpc_exec_ctx *exec_ctx, void *parser,
472 : grpc_chttp2_transport_parsing *transport_parsing,
473 : grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
474 274706 : return GRPC_CHTTP2_PARSE_OK;
475 : }
476 :
477 186 : static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
478 :
479 272599 : static int init_skip_frame_parser(
480 : grpc_chttp2_transport_parsing *transport_parsing, int is_header) {
481 272599 : if (is_header) {
482 42 : gpr_uint8 is_eoh = transport_parsing->expect_continuation_stream_id != 0;
483 42 : transport_parsing->parser = grpc_chttp2_header_parser_parse;
484 42 : transport_parsing->parser_data = &transport_parsing->hpack_parser;
485 42 : transport_parsing->hpack_parser.on_header = skip_header;
486 42 : transport_parsing->hpack_parser.on_header_user_data = NULL;
487 42 : transport_parsing->hpack_parser.is_boundary = is_eoh;
488 42 : transport_parsing->hpack_parser.is_eof =
489 42 : (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
490 : } else {
491 272557 : transport_parsing->parser = skip_parser;
492 : }
493 272599 : return 1;
494 : }
495 :
496 9 : void grpc_chttp2_parsing_become_skip_parser(
497 : grpc_chttp2_transport_parsing *transport_parsing) {
498 9 : init_skip_frame_parser(
499 : transport_parsing,
500 9 : transport_parsing->parser == grpc_chttp2_header_parser_parse);
501 9 : }
502 :
503 3018587 : static grpc_chttp2_parse_error update_incoming_window(
504 : grpc_chttp2_transport_parsing *transport_parsing,
505 : grpc_chttp2_stream_parsing *stream_parsing) {
506 6037174 : if (transport_parsing->incoming_frame_size >
507 3018587 : transport_parsing->incoming_window) {
508 0 : gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
509 : transport_parsing->incoming_frame_size,
510 : transport_parsing->incoming_window);
511 0 : return GRPC_CHTTP2_CONNECTION_ERROR;
512 : }
513 :
514 6037174 : if (transport_parsing->incoming_frame_size >
515 3018587 : stream_parsing->incoming_window) {
516 0 : gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %d",
517 : transport_parsing->incoming_frame_size,
518 : stream_parsing->incoming_window);
519 0 : return GRPC_CHTTP2_CONNECTION_ERROR;
520 : }
521 :
522 3018587 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
523 : "data", transport_parsing, incoming_window,
524 : -(gpr_int64)transport_parsing->incoming_frame_size);
525 3018594 : GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT("data", transport_parsing,
526 : incoming_window_delta,
527 : transport_parsing->incoming_frame_size);
528 3018594 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM(
529 : "data", transport_parsing, stream_parsing, incoming_window,
530 : -(gpr_int64)transport_parsing->incoming_frame_size);
531 3018594 : GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("data", transport_parsing, stream_parsing,
532 : incoming_window_delta,
533 : transport_parsing->incoming_frame_size);
534 :
535 3018594 : transport_parsing->incoming_window -= transport_parsing->incoming_frame_size;
536 6037188 : transport_parsing->incoming_window_delta +=
537 3018594 : transport_parsing->incoming_frame_size;
538 3018594 : stream_parsing->incoming_window -= transport_parsing->incoming_frame_size;
539 6037188 : stream_parsing->incoming_window_delta +=
540 3018594 : transport_parsing->incoming_frame_size;
541 3018594 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
542 :
543 3018552 : return GRPC_CHTTP2_PARSE_OK;
544 : }
545 :
546 3018387 : static int init_data_frame_parser(
547 : grpc_chttp2_transport_parsing *transport_parsing) {
548 3018387 : grpc_chttp2_stream_parsing *stream_parsing =
549 3018387 : grpc_chttp2_parsing_lookup_stream(transport_parsing,
550 : transport_parsing->incoming_stream_id);
551 3018860 : grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
552 3018860 : if (!stream_parsing || stream_parsing->received_close)
553 258 : return init_skip_frame_parser(transport_parsing, 0);
554 3018602 : if (err == GRPC_CHTTP2_PARSE_OK) {
555 3018599 : err = update_incoming_window(transport_parsing, stream_parsing);
556 : }
557 3018534 : if (err == GRPC_CHTTP2_PARSE_OK) {
558 3018539 : err = grpc_chttp2_data_parser_begin_frame(
559 3018539 : &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
560 : }
561 3018510 : switch (err) {
562 : case GRPC_CHTTP2_PARSE_OK:
563 3018510 : transport_parsing->incoming_stream = stream_parsing;
564 3018510 : transport_parsing->parser = grpc_chttp2_data_parser_parse;
565 3018510 : transport_parsing->parser_data = &stream_parsing->data_parser;
566 3018510 : return 1;
567 : case GRPC_CHTTP2_STREAM_ERROR:
568 0 : stream_parsing->received_close = 1;
569 0 : stream_parsing->saw_rst_stream = 1;
570 0 : stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
571 0 : gpr_slice_buffer_add(
572 : &transport_parsing->qbuf,
573 : grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
574 : GRPC_CHTTP2_PROTOCOL_ERROR));
575 0 : return init_skip_frame_parser(transport_parsing, 0);
576 : case GRPC_CHTTP2_CONNECTION_ERROR:
577 0 : return 0;
578 : }
579 0 : GPR_UNREACHABLE_CODE(return 0);
580 : }
581 :
582 3083 : static void free_timeout(void *p) { gpr_free(p); }
583 :
584 18836607 : static void on_header(void *tp, grpc_mdelem *md) {
585 18836607 : grpc_chttp2_transport_parsing *transport_parsing = tp;
586 18836607 : grpc_chttp2_stream_parsing *stream_parsing =
587 : transport_parsing->incoming_stream;
588 :
589 18836607 : GPR_ASSERT(stream_parsing);
590 :
591 18836607 : GRPC_CHTTP2_IF_TRACING(gpr_log(
592 : GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
593 : transport_parsing->is_client ? "CLI" : "SVR",
594 : grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
595 :
596 18836675 : if (md->key == transport_parsing->str_grpc_timeout) {
597 5187 : gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
598 5187 : if (!cached_timeout) {
599 : /* not already parsed: parse it now, and store the result away */
600 3083 : cached_timeout = gpr_malloc(sizeof(gpr_timespec));
601 3083 : if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
602 : cached_timeout)) {
603 0 : gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
604 : grpc_mdstr_as_c_string(md->value));
605 0 : *cached_timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
606 : }
607 3083 : grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
608 : }
609 5187 : grpc_chttp2_incoming_metadata_buffer_set_deadline(
610 : &stream_parsing->incoming_metadata,
611 : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
612 5187 : GRPC_MDELEM_UNREF(md);
613 : } else {
614 18831488 : grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
615 : md);
616 : }
617 :
618 18814600 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
619 18811831 : }
620 :
621 4103524 : static int init_header_frame_parser(
622 : grpc_chttp2_transport_parsing *transport_parsing, int is_continuation) {
623 8207048 : gpr_uint8 is_eoh = (transport_parsing->incoming_frame_flags &
624 4103524 : GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
625 4103524 : int via_accept = 0;
626 : grpc_chttp2_stream_parsing *stream_parsing;
627 :
628 4103524 : if (is_eoh) {
629 4103420 : transport_parsing->expect_continuation_stream_id = 0;
630 : } else {
631 104 : transport_parsing->expect_continuation_stream_id =
632 104 : transport_parsing->incoming_stream_id;
633 : }
634 :
635 4103524 : if (!is_continuation) {
636 8207080 : transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
637 4103540 : GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
638 : }
639 :
640 : /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
641 4103524 : stream_parsing = grpc_chttp2_parsing_lookup_stream(
642 : transport_parsing, transport_parsing->incoming_stream_id);
643 4106891 : if (stream_parsing == NULL) {
644 1301816 : if (is_continuation) {
645 0 : gpr_log(GPR_ERROR,
646 : "grpc_chttp2_stream disbanded before CONTINUATION received");
647 0 : return init_skip_frame_parser(transport_parsing, 1);
648 : }
649 1301816 : if (transport_parsing->is_client) {
650 84 : if ((transport_parsing->incoming_stream_id & 1) &&
651 42 : transport_parsing->incoming_stream_id <
652 42 : transport_parsing->next_stream_id) {
653 : /* this is an old (probably cancelled) grpc_chttp2_stream */
654 : } else {
655 0 : gpr_log(GPR_ERROR,
656 : "ignoring new grpc_chttp2_stream creation on client");
657 : }
658 42 : return init_skip_frame_parser(transport_parsing, 1);
659 2603548 : } else if (transport_parsing->last_incoming_stream_id >
660 1301774 : transport_parsing->incoming_stream_id) {
661 0 : gpr_log(GPR_ERROR,
662 : "ignoring out of order new grpc_chttp2_stream request on server; "
663 : "last grpc_chttp2_stream "
664 : "id=%d, new grpc_chttp2_stream id=%d",
665 : transport_parsing->last_incoming_stream_id,
666 : transport_parsing->incoming_stream_id);
667 0 : return init_skip_frame_parser(transport_parsing, 1);
668 1301774 : } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
669 0 : gpr_log(GPR_ERROR,
670 : "ignoring grpc_chttp2_stream with non-client generated index %d",
671 : transport_parsing->incoming_stream_id);
672 0 : return init_skip_frame_parser(transport_parsing, 1);
673 : }
674 1301757 : stream_parsing = transport_parsing->incoming_stream =
675 1301774 : grpc_chttp2_parsing_accept_stream(
676 : transport_parsing, transport_parsing->incoming_stream_id);
677 1301757 : if (stream_parsing == NULL) {
678 0 : gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
679 0 : return init_skip_frame_parser(transport_parsing, 1);
680 : }
681 1301757 : via_accept = 1;
682 : } else {
683 2805075 : transport_parsing->incoming_stream = stream_parsing;
684 : }
685 4106832 : GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
686 4104247 : if (stream_parsing->received_close) {
687 0 : gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
688 0 : transport_parsing->incoming_stream = NULL;
689 0 : return init_skip_frame_parser(transport_parsing, 1);
690 : }
691 4104247 : transport_parsing->parser = grpc_chttp2_header_parser_parse;
692 4104247 : transport_parsing->parser_data = &transport_parsing->hpack_parser;
693 4104247 : transport_parsing->hpack_parser.on_header = on_header;
694 4104247 : transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
695 4104247 : transport_parsing->hpack_parser.is_boundary = is_eoh;
696 4104247 : transport_parsing->hpack_parser.is_eof =
697 4104247 : (gpr_uint8)(is_eoh ? transport_parsing->header_eof : 0);
698 4104247 : if (!is_continuation && (transport_parsing->incoming_frame_flags &
699 : GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
700 0 : grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
701 : }
702 4104298 : return 1;
703 : }
704 :
705 1602879 : static int init_window_update_frame_parser(
706 : grpc_chttp2_transport_parsing *transport_parsing) {
707 1602879 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
708 : &transport_parsing->simple.window_update,
709 : transport_parsing->incoming_frame_size,
710 1602879 : transport_parsing->incoming_frame_flags);
711 1602862 : if (transport_parsing->incoming_stream_id) {
712 1598768 : transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
713 : transport_parsing, transport_parsing->incoming_stream_id);
714 : }
715 1602942 : transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
716 1602942 : transport_parsing->parser_data = &transport_parsing->simple.window_update;
717 1602942 : return ok;
718 : }
719 :
720 0 : static int init_ping_parser(grpc_chttp2_transport_parsing *transport_parsing) {
721 0 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
722 : &transport_parsing->simple.ping,
723 : transport_parsing->incoming_frame_size,
724 0 : transport_parsing->incoming_frame_flags);
725 0 : transport_parsing->parser = grpc_chttp2_ping_parser_parse;
726 0 : transport_parsing->parser_data = &transport_parsing->simple.ping;
727 0 : return ok;
728 : }
729 :
730 278024 : static int init_rst_stream_parser(
731 : grpc_chttp2_transport_parsing *transport_parsing) {
732 278024 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
733 : &transport_parsing->simple.rst_stream,
734 : transport_parsing->incoming_frame_size,
735 278024 : transport_parsing->incoming_frame_flags);
736 278025 : transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
737 : transport_parsing, transport_parsing->incoming_stream_id);
738 278024 : if (!transport_parsing->incoming_stream) {
739 272291 : return init_skip_frame_parser(transport_parsing, 0);
740 : }
741 5733 : transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
742 5733 : transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
743 5733 : return ok;
744 : }
745 :
746 229 : static int init_goaway_parser(
747 : grpc_chttp2_transport_parsing *transport_parsing) {
748 229 : int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
749 : &transport_parsing->goaway_parser,
750 : transport_parsing->incoming_frame_size,
751 229 : transport_parsing->incoming_frame_flags);
752 229 : transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
753 229 : transport_parsing->parser_data = &transport_parsing->goaway_parser;
754 229 : return ok;
755 : }
756 :
757 7261 : static int init_settings_frame_parser(
758 : grpc_chttp2_transport_parsing *transport_parsing) {
759 : int ok;
760 :
761 7261 : if (transport_parsing->incoming_stream_id != 0) {
762 2 : gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
763 : transport_parsing->incoming_stream_id);
764 2 : return 0;
765 : }
766 :
767 7259 : ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
768 : &transport_parsing->simple.settings,
769 : transport_parsing->incoming_frame_size,
770 7259 : transport_parsing->incoming_frame_flags,
771 7259 : transport_parsing->settings);
772 7260 : if (!ok) {
773 5 : return 0;
774 : }
775 7255 : if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
776 3577 : transport_parsing->settings_ack_received = 1;
777 : }
778 7255 : transport_parsing->parser = grpc_chttp2_settings_parser_parse;
779 7255 : transport_parsing->parser_data = &transport_parsing->simple.settings;
780 7255 : return ok;
781 : }
782 :
783 : /*
784 : static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
785 : return window + window_update < MAX_WINDOW;
786 : }
787 : */
788 :
789 13202600 : static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
790 : grpc_chttp2_transport_parsing *transport_parsing,
791 : gpr_slice slice, int is_last) {
792 13202600 : grpc_chttp2_stream_parsing *stream_parsing =
793 : transport_parsing->incoming_stream;
794 13202600 : switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
795 : transport_parsing, stream_parsing, slice,
796 : is_last)) {
797 : case GRPC_CHTTP2_PARSE_OK:
798 13200147 : if (stream_parsing) {
799 12912463 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
800 : stream_parsing);
801 : }
802 13204240 : return 1;
803 : case GRPC_CHTTP2_STREAM_ERROR:
804 0 : grpc_chttp2_parsing_become_skip_parser(transport_parsing);
805 0 : if (stream_parsing) {
806 0 : stream_parsing->saw_rst_stream = 1;
807 0 : stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
808 0 : gpr_slice_buffer_add(
809 : &transport_parsing->qbuf,
810 : grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
811 : GRPC_CHTTP2_PROTOCOL_ERROR));
812 : }
813 0 : return 1;
814 : case GRPC_CHTTP2_CONNECTION_ERROR:
815 0 : return 0;
816 : }
817 0 : GPR_UNREACHABLE_CODE(return 0);
818 : }
|