blob: 9ee52f63f29b31076aeefb3e3a5b1350ae458da3 [file] [log] [blame]
Craig Tillerd8df50c2015-06-12 07:53:56 -07001/*
2 *
Craig Tiller0cb803d2016-03-02 22:17:24 -08003 * Copyright 2015-2016, Google Inc.
Craig Tillerd8df50c2015-06-12 07:53:56 -07004 * 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
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/transport/chttp2/internal.h"
Craig Tiller606d8742015-06-15 06:58:50 -070035
36#include <string.h>
37
Craig Tillerb2b42612015-11-20 12:02:17 -080038#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
40#include <grpc/support/string_util.h>
41
Craig Tiller9533d042016-03-25 17:11:06 -070042#include "src/core/lib/profiling/timers.h"
43#include "src/core/lib/transport/chttp2/http2_errors.h"
44#include "src/core/lib/transport/chttp2/status_conversion.h"
45#include "src/core/lib/transport/chttp2/timeout_encoding.h"
46#include "src/core/lib/transport/static_metadata.h"
Craig Tillerd20efd22015-06-12 16:17:09 -070047
Craig Tiller9d35a1f2015-11-02 14:16:12 -080048static int init_frame_parser(grpc_exec_ctx *exec_ctx,
49 grpc_chttp2_transport_parsing *transport_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -070050static int init_header_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -080051 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
52 int is_continuation);
Craig Tillera82950e2015-09-22 12:33:20 -070053static int init_data_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -080054 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -070055static int init_rst_stream_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -080056 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -070057static int init_settings_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -080058 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -070059static int init_window_update_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -080060 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
61static int init_ping_parser(grpc_exec_ctx *exec_ctx,
62 grpc_chttp2_transport_parsing *transport_parsing);
63static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
64 grpc_chttp2_transport_parsing *transport_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -070065static int init_skip_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -080066 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
67 int is_header);
Craig Tillerd20efd22015-06-12 16:17:09 -070068
Craig Tillera82950e2015-09-22 12:33:20 -070069static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
70 grpc_chttp2_transport_parsing *transport_parsing,
71 gpr_slice slice, int is_last);
Craig Tillerd20efd22015-06-12 16:17:09 -070072
Craig Tillera82950e2015-09-22 12:33:20 -070073void grpc_chttp2_prepare_to_read(
74 grpc_chttp2_transport_global *transport_global,
75 grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillercf1e3192015-06-16 14:28:22 -070076 grpc_chttp2_stream_global *stream_global;
77 grpc_chttp2_stream_parsing *stream_parsing;
78
Craig Tiller0ba432d2015-10-09 16:57:11 -070079 GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
Craig Tiller1f41b6b2015-10-09 15:07:02 -070080
Craig Tillercec9eb92015-06-17 17:16:48 -070081 transport_parsing->next_stream_id = transport_global->next_stream_id;
Craig Tiller3c53bb22015-11-10 14:24:36 +000082 transport_parsing->last_sent_max_table_size =
83 transport_global->settings[GRPC_SENT_SETTINGS]
84 [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
Craig Tillercec9eb92015-06-17 17:16:48 -070085
Craig Tillercf1e3192015-06-16 14:28:22 -070086 /* update the parsing view of incoming window */
Craig Tiller9d35a1f2015-11-02 14:16:12 -080087 while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
Craig Tillera82950e2015-09-22 12:33:20 -070088 transport_global, transport_parsing, &stream_global, &stream_parsing)) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -080089 GRPC_CHTTP2_FLOW_MOVE_STREAM("parse", transport_parsing, stream_parsing,
90 incoming_window, stream_global,
91 unannounced_incoming_window_for_parse);
Craig Tillera82950e2015-09-22 12:33:20 -070092 }
Craig Tiller1f41b6b2015-10-09 15:07:02 -070093
Craig Tiller0ba432d2015-10-09 16:57:11 -070094 GPR_TIMER_END("grpc_chttp2_prepare_to_read", 0);
Craig Tillercf1e3192015-06-16 14:28:22 -070095}
Craig Tiller1937b062015-06-16 08:47:38 -070096
Craig Tillera82950e2015-09-22 12:33:20 -070097void grpc_chttp2_publish_reads(
98 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
99 grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tiller606d8742015-06-15 06:58:50 -0700100 grpc_chttp2_stream_global *stream_global;
101 grpc_chttp2_stream_parsing *stream_parsing;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800102 int was_zero;
103 int is_zero;
Craig Tiller606d8742015-06-15 06:58:50 -0700104
Craig Tiller4aa71a12015-06-15 13:00:55 -0700105 /* transport_parsing->last_incoming_stream_id is used as
106 last-grpc_chttp2_stream-id when
Craig Tillerd20efd22015-06-12 16:17:09 -0700107 sending GOAWAY frame.
108 https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
Craig Tiller4aa71a12015-06-15 13:00:55 -0700109 says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream
110 ID. So,
Craig Tillerd20efd22015-06-12 16:17:09 -0700111 since we don't have server pushed streams, client should send
112 GOAWAY last-grpc_chttp2_stream-id=0 in this case. */
Craig Tillera82950e2015-09-22 12:33:20 -0700113 if (!transport_parsing->is_client) {
114 transport_global->last_incoming_stream_id =
115 transport_parsing->incoming_stream_id;
116 }
Craig Tiller606d8742015-06-15 06:58:50 -0700117
Craig Tiller606d8742015-06-15 06:58:50 -0700118 /* update global settings */
Craig Tillera82950e2015-09-22 12:33:20 -0700119 if (transport_parsing->settings_updated) {
120 memcpy(transport_global->settings[GRPC_PEER_SETTINGS],
121 transport_parsing->settings, sizeof(transport_parsing->settings));
122 transport_parsing->settings_updated = 0;
123 }
Craig Tiller606d8742015-06-15 06:58:50 -0700124
125 /* update settings based on ack if received */
Craig Tillera82950e2015-09-22 12:33:20 -0700126 if (transport_parsing->settings_ack_received) {
127 memcpy(transport_global->settings[GRPC_ACKED_SETTINGS],
128 transport_global->settings[GRPC_SENT_SETTINGS],
Craig Tiller7536af02015-12-22 13:49:30 -0800129 GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
Craig Tillera82950e2015-09-22 12:33:20 -0700130 transport_parsing->settings_ack_received = 0;
Craig Tiller027a74c2015-11-10 08:37:46 +0000131 transport_global->sent_local_settings = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700132 }
Craig Tiller606d8742015-06-15 06:58:50 -0700133
134 /* move goaway to the global state if we received one (it will be
135 published later */
Craig Tillera82950e2015-09-22 12:33:20 -0700136 if (transport_parsing->goaway_received) {
137 grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global,
Craig Tiller7536af02015-12-22 13:49:30 -0800138 (uint32_t)transport_parsing->goaway_error,
Craig Tillera82950e2015-09-22 12:33:20 -0700139 transport_parsing->goaway_text);
140 transport_parsing->goaway_text = gpr_empty_slice();
141 transport_parsing->goaway_received = 0;
142 }
Craig Tiller606d8742015-06-15 06:58:50 -0700143
Craig Tiller285b8822015-06-17 15:58:13 -0700144 /* propagate flow control tokens to global state */
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800145 was_zero = transport_global->outgoing_window <= 0;
146 GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window,
147 transport_parsing, outgoing_window);
148 is_zero = transport_global->outgoing_window <= 0;
149 if (was_zero && !is_zero) {
150 while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
151 &stream_global)) {
Craig Tiller0cb803d2016-03-02 22:17:24 -0800152 grpc_chttp2_become_writable(transport_global, stream_global);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800153 }
Craig Tillera82950e2015-09-22 12:33:20 -0700154 }
Craig Tiller285b8822015-06-17 15:58:13 -0700155
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800156 if (transport_parsing->incoming_window <
157 transport_global->connection_window_target * 3 / 4) {
Craig Tiller7536af02015-12-22 13:49:30 -0800158 int64_t announce_bytes = transport_global->connection_window_target -
159 transport_parsing->incoming_window;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800160 GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global,
161 announce_incoming_window, announce_bytes);
162 GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing,
163 incoming_window, announce_bytes);
Craig Tillera82950e2015-09-22 12:33:20 -0700164 }
Craig Tiller285b8822015-06-17 15:58:13 -0700165
Craig Tiller606d8742015-06-15 06:58:50 -0700166 /* for each stream that saw an update, fixup global state */
Craig Tillera82950e2015-09-22 12:33:20 -0700167 while (grpc_chttp2_list_pop_parsing_seen_stream(
168 transport_global, transport_parsing, &stream_global, &stream_parsing)) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800169 if (stream_parsing->seen_error) {
170 stream_global->seen_error = 1;
171 grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
Craig Tillerf73fcd12015-06-16 16:25:26 -0700172 }
Craig Tillera82950e2015-09-22 12:33:20 -0700173
174 /* update outgoing flow control window */
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800175 was_zero = stream_global->outgoing_window <= 0;
176 GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global,
177 outgoing_window, stream_parsing,
178 outgoing_window);
179 is_zero = stream_global->outgoing_window <= 0;
180 if (was_zero && !is_zero) {
Craig Tiller0cb803d2016-03-02 22:17:24 -0800181 grpc_chttp2_become_writable(transport_global, stream_global);
Craig Tillera82950e2015-09-22 12:33:20 -0700182 }
183
Craig Tiller7536af02015-12-22 13:49:30 -0800184 stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800185 stream_global->max_recv_bytes, stream_parsing->received_bytes);
186 stream_parsing->received_bytes = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700187
188 /* publish incoming stream ops */
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800189 if (stream_global->incoming_frames.tail != NULL) {
190 stream_global->incoming_frames.tail->is_tail = 0;
191 }
192 if (stream_parsing->data_parser.incoming_frames.head != NULL) {
193 grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
194 }
195 grpc_chttp2_incoming_frame_queue_merge(
196 &stream_global->incoming_frames,
197 &stream_parsing->data_parser.incoming_frames);
198 if (stream_global->incoming_frames.tail != NULL) {
199 stream_global->incoming_frames.tail->is_tail = 1;
200 }
201
202 if (!stream_global->published_initial_metadata &&
203 stream_parsing->got_metadata_on_parse[0]) {
204 stream_parsing->got_metadata_on_parse[0] = 0;
205 stream_global->published_initial_metadata = 1;
206 GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
207 stream_parsing->metadata_buffer[0],
208 stream_global->received_initial_metadata);
209 grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
210 }
211 if (!stream_global->published_trailing_metadata &&
212 stream_parsing->got_metadata_on_parse[1]) {
213 stream_parsing->got_metadata_on_parse[1] = 0;
214 stream_global->published_trailing_metadata = 1;
215 GPR_SWAP(grpc_chttp2_incoming_metadata_buffer,
216 stream_parsing->metadata_buffer[1],
217 stream_global->received_trailing_metadata);
218 grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
219 }
220
221 if (stream_parsing->saw_rst_stream) {
222 if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
223 grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
224 (grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
225 char *status_details;
226 gpr_slice slice_details;
227 gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
228 stream_parsing->rst_stream_reason);
229 slice_details = gpr_slice_from_copied_string(status_details);
230 gpr_free(status_details);
231 grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
232 status_code, &slice_details);
233 }
234 grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
235 1, 1);
236 }
237
238 if (stream_parsing->received_close) {
239 grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
240 1, 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700241 }
242 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700243}
244
Craig Tillera82950e2015-09-22 12:33:20 -0700245int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
246 grpc_chttp2_transport_parsing *transport_parsing,
247 gpr_slice slice) {
Craig Tiller7536af02015-12-22 13:49:30 -0800248 uint8_t *beg = GPR_SLICE_START_PTR(slice);
249 uint8_t *end = GPR_SLICE_END_PTR(slice);
250 uint8_t *cur = beg;
Craig Tillerd20efd22015-06-12 16:17:09 -0700251
Craig Tillera82950e2015-09-22 12:33:20 -0700252 if (cur == end) return 1;
Craig Tillerd20efd22015-06-12 16:17:09 -0700253
Craig Tillera82950e2015-09-22 12:33:20 -0700254 switch (transport_parsing->deframe_state) {
Craig Tillerab630732015-06-25 11:20:01 -0700255 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:
Craig Tillera82950e2015-09-22 12:33:20 -0700279 while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
280 if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
281 ->deframe_state]) {
282 gpr_log(GPR_INFO,
283 "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
284 "at byte %d",
285 GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
286 ->deframe_state],
Craig Tiller7536af02015-12-22 13:49:30 -0800287 (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
Craig Tillera82950e2015-09-22 12:33:20 -0700288 [transport_parsing->deframe_state],
289 *cur, (int)*cur, transport_parsing->deframe_state);
290 return 0;
291 }
292 ++cur;
293 ++transport_parsing->deframe_state;
294 }
295 if (cur == end) {
296 return 1;
297 }
298 /* fallthrough */
Craig Tillerd20efd22015-06-12 16:17:09 -0700299 dts_fh_0:
Craig Tillerab630732015-06-25 11:20:01 -0700300 case GRPC_DTS_FH_0:
Craig Tillera82950e2015-09-22 12:33:20 -0700301 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800302 transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
Craig Tillera82950e2015-09-22 12:33:20 -0700303 if (++cur == end) {
304 transport_parsing->deframe_state = GRPC_DTS_FH_1;
305 return 1;
306 }
307 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700308 case GRPC_DTS_FH_1:
Craig Tillera82950e2015-09-22 12:33:20 -0700309 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800310 transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
Craig Tillera82950e2015-09-22 12:33:20 -0700311 if (++cur == end) {
312 transport_parsing->deframe_state = GRPC_DTS_FH_2;
313 return 1;
314 }
315 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700316 case GRPC_DTS_FH_2:
Craig Tillera82950e2015-09-22 12:33:20 -0700317 GPR_ASSERT(cur < end);
Craig Tillerd20efd22015-06-12 16:17:09 -0700318 transport_parsing->incoming_frame_size |= *cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700319 if (++cur == end) {
320 transport_parsing->deframe_state = GRPC_DTS_FH_3;
321 return 1;
322 }
323 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700324 case GRPC_DTS_FH_3:
Craig Tillera82950e2015-09-22 12:33:20 -0700325 GPR_ASSERT(cur < end);
Craig Tillerd20efd22015-06-12 16:17:09 -0700326 transport_parsing->incoming_frame_type = *cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700327 if (++cur == end) {
328 transport_parsing->deframe_state = GRPC_DTS_FH_4;
329 return 1;
330 }
331 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700332 case GRPC_DTS_FH_4:
Craig Tillera82950e2015-09-22 12:33:20 -0700333 GPR_ASSERT(cur < end);
Craig Tillerd20efd22015-06-12 16:17:09 -0700334 transport_parsing->incoming_frame_flags = *cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700335 if (++cur == end) {
336 transport_parsing->deframe_state = GRPC_DTS_FH_5;
337 return 1;
338 }
339 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700340 case GRPC_DTS_FH_5:
Craig Tillera82950e2015-09-22 12:33:20 -0700341 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800342 transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
Craig Tillera82950e2015-09-22 12:33:20 -0700343 if (++cur == end) {
344 transport_parsing->deframe_state = GRPC_DTS_FH_6;
345 return 1;
346 }
347 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700348 case GRPC_DTS_FH_6:
Craig Tillera82950e2015-09-22 12:33:20 -0700349 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800350 transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
Craig Tillera82950e2015-09-22 12:33:20 -0700351 if (++cur == end) {
352 transport_parsing->deframe_state = GRPC_DTS_FH_7;
353 return 1;
354 }
355 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700356 case GRPC_DTS_FH_7:
Craig Tillera82950e2015-09-22 12:33:20 -0700357 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800358 transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
Craig Tillera82950e2015-09-22 12:33:20 -0700359 if (++cur == end) {
360 transport_parsing->deframe_state = GRPC_DTS_FH_8;
361 return 1;
362 }
363 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700364 case GRPC_DTS_FH_8:
Craig Tillera82950e2015-09-22 12:33:20 -0700365 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800366 transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
Craig Tillerab630732015-06-25 11:20:01 -0700367 transport_parsing->deframe_state = GRPC_DTS_FRAME;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800368 if (!init_frame_parser(exec_ctx, transport_parsing)) {
Craig Tillera82950e2015-09-22 12:33:20 -0700369 return 0;
370 }
371 if (transport_parsing->incoming_stream_id) {
372 transport_parsing->last_incoming_stream_id =
373 transport_parsing->incoming_stream_id;
374 }
375 if (transport_parsing->incoming_frame_size == 0) {
376 if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
377 1)) {
378 return 0;
379 }
380 transport_parsing->incoming_stream = NULL;
381 if (++cur == end) {
382 transport_parsing->deframe_state = GRPC_DTS_FH_0;
383 return 1;
384 }
385 goto dts_fh_0; /* loop */
386 }
387 if (++cur == end) {
388 return 1;
389 }
390 /* fallthrough */
Craig Tillerab630732015-06-25 11:20:01 -0700391 case GRPC_DTS_FRAME:
Craig Tillera82950e2015-09-22 12:33:20 -0700392 GPR_ASSERT(cur < end);
Craig Tiller7536af02015-12-22 13:49:30 -0800393 if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
Craig Tillera82950e2015-09-22 12:33:20 -0700394 if (!parse_frame_slice(exec_ctx, transport_parsing,
395 gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
396 (size_t)(end - beg)),
397 1)) {
398 return 0;
399 }
400 transport_parsing->deframe_state = GRPC_DTS_FH_0;
401 transport_parsing->incoming_stream = NULL;
402 return 1;
Craig Tiller7536af02015-12-22 13:49:30 -0800403 } else if ((uint32_t)(end - cur) >
Craig Tillera82950e2015-09-22 12:33:20 -0700404 transport_parsing->incoming_frame_size) {
405 size_t cur_offset = (size_t)(cur - beg);
406 if (!parse_frame_slice(
407 exec_ctx, transport_parsing,
408 gpr_slice_sub_no_ref(
409 slice, cur_offset,
410 cur_offset + transport_parsing->incoming_frame_size),
411 1)) {
412 return 0;
413 }
414 cur += transport_parsing->incoming_frame_size;
415 transport_parsing->incoming_stream = NULL;
416 goto dts_fh_0; /* loop */
417 } else {
418 if (!parse_frame_slice(exec_ctx, transport_parsing,
419 gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
420 (size_t)(end - beg)),
421 0)) {
422 return 0;
423 }
Craig Tiller7536af02015-12-22 13:49:30 -0800424 transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
Craig Tillera82950e2015-09-22 12:33:20 -0700425 return 1;
426 }
yang-gb063c872015-10-07 11:40:13 -0700427 GPR_UNREACHABLE_CODE(return 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700428 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700429
yang-gb063c872015-10-07 11:40:13 -0700430 GPR_UNREACHABLE_CODE(return 0);
Craig Tillerd20efd22015-06-12 16:17:09 -0700431}
432
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800433static int init_frame_parser(grpc_exec_ctx *exec_ctx,
434 grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700435 if (transport_parsing->expect_continuation_stream_id != 0) {
436 if (transport_parsing->incoming_frame_type !=
437 GRPC_CHTTP2_FRAME_CONTINUATION) {
438 gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
439 transport_parsing->incoming_frame_type);
440 return 0;
Craig Tillerd20efd22015-06-12 16:17:09 -0700441 }
Craig Tillera82950e2015-09-22 12:33:20 -0700442 if (transport_parsing->expect_continuation_stream_id !=
443 transport_parsing->incoming_stream_id) {
444 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 return 0;
450 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800451 return init_header_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700452 }
453 switch (transport_parsing->incoming_frame_type) {
Craig Tillerd20efd22015-06-12 16:17:09 -0700454 case GRPC_CHTTP2_FRAME_DATA:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800455 return init_data_frame_parser(exec_ctx, transport_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700456 case GRPC_CHTTP2_FRAME_HEADER:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800457 return init_header_frame_parser(exec_ctx, transport_parsing, 0);
Craig Tillerd20efd22015-06-12 16:17:09 -0700458 case GRPC_CHTTP2_FRAME_CONTINUATION:
Craig Tillera82950e2015-09-22 12:33:20 -0700459 gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
Craig Tillerd20efd22015-06-12 16:17:09 -0700460 return 0;
461 case GRPC_CHTTP2_FRAME_RST_STREAM:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800462 return init_rst_stream_parser(exec_ctx, transport_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700463 case GRPC_CHTTP2_FRAME_SETTINGS:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800464 return init_settings_frame_parser(exec_ctx, transport_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700465 case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800466 return init_window_update_frame_parser(exec_ctx, transport_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700467 case GRPC_CHTTP2_FRAME_PING:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800468 return init_ping_parser(exec_ctx, transport_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700469 case GRPC_CHTTP2_FRAME_GOAWAY:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800470 return init_goaway_parser(exec_ctx, transport_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700471 default:
Craig Tillera82950e2015-09-22 12:33:20 -0700472 gpr_log(GPR_ERROR, "Unknown frame type %02x",
473 transport_parsing->incoming_frame_type);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800474 return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700475 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700476}
477
Craig Tillera82950e2015-09-22 12:33:20 -0700478static 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) {
Craig Tillerd20efd22015-06-12 16:17:09 -0700482 return GRPC_CHTTP2_PARSE_OK;
483}
484
Craig Tillera82950e2015-09-22 12:33:20 -0700485static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
Craig Tillerd20efd22015-06-12 16:17:09 -0700486
Craig Tillera82950e2015-09-22 12:33:20 -0700487static int init_skip_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800488 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
489 int is_header) {
Craig Tillera82950e2015-09-22 12:33:20 -0700490 if (is_header) {
Craig Tiller7536af02015-12-22 13:49:30 -0800491 uint8_t is_eoh = transport_parsing->expect_continuation_stream_id != 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700492 transport_parsing->parser = grpc_chttp2_header_parser_parse;
493 transport_parsing->parser_data = &transport_parsing->hpack_parser;
494 transport_parsing->hpack_parser.on_header = skip_header;
495 transport_parsing->hpack_parser.on_header_user_data = NULL;
496 transport_parsing->hpack_parser.is_boundary = is_eoh;
497 transport_parsing->hpack_parser.is_eof =
Craig Tiller7536af02015-12-22 13:49:30 -0800498 (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700499 } else {
500 transport_parsing->parser = skip_parser;
501 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700502 return 1;
503}
504
Craig Tillera82950e2015-09-22 12:33:20 -0700505void grpc_chttp2_parsing_become_skip_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800506 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700507 init_skip_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800508 exec_ctx, transport_parsing,
Craig Tillera82950e2015-09-22 12:33:20 -0700509 transport_parsing->parser == grpc_chttp2_header_parser_parse);
Craig Tillerd20efd22015-06-12 16:17:09 -0700510}
511
Craig Tillera82950e2015-09-22 12:33:20 -0700512static grpc_chttp2_parse_error update_incoming_window(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800513 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
Craig Tillera82950e2015-09-22 12:33:20 -0700514 grpc_chttp2_stream_parsing *stream_parsing) {
Craig Tiller7536af02015-12-22 13:49:30 -0800515 uint32_t incoming_frame_size = transport_parsing->incoming_frame_size;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800516 if (incoming_frame_size > transport_parsing->incoming_window) {
Craig Tillera82950e2015-09-22 12:33:20 -0700517 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 return GRPC_CHTTP2_CONNECTION_ERROR;
521 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700522
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800523 if (incoming_frame_size > stream_parsing->incoming_window) {
Craig Tillera82950e2015-09-22 12:33:20 -0700524 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 return GRPC_CHTTP2_CONNECTION_ERROR;
528 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700529
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800530 GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
531 incoming_frame_size);
532 GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", transport_parsing, stream_parsing,
533 incoming_window, incoming_frame_size);
534 stream_parsing->received_bytes += incoming_frame_size;
Craig Tiller285b8822015-06-17 15:58:13 -0700535
Craig Tillera82950e2015-09-22 12:33:20 -0700536 grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
Craig Tillerd20efd22015-06-12 16:17:09 -0700537
538 return GRPC_CHTTP2_PARSE_OK;
539}
540
Craig Tillera82950e2015-09-22 12:33:20 -0700541static int init_data_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800542 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700543 grpc_chttp2_stream_parsing *stream_parsing =
544 grpc_chttp2_parsing_lookup_stream(transport_parsing,
545 transport_parsing->incoming_stream_id);
Craig Tillerd20efd22015-06-12 16:17:09 -0700546 grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
Craig Tiller4aa71a12015-06-15 13:00:55 -0700547 if (!stream_parsing || stream_parsing->received_close)
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800548 return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700549 if (err == GRPC_CHTTP2_PARSE_OK) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800550 err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -0700551 }
552 if (err == GRPC_CHTTP2_PARSE_OK) {
553 err = grpc_chttp2_data_parser_begin_frame(
554 &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
555 }
556 switch (err) {
Craig Tillerd20efd22015-06-12 16:17:09 -0700557 case GRPC_CHTTP2_PARSE_OK:
558 transport_parsing->incoming_stream = stream_parsing;
559 transport_parsing->parser = grpc_chttp2_data_parser_parse;
560 transport_parsing->parser_data = &stream_parsing->data_parser;
561 return 1;
562 case GRPC_CHTTP2_STREAM_ERROR:
563 stream_parsing->received_close = 1;
Craig Tiller5dc3b302015-06-15 16:06:50 -0700564 stream_parsing->saw_rst_stream = 1;
565 stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
Craig Tillera82950e2015-09-22 12:33:20 -0700566 gpr_slice_buffer_add(
567 &transport_parsing->qbuf,
568 grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
569 GRPC_CHTTP2_PROTOCOL_ERROR));
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800570 return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
Craig Tillerd20efd22015-06-12 16:17:09 -0700571 case GRPC_CHTTP2_CONNECTION_ERROR:
572 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700573 }
yang-gb063c872015-10-07 11:40:13 -0700574 GPR_UNREACHABLE_CODE(return 0);
Craig Tillerd20efd22015-06-12 16:17:09 -0700575}
576
Craig Tillera82950e2015-09-22 12:33:20 -0700577static void free_timeout(void *p) { gpr_free(p); }
Craig Tillerd20efd22015-06-12 16:17:09 -0700578
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800579static void on_initial_header(void *tp, grpc_mdelem *md) {
Craig Tiller45724b32015-09-22 10:42:19 -0700580 grpc_chttp2_transport_parsing *transport_parsing = tp;
Craig Tillera82950e2015-09-22 12:33:20 -0700581 grpc_chttp2_stream_parsing *stream_parsing =
582 transport_parsing->incoming_stream;
Craig Tiller45724b32015-09-22 10:42:19 -0700583
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800584 GPR_TIMER_BEGIN("on_initial_header", 0);
585
Craig Tillera82950e2015-09-22 12:33:20 -0700586 GPR_ASSERT(stream_parsing);
Craig Tiller45724b32015-09-22 10:42:19 -0700587
Craig Tillera82950e2015-09-22 12:33:20 -0700588 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)));
Craig Tiller45724b32015-09-22 10:42:19 -0700592
Craig Tillerb2b42612015-11-20 12:02:17 -0800593 if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800594 /* TODO(ctiller): check for a status like " 0" */
595 stream_parsing->seen_error = 1;
596 }
597
Craig Tillerb2b42612015-11-20 12:02:17 -0800598 if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
Craig Tillera82950e2015-09-22 12:33:20 -0700599 gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
600 if (!cached_timeout) {
601 /* not already parsed: parse it now, and store the result away */
602 cached_timeout = gpr_malloc(sizeof(gpr_timespec));
603 if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
604 cached_timeout)) {
605 gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
606 grpc_mdstr_as_c_string(md->value));
Craig Tiller25fd5712015-12-09 08:58:47 -0800607 *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
Craig Tillera82950e2015-09-22 12:33:20 -0700608 }
609 grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
Craig Tiller45724b32015-09-22 10:42:19 -0700610 }
Craig Tillera82950e2015-09-22 12:33:20 -0700611 grpc_chttp2_incoming_metadata_buffer_set_deadline(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800612 &stream_parsing->metadata_buffer[0],
Craig Tillera82950e2015-09-22 12:33:20 -0700613 gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
614 GRPC_MDELEM_UNREF(md);
615 } else {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800616 grpc_chttp2_incoming_metadata_buffer_add(
617 &stream_parsing->metadata_buffer[0], md);
Craig Tillera82950e2015-09-22 12:33:20 -0700618 }
Craig Tiller45724b32015-09-22 10:42:19 -0700619
Craig Tillera82950e2015-09-22 12:33:20 -0700620 grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800621
622 GPR_TIMER_END("on_initial_header", 0);
623}
624
625static void on_trailing_header(void *tp, grpc_mdelem *md) {
626 grpc_chttp2_transport_parsing *transport_parsing = tp;
627 grpc_chttp2_stream_parsing *stream_parsing =
628 transport_parsing->incoming_stream;
629
630 GPR_TIMER_BEGIN("on_trailing_header", 0);
631
632 GPR_ASSERT(stream_parsing);
633
634 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
Craig Tillerb2b42612015-11-20 12:02:17 -0800639 if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800640 /* TODO(ctiller): check for a status like " 0" */
641 stream_parsing->seen_error = 1;
642 }
643
644 grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->metadata_buffer[1],
645 md);
646
647 grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
648
649 GPR_TIMER_END("on_trailing_header", 0);
Craig Tiller45724b32015-09-22 10:42:19 -0700650}
651
Craig Tillera82950e2015-09-22 12:33:20 -0700652static int init_header_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800653 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
654 int is_continuation) {
Craig Tiller7536af02015-12-22 13:49:30 -0800655 uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
656 GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
Craig Tillerb951df12015-06-18 15:46:58 -0700657 int via_accept = 0;
Craig Tillerd20efd22015-06-12 16:17:09 -0700658 grpc_chttp2_stream_parsing *stream_parsing;
659
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800660 /* TODO(ctiller): when to increment header_frames_received? */
661
Craig Tillera82950e2015-09-22 12:33:20 -0700662 if (is_eoh) {
663 transport_parsing->expect_continuation_stream_id = 0;
664 } else {
665 transport_parsing->expect_continuation_stream_id =
666 transport_parsing->incoming_stream_id;
667 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700668
Craig Tillera82950e2015-09-22 12:33:20 -0700669 if (!is_continuation) {
670 transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
671 GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
672 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700673
674 /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
Craig Tillera82950e2015-09-22 12:33:20 -0700675 stream_parsing = grpc_chttp2_parsing_lookup_stream(
676 transport_parsing, transport_parsing->incoming_stream_id);
677 if (stream_parsing == NULL) {
678 if (is_continuation) {
679 gpr_log(GPR_ERROR,
680 "grpc_chttp2_stream disbanded before CONTINUATION received");
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800681 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillerd20efd22015-06-12 16:17:09 -0700682 }
Craig Tillera82950e2015-09-22 12:33:20 -0700683 if (transport_parsing->is_client) {
684 if ((transport_parsing->incoming_stream_id & 1) &&
685 transport_parsing->incoming_stream_id <
686 transport_parsing->next_stream_id) {
687 /* this is an old (probably cancelled) grpc_chttp2_stream */
688 } else {
689 gpr_log(GPR_ERROR,
690 "ignoring new grpc_chttp2_stream creation on client");
691 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800692 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700693 } else if (transport_parsing->last_incoming_stream_id >
694 transport_parsing->incoming_stream_id) {
695 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);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800701 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700702 } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
703 gpr_log(GPR_ERROR,
704 "ignoring grpc_chttp2_stream with non-client generated index %d",
705 transport_parsing->incoming_stream_id);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800706 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillerd20efd22015-06-12 16:17:09 -0700707 }
Craig Tillera82950e2015-09-22 12:33:20 -0700708 stream_parsing = transport_parsing->incoming_stream =
709 grpc_chttp2_parsing_accept_stream(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800710 exec_ctx, transport_parsing, transport_parsing->incoming_stream_id);
Craig Tillera82950e2015-09-22 12:33:20 -0700711 if (stream_parsing == NULL) {
712 gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800713 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillerd20efd22015-06-12 16:17:09 -0700714 }
Craig Tillera82950e2015-09-22 12:33:20 -0700715 via_accept = 1;
716 } else {
717 transport_parsing->incoming_stream = stream_parsing;
718 }
719 GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
720 if (stream_parsing->received_close) {
721 gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
722 transport_parsing->incoming_stream = NULL;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800723 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700724 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700725 transport_parsing->parser = grpc_chttp2_header_parser_parse;
726 transport_parsing->parser_data = &transport_parsing->hpack_parser;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800727 switch (stream_parsing->header_frames_received) {
728 case 0:
729 transport_parsing->hpack_parser.on_header = on_initial_header;
730 break;
731 case 1:
732 transport_parsing->hpack_parser.on_header = on_trailing_header;
733 break;
734 case 2:
735 gpr_log(GPR_ERROR, "too many header frames received");
736 return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
737 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700738 transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
739 transport_parsing->hpack_parser.is_boundary = is_eoh;
Craig Tillera82950e2015-09-22 12:33:20 -0700740 transport_parsing->hpack_parser.is_eof =
Craig Tiller7536af02015-12-22 13:49:30 -0800741 (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700742 if (!is_continuation && (transport_parsing->incoming_frame_flags &
743 GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
744 grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
745 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700746 return 1;
747}
748
Craig Tillera82950e2015-09-22 12:33:20 -0700749static int init_window_update_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800750 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700751 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 transport_parsing->incoming_frame_flags);
755 if (transport_parsing->incoming_stream_id) {
756 transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
757 transport_parsing, transport_parsing->incoming_stream_id);
758 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700759 transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
760 transport_parsing->parser_data = &transport_parsing->simple.window_update;
761 return ok;
762}
763
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800764static int init_ping_parser(grpc_exec_ctx *exec_ctx,
765 grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700766 int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
767 &transport_parsing->simple.ping,
768 transport_parsing->incoming_frame_size,
769 transport_parsing->incoming_frame_flags);
Craig Tillerd20efd22015-06-12 16:17:09 -0700770 transport_parsing->parser = grpc_chttp2_ping_parser_parse;
771 transport_parsing->parser_data = &transport_parsing->simple.ping;
772 return ok;
773}
774
Craig Tillera82950e2015-09-22 12:33:20 -0700775static int init_rst_stream_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800776 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700777 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 transport_parsing->incoming_frame_flags);
781 transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
782 transport_parsing, transport_parsing->incoming_stream_id);
783 if (!transport_parsing->incoming_stream) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800784 return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700785 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700786 transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
787 transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
788 return ok;
789}
790
Craig Tillera82950e2015-09-22 12:33:20 -0700791static int init_goaway_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800792 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillera82950e2015-09-22 12:33:20 -0700793 int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
794 &transport_parsing->goaway_parser,
795 transport_parsing->incoming_frame_size,
796 transport_parsing->incoming_frame_flags);
Craig Tillerd20efd22015-06-12 16:17:09 -0700797 transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
798 transport_parsing->parser_data = &transport_parsing->goaway_parser;
799 return ok;
800}
801
Craig Tillera82950e2015-09-22 12:33:20 -0700802static int init_settings_frame_parser(
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800803 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
Craig Tillerd20efd22015-06-12 16:17:09 -0700804 int ok;
805
Craig Tillera82950e2015-09-22 12:33:20 -0700806 if (transport_parsing->incoming_stream_id != 0) {
807 gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
808 transport_parsing->incoming_stream_id);
809 return 0;
810 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700811
Craig Tillera82950e2015-09-22 12:33:20 -0700812 ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
813 &transport_parsing->simple.settings,
814 transport_parsing->incoming_frame_size,
815 transport_parsing->incoming_frame_flags,
816 transport_parsing->settings);
817 if (!ok) {
818 return 0;
819 }
820 if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
821 transport_parsing->settings_ack_received = 1;
Craig Tiller3c53bb22015-11-10 14:24:36 +0000822 grpc_chttp2_hptbl_set_max_bytes(
823 &transport_parsing->hpack_parser.table,
824 transport_parsing->last_sent_max_table_size);
Craig Tillera82950e2015-09-22 12:33:20 -0700825 }
Craig Tillerd20efd22015-06-12 16:17:09 -0700826 transport_parsing->parser = grpc_chttp2_settings_parser_parse;
827 transport_parsing->parser_data = &transport_parsing->simple.settings;
828 return ok;
829}
830
831/*
Craig Tiller7536af02015-12-22 13:49:30 -0800832static int is_window_update_legal(int64_t window_update, int64_t window) {
Craig Tillerd20efd22015-06-12 16:17:09 -0700833 return window + window_update < MAX_WINDOW;
834}
835*/
836
Craig Tillera82950e2015-09-22 12:33:20 -0700837static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
838 grpc_chttp2_transport_parsing *transport_parsing,
839 gpr_slice slice, int is_last) {
840 grpc_chttp2_stream_parsing *stream_parsing =
841 transport_parsing->incoming_stream;
842 switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
843 transport_parsing, stream_parsing, slice,
844 is_last)) {
Craig Tillerd20efd22015-06-12 16:17:09 -0700845 case GRPC_CHTTP2_PARSE_OK:
Craig Tillera82950e2015-09-22 12:33:20 -0700846 if (stream_parsing) {
847 grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
848 stream_parsing);
849 }
Craig Tiller3719f072015-06-12 17:19:51 -0700850 return 1;
851 case GRPC_CHTTP2_STREAM_ERROR:
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800852 grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
Craig Tillera82950e2015-09-22 12:33:20 -0700853 if (stream_parsing) {
854 stream_parsing->saw_rst_stream = 1;
855 stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
856 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 }
Craig Tiller3719f072015-06-12 17:19:51 -0700861 return 1;
862 case GRPC_CHTTP2_CONNECTION_ERROR:
863 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700864 }
yang-gb063c872015-10-07 11:40:13 -0700865 GPR_UNREACHABLE_CODE(return 0);
Craig Tiller3719f072015-06-12 17:19:51 -0700866}