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 2703549 : grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
46 : grpc_chttp2_data_parser *parser) {
47 2703549 : parser->state = GRPC_CHTTP2_DATA_FH_0;
48 2703549 : grpc_sopb_init(&parser->incoming_sopb);
49 2704358 : return GRPC_CHTTP2_PARSE_OK;
50 : }
51 :
52 2703181 : void grpc_chttp2_data_parser_destroy(grpc_chttp2_data_parser *parser) {
53 2703181 : grpc_sopb_destroy(&parser->incoming_sopb);
54 2703286 : }
55 :
56 3018527 : grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
57 : grpc_chttp2_data_parser *parser, gpr_uint8 flags) {
58 3018527 : if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
59 0 : gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
60 0 : return GRPC_CHTTP2_STREAM_ERROR;
61 : }
62 :
63 3018527 : if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
64 1299956 : parser->is_last_frame = 1;
65 : } else {
66 1718571 : parser->is_last_frame = 0;
67 : }
68 :
69 3018527 : return GRPC_CHTTP2_PARSE_OK;
70 : }
71 :
72 7045849 : grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
73 : grpc_exec_ctx *exec_ctx, void *parser,
74 : grpc_chttp2_transport_parsing *transport_parsing,
75 : grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
76 7045849 : gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
77 7045849 : gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
78 7045849 : gpr_uint8 *cur = beg;
79 7045849 : grpc_chttp2_data_parser *p = parser;
80 7045849 : gpr_uint32 message_flags = 0;
81 :
82 7045849 : if (is_last && p->is_last_frame) {
83 1300076 : stream_parsing->received_close = 1;
84 : }
85 :
86 7045849 : if (cur == end) {
87 295 : return GRPC_CHTTP2_PARSE_OK;
88 : }
89 :
90 7045554 : switch (p->state) {
91 : fh_0:
92 : case GRPC_CHTTP2_DATA_FH_0:
93 3001503 : p->frame_type = *cur;
94 3001503 : switch (p->frame_type) {
95 : case 0:
96 3001424 : p->is_frame_compressed = 0; /* GPR_FALSE */
97 3001424 : break;
98 : case 1:
99 79 : p->is_frame_compressed = 1; /* GPR_TRUE */
100 79 : break;
101 : default:
102 0 : gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
103 0 : return GRPC_CHTTP2_STREAM_ERROR;
104 : }
105 3001503 : if (++cur == end) {
106 759 : p->state = GRPC_CHTTP2_DATA_FH_1;
107 759 : return GRPC_CHTTP2_PARSE_OK;
108 : }
109 : /* fallthrough */
110 : case GRPC_CHTTP2_DATA_FH_1:
111 3001485 : p->frame_size = ((gpr_uint32)*cur) << 24;
112 3001485 : if (++cur == end) {
113 644 : p->state = GRPC_CHTTP2_DATA_FH_2;
114 644 : return GRPC_CHTTP2_PARSE_OK;
115 : }
116 : /* fallthrough */
117 : case GRPC_CHTTP2_DATA_FH_2:
118 3001474 : p->frame_size |= ((gpr_uint32)*cur) << 16;
119 3001474 : if (++cur == end) {
120 587 : p->state = GRPC_CHTTP2_DATA_FH_3;
121 587 : return GRPC_CHTTP2_PARSE_OK;
122 : }
123 : /* fallthrough */
124 : case GRPC_CHTTP2_DATA_FH_3:
125 3001455 : p->frame_size |= ((gpr_uint32)*cur) << 8;
126 3001455 : if (++cur == end) {
127 596 : p->state = GRPC_CHTTP2_DATA_FH_4;
128 596 : return GRPC_CHTTP2_PARSE_OK;
129 : }
130 : /* fallthrough */
131 : case GRPC_CHTTP2_DATA_FH_4:
132 3001494 : p->frame_size |= ((gpr_uint32)*cur);
133 3001494 : p->state = GRPC_CHTTP2_DATA_FRAME;
134 3001494 : ++cur;
135 3001494 : if (p->is_frame_compressed) {
136 79 : message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
137 : }
138 3001494 : grpc_sopb_add_begin_message(&p->incoming_sopb, p->frame_size,
139 : message_flags);
140 : /* fallthrough */
141 : case GRPC_CHTTP2_DATA_FRAME:
142 7042860 : if (cur == end) {
143 633 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
144 : stream_parsing);
145 633 : return GRPC_CHTTP2_PARSE_OK;
146 : }
147 7042227 : grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
148 : stream_parsing);
149 7042199 : if ((gpr_uint32)(end - cur) == p->frame_size) {
150 6002664 : grpc_sopb_add_slice(
151 : &p->incoming_sopb,
152 6002664 : gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
153 3001500 : p->state = GRPC_CHTTP2_DATA_FH_0;
154 3001500 : return GRPC_CHTTP2_PARSE_OK;
155 4040867 : } else if ((gpr_uint32)(end - cur) > p->frame_size) {
156 12 : grpc_sopb_add_slice(&p->incoming_sopb,
157 6 : gpr_slice_sub(slice, (size_t)(cur - beg),
158 6 : (size_t)(cur + p->frame_size - beg)));
159 6 : cur += p->frame_size;
160 6 : goto fh_0; /* loop */
161 : } else {
162 8081722 : grpc_sopb_add_slice(
163 : &p->incoming_sopb,
164 8081722 : gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
165 4040861 : GPR_ASSERT((size_t)(end - cur) <= p->frame_size);
166 4040861 : p->frame_size -= (gpr_uint32)(end - cur);
167 4040861 : return GRPC_CHTTP2_PARSE_OK;
168 : }
169 : }
170 :
171 0 : GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
172 : }
|