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/lib/http/parser.h" 22 23 #include <stdbool.h> 24 #include <string.h> 25 26 #include <grpc/support/alloc.h> 27 #include <grpc/support/log.h> 28 29 #include "src/core/lib/gpr/useful.h" 30 31 grpc_core::TraceFlag grpc_http1_trace(false, "http1"); 32 33 static char* buf2str(void* buffer, size_t length) { 34 char* out = static_cast<char*>(gpr_malloc(length + 1)); 35 memcpy(out, buffer, length); 36 out[length] = 0; 37 return out; 38 } 39 40 static grpc_error* handle_response_line(grpc_http_parser* parser) { 41 uint8_t* beg = parser->cur_line; 42 uint8_t* cur = beg; 43 uint8_t* end = beg + parser->cur_line_length; 44 45 if (cur == end || *cur++ != 'H') 46 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'H'"); 47 if (cur == end || *cur++ != 'T') 48 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); 49 if (cur == end || *cur++ != 'T') 50 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); 51 if (cur == end || *cur++ != 'P') 52 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'P'"); 53 if (cur == end || *cur++ != '/') 54 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '/'"); 55 if (cur == end || *cur++ != '1') 56 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '1'"); 57 if (cur == end || *cur++ != '.') 58 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '.'"); 59 if (cur == end || *cur < '0' || *cur++ > '1') { 60 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 61 "Expected HTTP/1.0 or HTTP/1.1"); 62 } 63 if (cur == end || *cur++ != ' ') 64 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected ' '"); 65 if (cur == end || *cur < '1' || *cur++ > '9') 66 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected status code"); 67 if (cur == end || *cur < '0' || *cur++ > '9') 68 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected status code"); 69 if (cur == end || *cur < '0' || *cur++ > '9') 70 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected status code"); 71 parser->http.response->status = 72 (cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0'); 73 if (cur == end || *cur++ != ' ') 74 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected ' '"); 75 76 /* we don't really care about the status code message */ 77 78 return GRPC_ERROR_NONE; 79 } 80 81 static grpc_error* handle_request_line(grpc_http_parser* parser) { 82 uint8_t* beg = parser->cur_line; 83 uint8_t* cur = beg; 84 uint8_t* end = beg + parser->cur_line_length; 85 uint8_t vers_major = 0; 86 uint8_t vers_minor = 0; 87 88 while (cur != end && *cur++ != ' ') 89 ; 90 if (cur == end) 91 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 92 "No method on HTTP request line"); 93 parser->http.request->method = 94 buf2str(beg, static_cast<size_t>(cur - beg - 1)); 95 96 beg = cur; 97 while (cur != end && *cur++ != ' ') 98 ; 99 if (cur == end) 100 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No path on HTTP request line"); 101 parser->http.request->path = buf2str(beg, static_cast<size_t>(cur - beg - 1)); 102 103 if (cur == end || *cur++ != 'H') 104 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'H'"); 105 if (cur == end || *cur++ != 'T') 106 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); 107 if (cur == end || *cur++ != 'T') 108 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'T'"); 109 if (cur == end || *cur++ != 'P') 110 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected 'P'"); 111 if (cur == end || *cur++ != '/') 112 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Expected '/'"); 113 vers_major = static_cast<uint8_t>(*cur++ - '1' + 1); 114 ++cur; 115 if (cur == end) 116 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 117 "End of line in HTTP version string"); 118 vers_minor = static_cast<uint8_t>(*cur++ - '1' + 1); 119 120 if (vers_major == 1) { 121 if (vers_minor == 0) { 122 parser->http.request->version = GRPC_HTTP_HTTP10; 123 } else if (vers_minor == 1) { 124 parser->http.request->version = GRPC_HTTP_HTTP11; 125 } else { 126 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 127 "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); 128 } 129 } else if (vers_major == 2) { 130 if (vers_minor == 0) { 131 parser->http.request->version = GRPC_HTTP_HTTP20; 132 } else { 133 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 134 "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); 135 } 136 } else { 137 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 138 "Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0"); 139 } 140 141 return GRPC_ERROR_NONE; 142 } 143 144 static grpc_error* handle_first_line(grpc_http_parser* parser) { 145 switch (parser->type) { 146 case GRPC_HTTP_REQUEST: 147 return handle_request_line(parser); 148 case GRPC_HTTP_RESPONSE: 149 return handle_response_line(parser); 150 } 151 GPR_UNREACHABLE_CODE( 152 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); 153 } 154 155 static grpc_error* add_header(grpc_http_parser* parser) { 156 uint8_t* beg = parser->cur_line; 157 uint8_t* cur = beg; 158 uint8_t* end = beg + parser->cur_line_length; 159 size_t* hdr_count = nullptr; 160 grpc_http_header** hdrs = nullptr; 161 grpc_http_header hdr = {nullptr, nullptr}; 162 grpc_error* error = GRPC_ERROR_NONE; 163 164 GPR_ASSERT(cur != end); 165 166 if (*cur == ' ' || *cur == '\t') { 167 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( 168 "Continued header lines not supported yet"); 169 goto done; 170 } 171 172 while (cur != end && *cur != ':') { 173 cur++; 174 } 175 if (cur == end) { 176 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( 177 "Didn't find ':' in header string"); 178 goto done; 179 } 180 GPR_ASSERT(cur >= beg); 181 hdr.key = buf2str(beg, static_cast<size_t>(cur - beg)); 182 cur++; /* skip : */ 183 184 while (cur != end && (*cur == ' ' || *cur == '\t')) { 185 cur++; 186 } 187 GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length); 188 hdr.value = buf2str( 189 cur, static_cast<size_t>(end - cur) - parser->cur_line_end_length); 190 191 switch (parser->type) { 192 case GRPC_HTTP_RESPONSE: 193 hdr_count = &parser->http.response->hdr_count; 194 hdrs = &parser->http.response->hdrs; 195 break; 196 case GRPC_HTTP_REQUEST: 197 hdr_count = &parser->http.request->hdr_count; 198 hdrs = &parser->http.request->hdrs; 199 break; 200 } 201 202 if (*hdr_count == parser->hdr_capacity) { 203 parser->hdr_capacity = 204 GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2); 205 *hdrs = static_cast<grpc_http_header*>( 206 gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs))); 207 } 208 (*hdrs)[(*hdr_count)++] = hdr; 209 210 done: 211 if (error != GRPC_ERROR_NONE) { 212 gpr_free(hdr.key); 213 gpr_free(hdr.value); 214 } 215 return error; 216 } 217 218 static grpc_error* finish_line(grpc_http_parser* parser, 219 bool* found_body_start) { 220 grpc_error* err; 221 switch (parser->state) { 222 case GRPC_HTTP_FIRST_LINE: 223 err = handle_first_line(parser); 224 if (err != GRPC_ERROR_NONE) return err; 225 parser->state = GRPC_HTTP_HEADERS; 226 break; 227 case GRPC_HTTP_HEADERS: 228 if (parser->cur_line_length == parser->cur_line_end_length) { 229 parser->state = GRPC_HTTP_BODY; 230 *found_body_start = true; 231 break; 232 } 233 err = add_header(parser); 234 if (err != GRPC_ERROR_NONE) { 235 return err; 236 } 237 break; 238 case GRPC_HTTP_BODY: 239 GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 240 "Should never reach here")); 241 } 242 243 parser->cur_line_length = 0; 244 return GRPC_ERROR_NONE; 245 } 246 247 static grpc_error* addbyte_body(grpc_http_parser* parser, uint8_t byte) { 248 size_t* body_length = nullptr; 249 char** body = nullptr; 250 251 if (parser->type == GRPC_HTTP_RESPONSE) { 252 body_length = &parser->http.response->body_length; 253 body = &parser->http.response->body; 254 } else if (parser->type == GRPC_HTTP_REQUEST) { 255 body_length = &parser->http.request->body_length; 256 body = &parser->http.request->body; 257 } else { 258 GPR_UNREACHABLE_CODE( 259 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); 260 } 261 262 if (*body_length == parser->body_capacity) { 263 parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2); 264 *body = 265 static_cast<char*>(gpr_realloc((void*)*body, parser->body_capacity)); 266 } 267 (*body)[*body_length] = static_cast<char>(byte); 268 (*body_length)++; 269 270 return GRPC_ERROR_NONE; 271 } 272 273 static bool check_line(grpc_http_parser* parser) { 274 if (parser->cur_line_length >= 2 && 275 parser->cur_line[parser->cur_line_length - 2] == '\r' && 276 parser->cur_line[parser->cur_line_length - 1] == '\n') { 277 return true; 278 } 279 280 // HTTP request with \n\r line termiantors. 281 else if (parser->cur_line_length >= 2 && 282 parser->cur_line[parser->cur_line_length - 2] == '\n' && 283 parser->cur_line[parser->cur_line_length - 1] == '\r') { 284 return true; 285 } 286 287 // HTTP request with only \n line terminators. 288 else if (parser->cur_line_length >= 1 && 289 parser->cur_line[parser->cur_line_length - 1] == '\n') { 290 parser->cur_line_end_length = 1; 291 return true; 292 } 293 294 return false; 295 } 296 297 static grpc_error* addbyte(grpc_http_parser* parser, uint8_t byte, 298 bool* found_body_start) { 299 switch (parser->state) { 300 case GRPC_HTTP_FIRST_LINE: 301 case GRPC_HTTP_HEADERS: 302 if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) { 303 if (grpc_http1_trace.enabled()) 304 gpr_log(GPR_ERROR, "HTTP header max line length (%d) exceeded", 305 GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); 306 return GRPC_ERROR_CREATE_FROM_STATIC_STRING( 307 "HTTP header max line length exceeded"); 308 } 309 parser->cur_line[parser->cur_line_length] = byte; 310 parser->cur_line_length++; 311 if (check_line(parser)) { 312 return finish_line(parser, found_body_start); 313 } 314 return GRPC_ERROR_NONE; 315 case GRPC_HTTP_BODY: 316 return addbyte_body(parser, byte); 317 } 318 GPR_UNREACHABLE_CODE(return GRPC_ERROR_NONE); 319 } 320 321 void grpc_http_parser_init(grpc_http_parser* parser, grpc_http_type type, 322 void* request_or_response) { 323 memset(parser, 0, sizeof(*parser)); 324 parser->state = GRPC_HTTP_FIRST_LINE; 325 parser->type = type; 326 parser->http.request_or_response = request_or_response; 327 parser->cur_line_end_length = 2; 328 } 329 330 void grpc_http_parser_destroy(grpc_http_parser* parser) {} 331 332 void grpc_http_request_destroy(grpc_http_request* request) { 333 size_t i; 334 gpr_free(request->body); 335 for (i = 0; i < request->hdr_count; i++) { 336 gpr_free(request->hdrs[i].key); 337 gpr_free(request->hdrs[i].value); 338 } 339 gpr_free(request->hdrs); 340 gpr_free(request->method); 341 gpr_free(request->path); 342 } 343 344 void grpc_http_response_destroy(grpc_http_response* response) { 345 size_t i; 346 gpr_free(response->body); 347 for (i = 0; i < response->hdr_count; i++) { 348 gpr_free(response->hdrs[i].key); 349 gpr_free(response->hdrs[i].value); 350 } 351 gpr_free(response->hdrs); 352 } 353 354 grpc_error* grpc_http_parser_parse(grpc_http_parser* parser, grpc_slice slice, 355 size_t* start_of_body) { 356 for (size_t i = 0; i < GRPC_SLICE_LENGTH(slice); i++) { 357 bool found_body_start = false; 358 grpc_error* err = 359 addbyte(parser, GRPC_SLICE_START_PTR(slice)[i], &found_body_start); 360 if (err != GRPC_ERROR_NONE) return err; 361 if (found_body_start && start_of_body != nullptr) *start_of_body = i + 1; 362 } 363 return GRPC_ERROR_NONE; 364 } 365 366 grpc_error* grpc_http_parser_eof(grpc_http_parser* parser) { 367 if (parser->state != GRPC_HTTP_BODY) { 368 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Did not finish headers"); 369 } 370 return GRPC_ERROR_NONE; 371 } 372