blob: bb8c28df904e1e222057ff0551705e5ec42aeca5 [file] [log] [blame]
nnoble0c475f02014-12-05 15:37:39 -08001/*
2 *
Craig Tiller8a9fd522016-03-25 17:09:29 -07003 * Copyright 2015-2016, Google Inc.
nnoble0c475f02014-12-05 15:37:39 -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_goaway.h"
35#include "src/core/lib/transport/chttp2/internal.h"
nnoble0c475f02014-12-05 15:37:39 -080036
37#include <string.h>
38
39#include <grpc/support/alloc.h>
40#include <grpc/support/log.h>
41
Craig Tillera82950e2015-09-22 12:33:20 -070042void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) {
nnoble0c475f02014-12-05 15:37:39 -080043 p->debug_data = NULL;
44}
45
Craig Tillera82950e2015-09-22 12:33:20 -070046void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) {
47 gpr_free(p->debug_data);
nnoble0c475f02014-12-05 15:37:39 -080048}
49
Craig Tillera82950e2015-09-22 12:33:20 -070050grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
Craig Tiller7536af02015-12-22 13:49:30 -080051 grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) {
Craig Tillera82950e2015-09-22 12:33:20 -070052 if (length < 8) {
53 gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length);
54 return GRPC_CHTTP2_CONNECTION_ERROR;
55 }
nnoble0c475f02014-12-05 15:37:39 -080056
Craig Tillera82950e2015-09-22 12:33:20 -070057 gpr_free(p->debug_data);
nnoble0c475f02014-12-05 15:37:39 -080058 p->debug_length = length - 8;
Craig Tillera82950e2015-09-22 12:33:20 -070059 p->debug_data = gpr_malloc(p->debug_length);
nnoble0c475f02014-12-05 15:37:39 -080060 p->debug_pos = 0;
61 p->state = GRPC_CHTTP2_GOAWAY_LSI0;
62 return GRPC_CHTTP2_PARSE_OK;
63}
64
Craig Tillera82950e2015-09-22 12:33:20 -070065grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
66 grpc_exec_ctx *exec_ctx, void *parser,
67 grpc_chttp2_transport_parsing *transport_parsing,
68 grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
Craig Tiller7536af02015-12-22 13:49:30 -080069 uint8_t *const beg = GPR_SLICE_START_PTR(slice);
70 uint8_t *const end = GPR_SLICE_END_PTR(slice);
71 uint8_t *cur = beg;
nnoble0c475f02014-12-05 15:37:39 -080072 grpc_chttp2_goaway_parser *p = parser;
73
Craig Tillera82950e2015-09-22 12:33:20 -070074 switch (p->state) {
nnoble0c475f02014-12-05 15:37:39 -080075 case GRPC_CHTTP2_GOAWAY_LSI0:
Craig Tillera82950e2015-09-22 12:33:20 -070076 if (cur == end) {
77 p->state = GRPC_CHTTP2_GOAWAY_LSI0;
78 return GRPC_CHTTP2_PARSE_OK;
79 }
Craig Tiller7536af02015-12-22 13:49:30 -080080 p->last_stream_id = ((uint32_t)*cur) << 24;
nnoble0c475f02014-12-05 15:37:39 -080081 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -070082 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -080083 case GRPC_CHTTP2_GOAWAY_LSI1:
Craig Tillera82950e2015-09-22 12:33:20 -070084 if (cur == end) {
85 p->state = GRPC_CHTTP2_GOAWAY_LSI1;
86 return GRPC_CHTTP2_PARSE_OK;
87 }
Craig Tiller7536af02015-12-22 13:49:30 -080088 p->last_stream_id |= ((uint32_t)*cur) << 16;
nnoble0c475f02014-12-05 15:37:39 -080089 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -070090 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -080091 case GRPC_CHTTP2_GOAWAY_LSI2:
Craig Tillera82950e2015-09-22 12:33:20 -070092 if (cur == end) {
93 p->state = GRPC_CHTTP2_GOAWAY_LSI2;
94 return GRPC_CHTTP2_PARSE_OK;
95 }
Craig Tiller7536af02015-12-22 13:49:30 -080096 p->last_stream_id |= ((uint32_t)*cur) << 8;
nnoble0c475f02014-12-05 15:37:39 -080097 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -070098 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -080099 case GRPC_CHTTP2_GOAWAY_LSI3:
Craig Tillera82950e2015-09-22 12:33:20 -0700100 if (cur == end) {
101 p->state = GRPC_CHTTP2_GOAWAY_LSI3;
102 return GRPC_CHTTP2_PARSE_OK;
103 }
Craig Tiller7536af02015-12-22 13:49:30 -0800104 p->last_stream_id |= ((uint32_t)*cur);
nnoble0c475f02014-12-05 15:37:39 -0800105 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700106 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -0800107 case GRPC_CHTTP2_GOAWAY_ERR0:
Craig Tillera82950e2015-09-22 12:33:20 -0700108 if (cur == end) {
109 p->state = GRPC_CHTTP2_GOAWAY_ERR0;
110 return GRPC_CHTTP2_PARSE_OK;
111 }
Craig Tiller7536af02015-12-22 13:49:30 -0800112 p->error_code = ((uint32_t)*cur) << 24;
nnoble0c475f02014-12-05 15:37:39 -0800113 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700114 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -0800115 case GRPC_CHTTP2_GOAWAY_ERR1:
Craig Tillera82950e2015-09-22 12:33:20 -0700116 if (cur == end) {
117 p->state = GRPC_CHTTP2_GOAWAY_ERR1;
118 return GRPC_CHTTP2_PARSE_OK;
119 }
Craig Tiller7536af02015-12-22 13:49:30 -0800120 p->error_code |= ((uint32_t)*cur) << 16;
nnoble0c475f02014-12-05 15:37:39 -0800121 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700122 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -0800123 case GRPC_CHTTP2_GOAWAY_ERR2:
Craig Tillera82950e2015-09-22 12:33:20 -0700124 if (cur == end) {
125 p->state = GRPC_CHTTP2_GOAWAY_ERR2;
126 return GRPC_CHTTP2_PARSE_OK;
127 }
Craig Tiller7536af02015-12-22 13:49:30 -0800128 p->error_code |= ((uint32_t)*cur) << 8;
nnoble0c475f02014-12-05 15:37:39 -0800129 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700130 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -0800131 case GRPC_CHTTP2_GOAWAY_ERR3:
Craig Tillera82950e2015-09-22 12:33:20 -0700132 if (cur == end) {
133 p->state = GRPC_CHTTP2_GOAWAY_ERR3;
134 return GRPC_CHTTP2_PARSE_OK;
135 }
Craig Tiller7536af02015-12-22 13:49:30 -0800136 p->error_code |= ((uint32_t)*cur);
nnoble0c475f02014-12-05 15:37:39 -0800137 ++cur;
Craig Tillera82950e2015-09-22 12:33:20 -0700138 /* fallthrough */
nnoble0c475f02014-12-05 15:37:39 -0800139 case GRPC_CHTTP2_GOAWAY_DEBUG:
Craig Tillera82950e2015-09-22 12:33:20 -0700140 memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur));
Craig Tiller7536af02015-12-22 13:49:30 -0800141 GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos);
142 p->debug_pos += (uint32_t)(end - cur);
nnoble0c475f02014-12-05 15:37:39 -0800143 p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
Craig Tillera82950e2015-09-22 12:33:20 -0700144 if (is_last) {
145 transport_parsing->goaway_received = 1;
146 transport_parsing->goaway_last_stream_index = p->last_stream_id;
147 gpr_slice_unref(transport_parsing->goaway_text);
148 transport_parsing->goaway_error = (grpc_status_code)p->error_code;
149 transport_parsing->goaway_text =
150 gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
151 p->debug_data = NULL;
152 }
nnoble0c475f02014-12-05 15:37:39 -0800153 return GRPC_CHTTP2_PARSE_OK;
Craig Tillera82950e2015-09-22 12:33:20 -0700154 }
yang-gb063c872015-10-07 11:40:13 -0700155 GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
nnoble0c475f02014-12-05 15:37:39 -0800156}
157
Craig Tiller7536af02015-12-22 13:49:30 -0800158void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,
Craig Tillera82950e2015-09-22 12:33:20 -0700159 gpr_slice debug_data,
160 gpr_slice_buffer *slice_buffer) {
161 gpr_slice header = gpr_slice_malloc(9 + 4 + 4);
Craig Tiller7536af02015-12-22 13:49:30 -0800162 uint8_t *p = GPR_SLICE_START_PTR(header);
163 uint32_t frame_length;
164 GPR_ASSERT(GPR_SLICE_LENGTH(debug_data) < UINT32_MAX - 4 - 4);
165 frame_length = 4 + 4 + (uint32_t)GPR_SLICE_LENGTH(debug_data);
nnoble0c475f02014-12-05 15:37:39 -0800166
167 /* frame header: length */
Craig Tiller7536af02015-12-22 13:49:30 -0800168 *p++ = (uint8_t)(frame_length >> 16);
169 *p++ = (uint8_t)(frame_length >> 8);
170 *p++ = (uint8_t)(frame_length);
nnoble0c475f02014-12-05 15:37:39 -0800171 /* frame header: type */
172 *p++ = GRPC_CHTTP2_FRAME_GOAWAY;
173 /* frame header: flags */
174 *p++ = 0;
175 /* frame header: stream id */
176 *p++ = 0;
177 *p++ = 0;
178 *p++ = 0;
179 *p++ = 0;
180 /* payload: last stream id */
Craig Tiller7536af02015-12-22 13:49:30 -0800181 *p++ = (uint8_t)(last_stream_id >> 24);
182 *p++ = (uint8_t)(last_stream_id >> 16);
183 *p++ = (uint8_t)(last_stream_id >> 8);
184 *p++ = (uint8_t)(last_stream_id);
nnoble0c475f02014-12-05 15:37:39 -0800185 /* payload: error code */
Craig Tiller7536af02015-12-22 13:49:30 -0800186 *p++ = (uint8_t)(error_code >> 24);
187 *p++ = (uint8_t)(error_code >> 16);
188 *p++ = (uint8_t)(error_code >> 8);
189 *p++ = (uint8_t)(error_code);
Craig Tillera82950e2015-09-22 12:33:20 -0700190 GPR_ASSERT(p == GPR_SLICE_END_PTR(header));
191 gpr_slice_buffer_add(slice_buffer, header);
192 gpr_slice_buffer_add(slice_buffer, debug_data);
Craig Tiller190d3602015-02-18 09:23:38 -0800193}