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/frame_data.h"
35 :
36 : #include <string.h>
37 :
38 : #include "src/core/transport/chttp2/internal.h"
39 : #include "src/core/support/string.h"
40 : #include <grpc/support/alloc.h>
41 : #include <grpc/support/log.h>
42 : #include <grpc/support/useful.h>
43 : #include "src/core/transport/transport.h"
44 :
45 4440066 : grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
46 : grpc_chttp2_data_parser *parser) {
47 4440066 : parser->state = GRPC_CHTTP2_DATA_FH_0;
48 4440066 : parser->parsing_frame = NULL;
49 4440066 : return GRPC_CHTTP2_PARSE_OK;
50 : }
51 :
52 4442585 : void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
53 : grpc_chttp2_data_parser *parser) {
54 : grpc_byte_stream *bs;
55 4442585 : if (parser->parsing_frame) {
56 1545986 : grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame);
57 : }
58 8881930 : while (
59 4440990 : (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
60 0 : grpc_byte_stream_destroy(bs);
61 : }
62 4441280 : }
63 :
64 4490687 : grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
65 : grpc_chttp2_data_parser *parser, gpr_uint8 flags) {
66 4490687 : if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
67 1 : gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
68 1 : return GRPC_CHTTP2_STREAM_ERROR;
69 : }
70 :
71 4490686 : if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
72 2170332 : parser->is_last_frame = 1;
73 : } else {
74 2320354 : parser->is_last_frame = 0;
75 : }
76 :
77 4490363 : return GRPC_CHTTP2_PARSE_OK;
78 : }
79 :
80 8719175 : void grpc_chttp2_incoming_frame_queue_merge(
81 : grpc_chttp2_incoming_frame_queue *head_dst,
82 : grpc_chttp2_incoming_frame_queue *tail_src) {
83 8719175 : if (tail_src->head == NULL) {
84 4764170 : return;
85 : }
86 :
87 3954778 : if (head_dst->head == NULL) {
88 3951367 : *head_dst = *tail_src;
89 3951367 : memset(tail_src, 0, sizeof(*tail_src));
90 3951367 : return;
91 : }
92 :
93 3411 : head_dst->tail->next_message = tail_src->head;
94 3411 : head_dst->tail = tail_src->tail;
95 3411 : memset(tail_src, 0, sizeof(*tail_src));
96 : }
97 :
98 13887412 : grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
99 : grpc_chttp2_incoming_frame_queue *q) {
100 : grpc_byte_stream *out;
101 13887412 : if (q->head == NULL) {
102 9926787 : return NULL;
103 : }
104 3960456 : out = &q->head->base;
105 3960456 : if (q->head == q->tail) {
106 3950436 : memset(q, 0, sizeof(*q));
107 : } else {
108 10020 : q->head = q->head->next_message;
109 : }
110 3960456 : return out;
111 : }
112 :
113 4486485 : void grpc_chttp2_encode_data(gpr_uint32 id, gpr_slice_buffer *inbuf,
114 : gpr_uint32 write_bytes, int is_eof,
115 : gpr_slice_buffer *outbuf) {
116 : gpr_slice hdr;
117 : gpr_uint8 *p;
118 :
119 4486485 : hdr = gpr_slice_malloc(9);
120 4491249 : p = GPR_SLICE_START_PTR(hdr);
121 4491249 : GPR_ASSERT(write_bytes < (1<<24));
122 4491249 : *p++ = (gpr_uint8)(write_bytes >> 16);
123 4491249 : *p++ = (gpr_uint8)(write_bytes >> 8);
124 4491249 : *p++ = (gpr_uint8)(write_bytes);
125 4491249 : *p++ = GRPC_CHTTP2_FRAME_DATA;
126 4491249 : *p++ = is_eof ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0;
127 4491249 : *p++ = (gpr_uint8)(id >> 24);
128 4491249 : *p++ = (gpr_uint8)(id >> 16);
129 4491249 : *p++ = (gpr_uint8)(id >> 8);
130 4491249 : *p++ = (gpr_uint8)(id);
131 4491249 : gpr_slice_buffer_add(outbuf, hdr);
132 :
133 4491222 : gpr_slice_buffer_move_first(inbuf, write_bytes, outbuf);
134 4490249 : }
135 :
136 8519621 : grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
137 : grpc_exec_ctx *exec_ctx, void *parser,
138 : grpc_chttp2_transport_parsing *transport_parsing,
139 : grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
140 8519621 : gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
141 8519621 : gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
142 8519019 : gpr_uint8 *cur = beg;
143 8519019 : grpc_chttp2_data_parser *p = parser;
144 : gpr_uint32 message_flags;
145 : grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
146 :
147 8519621 : if (is_last && p->is_last_frame) {
148 2170676 : stream_parsing->received_close = 1;
149 : }
150 :
151 8519621 : if (cur == end) {
152 523089 : return GRPC_CHTTP2_PARSE_OK;
153 : }
154 :
155 7996504 : switch (p->state) {
156 : fh_0:
157 : case GRPC_CHTTP2_DATA_FH_0:
158 3963706 : p->frame_type = *cur;
159 3963706 : switch (p->frame_type) {
160 : case 0:
161 3963622 : p->is_frame_compressed = 0; /* GPR_FALSE */
162 3963622 : break;
163 : case 1:
164 83 : p->is_frame_compressed = 1; /* GPR_TRUE */
165 83 : break;
166 : default:
167 1 : gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
168 1 : return GRPC_CHTTP2_STREAM_ERROR;
169 : }
170 3963705 : if (++cur == end) {
171 673 : p->state = GRPC_CHTTP2_DATA_FH_1;
172 673 : return GRPC_CHTTP2_PARSE_OK;
173 : }
174 : /* fallthrough */
175 : case GRPC_CHTTP2_DATA_FH_1:
176 3963861 : p->frame_size = ((gpr_uint32)*cur) << 24;
177 3963861 : if (++cur == end) {
178 650 : p->state = GRPC_CHTTP2_DATA_FH_2;
179 650 : return GRPC_CHTTP2_PARSE_OK;
180 : }
181 : /* fallthrough */
182 : case GRPC_CHTTP2_DATA_FH_2:
183 3963833 : p->frame_size |= ((gpr_uint32)*cur) << 16;
184 3963833 : if (++cur == end) {
185 809 : p->state = GRPC_CHTTP2_DATA_FH_3;
186 809 : return GRPC_CHTTP2_PARSE_OK;
187 : }
188 : /* fallthrough */
189 : case GRPC_CHTTP2_DATA_FH_3:
190 3963581 : p->frame_size |= ((gpr_uint32)*cur) << 8;
191 3963581 : if (++cur == end) {
192 643 : p->state = GRPC_CHTTP2_DATA_FH_4;
193 643 : return GRPC_CHTTP2_PARSE_OK;
194 : }
195 : /* fallthrough */
196 : case GRPC_CHTTP2_DATA_FH_4:
197 3962391 : p->frame_size |= ((gpr_uint32)*cur);
198 3962391 : p->state = GRPC_CHTTP2_DATA_FRAME;
199 3962391 : ++cur;
200 3962204 : message_flags = 0;
201 3962391 : if (p->is_frame_compressed) {
202 83 : message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
203 : }
204 3962391 : p->parsing_frame = incoming_byte_stream =
205 3962391 : grpc_chttp2_incoming_byte_stream_create(
206 : exec_ctx, transport_parsing, stream_parsing, p->frame_size,
207 : message_flags, &p->incoming_frames);
208 : /* fallthrough */
209 : case GRPC_CHTTP2_DATA_FRAME:
210 8206637 : if (cur == end) {
211 1761969 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
212 : stream_parsing);
213 1761957 : return GRPC_CHTTP2_PARSE_OK;
214 : }
215 6444668 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
216 : stream_parsing);
217 6444666 : if ((gpr_uint32)(end - cur) == p->frame_size) {
218 4409358 : grpc_chttp2_incoming_byte_stream_push(
219 : exec_ctx, p->parsing_frame,
220 4409358 : gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
221 2204849 : grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame);
222 2204863 : p->parsing_frame = NULL;
223 2204863 : p->state = GRPC_CHTTP2_DATA_FH_0;
224 2204863 : return GRPC_CHTTP2_PARSE_OK;
225 4239987 : } else if ((gpr_uint32)(end - cur) > p->frame_size) {
226 426012 : grpc_chttp2_incoming_byte_stream_push(
227 : exec_ctx, p->parsing_frame,
228 213006 : gpr_slice_sub(slice, (size_t)(cur - beg),
229 213006 : (size_t)(cur + p->frame_size - beg)));
230 213006 : grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame);
231 213006 : p->parsing_frame = NULL;
232 213006 : cur += p->frame_size;
233 213006 : goto fh_0; /* loop */
234 : } else {
235 8053962 : grpc_chttp2_incoming_byte_stream_push(
236 : exec_ctx, p->parsing_frame,
237 8053962 : gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
238 4026981 : GPR_ASSERT((size_t)(end - cur) <= p->frame_size);
239 4026981 : p->frame_size -= (gpr_uint32)(end - cur);
240 4026981 : return GRPC_CHTTP2_PARSE_OK;
241 : }
242 : }
243 :
244 0 : GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
245 0 : }
|