blob: cf25c3ccc1a4a24cb7343ca283fbf8b1b07a542a [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller2e190362016-03-25 14:33:26 -07003 * Copyright 2015-2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * 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/frame_data.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
36#include <string.h>
37
38#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080040#include <grpc/support/useful.h>
Craig Tiller9533d042016-03-25 17:11:06 -070041#include "src/core/lib/support/string.h"
42#include "src/core/lib/transport/chttp2/internal.h"
43#include "src/core/lib/transport/transport.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080044
Craig Tillera82950e2015-09-22 12:33:20 -070045grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
46 grpc_chttp2_data_parser *parser) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080047 parser->state = GRPC_CHTTP2_DATA_FH_0;
Craig Tiller7be556e2015-11-06 12:29:33 -080048 parser->parsing_frame = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080049 return GRPC_CHTTP2_PARSE_OK;
50}
51
Craig Tiller7be556e2015-11-06 12:29:33 -080052void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
53 grpc_chttp2_data_parser *parser) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -080054 grpc_byte_stream *bs;
Craig Tiller7be556e2015-11-06 12:29:33 -080055 if (parser->parsing_frame) {
Craig Tiller38edec62015-12-14 15:01:29 -080056 grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
57 0, 1);
Craig Tiller7be556e2015-11-06 12:29:33 -080058 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -080059 while (
60 (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
Craig Tiller3b66ab92015-12-09 19:42:22 -080061 grpc_byte_stream_destroy(exec_ctx, bs);
Craig Tiller9d35a1f2015-11-02 14:16:12 -080062 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080063}
64
Craig Tillera82950e2015-09-22 12:33:20 -070065grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
Craig Tiller7536af02015-12-22 13:49:30 -080066 grpc_chttp2_data_parser *parser, uint8_t flags) {
Craig Tillera82950e2015-09-22 12:33:20 -070067 if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
68 gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
69 return GRPC_CHTTP2_STREAM_ERROR;
70 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071
Craig Tillera82950e2015-09-22 12:33:20 -070072 if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
73 parser->is_last_frame = 1;
74 } else {
75 parser->is_last_frame = 0;
76 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080077
78 return GRPC_CHTTP2_PARSE_OK;
79}
80
Craig Tiller9d35a1f2015-11-02 14:16:12 -080081void grpc_chttp2_incoming_frame_queue_merge(
82 grpc_chttp2_incoming_frame_queue *head_dst,
83 grpc_chttp2_incoming_frame_queue *tail_src) {
84 if (tail_src->head == NULL) {
85 return;
86 }
87
88 if (head_dst->head == NULL) {
89 *head_dst = *tail_src;
90 memset(tail_src, 0, sizeof(*tail_src));
91 return;
92 }
93
94 head_dst->tail->next_message = tail_src->head;
95 head_dst->tail = tail_src->tail;
96 memset(tail_src, 0, sizeof(*tail_src));
97}
98
99grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
100 grpc_chttp2_incoming_frame_queue *q) {
101 grpc_byte_stream *out;
102 if (q->head == NULL) {
103 return NULL;
104 }
105 out = &q->head->base;
106 if (q->head == q->tail) {
107 memset(q, 0, sizeof(*q));
108 } else {
109 q->head = q->head->next_message;
110 }
111 return out;
112}
113
Craig Tiller7536af02015-12-22 13:49:30 -0800114void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
115 uint32_t write_bytes, int is_eof,
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800116 gpr_slice_buffer *outbuf) {
117 gpr_slice hdr;
Craig Tiller7536af02015-12-22 13:49:30 -0800118 uint8_t *p;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800119
120 hdr = gpr_slice_malloc(9);
121 p = GPR_SLICE_START_PTR(hdr);
Craig Tiller620e9652015-12-14 12:02:50 -0800122 GPR_ASSERT(write_bytes < (1 << 24));
Craig Tiller7536af02015-12-22 13:49:30 -0800123 *p++ = (uint8_t)(write_bytes >> 16);
124 *p++ = (uint8_t)(write_bytes >> 8);
125 *p++ = (uint8_t)(write_bytes);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800126 *p++ = GRPC_CHTTP2_FRAME_DATA;
127 *p++ = is_eof ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0;
Craig Tiller7536af02015-12-22 13:49:30 -0800128 *p++ = (uint8_t)(id >> 24);
129 *p++ = (uint8_t)(id >> 16);
130 *p++ = (uint8_t)(id >> 8);
131 *p++ = (uint8_t)(id);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800132 gpr_slice_buffer_add(outbuf, hdr);
133
134 gpr_slice_buffer_move_first(inbuf, write_bytes, outbuf);
135}
136
Craig Tillera82950e2015-09-22 12:33:20 -0700137grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
138 grpc_exec_ctx *exec_ctx, void *parser,
139 grpc_chttp2_transport_parsing *transport_parsing,
140 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
Craig Tiller7536af02015-12-22 13:49:30 -0800141 uint8_t *const beg = GPR_SLICE_START_PTR(slice);
142 uint8_t *const end = GPR_SLICE_END_PTR(slice);
143 uint8_t *cur = beg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800144 grpc_chttp2_data_parser *p = parser;
Craig Tiller7536af02015-12-22 13:49:30 -0800145 uint32_t message_flags;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800146 grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800147
Craig Tillera82950e2015-09-22 12:33:20 -0700148 if (is_last && p->is_last_frame) {
149 stream_parsing->received_close = 1;
150 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800151
Craig Tillera82950e2015-09-22 12:33:20 -0700152 if (cur == end) {
153 return GRPC_CHTTP2_PARSE_OK;
154 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800155
Craig Tillera82950e2015-09-22 12:33:20 -0700156 switch (p->state) {
157 fh_0:
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800158 case GRPC_CHTTP2_DATA_FH_0:
159 p->frame_type = *cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700160 switch (p->frame_type) {
161 case 0:
162 p->is_frame_compressed = 0; /* GPR_FALSE */
163 break;
164 case 1:
165 p->is_frame_compressed = 1; /* GPR_TRUE */
166 break;
167 default:
168 gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
169 return GRPC_CHTTP2_STREAM_ERROR;
170 }
171 if (++cur == end) {
172 p->state = GRPC_CHTTP2_DATA_FH_1;
173 return GRPC_CHTTP2_PARSE_OK;
174 }
175 /* fallthrough */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800176 case GRPC_CHTTP2_DATA_FH_1:
Craig Tiller7536af02015-12-22 13:49:30 -0800177 p->frame_size = ((uint32_t)*cur) << 24;
Craig Tillera82950e2015-09-22 12:33:20 -0700178 if (++cur == end) {
179 p->state = GRPC_CHTTP2_DATA_FH_2;
180 return GRPC_CHTTP2_PARSE_OK;
181 }
182 /* fallthrough */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800183 case GRPC_CHTTP2_DATA_FH_2:
Craig Tiller7536af02015-12-22 13:49:30 -0800184 p->frame_size |= ((uint32_t)*cur) << 16;
Craig Tillera82950e2015-09-22 12:33:20 -0700185 if (++cur == end) {
186 p->state = GRPC_CHTTP2_DATA_FH_3;
187 return GRPC_CHTTP2_PARSE_OK;
188 }
189 /* fallthrough */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800190 case GRPC_CHTTP2_DATA_FH_3:
Craig Tiller7536af02015-12-22 13:49:30 -0800191 p->frame_size |= ((uint32_t)*cur) << 8;
Craig Tillera82950e2015-09-22 12:33:20 -0700192 if (++cur == end) {
193 p->state = GRPC_CHTTP2_DATA_FH_4;
194 return GRPC_CHTTP2_PARSE_OK;
195 }
196 /* fallthrough */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197 case GRPC_CHTTP2_DATA_FH_4:
Craig Tiller7536af02015-12-22 13:49:30 -0800198 p->frame_size |= ((uint32_t)*cur);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800199 p->state = GRPC_CHTTP2_DATA_FRAME;
200 ++cur;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800201 message_flags = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700202 if (p->is_frame_compressed) {
203 message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
204 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800205 p->parsing_frame = incoming_byte_stream =
206 grpc_chttp2_incoming_byte_stream_create(
Craig Tiller20df14e2015-11-06 09:10:49 -0800207 exec_ctx, transport_parsing, stream_parsing, p->frame_size,
208 message_flags, &p->incoming_frames);
Craig Tillera82950e2015-09-22 12:33:20 -0700209 /* fallthrough */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210 case GRPC_CHTTP2_DATA_FRAME:
Craig Tillera82950e2015-09-22 12:33:20 -0700211 if (cur == end) {
212 grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
213 stream_parsing);
214 return GRPC_CHTTP2_PARSE_OK;
215 }
216 grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
217 stream_parsing);
Craig Tiller7536af02015-12-22 13:49:30 -0800218 if ((uint32_t)(end - cur) == p->frame_size) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800219 grpc_chttp2_incoming_byte_stream_push(
220 exec_ctx, p->parsing_frame,
Craig Tillera82950e2015-09-22 12:33:20 -0700221 gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
Craig Tiller38edec62015-12-14 15:01:29 -0800222 grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
223 1);
Craig Tiller7be556e2015-11-06 12:29:33 -0800224 p->parsing_frame = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700225 p->state = GRPC_CHTTP2_DATA_FH_0;
226 return GRPC_CHTTP2_PARSE_OK;
Craig Tiller7536af02015-12-22 13:49:30 -0800227 } else if ((uint32_t)(end - cur) > p->frame_size) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800228 grpc_chttp2_incoming_byte_stream_push(
229 exec_ctx, p->parsing_frame,
230 gpr_slice_sub(slice, (size_t)(cur - beg),
231 (size_t)(cur + p->frame_size - beg)));
Craig Tiller38edec62015-12-14 15:01:29 -0800232 grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
233 1);
Craig Tiller7be556e2015-11-06 12:29:33 -0800234 p->parsing_frame = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700235 cur += p->frame_size;
236 goto fh_0; /* loop */
237 } else {
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800238 grpc_chttp2_incoming_byte_stream_push(
239 exec_ctx, p->parsing_frame,
Craig Tillera82950e2015-09-22 12:33:20 -0700240 gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
Craig Tiller82f9bd82015-09-23 09:31:51 -0700241 GPR_ASSERT((size_t)(end - cur) <= p->frame_size);
Craig Tiller7536af02015-12-22 13:49:30 -0800242 p->frame_size -= (uint32_t)(end - cur);
Craig Tillera82950e2015-09-22 12:33:20 -0700243 return GRPC_CHTTP2_PARSE_OK;
244 }
245 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800246
yang-gb063c872015-10-07 11:40:13 -0700247 GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
Craig Tiller190d3602015-02-18 09:23:38 -0800248}