1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/ext/transport/chttp2/transport/frame_settings.h"
22 #include "src/core/ext/transport/chttp2/transport/internal.h"
23
24 #include <string.h>
25
26 #include <grpc/support/alloc.h>
27 #include <grpc/support/log.h>
28 #include <grpc/support/string_util.h>
29
30 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
31 #include "src/core/ext/transport/chttp2/transport/frame.h"
32 #include "src/core/lib/debug/trace.h"
33 #include "src/core/lib/transport/http2_errors.h"
34
fill_header(uint8_t * out,uint32_t length,uint8_t flags)35 static uint8_t* fill_header(uint8_t* out, uint32_t length, uint8_t flags) {
36 *out++ = static_cast<uint8_t>(length >> 16);
37 *out++ = static_cast<uint8_t>(length >> 8);
38 *out++ = static_cast<uint8_t>(length);
39 *out++ = GRPC_CHTTP2_FRAME_SETTINGS;
40 *out++ = flags;
41 *out++ = 0;
42 *out++ = 0;
43 *out++ = 0;
44 *out++ = 0;
45 return out;
46 }
47
grpc_chttp2_settings_create(uint32_t * old_settings,const uint32_t * new_settings,uint32_t force_mask,size_t count)48 grpc_slice grpc_chttp2_settings_create(uint32_t* old_settings,
49 const uint32_t* new_settings,
50 uint32_t force_mask, size_t count) {
51 size_t i;
52 uint32_t n = 0;
53 grpc_slice output;
54 uint8_t* p;
55
56 for (i = 0; i < count; i++) {
57 n += (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0);
58 }
59
60 output = GRPC_SLICE_MALLOC(9 + 6 * n);
61 p = fill_header(GRPC_SLICE_START_PTR(output), 6 * n, 0);
62
63 for (i = 0; i < count; i++) {
64 if (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0) {
65 *p++ = static_cast<uint8_t>(grpc_setting_id_to_wire_id[i] >> 8);
66 *p++ = static_cast<uint8_t>(grpc_setting_id_to_wire_id[i]);
67 *p++ = static_cast<uint8_t>(new_settings[i] >> 24);
68 *p++ = static_cast<uint8_t>(new_settings[i] >> 16);
69 *p++ = static_cast<uint8_t>(new_settings[i] >> 8);
70 *p++ = static_cast<uint8_t>(new_settings[i]);
71 old_settings[i] = new_settings[i];
72 }
73 }
74
75 GPR_ASSERT(p == GRPC_SLICE_END_PTR(output));
76
77 return output;
78 }
79
grpc_chttp2_settings_ack_create(void)80 grpc_slice grpc_chttp2_settings_ack_create(void) {
81 grpc_slice output = GRPC_SLICE_MALLOC(9);
82 fill_header(GRPC_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK);
83 return output;
84 }
85
grpc_chttp2_settings_parser_begin_frame(grpc_chttp2_settings_parser * parser,uint32_t length,uint8_t flags,uint32_t * settings)86 grpc_error* grpc_chttp2_settings_parser_begin_frame(
87 grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags,
88 uint32_t* settings) {
89 parser->target_settings = settings;
90 memcpy(parser->incoming_settings, settings,
91 GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
92 parser->is_ack = 0;
93 parser->state = GRPC_CHTTP2_SPS_ID0;
94 if (flags == GRPC_CHTTP2_FLAG_ACK) {
95 parser->is_ack = 1;
96 if (length != 0) {
97 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
98 "non-empty settings ack frame received");
99 }
100 return GRPC_ERROR_NONE;
101 } else if (flags != 0) {
102 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
103 "invalid flags on settings frame");
104 } else if (length % 6 != 0) {
105 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
106 "settings frames must be a multiple of six bytes");
107 } else {
108 return GRPC_ERROR_NONE;
109 }
110 }
111
grpc_chttp2_settings_parser_parse(void * p,grpc_chttp2_transport * t,grpc_chttp2_stream * s,grpc_slice slice,int is_last)112 grpc_error* grpc_chttp2_settings_parser_parse(void* p, grpc_chttp2_transport* t,
113 grpc_chttp2_stream* s,
114 grpc_slice slice, int is_last) {
115 grpc_chttp2_settings_parser* parser =
116 static_cast<grpc_chttp2_settings_parser*>(p);
117 const uint8_t* cur = GRPC_SLICE_START_PTR(slice);
118 const uint8_t* end = GRPC_SLICE_END_PTR(slice);
119 char* msg;
120 grpc_chttp2_setting_id id;
121
122 if (parser->is_ack) {
123 return GRPC_ERROR_NONE;
124 }
125
126 for (;;) {
127 switch (parser->state) {
128 case GRPC_CHTTP2_SPS_ID0:
129 if (cur == end) {
130 parser->state = GRPC_CHTTP2_SPS_ID0;
131 if (is_last) {
132 memcpy(parser->target_settings, parser->incoming_settings,
133 GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
134 grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create());
135 if (t->notify_on_receive_settings != nullptr) {
136 GRPC_CLOSURE_SCHED(t->notify_on_receive_settings,
137 GRPC_ERROR_NONE);
138 t->notify_on_receive_settings = nullptr;
139 }
140 }
141 return GRPC_ERROR_NONE;
142 }
143 parser->id = static_cast<uint16_t>((static_cast<uint16_t>(*cur)) << 8);
144 cur++;
145 /* fallthrough */
146 case GRPC_CHTTP2_SPS_ID1:
147 if (cur == end) {
148 parser->state = GRPC_CHTTP2_SPS_ID1;
149 return GRPC_ERROR_NONE;
150 }
151 parser->id = static_cast<uint16_t>(parser->id | (*cur));
152 cur++;
153 /* fallthrough */
154 case GRPC_CHTTP2_SPS_VAL0:
155 if (cur == end) {
156 parser->state = GRPC_CHTTP2_SPS_VAL0;
157 return GRPC_ERROR_NONE;
158 }
159 parser->value = (static_cast<uint32_t>(*cur)) << 24;
160 cur++;
161 /* fallthrough */
162 case GRPC_CHTTP2_SPS_VAL1:
163 if (cur == end) {
164 parser->state = GRPC_CHTTP2_SPS_VAL1;
165 return GRPC_ERROR_NONE;
166 }
167 parser->value |= (static_cast<uint32_t>(*cur)) << 16;
168 cur++;
169 /* fallthrough */
170 case GRPC_CHTTP2_SPS_VAL2:
171 if (cur == end) {
172 parser->state = GRPC_CHTTP2_SPS_VAL2;
173 return GRPC_ERROR_NONE;
174 }
175 parser->value |= (static_cast<uint32_t>(*cur)) << 8;
176 cur++;
177 /* fallthrough */
178 case GRPC_CHTTP2_SPS_VAL3:
179 if (cur == end) {
180 parser->state = GRPC_CHTTP2_SPS_VAL3;
181 return GRPC_ERROR_NONE;
182 } else {
183 parser->state = GRPC_CHTTP2_SPS_ID0;
184 }
185 parser->value |= *cur;
186 cur++;
187
188 if (grpc_wire_id_to_setting_id(parser->id, &id)) {
189 const grpc_chttp2_setting_parameters* sp =
190 &grpc_chttp2_settings_parameters[id];
191 // If flow control is disabled we skip these.
192 if (!t->flow_control->flow_control_enabled() &&
193 (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ||
194 id == GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE)) {
195 continue;
196 }
197 if (parser->value < sp->min_value || parser->value > sp->max_value) {
198 switch (sp->invalid_value_behavior) {
199 case GRPC_CHTTP2_CLAMP_INVALID_VALUE:
200 parser->value =
201 GPR_CLAMP(parser->value, sp->min_value, sp->max_value);
202 break;
203 case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE:
204 grpc_chttp2_goaway_append(
205 t->last_new_stream_id, sp->error_value,
206 grpc_slice_from_static_string("HTTP2 settings error"),
207 &t->qbuf);
208 gpr_asprintf(&msg, "invalid value %u passed for %s",
209 parser->value, sp->name);
210 grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
211 gpr_free(msg);
212 return err;
213 }
214 }
215 if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
216 parser->incoming_settings[id] != parser->value) {
217 t->initial_window_update += static_cast<int64_t>(parser->value) -
218 parser->incoming_settings[id];
219 if (grpc_http_trace.enabled() || grpc_flowctl_trace.enabled()) {
220 gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t,
221 t->is_client ? "cli" : "svr",
222 static_cast<int>(t->initial_window_update));
223 }
224 }
225 parser->incoming_settings[id] = parser->value;
226 if (grpc_http_trace.enabled()) {
227 gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d",
228 t->is_client ? "CLI" : "SVR", t->peer_string, sp->name,
229 parser->value);
230 }
231 } else if (grpc_http_trace.enabled()) {
232 gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
233 parser->id, parser->value);
234 }
235 break;
236 }
237 }
238 }
239