tcpflow  1.6.1
About: tcpflow is a TCP/IP packet demultiplexer that captures data transmitted as part of TCP connections (flows), and stores the data in a way that is convenient for protocol analysis and debugging.
  Fossies Dox: tcpflow-1.6.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

http_parser.c
Go to the documentation of this file.
1 /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
2  *
3  * Additional changes are licensed under the same terms as NGINX and
4  * copyright Joyent, Inc. and other Node contributors. All rights reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 #include "http_parser.h"
25 #include <assert.h>
26 #include <stddef.h>
27 #include <ctype.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <limits.h>
31 
32 #ifndef ULLONG_MAX
33 # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
34 #endif
35 
36 #ifndef MIN
37 # define MIN(a,b) ((a) < (b) ? (a) : (b))
38 #endif
39 
40 #ifndef ARRAY_SIZE
41 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
42 #endif
43 
44 #ifndef BIT_AT
45 # define BIT_AT(a, i) \
46  (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
47  (1 << ((unsigned int) (i) & 7))))
48 #endif
49 
50 #ifndef ELEM_AT
51 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
52 #endif
53 
54 #define SET_ERRNO(e) \
55 do { \
56  parser->http_errno = (e); \
57 } while(0)
58 
59 #define CURRENT_STATE() p_state
60 #define UPDATE_STATE(V) p_state = (enum state) (V);
61 #define RETURN(V) \
62 do { \
63  parser->state = CURRENT_STATE(); \
64  return (V); \
65 } while (0);
66 #define REEXECUTE() \
67  goto reexecute; \
68 
69 
70 #ifdef __GNUC__
71 # define LIKELY(X) __builtin_expect(!!(X), 1)
72 # define UNLIKELY(X) __builtin_expect(!!(X), 0)
73 #else
74 # define LIKELY(X) (X)
75 # define UNLIKELY(X) (X)
76 #endif
77 
78 
79 /* Run the notify callback FOR, returning ER if it fails */
80 #define CALLBACK_NOTIFY_(FOR, ER) \
81 do { \
82  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
83  \
84  if (LIKELY(settings->on_##FOR)) { \
85  parser->state = CURRENT_STATE(); \
86  if (UNLIKELY(0 != settings->on_##FOR(parser))) { \
87  SET_ERRNO(HPE_CB_##FOR); \
88  } \
89  UPDATE_STATE(parser->state); \
90  \
91  /* We either errored above or got paused; get out */ \
92  if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
93  return (ER); \
94  } \
95  } \
96 } while (0)
97 
98 /* Run the notify callback FOR and consume the current byte */
99 #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
100 
101 /* Run the notify callback FOR and don't consume the current byte */
102 #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
103 
104 /* Run data callback FOR with LEN bytes, returning ER if it fails */
105 #define CALLBACK_DATA_(FOR, LEN, ER) \
106 do { \
107  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
108  \
109  if (FOR##_mark) { \
110  if (LIKELY(settings->on_##FOR)) { \
111  parser->state = CURRENT_STATE(); \
112  if (UNLIKELY(0 != \
113  settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
114  SET_ERRNO(HPE_CB_##FOR); \
115  } \
116  UPDATE_STATE(parser->state); \
117  \
118  /* We either errored above or got paused; get out */ \
119  if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
120  return (ER); \
121  } \
122  } \
123  FOR##_mark = NULL; \
124  } \
125 } while (0)
126 
127 /* Run the data callback FOR and consume the current byte */
128 #define CALLBACK_DATA(FOR) \
129  CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
130 
131 /* Run the data callback FOR and don't consume the current byte */
132 #define CALLBACK_DATA_NOADVANCE(FOR) \
133  CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
134 
135 /* Set the mark FOR; non-destructive if mark is already set */
136 #define MARK(FOR) \
137 do { \
138  if (!FOR##_mark) { \
139  FOR##_mark = p; \
140  } \
141 } while (0)
142 
143 /* Don't allow the total size of the HTTP headers (including the status
144  * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect
145  * embedders against denial-of-service attacks where the attacker feeds
146  * us a never-ending header that the embedder keeps buffering.
147  *
148  * This check is arguably the responsibility of embedders but we're doing
149  * it on the embedder's behalf because most won't bother and this way we
150  * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger
151  * than any reasonable request or response so this should never affect
152  * day-to-day operation.
153  */
154 #define COUNT_HEADER_SIZE(V) \
155 do { \
156  parser->nread += (V); \
157  if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \
158  SET_ERRNO(HPE_HEADER_OVERFLOW); \
159  goto error; \
160  } \
161 } while (0)
162 
163 
164 #define PROXY_CONNECTION "proxy-connection"
165 #define CONNECTION "connection"
166 #define CONTENT_LENGTH "content-length"
167 #define TRANSFER_ENCODING "transfer-encoding"
168 #define UPGRADE "upgrade"
169 #define CHUNKED "chunked"
170 #define KEEP_ALIVE "keep-alive"
171 #define CLOSE "close"
172 
173 
174 static const char *method_strings[] =
175  {
176 #define XX(num, name, string) #string,
178 #undef XX
179  };
180 
181 
182 /* Tokens as defined by rfc 2616. Also lowercases them.
183  * token = 1*<any CHAR except CTLs or separators>
184  * separators = "(" | ")" | "<" | ">" | "@"
185  * | "," | ";" | ":" | "\" | <">
186  * | "/" | "[" | "]" | "?" | "="
187  * | "{" | "}" | SP | HT
188  */
189 static const char tokens[256] = {
190 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
191  0, 0, 0, 0, 0, 0, 0, 0,
192 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
193  0, 0, 0, 0, 0, 0, 0, 0,
194 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
195  0, 0, 0, 0, 0, 0, 0, 0,
196 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
197  0, 0, 0, 0, 0, 0, 0, 0,
198 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
199  0, '!', 0, '#', '$', '%', '&', '\'',
200 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
201  0, 0, '*', '+', 0, '-', '.', 0,
202 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
203  '0', '1', '2', '3', '4', '5', '6', '7',
204 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
205  '8', '9', 0, 0, 0, 0, 0, 0,
206 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
207  0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
208 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
209  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
210 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
211  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
212 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
213  'x', 'y', 'z', 0, 0, 0, '^', '_',
214 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
215  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
216 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
217  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
218 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
219  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
220 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
221  'x', 'y', 'z', 0, '|', 0, '~', 0 };
222 
223 
224 static const int8_t unhex[256] =
225  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
226  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
227  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
228  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
229  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
230  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
231  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
232  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
233  };
234 
235 
236 #if HTTP_PARSER_STRICT
237 # define T(v) 0
238 #else
239 # define T(v) v
240 #endif
241 
242 
243 static const uint8_t normal_url_char[32] = {
244 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
245  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
246 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
247  0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
248 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
249  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
250 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
251  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
252 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
253  0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
254 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
255  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
256 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
257  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
258 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
259  1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
260 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
261  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
262 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
263  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
264 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
265  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
266 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
267  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
268 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
269  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
270 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
271  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
272 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
273  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
274 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
275  1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
276 
277 #undef T
278 
279 enum state
280  { s_dead = 1 /* important that this is > 0 */
281 
298 
299  , s_start_req
300 
324 
333 
335 
340 
343 
344  /* Important: 's_headers_done' must be the last 'header' state. All
345  * states beyond this must be 'body' states. It is used for overflow
346  * checking. See the PARSING_HEADER() macro.
347  */
348 
352 
355 
357  };
358 
359 
360 #define PARSING_HEADER(state) (state <= s_headers_done)
361 
362 
363 enum header_states
364  { h_general = 0
365  , h_C
367  , h_CON
368 
374 
378  , h_upgrade
379 
386 
391  };
392 
393 enum http_host_state
394  {
407 };
408 
409 /* Macros for character classes; depends on strict-mode */
410 #define CR '\r'
411 #define LF '\n'
412 #define LOWER(c) (unsigned char)(c | 0x20)
413 #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
414 #define IS_NUM(c) ((c) >= '0' && (c) <= '9')
415 #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
416 #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
417 #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
418  (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
419  (c) == ')')
420 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
421  (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
422  (c) == '$' || (c) == ',')
423 
424 #define STRICT_TOKEN(c) (tokens[(unsigned char)c])
425 
426 #if HTTP_PARSER_STRICT
427 #define TOKEN(c) (tokens[(unsigned char)c])
428 #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
429 #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
430 #else
431 #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
432 #define IS_URL_CHAR(c) \
433  (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
434 #define IS_HOST_CHAR(c) \
435  (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
436 #endif
437 
438 /**
439  * Verify that a char is a valid visible (printable) US-ASCII
440  * character or %x80-FF
441  **/
442 #define IS_HEADER_CHAR(ch) \
443  (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
444 
445 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
446 
447 
448 #if HTTP_PARSER_STRICT
449 # define STRICT_CHECK(cond) \
450 do { \
451  if (cond) { \
452  SET_ERRNO(HPE_STRICT); \
453  goto error; \
454  } \
455 } while (0)
456 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
457 #else
458 # define STRICT_CHECK(cond)
459 # define NEW_MESSAGE() start_state
460 #endif
461 
462 
463 /* Map errno values to strings for human-readable output */
464 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
465 static struct {
466  const char *name;
467  const char *description;
470 };
471 #undef HTTP_STRERROR_GEN
472 
473 int http_message_needs_eof(const http_parser *parser);
474 
475 /* Our URL parser.
476  *
477  * This is designed to be shared by http_parser_execute() for URL validation,
478  * hence it has a state transition + byte-for-byte interface. In addition, it
479  * is meant to be embedded in http_parser_parse_url(), which does the dirty
480  * work of turning state transitions URL components for its API.
481  *
482  * This function should only be invoked with non-space characters. It is
483  * assumed that the caller cares about (and can detect) the transition between
484  * URL and non-URL states by looking for these.
485  */
486 static enum state
487 parse_url_char(enum state s, const char ch)
488 {
489  if (ch == ' ' || ch == '\r' || ch == '\n') {
490  return s_dead;
491  }
492 
493 #if HTTP_PARSER_STRICT
494  if (ch == '\t' || ch == '\f') {
495  return s_dead;
496  }
497 #endif
498 
499  switch (s) {
501  /* Proxied requests are followed by scheme of an absolute URI (alpha).
502  * All methods except CONNECT are followed by '/' or '*'.
503  */
504 
505  if (ch == '/' || ch == '*') {
506  return s_req_path;
507  }
508 
509  if (IS_ALPHA(ch)) {
510  return s_req_schema;
511  }
512 
513  break;
514 
515  case s_req_schema:
516  if (IS_ALPHA(ch)) {
517  return s;
518  }
519 
520  if (ch == ':') {
521  return s_req_schema_slash;
522  }
523 
524  break;
525 
526  case s_req_schema_slash:
527  if (ch == '/') {
529  }
530 
531  break;
532 
534  if (ch == '/') {
535  return s_req_server_start;
536  }
537 
538  break;
539 
541  if (ch == '@') {
542  return s_dead;
543  }
544 
545  /* FALLTHROUGH */
546  case s_req_server_start:
547  case s_req_server:
548  if (ch == '/') {
549  return s_req_path;
550  }
551 
552  if (ch == '?') {
554  }
555 
556  if (ch == '@') {
557  return s_req_server_with_at;
558  }
559 
560  if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
561  return s_req_server;
562  }
563 
564  break;
565 
566  case s_req_path:
567  if (IS_URL_CHAR(ch)) {
568  return s;
569  }
570 
571  switch (ch) {
572  case '?':
574 
575  case '#':
576  return s_req_fragment_start;
577  }
578 
579  break;
580 
582  case s_req_query_string:
583  if (IS_URL_CHAR(ch)) {
584  return s_req_query_string;
585  }
586 
587  switch (ch) {
588  case '?':
589  /* allow extra '?' in query string */
590  return s_req_query_string;
591 
592  case '#':
593  return s_req_fragment_start;
594  }
595 
596  break;
597 
599  if (IS_URL_CHAR(ch)) {
600  return s_req_fragment;
601  }
602 
603  switch (ch) {
604  case '?':
605  return s_req_fragment;
606 
607  case '#':
608  return s;
609  }
610 
611  break;
612 
613  case s_req_fragment:
614  if (IS_URL_CHAR(ch)) {
615  return s;
616  }
617 
618  switch (ch) {
619  case '?':
620  case '#':
621  return s;
622  }
623 
624  break;
625 
626  default:
627  break;
628  }
629 
630  /* We should never fall out of the switch above unless there's an error */
631  return s_dead;
632 }
633 
634 size_t http_parser_execute (http_parser *parser,
635  const http_parser_settings *settings,
636  const char *data,
637  size_t len)
638 {
639  char c, ch;
640  int8_t unhex_val;
641  const char *p = data;
642  const char *header_field_mark = 0;
643  const char *header_value_mark = 0;
644  const char *url_mark = 0;
645  const char *body_mark = 0;
646  const char *status_mark = 0;
647  enum state p_state = (enum state) parser->state;
648  const unsigned int lenient = parser->lenient_http_headers;
649 
650  /* We're in an error state. Don't bother doing anything. */
651  if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
652  return 0;
653  }
654 
655  if (len == 0) {
656  switch (CURRENT_STATE()) {
657  case s_body_identity_eof:
658  /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
659  * we got paused.
660  */
661  CALLBACK_NOTIFY_NOADVANCE(message_complete);
662  return 0;
663 
664  case s_dead:
665  case s_start_req_or_res:
666  case s_start_res:
667  case s_start_req:
668  return 0;
669 
670  default:
672  return 1;
673  }
674  }
675 
676 
677  if (CURRENT_STATE() == s_header_field)
678  header_field_mark = data;
679  if (CURRENT_STATE() == s_header_value)
680  header_value_mark = data;
681  switch (CURRENT_STATE()) {
682  case s_req_path:
683  case s_req_schema:
684  case s_req_schema_slash:
686  case s_req_server_start:
687  case s_req_server:
690  case s_req_query_string:
692  case s_req_fragment:
693  url_mark = data;
694  break;
695  case s_res_status:
696  status_mark = data;
697  break;
698  default:
699  break;
700  }
701 
702  for (p=data; p != data + len; p++) {
703  ch = *p;
704 
707 
708 reexecute:
709  switch (CURRENT_STATE()) {
710 
711  case s_dead:
712  /* this state is used after a 'Connection: close' message
713  * the parser will error out if it reads another message
714  */
715  if (LIKELY(ch == CR || ch == LF))
716  break;
717 
719  goto error;
720 
721  case s_start_req_or_res:
722  {
723  if (ch == CR || ch == LF)
724  break;
725  parser->flags = 0;
726  parser->content_length = ULLONG_MAX;
727 
728  if (ch == 'H') {
730 
731  CALLBACK_NOTIFY(message_begin);
732  } else {
733  parser->type = HTTP_REQUEST;
735  REEXECUTE();
736  }
737 
738  break;
739  }
740 
741  case s_res_or_resp_H:
742  if (ch == 'T') {
743  parser->type = HTTP_RESPONSE;
745  } else {
746  if (UNLIKELY(ch != 'E')) {
748  goto error;
749  }
750 
751  parser->type = HTTP_REQUEST;
752  parser->method = HTTP_HEAD;
753  parser->index = 2;
755  }
756  break;
757 
758  case s_start_res:
759  {
760  parser->flags = 0;
761  parser->content_length = ULLONG_MAX;
762 
763  switch (ch) {
764  case 'H':
766  break;
767 
768  case CR:
769  case LF:
770  break;
771 
772  default:
774  goto error;
775  }
776 
777  CALLBACK_NOTIFY(message_begin);
778  break;
779  }
780 
781  case s_res_H:
782  STRICT_CHECK(ch != 'T');
784  break;
785 
786  case s_res_HT:
787  STRICT_CHECK(ch != 'T');
789  break;
790 
791  case s_res_HTT:
792  STRICT_CHECK(ch != 'P');
794  break;
795 
796  case s_res_HTTP:
797  STRICT_CHECK(ch != '/');
799  break;
800 
801  case s_res_http_major:
802  if (UNLIKELY(!IS_NUM(ch))) {
804  goto error;
805  }
806 
807  parser->http_major = ch - '0';
809  break;
810 
811  case s_res_http_dot:
812  {
813  if (UNLIKELY(ch != '.')) {
815  goto error;
816  }
817 
819  break;
820  }
821 
822  case s_res_http_minor:
823  if (UNLIKELY(!IS_NUM(ch))) {
825  goto error;
826  }
827 
828  parser->http_minor = ch - '0';
830  break;
831 
832  case s_res_http_end:
833  {
834  if (UNLIKELY(ch != ' ')) {
836  goto error;
837  }
838 
840  break;
841  }
842 
844  {
845  if (!IS_NUM(ch)) {
846  if (ch == ' ') {
847  break;
848  }
849 
851  goto error;
852  }
853  parser->status_code = ch - '0';
855  break;
856  }
857 
858  case s_res_status_code:
859  {
860  if (!IS_NUM(ch)) {
861  switch (ch) {
862  case ' ':
864  break;
865  case CR:
866  case LF:
868  REEXECUTE();
869  break;
870  default:
872  goto error;
873  }
874  break;
875  }
876 
877  parser->status_code *= 10;
878  parser->status_code += ch - '0';
879 
880  if (UNLIKELY(parser->status_code > 999)) {
882  goto error;
883  }
884 
885  break;
886  }
887 
888  case s_res_status_start:
889  {
890  MARK(status);
892  parser->index = 0;
893 
894  if (ch == CR || ch == LF)
895  REEXECUTE();
896 
897  break;
898  }
899 
900  case s_res_status:
901  if (ch == CR) {
903  CALLBACK_DATA(status);
904  break;
905  }
906 
907  if (ch == LF) {
909  CALLBACK_DATA(status);
910  break;
911  }
912 
913  break;
914 
916  STRICT_CHECK(ch != LF);
918  break;
919 
920  case s_start_req:
921  {
922  if (ch == CR || ch == LF)
923  break;
924  parser->flags = 0;
925  parser->content_length = ULLONG_MAX;
926 
927  if (UNLIKELY(!IS_ALPHA(ch))) {
929  goto error;
930  }
931 
932  parser->method = (enum http_method) 0;
933  parser->index = 1;
934  switch (ch) {
935  case 'A': parser->method = HTTP_ACL; break;
936  case 'B': parser->method = HTTP_BIND; break;
937  case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
938  case 'D': parser->method = HTTP_DELETE; break;
939  case 'G': parser->method = HTTP_GET; break;
940  case 'H': parser->method = HTTP_HEAD; break;
941  case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;
942  case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
943  case 'N': parser->method = HTTP_NOTIFY; break;
944  case 'O': parser->method = HTTP_OPTIONS; break;
945  case 'P': parser->method = HTTP_POST;
946  /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
947  break;
948  case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
949  case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
950  case 'T': parser->method = HTTP_TRACE; break;
951  case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
952  default:
954  goto error;
955  }
957 
958  CALLBACK_NOTIFY(message_begin);
959 
960  break;
961  }
962 
963  case s_req_method:
964  {
965  const char *matcher;
966  if (UNLIKELY(ch == '\0')) {
968  goto error;
969  }
970 
971  matcher = method_strings[parser->method];
972  if (ch == ' ' && matcher[parser->index] == '\0') {
974  } else if (ch == matcher[parser->index]) {
975  ; /* nada */
976  } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') {
977 
978  switch (parser->method << 16 | parser->index << 8 | ch) {
979 #define XX(meth, pos, ch, new_meth) \
980  case (HTTP_##meth << 16 | pos << 8 | ch): \
981  parser->method = HTTP_##new_meth; break;
982 
983  XX(POST, 1, 'U', PUT)
984  XX(POST, 1, 'A', PATCH)
985  XX(POST, 1, 'R', PROPFIND)
986  XX(PUT, 2, 'R', PURGE)
987  XX(CONNECT, 1, 'H', CHECKOUT)
988  XX(CONNECT, 2, 'P', COPY)
989  XX(MKCOL, 1, 'O', MOVE)
990  XX(MKCOL, 1, 'E', MERGE)
991  XX(MKCOL, 1, '-', MSEARCH)
992  XX(MKCOL, 2, 'A', MKACTIVITY)
993  XX(MKCOL, 3, 'A', MKCALENDAR)
994  XX(SUBSCRIBE, 1, 'E', SEARCH)
995  XX(REPORT, 2, 'B', REBIND)
996  XX(PROPFIND, 4, 'P', PROPPATCH)
997  XX(LOCK, 1, 'I', LINK)
998  XX(UNLOCK, 2, 'S', UNSUBSCRIBE)
999  XX(UNLOCK, 2, 'B', UNBIND)
1000  XX(UNLOCK, 3, 'I', UNLINK)
1001 #undef XX
1002  default:
1004  goto error;
1005  }
1006  } else {
1008  goto error;
1009  }
1010 
1011  ++parser->index;
1012  break;
1013  }
1014 
1016  {
1017  if (ch == ' ') break;
1018 
1019  MARK(url);
1020  if (parser->method == HTTP_CONNECT) {
1022  }
1023 
1025  if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1027  goto error;
1028  }
1029 
1030  break;
1031  }
1032 
1033  case s_req_schema:
1034  case s_req_schema_slash:
1036  case s_req_server_start:
1037  {
1038  switch (ch) {
1039  /* No whitespace allowed here */
1040  case ' ':
1041  case CR:
1042  case LF:
1044  goto error;
1045  default:
1047  if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1049  goto error;
1050  }
1051  }
1052 
1053  break;
1054  }
1055 
1056  case s_req_server:
1057  case s_req_server_with_at:
1058  case s_req_path:
1060  case s_req_query_string:
1061  case s_req_fragment_start:
1062  case s_req_fragment:
1063  {
1064  switch (ch) {
1065  case ' ':
1067  CALLBACK_DATA(url);
1068  break;
1069  case CR:
1070  case LF:
1071  parser->http_major = 0;
1072  parser->http_minor = 9;
1073  UPDATE_STATE((ch == CR) ?
1076  CALLBACK_DATA(url);
1077  break;
1078  default:
1080  if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1082  goto error;
1083  }
1084  }
1085  break;
1086  }
1087 
1088  case s_req_http_start:
1089  switch (ch) {
1090  case 'H':
1092  break;
1093  case ' ':
1094  break;
1095  default:
1097  goto error;
1098  }
1099  break;
1100 
1101  case s_req_http_H:
1102  STRICT_CHECK(ch != 'T');
1104  break;
1105 
1106  case s_req_http_HT:
1107  STRICT_CHECK(ch != 'T');
1109  break;
1110 
1111  case s_req_http_HTT:
1112  STRICT_CHECK(ch != 'P');
1114  break;
1115 
1116  case s_req_http_HTTP:
1117  STRICT_CHECK(ch != '/');
1119  break;
1120 
1121  case s_req_http_major:
1122  if (UNLIKELY(!IS_NUM(ch))) {
1124  goto error;
1125  }
1126 
1127  parser->http_major = ch - '0';
1129  break;
1130 
1131  case s_req_http_dot:
1132  {
1133  if (UNLIKELY(ch != '.')) {
1135  goto error;
1136  }
1137 
1139  break;
1140  }
1141 
1142  case s_req_http_minor:
1143  if (UNLIKELY(!IS_NUM(ch))) {
1145  goto error;
1146  }
1147 
1148  parser->http_minor = ch - '0';
1150  break;
1151 
1152  case s_req_http_end:
1153  {
1154  if (ch == CR) {
1156  break;
1157  }
1158 
1159  if (ch == LF) {
1161  break;
1162  }
1163 
1165  goto error;
1166  break;
1167  }
1168 
1169  /* end of request line */
1171  {
1172  if (UNLIKELY(ch != LF)) {
1174  goto error;
1175  }
1176 
1178  break;
1179  }
1180 
1181  case s_header_field_start:
1182  {
1183  if (ch == CR) {
1185  break;
1186  }
1187 
1188  if (ch == LF) {
1189  /* they might be just sending \n instead of \r\n so this would be
1190  * the second \n to denote the end of headers*/
1192  REEXECUTE();
1193  }
1194 
1195  c = TOKEN(ch);
1196 
1197  if (UNLIKELY(!c)) {
1199  goto error;
1200  }
1201 
1202  MARK(header_field);
1203 
1204  parser->index = 0;
1206 
1207  switch (c) {
1208  case 'c':
1209  parser->header_state = h_C;
1210  break;
1211 
1212  case 'p':
1214  break;
1215 
1216  case 't':
1218  break;
1219 
1220  case 'u':
1221  parser->header_state = h_matching_upgrade;
1222  break;
1223 
1224  default:
1225  parser->header_state = h_general;
1226  break;
1227  }
1228  break;
1229  }
1230 
1231  case s_header_field:
1232  {
1233  const char* start = p;
1234  for (; p != data + len; p++) {
1235  ch = *p;
1236  c = TOKEN(ch);
1237 
1238  if (!c)
1239  break;
1240 
1241  switch (parser->header_state) {
1242  case h_general:
1243  break;
1244 
1245  case h_C:
1246  parser->index++;
1247  parser->header_state = (c == 'o' ? h_CO : h_general);
1248  break;
1249 
1250  case h_CO:
1251  parser->index++;
1252  parser->header_state = (c == 'n' ? h_CON : h_general);
1253  break;
1254 
1255  case h_CON:
1256  parser->index++;
1257  switch (c) {
1258  case 'n':
1260  break;
1261  case 't':
1263  break;
1264  default:
1265  parser->header_state = h_general;
1266  break;
1267  }
1268  break;
1269 
1270  /* connection */
1271 
1272  case h_matching_connection:
1273  parser->index++;
1274  if (parser->index > sizeof(CONNECTION)-1
1275  || c != CONNECTION[parser->index]) {
1276  parser->header_state = h_general;
1277  } else if (parser->index == sizeof(CONNECTION)-2) {
1278  parser->header_state = h_connection;
1279  }
1280  break;
1281 
1282  /* proxy-connection */
1283 
1285  parser->index++;
1286  if (parser->index > sizeof(PROXY_CONNECTION)-1
1287  || c != PROXY_CONNECTION[parser->index]) {
1288  parser->header_state = h_general;
1289  } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
1290  parser->header_state = h_connection;
1291  }
1292  break;
1293 
1294  /* content-length */
1295 
1297  parser->index++;
1298  if (parser->index > sizeof(CONTENT_LENGTH)-1
1299  || c != CONTENT_LENGTH[parser->index]) {
1300  parser->header_state = h_general;
1301  } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
1302  parser->header_state = h_content_length;
1303  }
1304  break;
1305 
1306  /* transfer-encoding */
1307 
1309  parser->index++;
1310  if (parser->index > sizeof(TRANSFER_ENCODING)-1
1311  || c != TRANSFER_ENCODING[parser->index]) {
1312  parser->header_state = h_general;
1313  } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
1315  }
1316  break;
1317 
1318  /* upgrade */
1319 
1320  case h_matching_upgrade:
1321  parser->index++;
1322  if (parser->index > sizeof(UPGRADE)-1
1323  || c != UPGRADE[parser->index]) {
1324  parser->header_state = h_general;
1325  } else if (parser->index == sizeof(UPGRADE)-2) {
1326  parser->header_state = h_upgrade;
1327  }
1328  break;
1329 
1330  case h_connection:
1331  case h_content_length:
1332  case h_transfer_encoding:
1333  case h_upgrade:
1334  if (ch != ' ') parser->header_state = h_general;
1335  break;
1336 
1337  default:
1338  assert(0 && "Unknown header_state");
1339  break;
1340  }
1341  }
1342 
1343  COUNT_HEADER_SIZE(p - start);
1344 
1345  if (p == data + len) {
1346  --p;
1347  break;
1348  }
1349 
1350  if (ch == ':') {
1352  CALLBACK_DATA(header_field);
1353  break;
1354  }
1355 
1357  goto error;
1358  }
1359 
1361  if (ch == ' ' || ch == '\t') break;
1362 
1363  if (ch == CR) {
1365  break;
1366  }
1367 
1368  if (ch == LF) {
1370  break;
1371  }
1372 
1373  /* FALLTHROUGH */
1374 
1375  case s_header_value_start:
1376  {
1377  MARK(header_value);
1378 
1380  parser->index = 0;
1381 
1382  c = LOWER(ch);
1383 
1384  switch (parser->header_state) {
1385  case h_upgrade:
1386  parser->flags |= F_UPGRADE;
1387  parser->header_state = h_general;
1388  break;
1389 
1390  case h_transfer_encoding:
1391  /* looking for 'Transfer-Encoding: chunked' */
1392  if ('c' == c) {
1394  } else {
1395  parser->header_state = h_general;
1396  }
1397  break;
1398 
1399  case h_content_length:
1400  if (UNLIKELY(!IS_NUM(ch))) {
1402  goto error;
1403  }
1404 
1405  if (parser->flags & F_CONTENTLENGTH) {
1407  goto error;
1408  }
1409 
1410  parser->flags |= F_CONTENTLENGTH;
1411  parser->content_length = ch - '0';
1412  break;
1413 
1414  case h_connection:
1415  /* looking for 'Connection: keep-alive' */
1416  if (c == 'k') {
1418  /* looking for 'Connection: close' */
1419  } else if (c == 'c') {
1421  } else if (c == 'u') {
1423  } else {
1425  }
1426  break;
1427 
1428  /* Multi-value `Connection` header */
1430  break;
1431 
1432  default:
1433  parser->header_state = h_general;
1434  break;
1435  }
1436  break;
1437  }
1438 
1439  case s_header_value:
1440  {
1441  const char* start = p;
1442  enum header_states h_state = (enum header_states) parser->header_state;
1443  for (; p != data + len; p++) {
1444  ch = *p;
1445  if (ch == CR) {
1447  parser->header_state = h_state;
1448  CALLBACK_DATA(header_value);
1449  break;
1450  }
1451 
1452  if (ch == LF) {
1454  COUNT_HEADER_SIZE(p - start);
1455  parser->header_state = h_state;
1456  CALLBACK_DATA_NOADVANCE(header_value);
1457  REEXECUTE();
1458  }
1459 
1460  if (!lenient && !IS_HEADER_CHAR(ch)) {
1462  goto error;
1463  }
1464 
1465  c = LOWER(ch);
1466 
1467  switch (h_state) {
1468  case h_general:
1469  {
1470  const char* p_cr;
1471  const char* p_lf;
1472  size_t limit = data + len - p;
1473 
1474  limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
1475 
1476  p_cr = (const char*) memchr(p, CR, limit);
1477  p_lf = (const char*) memchr(p, LF, limit);
1478  if (p_cr != NULL) {
1479  if (p_lf != NULL && p_cr >= p_lf)
1480  p = p_lf;
1481  else
1482  p = p_cr;
1483  } else if (UNLIKELY(p_lf != NULL)) {
1484  p = p_lf;
1485  } else {
1486  p = data + len;
1487  }
1488  --p;
1489 
1490  break;
1491  }
1492 
1493  case h_connection:
1494  case h_transfer_encoding:
1495  assert(0 && "Shouldn't get here.");
1496  break;
1497 
1498  case h_content_length:
1499  {
1500  uint64_t t;
1501 
1502  if (ch == ' ') break;
1503 
1504  if (UNLIKELY(!IS_NUM(ch))) {
1506  parser->header_state = h_state;
1507  goto error;
1508  }
1509 
1510  t = parser->content_length;
1511  t *= 10;
1512  t += ch - '0';
1513 
1514  /* Overflow? Test against a conservative limit for simplicity. */
1515  if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
1517  parser->header_state = h_state;
1518  goto error;
1519  }
1520 
1521  parser->content_length = t;
1522  break;
1523  }
1524 
1525  /* Transfer-Encoding: chunked */
1527  parser->index++;
1528  if (parser->index > sizeof(CHUNKED)-1
1529  || c != CHUNKED[parser->index]) {
1530  h_state = h_general;
1531  } else if (parser->index == sizeof(CHUNKED)-2) {
1532  h_state = h_transfer_encoding_chunked;
1533  }
1534  break;
1535 
1537  /* looking for 'Connection: keep-alive' */
1538  if (c == 'k') {
1540  /* looking for 'Connection: close' */
1541  } else if (c == 'c') {
1542  h_state = h_matching_connection_close;
1543  } else if (c == 'u') {
1545  } else if (STRICT_TOKEN(c)) {
1546  h_state = h_matching_connection_token;
1547  } else if (c == ' ' || c == '\t') {
1548  /* Skip lws */
1549  } else {
1550  h_state = h_general;
1551  }
1552  break;
1553 
1554  /* looking for 'Connection: keep-alive' */
1556  parser->index++;
1557  if (parser->index > sizeof(KEEP_ALIVE)-1
1558  || c != KEEP_ALIVE[parser->index]) {
1559  h_state = h_matching_connection_token;
1560  } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
1561  h_state = h_connection_keep_alive;
1562  }
1563  break;
1564 
1565  /* looking for 'Connection: close' */
1567  parser->index++;
1568  if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
1569  h_state = h_matching_connection_token;
1570  } else if (parser->index == sizeof(CLOSE)-2) {
1571  h_state = h_connection_close;
1572  }
1573  break;
1574 
1575  /* looking for 'Connection: upgrade' */
1577  parser->index++;
1578  if (parser->index > sizeof(UPGRADE) - 1 ||
1579  c != UPGRADE[parser->index]) {
1580  h_state = h_matching_connection_token;
1581  } else if (parser->index == sizeof(UPGRADE)-2) {
1582  h_state = h_connection_upgrade;
1583  }
1584  break;
1585 
1587  if (ch == ',') {
1589  parser->index = 0;
1590  }
1591  break;
1592 
1594  if (ch != ' ') h_state = h_general;
1595  break;
1596 
1598  case h_connection_close:
1599  case h_connection_upgrade:
1600  if (ch == ',') {
1601  if (h_state == h_connection_keep_alive) {
1602  parser->flags |= F_CONNECTION_KEEP_ALIVE;
1603  } else if (h_state == h_connection_close) {
1604  parser->flags |= F_CONNECTION_CLOSE;
1605  } else if (h_state == h_connection_upgrade) {
1606  parser->flags |= F_CONNECTION_UPGRADE;
1607  }
1609  parser->index = 0;
1610  } else if (ch != ' ') {
1611  h_state = h_matching_connection_token;
1612  }
1613  break;
1614 
1615  default:
1617  h_state = h_general;
1618  break;
1619  }
1620  }
1621  parser->header_state = h_state;
1622 
1623  COUNT_HEADER_SIZE(p - start);
1624 
1625  if (p == data + len)
1626  --p;
1627  break;
1628  }
1629 
1630  case s_header_almost_done:
1631  {
1632  if (UNLIKELY(ch != LF)) {
1634  goto error;
1635  }
1636 
1638  break;
1639  }
1640 
1641  case s_header_value_lws:
1642  {
1643  if (ch == ' ' || ch == '\t') {
1645  REEXECUTE();
1646  }
1647 
1648  /* finished the header */
1649  switch (parser->header_state) {
1651  parser->flags |= F_CONNECTION_KEEP_ALIVE;
1652  break;
1653  case h_connection_close:
1654  parser->flags |= F_CONNECTION_CLOSE;
1655  break;
1657  parser->flags |= F_CHUNKED;
1658  break;
1659  case h_connection_upgrade:
1660  parser->flags |= F_CONNECTION_UPGRADE;
1661  break;
1662  default:
1663  break;
1664  }
1665 
1667  REEXECUTE();
1668  }
1669 
1671  {
1672  STRICT_CHECK(ch != LF);
1674  break;
1675  }
1676 
1678  {
1679  if (ch == ' ' || ch == '\t') {
1681  break;
1682  } else {
1683  switch (parser->header_state) {
1685  parser->flags |= F_CONNECTION_KEEP_ALIVE;
1686  break;
1687  case h_connection_close:
1688  parser->flags |= F_CONNECTION_CLOSE;
1689  break;
1690  case h_connection_upgrade:
1691  parser->flags |= F_CONNECTION_UPGRADE;
1692  break;
1694  parser->flags |= F_CHUNKED;
1695  break;
1696  default:
1697  break;
1698  }
1699 
1700  /* header value was empty */
1701  MARK(header_value);
1703  CALLBACK_DATA_NOADVANCE(header_value);
1704  REEXECUTE();
1705  }
1706  }
1707 
1708  case s_headers_almost_done:
1709  {
1710  STRICT_CHECK(ch != LF);
1711 
1712  if (parser->flags & F_TRAILING) {
1713  /* End of a chunked request */
1715  CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
1716  REEXECUTE();
1717  }
1718 
1719  /* Cannot use chunked encoding and a content-length header together
1720  per the HTTP specification. */
1721  if ((parser->flags & F_CHUNKED) &&
1722  (parser->flags & F_CONTENTLENGTH)) {
1724  goto error;
1725  }
1726 
1728 
1729  /* Set this here so that on_headers_complete() callbacks can see it */
1730  if ((parser->flags & F_UPGRADE) &&
1731  (parser->flags & F_CONNECTION_UPGRADE)) {
1732  /* For responses, "Upgrade: foo" and "Connection: upgrade" are
1733  * mandatory only when it is a 101 Switching Protocols response,
1734  * otherwise it is purely informational, to announce support.
1735  */
1736  parser->upgrade =
1737  (parser->type == HTTP_REQUEST || parser->status_code == 101);
1738  } else {
1739  parser->upgrade = (parser->method == HTTP_CONNECT);
1740  }
1741 
1742  /* Here we call the headers_complete callback. This is somewhat
1743  * different than other callbacks because if the user returns 1, we
1744  * will interpret that as saying that this message has no body. This
1745  * is needed for the annoying case of recieving a response to a HEAD
1746  * request.
1747  *
1748  * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1749  * we have to simulate it by handling a change in errno below.
1750  */
1751  if (settings->on_headers_complete) {
1752  switch (settings->on_headers_complete(parser)) {
1753  case 0:
1754  break;
1755 
1756  case 2:
1757  parser->upgrade = 1;
1758 
1759  /* FALLTHROUGH */
1760  case 1:
1761  parser->flags |= F_SKIPBODY;
1762  break;
1763 
1764  default:
1766  RETURN(p - data); /* Error */
1767  }
1768  }
1769 
1770  if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
1771  RETURN(p - data);
1772  }
1773 
1774  REEXECUTE();
1775  }
1776 
1777  case s_headers_done:
1778  {
1779  int hasBody;
1780  STRICT_CHECK(ch != LF);
1781 
1782  parser->nread = 0;
1783 
1784  hasBody = parser->flags & F_CHUNKED ||
1785  (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
1786  if (parser->upgrade && (parser->method == HTTP_CONNECT ||
1787  (parser->flags & F_SKIPBODY) || !hasBody)) {
1788  /* Exit, the rest of the message is in a different protocol. */
1790  CALLBACK_NOTIFY(message_complete);
1791  RETURN((p - data) + 1);
1792  }
1793 
1794  if (parser->flags & F_SKIPBODY) {
1796  CALLBACK_NOTIFY(message_complete);
1797  } else if (parser->flags & F_CHUNKED) {
1798  /* chunked encoding - ignore Content-Length header */
1800  } else {
1801  if (parser->content_length == 0) {
1802  /* Content-Length header given but zero: Content-Length: 0\r\n */
1804  CALLBACK_NOTIFY(message_complete);
1805  } else if (parser->content_length != ULLONG_MAX) {
1806  /* Content-Length header given and non-zero */
1808  } else {
1809  if (!http_message_needs_eof(parser)) {
1810  /* Assume content-length 0 - read the next */
1812  CALLBACK_NOTIFY(message_complete);
1813  } else {
1814  /* Read body until EOF */
1816  }
1817  }
1818  }
1819 
1820  break;
1821  }
1822 
1823  case s_body_identity:
1824  {
1825  uint64_t to_read = MIN(parser->content_length,
1826  (uint64_t) ((data + len) - p));
1827 
1828  assert(parser->content_length != 0
1829  && parser->content_length != ULLONG_MAX);
1830 
1831  /* The difference between advancing content_length and p is because
1832  * the latter will automaticaly advance on the next loop iteration.
1833  * Further, if content_length ends up at 0, we want to see the last
1834  * byte again for our message complete callback.
1835  */
1836  MARK(body);
1837  parser->content_length -= to_read;
1838  p += to_read - 1;
1839 
1840  if (parser->content_length == 0) {
1842 
1843  /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1844  *
1845  * The alternative to doing this is to wait for the next byte to
1846  * trigger the data callback, just as in every other case. The
1847  * problem with this is that this makes it difficult for the test
1848  * harness to distinguish between complete-on-EOF and
1849  * complete-on-length. It's not clear that this distinction is
1850  * important for applications, but let's keep it for now.
1851  */
1852  CALLBACK_DATA_(body, p - body_mark + 1, p - data);
1853  REEXECUTE();
1854  }
1855 
1856  break;
1857  }
1858 
1859  /* read until EOF */
1860  case s_body_identity_eof:
1861  MARK(body);
1862  p = data + len - 1;
1863 
1864  break;
1865 
1866  case s_message_done:
1868  CALLBACK_NOTIFY(message_complete);
1869  if (parser->upgrade) {
1870  /* Exit, the rest of the message is in a different protocol. */
1871  RETURN((p - data) + 1);
1872  }
1873  break;
1874 
1875  case s_chunk_size_start:
1876  {
1877  assert(parser->nread == 1);
1878  assert(parser->flags & F_CHUNKED);
1879 
1880  unhex_val = unhex[(unsigned char)ch];
1881  if (UNLIKELY(unhex_val == -1)) {
1883  goto error;
1884  }
1885 
1886  parser->content_length = unhex_val;
1888  break;
1889  }
1890 
1891  case s_chunk_size:
1892  {
1893  uint64_t t;
1894 
1895  assert(parser->flags & F_CHUNKED);
1896 
1897  if (ch == CR) {
1899  break;
1900  }
1901 
1902  unhex_val = unhex[(unsigned char)ch];
1903 
1904  if (unhex_val == -1) {
1905  if (ch == ';' || ch == ' ') {
1907  break;
1908  }
1909 
1911  goto error;
1912  }
1913 
1914  t = parser->content_length;
1915  t *= 16;
1916  t += unhex_val;
1917 
1918  /* Overflow? Test against a conservative limit for simplicity. */
1919  if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
1921  goto error;
1922  }
1923 
1924  parser->content_length = t;
1925  break;
1926  }
1927 
1928  case s_chunk_parameters:
1929  {
1930  assert(parser->flags & F_CHUNKED);
1931  /* just ignore this shit. TODO check for overflow */
1932  if (ch == CR) {
1934  break;
1935  }
1936  break;
1937  }
1938 
1940  {
1941  assert(parser->flags & F_CHUNKED);
1942  STRICT_CHECK(ch != LF);
1943 
1944  parser->nread = 0;
1945 
1946  if (parser->content_length == 0) {
1947  parser->flags |= F_TRAILING;
1949  } else {
1951  }
1952  CALLBACK_NOTIFY(chunk_header);
1953  break;
1954  }
1955 
1956  case s_chunk_data:
1957  {
1958  uint64_t to_read = MIN(parser->content_length,
1959  (uint64_t) ((data + len) - p));
1960 
1961  assert(parser->flags & F_CHUNKED);
1962  assert(parser->content_length != 0
1963  && parser->content_length != ULLONG_MAX);
1964 
1965  /* See the explanation in s_body_identity for why the content
1966  * length and data pointers are managed this way.
1967  */
1968  MARK(body);
1969  parser->content_length -= to_read;
1970  p += to_read - 1;
1971 
1972  if (parser->content_length == 0) {
1974  }
1975 
1976  break;
1977  }
1978 
1980  assert(parser->flags & F_CHUNKED);
1981  assert(parser->content_length == 0);
1982  STRICT_CHECK(ch != CR);
1984  CALLBACK_DATA(body);
1985  break;
1986 
1987  case s_chunk_data_done:
1988  assert(parser->flags & F_CHUNKED);
1989  STRICT_CHECK(ch != LF);
1990  parser->nread = 0;
1992  CALLBACK_NOTIFY(chunk_complete);
1993  break;
1994 
1995  default:
1996  assert(0 && "unhandled state");
1998  goto error;
1999  }
2000  }
2001 
2002  /* Run callbacks for any marks that we have leftover after we ran our of
2003  * bytes. There should be at most one of these set, so it's OK to invoke
2004  * them in series (unset marks will not result in callbacks).
2005  *
2006  * We use the NOADVANCE() variety of callbacks here because 'p' has already
2007  * overflowed 'data' and this allows us to correct for the off-by-one that
2008  * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
2009  * value that's in-bounds).
2010  */
2011 
2012  assert(((header_field_mark ? 1 : 0) +
2013  (header_value_mark ? 1 : 0) +
2014  (url_mark ? 1 : 0) +
2015  (body_mark ? 1 : 0) +
2016  (status_mark ? 1 : 0)) <= 1);
2017 
2018  CALLBACK_DATA_NOADVANCE(header_field);
2019  CALLBACK_DATA_NOADVANCE(header_value);
2022  CALLBACK_DATA_NOADVANCE(status);
2023 
2024  RETURN(len);
2025 
2026 error:
2027  if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2029  }
2030 
2031  RETURN(p - data);
2032 }
2033 
2034 
2035 /* Does the parser need to see an EOF to find the end of the message? */
2036 int
2037 http_message_needs_eof (const http_parser *parser)
2038 {
2039  if (parser->type == HTTP_REQUEST) {
2040  return 0;
2041  }
2042 
2043  /* See RFC 2616 section 4.4 */
2044  if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
2045  parser->status_code == 204 || /* No Content */
2046  parser->status_code == 304 || /* Not Modified */
2047  parser->flags & F_SKIPBODY) { /* response to a HEAD request */
2048  return 0;
2049  }
2050 
2051  if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
2052  return 0;
2053  }
2054 
2055  return 1;
2056 }
2057 
2059 int
2060 http_should_keep_alive (const http_parser *parser)
2061 {
2062  if (parser->http_major > 0 && parser->http_minor > 0) {
2063  /* HTTP/1.1 */
2064  if (parser->flags & F_CONNECTION_CLOSE) {
2065  return 0;
2066  }
2067  } else {
2068  /* HTTP/1.0 or earlier */
2069  if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2070  return 0;
2071  }
2072  }
2073 
2074  return !http_message_needs_eof(parser);
2075 }
2076 
2078 const char *
2080 {
2081  return ELEM_AT(method_strings, m, "<unknown>");
2082 }
2083 
2085 void
2087 {
2088  void *data = parser->data; /* preserve application data */
2089  memset(parser, 0, sizeof(*parser));
2090  parser->data = data;
2091  parser->type = t;
2093  parser->http_errno = HPE_OK;
2094 }
2096 void
2098 {
2099  memset(settings, 0, sizeof(*settings));
2100 }
2102 const char *
2104  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2105  return http_strerror_tab[err].name;
2106 }
2108 const char *
2110  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2111  return http_strerror_tab[err].description;
2112 }
2113 
2114 static enum http_host_state
2115 http_parse_host_char(enum http_host_state s, const char ch) {
2116  switch(s) {
2117  case s_http_userinfo:
2118  case s_http_userinfo_start:
2119  if (ch == '@') {
2120  return s_http_host_start;
2121  }
2122 
2123  if (IS_USERINFO_CHAR(ch)) {
2124  return s_http_userinfo;
2125  }
2126  break;
2127 
2128  case s_http_host_start:
2129  if (ch == '[') {
2130  return s_http_host_v6_start;
2131  }
2132 
2133  if (IS_HOST_CHAR(ch)) {
2134  return s_http_host;
2135  }
2136 
2137  break;
2138 
2139  case s_http_host:
2140  if (IS_HOST_CHAR(ch)) {
2141  return s_http_host;
2142  }
2143 
2144  /* FALLTHROUGH */
2145  case s_http_host_v6_end:
2146  if (ch == ':') {
2147  return s_http_host_port_start;
2148  }
2149 
2150  break;
2151 
2152  case s_http_host_v6:
2153  if (ch == ']') {
2154  return s_http_host_v6_end;
2155  }
2156 
2157  /* FALLTHROUGH */
2158  case s_http_host_v6_start:
2159  if (IS_HEX(ch) || ch == ':' || ch == '.') {
2160  return s_http_host_v6;
2161  }
2162 
2163  if (s == s_http_host_v6 && ch == '%') {
2165  }
2166  break;
2167 
2168  case s_http_host_v6_zone:
2169  if (ch == ']') {
2170  return s_http_host_v6_end;
2171  }
2172 
2173  /* FALLTHROUGH */
2175  /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
2176  if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
2177  ch == '~') {
2178  return s_http_host_v6_zone;
2179  }
2180  break;
2181 
2182  case s_http_host_port:
2184  if (IS_NUM(ch)) {
2185  return s_http_host_port;
2186  }
2187 
2188  break;
2189 
2190  default:
2191  break;
2192  }
2193  return s_http_host_dead;
2194 }
2196 static int
2197 http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
2198  enum http_host_state s;
2199 
2200  const char *p;
2201  size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
2202 
2203  assert(u->field_set & (1 << UF_HOST));
2204 
2205  u->field_data[UF_HOST].len = 0;
2206 
2207  s = found_at ? s_http_userinfo_start : s_http_host_start;
2208 
2209  for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
2210  enum http_host_state new_s = http_parse_host_char(s, *p);
2211 
2212  if (new_s == s_http_host_dead) {
2213  return 1;
2214  }
2215 
2216  switch(new_s) {
2217  case s_http_host:
2218  if (s != s_http_host) {
2219  u->field_data[UF_HOST].off = p - buf;
2220  }
2221  u->field_data[UF_HOST].len++;
2222  break;
2223 
2224  case s_http_host_v6:
2225  if (s != s_http_host_v6) {
2226  u->field_data[UF_HOST].off = p - buf;
2227  }
2228  u->field_data[UF_HOST].len++;
2229  break;
2230 
2232  case s_http_host_v6_zone:
2233  u->field_data[UF_HOST].len++;
2234  break;
2235 
2236  case s_http_host_port:
2237  if (s != s_http_host_port) {
2238  u->field_data[UF_PORT].off = p - buf;
2239  u->field_data[UF_PORT].len = 0;
2240  u->field_set |= (1 << UF_PORT);
2241  }
2242  u->field_data[UF_PORT].len++;
2243  break;
2244 
2245  case s_http_userinfo:
2246  if (s != s_http_userinfo) {
2247  u->field_data[UF_USERINFO].off = p - buf ;
2248  u->field_data[UF_USERINFO].len = 0;
2249  u->field_set |= (1 << UF_USERINFO);
2250  }
2251  u->field_data[UF_USERINFO].len++;
2252  break;
2253 
2254  default:
2255  break;
2256  }
2257  s = new_s;
2258  }
2259 
2260  /* Make sure we don't end somewhere unexpected */
2261  switch (s) {
2262  case s_http_host_start:
2263  case s_http_host_v6_start:
2264  case s_http_host_v6:
2266  case s_http_host_v6_zone:
2268  case s_http_userinfo:
2269  case s_http_userinfo_start:
2270  return 1;
2271  default:
2272  break;
2273  }
2274 
2275  return 0;
2276 }
2278 void
2280  memset(u, 0, sizeof(*u));
2281 }
2283 int
2284 http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2285  struct http_parser_url *u)
2286 {
2287  enum state s;
2288  const char *p;
2289  enum http_parser_url_fields uf, old_uf;
2290  int found_at = 0;
2291 
2292  u->port = u->field_set = 0;
2293  s = is_connect ? s_req_server_start : s_req_spaces_before_url;
2294  old_uf = UF_MAX;
2295 
2296  for (p = buf; p < buf + buflen; p++) {
2297  s = parse_url_char(s, *p);
2298 
2299  /* Figure out the next field that we're operating on */
2300  switch (s) {
2301  case s_dead:
2302  return 1;
2303 
2304  /* Skip delimeters */
2305  case s_req_schema_slash:
2307  case s_req_server_start:
2309  case s_req_fragment_start:
2310  continue;
2311 
2312  case s_req_schema:
2313  uf = UF_SCHEMA;
2314  break;
2315 
2316  case s_req_server_with_at:
2317  found_at = 1;
2318 
2319  /* FALLTHROUGH */
2320  case s_req_server:
2321  uf = UF_HOST;
2322  break;
2323 
2324  case s_req_path:
2325  uf = UF_PATH;
2326  break;
2327 
2328  case s_req_query_string:
2329  uf = UF_QUERY;
2330  break;
2331 
2332  case s_req_fragment:
2333  uf = UF_FRAGMENT;
2334  break;
2335 
2336  default:
2337  assert(!"Unexpected state");
2338  return 1;
2339  }
2340 
2341  /* Nothing's changed; soldier on */
2342  if (uf == old_uf) {
2343  u->field_data[uf].len++;
2344  continue;
2345  }
2346 
2347  u->field_data[uf].off = p - buf;
2348  u->field_data[uf].len = 1;
2349 
2350  u->field_set |= (1 << uf);
2351  old_uf = uf;
2352  }
2353 
2354  /* host must be present if there is a schema */
2355  /* parsing http:///toto will fail */
2356  if ((u->field_set & (1 << UF_SCHEMA)) &&
2357  (u->field_set & (1 << UF_HOST)) == 0) {
2358  return 1;
2359  }
2360 
2361  if (u->field_set & (1 << UF_HOST)) {
2362  if (http_parse_host(buf, u, found_at) != 0) {
2363  return 1;
2364  }
2365  }
2366 
2367  /* CONNECT requests can only contain "hostname:port" */
2368  if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
2369  return 1;
2370  }
2371 
2372  if (u->field_set & (1 << UF_PORT)) {
2373  /* Don't bother with endp; we've already validated the string */
2374  unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
2375 
2376  /* Ports have a max value of 2^16 */
2377  if (v > 0xffff) {
2378  return 1;
2379  }
2380 
2381  u->port = (uint16_t) v;
2382  }
2383 
2384  return 0;
2385 }
2387 void
2388 http_parser_pause(http_parser *parser, int paused) {
2389  /* Users should only be pausing/unpausing a parser that is not in an error
2390  * state. In non-debug builds, there's not much that we can do about this
2391  * other than ignore it.
2392  */
2393  if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2394  HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2395  SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2396  } else {
2397  assert(0 && "Attempting to pause parser in error state");
2398  }
2399 }
2401 int
2402 http_body_is_final(const struct http_parser *parser) {
2403  return parser->state == s_message_done;
2404 }
2406 unsigned long
2407 http_parser_version(void) {
2408  return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2409  HTTP_PARSER_VERSION_MINOR * 0x00100 |
2410  HTTP_PARSER_VERSION_PATCH * 0x00001;
2411 }
#define XX(num, name, string)
void http_parser_settings_init(http_parser_settings *settings)
Definition: http_parser.c:2095
static enum state parse_url_char(enum state s, const char ch)
Definition: http_parser.c:485
#define CLOSE
Definition: http_parser.c:171
#define CALLBACK_DATA_NOADVANCE(FOR)
Definition: http_parser.c:132
static int http_parse_host(const char *buf, struct http_parser_url *u, int found_at)
Definition: http_parser.c:2195
#define LOWER(c)
Definition: http_parser.c:411
unsigned long http_parser_version(void)
Definition: http_parser.c:2405
#define ARRAY_SIZE(a)
Definition: http_parser.c:41
#define MARK(FOR)
Definition: http_parser.c:136
header_states
Definition: http_parser.c:363
@ h_matching_transfer_encoding
Definition: http_parser.c:371
@ h_matching_connection_token
Definition: http_parser.c:384
@ h_matching_connection_upgrade
Definition: http_parser.c:383
@ h_content_length
Definition: http_parser.c:375
@ h_CON
Definition: http_parser.c:366
@ h_matching_upgrade
Definition: http_parser.c:372
@ h_matching_connection
Definition: http_parser.c:368
@ h_upgrade
Definition: http_parser.c:377
@ h_CO
Definition: http_parser.c:365
@ h_matching_proxy_connection
Definition: http_parser.c:369
@ h_connection_keep_alive
Definition: http_parser.c:387
@ h_matching_connection_token_start
Definition: http_parser.c:380
@ h_matching_connection_keep_alive
Definition: http_parser.c:381
@ h_C
Definition: http_parser.c:364
@ h_connection_upgrade
Definition: http_parser.c:389
@ h_transfer_encoding_chunked
Definition: http_parser.c:386
@ h_matching_content_length
Definition: http_parser.c:370
@ h_connection
Definition: http_parser.c:374
@ h_connection_close
Definition: http_parser.c:388
@ h_matching_connection_close
Definition: http_parser.c:382
@ h_matching_transfer_encoding_chunked
Definition: http_parser.c:379
@ h_general
Definition: http_parser.c:363
@ h_transfer_encoding
Definition: http_parser.c:376
#define CHUNKED
Definition: http_parser.c:169
#define LF
Definition: http_parser.c:410
#define PARSING_HEADER(state)
Definition: http_parser.c:359
#define MIN(a, b)
Definition: http_parser.c:37
#define KEEP_ALIVE
Definition: http_parser.c:170
#define HTTP_STRERROR_GEN(n, s)
Definition: http_parser.c:463
#define CALLBACK_NOTIFY(FOR)
Definition: http_parser.c:99
#define NEW_MESSAGE()
Definition: http_parser.c:455
#define IS_ALPHANUM(c)
Definition: http_parser.c:414
#define SET_ERRNO(e)
Definition: http_parser.c:54
static const char tokens[256]
Definition: http_parser.c:188
size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len)
Definition: http_parser.c:632
static const int8_t unhex[256]
Definition: http_parser.c:223
int http_body_is_final(const struct http_parser *parser)
Definition: http_parser.c:2400
#define STRICT_CHECK(cond)
Definition: http_parser.c:448
#define REEXECUTE()
Definition: http_parser.c:66
#define TOKEN(c)
Definition: http_parser.c:426
int http_message_needs_eof(const http_parser *parser)
Definition: http_parser.c:2035
static const char * method_strings[]
Definition: http_parser.c:174
#define STRICT_TOKEN(c)
Definition: http_parser.c:423
#define CONNECTION
Definition: http_parser.c:165
void http_parser_url_init(struct http_parser_url *u)
Definition: http_parser.c:2277
#define TRANSFER_ENCODING
Definition: http_parser.c:167
const char * description
Definition: http_parser.c:466
static const uint8_t normal_url_char[32]
Definition: http_parser.c:242
const char * http_errno_description(enum http_errno err)
Definition: http_parser.c:2107
#define CONTENT_LENGTH
Definition: http_parser.c:166
#define IS_URL_CHAR(c)
Definition: http_parser.c:427
#define PROXY_CONNECTION
Definition: http_parser.c:164
static struct @2 http_strerror_tab[]
#define CR
Definition: http_parser.c:409
const char * http_errno_name(enum http_errno err)
Definition: http_parser.c:2101
#define CURRENT_STATE()
Definition: http_parser.c:59
#define CALLBACK_DATA_(FOR, LEN, ER)
Definition: http_parser.c:105
const char * name
Definition: http_parser.c:465
#define UNLIKELY(X)
Definition: http_parser.c:75
#define IS_NUM(c)
Definition: http_parser.c:413
#define IS_HEADER_CHAR(ch)
Definition: http_parser.c:441
#define ULLONG_MAX
Definition: http_parser.c:33
#define ELEM_AT(a, i, v)
Definition: http_parser.c:51
#define RETURN(V)
Definition: http_parser.c:61
#define UPDATE_STATE(V)
Definition: http_parser.c:60
#define IS_HOST_CHAR(c)
Definition: http_parser.c:428
#define LIKELY(X)
Definition: http_parser.c:74
void http_parser_pause(http_parser *parser, int paused)
Definition: http_parser.c:2386
#define IS_ALPHA(c)
Definition: http_parser.c:412
int http_should_keep_alive(const http_parser *parser)
Definition: http_parser.c:2058
#define UPGRADE
Definition: http_parser.c:168
#define COUNT_HEADER_SIZE(V)
Definition: http_parser.c:154
#define CALLBACK_DATA(FOR)
Definition: http_parser.c:128
const char * http_method_str(enum http_method m)
Definition: http_parser.c:2077
#define T(v)
Definition: http_parser.c:236
state
Definition: http_parser.c:279
@ s_body_identity
Definition: http_parser.c:352
@ s_req_server_with_at
Definition: http_parser.c:307
@ s_header_value_discard_ws_almost_done
Definition: http_parser.c:327
@ s_chunk_data_done
Definition: http_parser.c:350
@ s_chunk_size_almost_done
Definition: http_parser.c:338
@ s_start_res
Definition: http_parser.c:283
@ s_body_identity_eof
Definition: http_parser.c:353
@ s_chunk_data
Definition: http_parser.c:348
@ s_res_H
Definition: http_parser.c:284
@ s_headers_done
Definition: http_parser.c:341
@ s_res_first_status_code
Definition: http_parser.c:292
@ s_req_http_end
Definition: http_parser.c:321
@ s_header_value_discard_lws
Definition: http_parser.c:328
@ s_res_status
Definition: http_parser.c:295
@ s_header_field
Definition: http_parser.c:325
@ s_req_query_string
Definition: http_parser.c:310
@ s_req_query_string_start
Definition: http_parser.c:309
@ s_res_http_major
Definition: http_parser.c:288
@ s_req_spaces_before_url
Definition: http_parser.c:301
@ s_header_almost_done
Definition: http_parser.c:333
@ s_req_path
Definition: http_parser.c:308
@ s_res_HTTP
Definition: http_parser.c:287
@ s_header_value
Definition: http_parser.c:330
@ s_start_req_or_res
Definition: http_parser.c:281
@ s_req_http_dot
Definition: http_parser.c:319
@ s_req_method
Definition: http_parser.c:300
@ s_chunk_size
Definition: http_parser.c:336
@ s_req_http_HTTP
Definition: http_parser.c:317
@ s_req_http_minor
Definition: http_parser.c:320
@ s_req_server
Definition: http_parser.c:306
@ s_chunk_parameters
Definition: http_parser.c:337
@ s_start_req
Definition: http_parser.c:298
@ s_res_http_minor
Definition: http_parser.c:290
@ s_req_schema
Definition: http_parser.c:302
@ s_req_http_H
Definition: http_parser.c:314
@ s_req_schema_slash_slash
Definition: http_parser.c:304
@ s_header_field_start
Definition: http_parser.c:324
@ s_res_line_almost_done
Definition: http_parser.c:296
@ s_header_value_start
Definition: http_parser.c:329
@ s_res_http_dot
Definition: http_parser.c:289
@ s_res_HTT
Definition: http_parser.c:286
@ s_req_http_major
Definition: http_parser.c:318
@ s_header_value_lws
Definition: http_parser.c:331
@ s_req_line_almost_done
Definition: http_parser.c:322
@ s_headers_almost_done
Definition: http_parser.c:340
@ s_req_fragment
Definition: http_parser.c:312
@ s_req_schema_slash
Definition: http_parser.c:303
@ s_res_http_end
Definition: http_parser.c:291
@ s_res_or_resp_H
Definition: http_parser.c:282
@ s_req_fragment_start
Definition: http_parser.c:311
@ s_req_http_HT
Definition: http_parser.c:315
@ s_header_value_discard_ws
Definition: http_parser.c:326
@ s_message_done
Definition: http_parser.c:355
@ s_dead
Definition: http_parser.c:279
@ s_req_http_start
Definition: http_parser.c:313
@ s_req_http_HTT
Definition: http_parser.c:316
@ s_res_HT
Definition: http_parser.c:285
@ s_res_status_start
Definition: http_parser.c:294
@ s_res_status_code
Definition: http_parser.c:293
@ s_chunk_size_start
Definition: http_parser.c:335
@ s_req_server_start
Definition: http_parser.c:305
@ s_chunk_data_almost_done
Definition: http_parser.c:349
#define IS_HEX(c)
Definition: http_parser.c:415
#define IS_USERINFO_CHAR(c)
Definition: http_parser.c:419
http_host_state
Definition: http_parser.c:393
@ s_http_host_v6_zone
Definition: http_parser.c:403
@ s_http_host_v6_end
Definition: http_parser.c:401
@ s_http_host_port_start
Definition: http_parser.c:404
@ s_http_userinfo_start
Definition: http_parser.c:395
@ s_http_userinfo
Definition: http_parser.c:396
@ s_http_host_port
Definition: http_parser.c:405
@ s_http_host_v6
Definition: http_parser.c:400
@ s_http_host
Definition: http_parser.c:399
@ s_http_host_v6_zone_start
Definition: http_parser.c:402
@ s_http_host_v6_start
Definition: http_parser.c:398
@ s_http_host_dead
Definition: http_parser.c:394
@ s_http_host_start
Definition: http_parser.c:397
static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch)
Definition: http_parser.c:2113
int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u)
Definition: http_parser.c:2282
#define CALLBACK_NOTIFY_NOADVANCE(FOR)
Definition: http_parser.c:102
void http_parser_init(http_parser *parser, enum http_parser_type t)
Definition: http_parser.c:2084
#define HTTP_METHOD_MAP(XX)
Definition: http_parser.h:162
http_errno
Definition: http_parser.h:279
@ HPE_INVALID_CONTENT_LENGTH
Definition: http_parser.h:280
@ HPE_INVALID_CONSTANT
Definition: http_parser.h:280
@ HPE_UNEXPECTED_CONTENT_LENGTH
Definition: http_parser.h:280
@ HPE_INVALID_CHUNK_SIZE
Definition: http_parser.h:280
@ HPE_UNKNOWN
Definition: http_parser.h:280
@ HPE_INVALID_EOF_STATE
Definition: http_parser.h:280
@ HPE_INVALID_VERSION
Definition: http_parser.h:280
@ HPE_CB_headers_complete
Definition: http_parser.h:280
@ HPE_CLOSED_CONNECTION
Definition: http_parser.h:280
@ HPE_INVALID_STATUS
Definition: http_parser.h:280
@ HPE_INVALID_INTERNAL_STATE
Definition: http_parser.h:280
@ HPE_INVALID_METHOD
Definition: http_parser.h:280
@ HPE_INVALID_HEADER_TOKEN
Definition: http_parser.h:280
@ HPE_INVALID_URL
Definition: http_parser.h:280
@ HPE_OK
Definition: http_parser.h:280
@ HPE_PAUSED
Definition: http_parser.h:280
@ HPE_LF_EXPECTED
Definition: http_parser.h:280
#define HTTP_PARSER_ERRNO(p)
Definition: http_parser.h:285
#define HTTP_ERRNO_MAP(XX)
Definition: http_parser.h:231
#define HTTP_MAX_HEADER_SIZE
Definition: http_parser.h:63
http_parser_url_fields
Definition: http_parser.h:337
@ UF_FRAGMENT
Definition: http_parser.h:342
@ UF_PORT
Definition: http_parser.h:339
@ UF_MAX
Definition: http_parser.h:344
@ UF_PATH
Definition: http_parser.h:340
@ UF_SCHEMA
Definition: http_parser.h:337
@ UF_QUERY
Definition: http_parser.h:341
@ UF_USERINFO
Definition: http_parser.h:343
@ UF_HOST
Definition: http_parser.h:338
http_method
Definition: http_parser.h:205
@ F_CHUNKED
Definition: http_parser.h:216
@ F_CONNECTION_CLOSE
Definition: http_parser.h:218
@ F_CONNECTION_KEEP_ALIVE
Definition: http_parser.h:217
@ F_UPGRADE
Definition: http_parser.h:221
@ F_CONTENTLENGTH
Definition: http_parser.h:223
@ F_TRAILING
Definition: http_parser.h:220
@ F_SKIPBODY
Definition: http_parser.h:222
@ F_CONNECTION_UPGRADE
Definition: http_parser.h:219
#define HTTP_PARSER_VERSION_MINOR
Definition: http_parser.h:29
#define HTTP_PARSER_VERSION_MAJOR
Definition: http_parser.h:28
http_parser_type
Definition: http_parser.h:211
@ HTTP_RESPONSE
Definition: http_parser.h:211
@ HTTP_REQUEST
Definition: http_parser.h:211
#define HTTP_PARSER_VERSION_PATCH
Definition: http_parser.h:30
http_cb on_headers_complete
Definition: http_parser.h:325
struct http_parser_url::@3 field_data[UF_MAX]
uint16_t field_set
Definition: http_parser.h:356
unsigned int flags
Definition: http_parser.h:291
unsigned int state
Definition: http_parser.h:292
unsigned int index
Definition: http_parser.h:294
unsigned int upgrade
Definition: http_parser.h:312
uint32_t nread
Definition: http_parser.h:297
unsigned int method
Definition: http_parser.h:304
void * data
Definition: http_parser.h:315
uint64_t content_length
Definition: http_parser.h:298
unsigned int status_code
Definition: http_parser.h:303
unsigned int http_errno
Definition: http_parser.h:305
unsigned int header_state
Definition: http_parser.h:293
unsigned int type
Definition: http_parser.h:290
unsigned short http_major
Definition: http_parser.h:301
unsigned int lenient_http_headers
Definition: http_parser.h:295
unsigned short http_minor
Definition: http_parser.h:302
int c
Definition: tcpdemux.cpp:366
unsigned short uint16_t
Definition: util.h:7
unsigned char uint8_t
Definition: util.h:6
void err(int eval, const char *fmt,...)
Definition: utils.cpp:33