3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <grpc/support/port_platform.h>
21 #include "src/core/ext/transport/chttp2/transport/frame_goaway.h"
22 #include "src/core/ext/transport/chttp2/transport/internal.h"
26 #include <grpc/support/alloc.h>
27 #include <grpc/support/log.h>
28 #include <grpc/support/string_util.h>
30 void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser* p) {
31 p->debug_data = nullptr;
34 void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p) {
35 gpr_free(p->debug_data);
38 grpc_error* grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser* p,
43 gpr_asprintf(&msg, "goaway frame too short (%d bytes)", length);
44 grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
49 gpr_free(p->debug_data);
50 p->debug_length = length - 8;
51 p->debug_data = static_cast<char*>(gpr_malloc(p->debug_length));
53 p->state = GRPC_CHTTP2_GOAWAY_LSI0;
54 return GRPC_ERROR_NONE;
57 grpc_error* grpc_chttp2_goaway_parser_parse(void* parser,
58 grpc_chttp2_transport* t,
59 grpc_chttp2_stream* s,
60 const grpc_slice& slice,
62 const uint8_t* const beg = GRPC_SLICE_START_PTR(slice);
63 const uint8_t* const end = GRPC_SLICE_END_PTR(slice);
64 const uint8_t* cur = beg;
65 grpc_chttp2_goaway_parser* p =
66 static_cast<grpc_chttp2_goaway_parser*>(parser);
69 case GRPC_CHTTP2_GOAWAY_LSI0:
71 p->state = GRPC_CHTTP2_GOAWAY_LSI0;
72 return GRPC_ERROR_NONE;
74 p->last_stream_id = (static_cast<uint32_t>(*cur)) << 24;
77 case GRPC_CHTTP2_GOAWAY_LSI1:
79 p->state = GRPC_CHTTP2_GOAWAY_LSI1;
80 return GRPC_ERROR_NONE;
82 p->last_stream_id |= (static_cast<uint32_t>(*cur)) << 16;
85 case GRPC_CHTTP2_GOAWAY_LSI2:
87 p->state = GRPC_CHTTP2_GOAWAY_LSI2;
88 return GRPC_ERROR_NONE;
90 p->last_stream_id |= (static_cast<uint32_t>(*cur)) << 8;
93 case GRPC_CHTTP2_GOAWAY_LSI3:
95 p->state = GRPC_CHTTP2_GOAWAY_LSI3;
96 return GRPC_ERROR_NONE;
98 p->last_stream_id |= (static_cast<uint32_t>(*cur));
101 case GRPC_CHTTP2_GOAWAY_ERR0:
103 p->state = GRPC_CHTTP2_GOAWAY_ERR0;
104 return GRPC_ERROR_NONE;
106 p->error_code = (static_cast<uint32_t>(*cur)) << 24;
109 case GRPC_CHTTP2_GOAWAY_ERR1:
111 p->state = GRPC_CHTTP2_GOAWAY_ERR1;
112 return GRPC_ERROR_NONE;
114 p->error_code |= (static_cast<uint32_t>(*cur)) << 16;
117 case GRPC_CHTTP2_GOAWAY_ERR2:
119 p->state = GRPC_CHTTP2_GOAWAY_ERR2;
120 return GRPC_ERROR_NONE;
122 p->error_code |= (static_cast<uint32_t>(*cur)) << 8;
125 case GRPC_CHTTP2_GOAWAY_ERR3:
127 p->state = GRPC_CHTTP2_GOAWAY_ERR3;
128 return GRPC_ERROR_NONE;
130 p->error_code |= (static_cast<uint32_t>(*cur));
133 case GRPC_CHTTP2_GOAWAY_DEBUG:
135 memcpy(p->debug_data + p->debug_pos, cur,
136 static_cast<size_t>(end - cur));
137 GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos);
138 p->debug_pos += static_cast<uint32_t>(end - cur);
139 p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
141 grpc_chttp2_add_incoming_goaway(
142 t, p->error_code, p->last_stream_id,
143 grpc_slice_new(p->debug_data, p->debug_length, gpr_free));
144 p->debug_data = nullptr;
146 return GRPC_ERROR_NONE;
148 GPR_UNREACHABLE_CODE(
149 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here"));
152 void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
153 const grpc_slice& debug_data,
154 grpc_slice_buffer* slice_buffer) {
155 grpc_slice header = GRPC_SLICE_MALLOC(9 + 4 + 4);
156 uint8_t* p = GRPC_SLICE_START_PTR(header);
157 uint32_t frame_length;
158 GPR_ASSERT(GRPC_SLICE_LENGTH(debug_data) < UINT32_MAX - 4 - 4);
159 frame_length = 4 + 4 + static_cast<uint32_t> GRPC_SLICE_LENGTH(debug_data);
161 /* frame header: length */
162 *p++ = static_cast<uint8_t>(frame_length >> 16);
163 *p++ = static_cast<uint8_t>(frame_length >> 8);
164 *p++ = static_cast<uint8_t>(frame_length);
165 /* frame header: type */
166 *p++ = GRPC_CHTTP2_FRAME_GOAWAY;
167 /* frame header: flags */
169 /* frame header: stream id */
174 /* payload: last stream id */
175 *p++ = static_cast<uint8_t>(last_stream_id >> 24);
176 *p++ = static_cast<uint8_t>(last_stream_id >> 16);
177 *p++ = static_cast<uint8_t>(last_stream_id >> 8);
178 *p++ = static_cast<uint8_t>(last_stream_id);
179 /* payload: error code */
180 *p++ = static_cast<uint8_t>(error_code >> 24);
181 *p++ = static_cast<uint8_t>(error_code >> 16);
182 *p++ = static_cast<uint8_t>(error_code >> 8);
183 *p++ = static_cast<uint8_t>(error_code);
184 GPR_ASSERT(p == GRPC_SLICE_END_PTR(header));
185 grpc_slice_buffer_add(slice_buffer, header);
186 grpc_slice_buffer_add(slice_buffer, debug_data);