parser.cc 12 KB

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