]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - vendor/http_parser/http_parser.c
Update the vendored http_parser library to v1.3.
[user/henk/code/inspircd.git] / vendor / http_parser / http_parser.c
1 /* Copyright Joyent, Inc. and other Node contributors.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 #include "http_parser.h"
22 #include <assert.h>
23 #include <stddef.h>
24 #include <ctype.h>
25 #include <string.h>
26 #include <limits.h>
27
28 static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE;
29
30 #ifndef ULLONG_MAX
31 # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
32 #endif
33
34 #ifndef MIN
35 # define MIN(a,b) ((a) < (b) ? (a) : (b))
36 #endif
37
38 #ifndef ARRAY_SIZE
39 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
40 #endif
41
42 #ifndef BIT_AT
43 # define BIT_AT(a, i)                                                \
44   (!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
45    (1 << ((unsigned int) (i) & 7))))
46 #endif
47
48 #ifndef ELEM_AT
49 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
50 #endif
51
52 #define SET_ERRNO(e)                                                 \
53 do {                                                                 \
54   parser->nread = nread;                                             \
55   parser->http_errno = (e);                                          \
56 } while(0)
57
58 #define CURRENT_STATE() p_state
59 #define UPDATE_STATE(V) p_state = (enum state) (V);
60 #define RETURN(V)                                                    \
61 do {                                                                 \
62   parser->nread = nread;                                             \
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 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.  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   nread += (uint32_t)(V);                                            \
157   if (UNLIKELY(nread > 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,
177   HTTP_METHOD_MAP(XX)
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,      '#',     '$',     '%',     '&',    '\'',
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
282   , s_start_req_or_res
283   , s_res_or_resp_H
284   , s_start_res
285   , s_res_H
286   , s_res_HT
287   , s_res_HTT
288   , s_res_HTTP
289   , s_res_http_major
290   , s_res_http_dot
291   , s_res_http_minor
292   , s_res_http_end
293   , s_res_first_status_code
294   , s_res_status_code
295   , s_res_status_start
296   , s_res_status
297   , s_res_line_almost_done
298
299   , s_start_req
300
301   , s_req_method
302   , s_req_spaces_before_url
303   , s_req_schema
304   , s_req_schema_slash
305   , s_req_schema_slash_slash
306   , s_req_server_start
307   , s_req_server
308   , s_req_server_with_at
309   , s_req_path
310   , s_req_query_string_start
311   , s_req_query_string
312   , s_req_fragment_start
313   , s_req_fragment
314   , s_req_http_start
315   , s_req_http_H
316   , s_req_http_HT
317   , s_req_http_HTT
318   , s_req_http_HTTP
319   , s_req_http_I
320   , s_req_http_IC
321   , s_req_http_major
322   , s_req_http_dot
323   , s_req_http_minor
324   , s_req_http_end
325   , s_req_line_almost_done
326
327   , s_header_field_start
328   , s_header_field
329   , s_header_value_discard_ws
330   , s_header_value_discard_ws_almost_done
331   , s_header_value_discard_lws
332   , s_header_value_start
333   , s_header_value
334   , s_header_value_lws
335
336   , s_header_almost_done
337
338   , s_chunk_size_start
339   , s_chunk_size
340   , s_chunk_parameters
341   , s_chunk_size_almost_done
342
343   , s_headers_almost_done
344   , s_headers_done
345
346   /* Important: 's_headers_done' must be the last 'header' state. All
347    * states beyond this must be 'body' states. It is used for overflow
348    * checking. See the PARSING_HEADER() macro.
349    */
350
351   , s_chunk_data
352   , s_chunk_data_almost_done
353   , s_chunk_data_done
354
355   , s_body_identity
356   , s_body_identity_eof
357
358   , s_message_done
359   };
360
361
362 #define PARSING_HEADER(state) (state <= s_headers_done)
363
364
365 enum header_states
366   { h_general = 0
367   , h_C
368   , h_CO
369   , h_CON
370
371   , h_matching_connection
372   , h_matching_proxy_connection
373   , h_matching_content_length
374   , h_matching_transfer_encoding
375   , h_matching_upgrade
376
377   , h_connection
378   , h_content_length
379   , h_content_length_num
380   , h_content_length_ws
381   , h_transfer_encoding
382   , h_upgrade
383
384   , h_matching_transfer_encoding_chunked
385   , h_matching_connection_token_start
386   , h_matching_connection_keep_alive
387   , h_matching_connection_close
388   , h_matching_connection_upgrade
389   , h_matching_connection_token
390
391   , h_transfer_encoding_chunked
392   , h_connection_keep_alive
393   , h_connection_close
394   , h_connection_upgrade
395   };
396
397 enum http_host_state
398   {
399     s_http_host_dead = 1
400   , s_http_userinfo_start
401   , s_http_userinfo
402   , s_http_host_start
403   , s_http_host_v6_start
404   , s_http_host
405   , s_http_host_v6
406   , s_http_host_v6_end
407   , s_http_host_v6_zone_start
408   , s_http_host_v6_zone
409   , s_http_host_port_start
410   , s_http_host_port
411 };
412
413 /* Macros for character classes; depends on strict-mode  */
414 #define CR                  '\r'
415 #define LF                  '\n'
416 #define LOWER(c)            (unsigned char)(c | 0x20)
417 #define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')
418 #define IS_NUM(c)           ((c) >= '0' && (c) <= '9')
419 #define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))
420 #define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
421 #define IS_MARK(c)          ((c) == '-' || (c) == '_' || (c) == '.' || \
422   (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
423   (c) == ')')
424 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
425   (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
426   (c) == '$' || (c) == ',')
427
428 #define STRICT_TOKEN(c)     ((c == ' ') ? 0 : tokens[(unsigned char)c])
429
430 #if HTTP_PARSER_STRICT
431 #define TOKEN(c)            STRICT_TOKEN(c)
432 #define IS_URL_CHAR(c)      (BIT_AT(normal_url_char, (unsigned char)c))
433 #define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
434 #else
435 #define TOKEN(c)            tokens[(unsigned char)c]
436 #define IS_URL_CHAR(c)                                                         \
437   (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
438 #define IS_HOST_CHAR(c)                                                        \
439   (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
440 #endif
441
442 /**
443  * Verify that a char is a valid visible (printable) US-ASCII
444  * character or %x80-FF
445  **/
446 #define IS_HEADER_CHAR(ch)                                                     \
447   (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
448
449 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
450
451
452 #if HTTP_PARSER_STRICT
453 # define STRICT_CHECK(cond)                                          \
454 do {                                                                 \
455   if (cond) {                                                        \
456     SET_ERRNO(HPE_STRICT);                                           \
457     goto error;                                                      \
458   }                                                                  \
459 } while (0)
460 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
461 #else
462 # define STRICT_CHECK(cond)
463 # define NEW_MESSAGE() start_state
464 #endif
465
466
467 /* Map errno values to strings for human-readable output */
468 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
469 static struct {
470   const char *name;
471   const char *description;
472 } http_strerror_tab[] = {
473   HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
474 };
475 #undef HTTP_STRERROR_GEN
476
477 int http_message_needs_eof(const http_parser *parser);
478
479 /* Our URL parser.
480  *
481  * This is designed to be shared by http_parser_execute() for URL validation,
482  * hence it has a state transition + byte-for-byte interface. In addition, it
483  * is meant to be embedded in http_parser_parse_url(), which does the dirty
484  * work of turning state transitions URL components for its API.
485  *
486  * This function should only be invoked with non-space characters. It is
487  * assumed that the caller cares about (and can detect) the transition between
488  * URL and non-URL states by looking for these.
489  */
490 static enum state
491 parse_url_char(enum state s, const char ch)
492 {
493   if (ch == ' ' || ch == '\r' || ch == '\n') {
494     return s_dead;
495   }
496
497 #if HTTP_PARSER_STRICT
498   if (ch == '\t' || ch == '\f') {
499     return s_dead;
500   }
501 #endif
502
503   switch (s) {
504     case s_req_spaces_before_url:
505       /* Proxied requests are followed by scheme of an absolute URI (alpha).
506        * All methods except CONNECT are followed by '/' or '*'.
507        */
508
509       if (ch == '/' || ch == '*') {
510         return s_req_path;
511       }
512
513       if (IS_ALPHA(ch)) {
514         return s_req_schema;
515       }
516
517       break;
518
519     case s_req_schema:
520       if (IS_ALPHA(ch)) {
521         return s;
522       }
523
524       if (ch == ':') {
525         return s_req_schema_slash;
526       }
527
528       break;
529
530     case s_req_schema_slash:
531       if (ch == '/') {
532         return s_req_schema_slash_slash;
533       }
534
535       break;
536
537     case s_req_schema_slash_slash:
538       if (ch == '/') {
539         return s_req_server_start;
540       }
541
542       break;
543
544     case s_req_server_with_at:
545       if (ch == '@') {
546         return s_dead;
547       }
548
549     /* fall through */
550     case s_req_server_start:
551     case s_req_server:
552       if (ch == '/') {
553         return s_req_path;
554       }
555
556       if (ch == '?') {
557         return s_req_query_string_start;
558       }
559
560       if (ch == '@') {
561         return s_req_server_with_at;
562       }
563
564       if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
565         return s_req_server;
566       }
567
568       break;
569
570     case s_req_path:
571       if (IS_URL_CHAR(ch)) {
572         return s;
573       }
574
575       switch (ch) {
576         case '?':
577           return s_req_query_string_start;
578
579         case '#':
580           return s_req_fragment_start;
581       }
582
583       break;
584
585     case s_req_query_string_start:
586     case s_req_query_string:
587       if (IS_URL_CHAR(ch)) {
588         return s_req_query_string;
589       }
590
591       switch (ch) {
592         case '?':
593           /* allow extra '?' in query string */
594           return s_req_query_string;
595
596         case '#':
597           return s_req_fragment_start;
598       }
599
600       break;
601
602     case s_req_fragment_start:
603       if (IS_URL_CHAR(ch)) {
604         return s_req_fragment;
605       }
606
607       switch (ch) {
608         case '?':
609           return s_req_fragment;
610
611         case '#':
612           return s;
613       }
614
615       break;
616
617     case s_req_fragment:
618       if (IS_URL_CHAR(ch)) {
619         return s;
620       }
621
622       switch (ch) {
623         case '?':
624         case '#':
625           return s;
626       }
627
628       break;
629
630     default:
631       break;
632   }
633
634   /* We should never fall out of the switch above unless there's an error */
635   return s_dead;
636 }
637
638 size_t http_parser_execute (http_parser *parser,
639                             const http_parser_settings *settings,
640                             const char *data,
641                             size_t len)
642 {
643   char c, ch;
644   int8_t unhex_val;
645   const char *p = data;
646   const char *header_field_mark = 0;
647   const char *header_value_mark = 0;
648   const char *url_mark = 0;
649   const char *body_mark = 0;
650   const char *status_mark = 0;
651   enum state p_state = (enum state) parser->state;
652   const unsigned int lenient = parser->lenient_http_headers;
653   uint32_t nread = parser->nread;
654
655   /* We're in an error state. Don't bother doing anything. */
656   if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
657     return 0;
658   }
659
660   if (len == 0) {
661     switch (CURRENT_STATE()) {
662       case s_body_identity_eof:
663         /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
664          * we got paused.
665          */
666         CALLBACK_NOTIFY_NOADVANCE(message_complete);
667         return 0;
668
669       case s_dead:
670       case s_start_req_or_res:
671       case s_start_res:
672       case s_start_req:
673         return 0;
674
675       default:
676         SET_ERRNO(HPE_INVALID_EOF_STATE);
677         return 1;
678     }
679   }
680
681
682   if (CURRENT_STATE() == s_header_field)
683     header_field_mark = data;
684   if (CURRENT_STATE() == s_header_value)
685     header_value_mark = data;
686   switch (CURRENT_STATE()) {
687   case s_req_path:
688   case s_req_schema:
689   case s_req_schema_slash:
690   case s_req_schema_slash_slash:
691   case s_req_server_start:
692   case s_req_server:
693   case s_req_server_with_at:
694   case s_req_query_string_start:
695   case s_req_query_string:
696   case s_req_fragment_start:
697   case s_req_fragment:
698     url_mark = data;
699     break;
700   case s_res_status:
701     status_mark = data;
702     break;
703   default:
704     break;
705   }
706
707   for (p=data; p != data + len; p++) {
708     ch = *p;
709
710     if (PARSING_HEADER(CURRENT_STATE()))
711       COUNT_HEADER_SIZE(1);
712
713 reexecute:
714     switch (CURRENT_STATE()) {
715
716       case s_dead:
717         /* this state is used after a 'Connection: close' message
718          * the parser will error out if it reads another message
719          */
720         if (LIKELY(ch == CR || ch == LF))
721           break;
722
723         SET_ERRNO(HPE_CLOSED_CONNECTION);
724         goto error;
725
726       case s_start_req_or_res:
727       {
728         if (ch == CR || ch == LF)
729           break;
730         parser->flags = 0;
731         parser->content_length = ULLONG_MAX;
732
733         if (ch == 'H') {
734           UPDATE_STATE(s_res_or_resp_H);
735
736           CALLBACK_NOTIFY(message_begin);
737         } else {
738           parser->type = HTTP_REQUEST;
739           UPDATE_STATE(s_start_req);
740           REEXECUTE();
741         }
742
743         break;
744       }
745
746       case s_res_or_resp_H:
747         if (ch == 'T') {
748           parser->type = HTTP_RESPONSE;
749           UPDATE_STATE(s_res_HT);
750         } else {
751           if (UNLIKELY(ch != 'E')) {
752             SET_ERRNO(HPE_INVALID_CONSTANT);
753             goto error;
754           }
755
756           parser->type = HTTP_REQUEST;
757           parser->method = HTTP_HEAD;
758           parser->index = 2;
759           UPDATE_STATE(s_req_method);
760         }
761         break;
762
763       case s_start_res:
764       {
765         if (ch == CR || ch == LF)
766           break;
767         parser->flags = 0;
768         parser->content_length = ULLONG_MAX;
769
770         if (ch == 'H') {
771           UPDATE_STATE(s_res_H);
772         } else {
773           SET_ERRNO(HPE_INVALID_CONSTANT);
774           goto error;
775         }
776
777         CALLBACK_NOTIFY(message_begin);
778         break;
779       }
780
781       case s_res_H:
782         STRICT_CHECK(ch != 'T');
783         UPDATE_STATE(s_res_HT);
784         break;
785
786       case s_res_HT:
787         STRICT_CHECK(ch != 'T');
788         UPDATE_STATE(s_res_HTT);
789         break;
790
791       case s_res_HTT:
792         STRICT_CHECK(ch != 'P');
793         UPDATE_STATE(s_res_HTTP);
794         break;
795
796       case s_res_HTTP:
797         STRICT_CHECK(ch != '/');
798         UPDATE_STATE(s_res_http_major);
799         break;
800
801       case s_res_http_major:
802         if (UNLIKELY(!IS_NUM(ch))) {
803           SET_ERRNO(HPE_INVALID_VERSION);
804           goto error;
805         }
806
807         parser->http_major = ch - '0';
808         UPDATE_STATE(s_res_http_dot);
809         break;
810
811       case s_res_http_dot:
812       {
813         if (UNLIKELY(ch != '.')) {
814           SET_ERRNO(HPE_INVALID_VERSION);
815           goto error;
816         }
817
818         UPDATE_STATE(s_res_http_minor);
819         break;
820       }
821
822       case s_res_http_minor:
823         if (UNLIKELY(!IS_NUM(ch))) {
824           SET_ERRNO(HPE_INVALID_VERSION);
825           goto error;
826         }
827
828         parser->http_minor = ch - '0';
829         UPDATE_STATE(s_res_http_end);
830         break;
831
832       case s_res_http_end:
833       {
834         if (UNLIKELY(ch != ' ')) {
835           SET_ERRNO(HPE_INVALID_VERSION);
836           goto error;
837         }
838
839         UPDATE_STATE(s_res_first_status_code);
840         break;
841       }
842
843       case s_res_first_status_code:
844       {
845         if (!IS_NUM(ch)) {
846           if (ch == ' ') {
847             break;
848           }
849
850           SET_ERRNO(HPE_INVALID_STATUS);
851           goto error;
852         }
853         parser->status_code = ch - '0';
854         UPDATE_STATE(s_res_status_code);
855         break;
856       }
857
858       case s_res_status_code:
859       {
860         if (!IS_NUM(ch)) {
861           switch (ch) {
862             case ' ':
863               UPDATE_STATE(s_res_status_start);
864               break;
865             case CR:
866             case LF:
867               UPDATE_STATE(s_res_status_start);
868               REEXECUTE();
869               break;
870             default:
871               SET_ERRNO(HPE_INVALID_STATUS);
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)) {
881           SET_ERRNO(HPE_INVALID_STATUS);
882           goto error;
883         }
884
885         break;
886       }
887
888       case s_res_status_start:
889       {
890         MARK(status);
891         UPDATE_STATE(s_res_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) {
902           UPDATE_STATE(s_res_line_almost_done);
903           CALLBACK_DATA(status);
904           break;
905         }
906
907         if (ch == LF) {
908           UPDATE_STATE(s_header_field_start);
909           CALLBACK_DATA(status);
910           break;
911         }
912
913         break;
914
915       case s_res_line_almost_done:
916         STRICT_CHECK(ch != LF);
917         UPDATE_STATE(s_header_field_start);
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))) {
928           SET_ERRNO(HPE_INVALID_METHOD);
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, SOURCE */ break;
950           case 'T': parser->method = HTTP_TRACE; break;
951           case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
952           default:
953             SET_ERRNO(HPE_INVALID_METHOD);
954             goto error;
955         }
956         UPDATE_STATE(s_req_method);
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')) {
967           SET_ERRNO(HPE_INVALID_METHOD);
968           goto error;
969         }
970
971         matcher = method_strings[parser->method];
972         if (ch == ' ' && matcher[parser->index] == '\0') {
973           UPDATE_STATE(s_req_spaces_before_url);
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(SUBSCRIBE, 1, 'O', SOURCE)
996             XX(REPORT,    2, 'B', REBIND)
997             XX(PROPFIND,  4, 'P', PROPPATCH)
998             XX(LOCK,      1, 'I', LINK)
999             XX(UNLOCK,    2, 'S', UNSUBSCRIBE)
1000             XX(UNLOCK,    2, 'B', UNBIND)
1001             XX(UNLOCK,    3, 'I', UNLINK)
1002 #undef XX
1003             default:
1004               SET_ERRNO(HPE_INVALID_METHOD);
1005               goto error;
1006           }
1007         } else {
1008           SET_ERRNO(HPE_INVALID_METHOD);
1009           goto error;
1010         }
1011
1012         ++parser->index;
1013         break;
1014       }
1015
1016       case s_req_spaces_before_url:
1017       {
1018         if (ch == ' ') break;
1019
1020         MARK(url);
1021         if (parser->method == HTTP_CONNECT) {
1022           UPDATE_STATE(s_req_server_start);
1023         }
1024
1025         UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1026         if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1027           SET_ERRNO(HPE_INVALID_URL);
1028           goto error;
1029         }
1030
1031         break;
1032       }
1033
1034       case s_req_schema:
1035       case s_req_schema_slash:
1036       case s_req_schema_slash_slash:
1037       case s_req_server_start:
1038       {
1039         switch (ch) {
1040           /* No whitespace allowed here */
1041           case ' ':
1042           case CR:
1043           case LF:
1044             SET_ERRNO(HPE_INVALID_URL);
1045             goto error;
1046           default:
1047             UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1048             if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1049               SET_ERRNO(HPE_INVALID_URL);
1050               goto error;
1051             }
1052         }
1053
1054         break;
1055       }
1056
1057       case s_req_server:
1058       case s_req_server_with_at:
1059       case s_req_path:
1060       case s_req_query_string_start:
1061       case s_req_query_string:
1062       case s_req_fragment_start:
1063       case s_req_fragment:
1064       {
1065         switch (ch) {
1066           case ' ':
1067             UPDATE_STATE(s_req_http_start);
1068             CALLBACK_DATA(url);
1069             break;
1070           case CR:
1071           case LF:
1072             parser->http_major = 0;
1073             parser->http_minor = 9;
1074             UPDATE_STATE((ch == CR) ?
1075               s_req_line_almost_done :
1076               s_header_field_start);
1077             CALLBACK_DATA(url);
1078             break;
1079           default:
1080             UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1081             if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1082               SET_ERRNO(HPE_INVALID_URL);
1083               goto error;
1084             }
1085         }
1086         break;
1087       }
1088
1089       case s_req_http_start:
1090         switch (ch) {
1091           case ' ':
1092             break;
1093           case 'H':
1094             UPDATE_STATE(s_req_http_H);
1095             break;
1096           case 'I':
1097             if (parser->method == HTTP_SOURCE) {
1098               UPDATE_STATE(s_req_http_I);
1099               break;
1100             }
1101             /* fall through */
1102           default:
1103             SET_ERRNO(HPE_INVALID_CONSTANT);
1104             goto error;
1105         }
1106         break;
1107
1108       case s_req_http_H:
1109         STRICT_CHECK(ch != 'T');
1110         UPDATE_STATE(s_req_http_HT);
1111         break;
1112
1113       case s_req_http_HT:
1114         STRICT_CHECK(ch != 'T');
1115         UPDATE_STATE(s_req_http_HTT);
1116         break;
1117
1118       case s_req_http_HTT:
1119         STRICT_CHECK(ch != 'P');
1120         UPDATE_STATE(s_req_http_HTTP);
1121         break;
1122
1123       case s_req_http_I:
1124         STRICT_CHECK(ch != 'C');
1125         UPDATE_STATE(s_req_http_IC);
1126         break;
1127
1128       case s_req_http_IC:
1129         STRICT_CHECK(ch != 'E');
1130         UPDATE_STATE(s_req_http_HTTP);  /* Treat "ICE" as "HTTP". */
1131         break;
1132
1133       case s_req_http_HTTP:
1134         STRICT_CHECK(ch != '/');
1135         UPDATE_STATE(s_req_http_major);
1136         break;
1137
1138       case s_req_http_major:
1139         if (UNLIKELY(!IS_NUM(ch))) {
1140           SET_ERRNO(HPE_INVALID_VERSION);
1141           goto error;
1142         }
1143
1144         parser->http_major = ch - '0';
1145         UPDATE_STATE(s_req_http_dot);
1146         break;
1147
1148       case s_req_http_dot:
1149       {
1150         if (UNLIKELY(ch != '.')) {
1151           SET_ERRNO(HPE_INVALID_VERSION);
1152           goto error;
1153         }
1154
1155         UPDATE_STATE(s_req_http_minor);
1156         break;
1157       }
1158
1159       case s_req_http_minor:
1160         if (UNLIKELY(!IS_NUM(ch))) {
1161           SET_ERRNO(HPE_INVALID_VERSION);
1162           goto error;
1163         }
1164
1165         parser->http_minor = ch - '0';
1166         UPDATE_STATE(s_req_http_end);
1167         break;
1168
1169       case s_req_http_end:
1170       {
1171         if (ch == CR) {
1172           UPDATE_STATE(s_req_line_almost_done);
1173           break;
1174         }
1175
1176         if (ch == LF) {
1177           UPDATE_STATE(s_header_field_start);
1178           break;
1179         }
1180
1181         SET_ERRNO(HPE_INVALID_VERSION);
1182         goto error;
1183         break;
1184       }
1185
1186       /* end of request line */
1187       case s_req_line_almost_done:
1188       {
1189         if (UNLIKELY(ch != LF)) {
1190           SET_ERRNO(HPE_LF_EXPECTED);
1191           goto error;
1192         }
1193
1194         UPDATE_STATE(s_header_field_start);
1195         break;
1196       }
1197
1198       case s_header_field_start:
1199       {
1200         if (ch == CR) {
1201           UPDATE_STATE(s_headers_almost_done);
1202           break;
1203         }
1204
1205         if (ch == LF) {
1206           /* they might be just sending \n instead of \r\n so this would be
1207            * the second \n to denote the end of headers*/
1208           UPDATE_STATE(s_headers_almost_done);
1209           REEXECUTE();
1210         }
1211
1212         c = TOKEN(ch);
1213
1214         if (UNLIKELY(!c)) {
1215           SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1216           goto error;
1217         }
1218
1219         MARK(header_field);
1220
1221         parser->index = 0;
1222         UPDATE_STATE(s_header_field);
1223
1224         switch (c) {
1225           case 'c':
1226             parser->header_state = h_C;
1227             break;
1228
1229           case 'p':
1230             parser->header_state = h_matching_proxy_connection;
1231             break;
1232
1233           case 't':
1234             parser->header_state = h_matching_transfer_encoding;
1235             break;
1236
1237           case 'u':
1238             parser->header_state = h_matching_upgrade;
1239             break;
1240
1241           default:
1242             parser->header_state = h_general;
1243             break;
1244         }
1245         break;
1246       }
1247
1248       case s_header_field:
1249       {
1250         const char* start = p;
1251         for (; p != data + len; p++) {
1252           ch = *p;
1253           c = TOKEN(ch);
1254
1255           if (!c)
1256             break;
1257
1258           switch (parser->header_state) {
1259             case h_general: {
1260               size_t limit = data + len - p;
1261               limit = MIN(limit, max_header_size);
1262               while (p+1 < data + limit && TOKEN(p[1])) {
1263                 p++;
1264               }
1265               break;
1266             }
1267
1268             case h_C:
1269               parser->index++;
1270               parser->header_state = (c == 'o' ? h_CO : h_general);
1271               break;
1272
1273             case h_CO:
1274               parser->index++;
1275               parser->header_state = (c == 'n' ? h_CON : h_general);
1276               break;
1277
1278             case h_CON:
1279               parser->index++;
1280               switch (c) {
1281                 case 'n':
1282                   parser->header_state = h_matching_connection;
1283                   break;
1284                 case 't':
1285                   parser->header_state = h_matching_content_length;
1286                   break;
1287                 default:
1288                   parser->header_state = h_general;
1289                   break;
1290               }
1291               break;
1292
1293             /* connection */
1294
1295             case h_matching_connection:
1296               parser->index++;
1297               if (parser->index > sizeof(CONNECTION)-1
1298                   || c != CONNECTION[parser->index]) {
1299                 parser->header_state = h_general;
1300               } else if (parser->index == sizeof(CONNECTION)-2) {
1301                 parser->header_state = h_connection;
1302               }
1303               break;
1304
1305             /* proxy-connection */
1306
1307             case h_matching_proxy_connection:
1308               parser->index++;
1309               if (parser->index > sizeof(PROXY_CONNECTION)-1
1310                   || c != PROXY_CONNECTION[parser->index]) {
1311                 parser->header_state = h_general;
1312               } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
1313                 parser->header_state = h_connection;
1314               }
1315               break;
1316
1317             /* content-length */
1318
1319             case h_matching_content_length:
1320               parser->index++;
1321               if (parser->index > sizeof(CONTENT_LENGTH)-1
1322                   || c != CONTENT_LENGTH[parser->index]) {
1323                 parser->header_state = h_general;
1324               } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
1325                 parser->header_state = h_content_length;
1326               }
1327               break;
1328
1329             /* transfer-encoding */
1330
1331             case h_matching_transfer_encoding:
1332               parser->index++;
1333               if (parser->index > sizeof(TRANSFER_ENCODING)-1
1334                   || c != TRANSFER_ENCODING[parser->index]) {
1335                 parser->header_state = h_general;
1336               } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
1337                 parser->header_state = h_transfer_encoding;
1338               }
1339               break;
1340
1341             /* upgrade */
1342
1343             case h_matching_upgrade:
1344               parser->index++;
1345               if (parser->index > sizeof(UPGRADE)-1
1346                   || c != UPGRADE[parser->index]) {
1347                 parser->header_state = h_general;
1348               } else if (parser->index == sizeof(UPGRADE)-2) {
1349                 parser->header_state = h_upgrade;
1350               }
1351               break;
1352
1353             case h_connection:
1354             case h_content_length:
1355             case h_transfer_encoding:
1356             case h_upgrade:
1357               if (ch != ' ') parser->header_state = h_general;
1358               break;
1359
1360             default:
1361               assert(0 && "Unknown header_state");
1362               break;
1363           }
1364         }
1365
1366         if (p == data + len) {
1367           --p;
1368           COUNT_HEADER_SIZE(p - start);
1369           break;
1370         }
1371
1372         COUNT_HEADER_SIZE(p - start);
1373
1374         if (ch == ':') {
1375           UPDATE_STATE(s_header_value_discard_ws);
1376           CALLBACK_DATA(header_field);
1377           break;
1378         }
1379
1380         SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1381         goto error;
1382       }
1383
1384       case s_header_value_discard_ws:
1385         if (ch == ' ' || ch == '\t') break;
1386
1387         if (ch == CR) {
1388           UPDATE_STATE(s_header_value_discard_ws_almost_done);
1389           break;
1390         }
1391
1392         if (ch == LF) {
1393           UPDATE_STATE(s_header_value_discard_lws);
1394           break;
1395         }
1396
1397         /* fall through */
1398
1399       case s_header_value_start:
1400       {
1401         MARK(header_value);
1402
1403         UPDATE_STATE(s_header_value);
1404         parser->index = 0;
1405
1406         c = LOWER(ch);
1407
1408         switch (parser->header_state) {
1409           case h_upgrade:
1410             parser->flags |= F_UPGRADE;
1411             parser->header_state = h_general;
1412             break;
1413
1414           case h_transfer_encoding:
1415             /* looking for 'Transfer-Encoding: chunked' */
1416             if ('c' == c) {
1417               parser->header_state = h_matching_transfer_encoding_chunked;
1418             } else {
1419               parser->header_state = h_general;
1420             }
1421             break;
1422
1423           case h_content_length:
1424             if (UNLIKELY(!IS_NUM(ch))) {
1425               SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1426               goto error;
1427             }
1428
1429             if (parser->flags & F_CONTENTLENGTH) {
1430               SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
1431               goto error;
1432             }
1433
1434             parser->flags |= F_CONTENTLENGTH;
1435             parser->content_length = ch - '0';
1436             parser->header_state = h_content_length_num;
1437             break;
1438
1439           /* when obsolete line folding is encountered for content length
1440            * continue to the s_header_value state */
1441           case h_content_length_ws:
1442             break;
1443
1444           case h_connection:
1445             /* looking for 'Connection: keep-alive' */
1446             if (c == 'k') {
1447               parser->header_state = h_matching_connection_keep_alive;
1448             /* looking for 'Connection: close' */
1449             } else if (c == 'c') {
1450               parser->header_state = h_matching_connection_close;
1451             } else if (c == 'u') {
1452               parser->header_state = h_matching_connection_upgrade;
1453             } else {
1454               parser->header_state = h_matching_connection_token;
1455             }
1456             break;
1457
1458           /* Multi-value `Connection` header */
1459           case h_matching_connection_token_start:
1460             break;
1461
1462           default:
1463             parser->header_state = h_general;
1464             break;
1465         }
1466         break;
1467       }
1468
1469       case s_header_value:
1470       {
1471         const char* start = p;
1472         enum header_states h_state = (enum header_states) parser->header_state;
1473         for (; p != data + len; p++) {
1474           ch = *p;
1475           if (ch == CR) {
1476             UPDATE_STATE(s_header_almost_done);
1477             parser->header_state = h_state;
1478             CALLBACK_DATA(header_value);
1479             break;
1480           }
1481
1482           if (ch == LF) {
1483             UPDATE_STATE(s_header_almost_done);
1484             COUNT_HEADER_SIZE(p - start);
1485             parser->header_state = h_state;
1486             CALLBACK_DATA_NOADVANCE(header_value);
1487             REEXECUTE();
1488           }
1489
1490           if (!lenient && !IS_HEADER_CHAR(ch)) {
1491             SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1492             goto error;
1493           }
1494
1495           c = LOWER(ch);
1496
1497           switch (h_state) {
1498             case h_general:
1499             {
1500               const char* p_cr;
1501               const char* p_lf;
1502               size_t limit = data + len - p;
1503
1504               limit = MIN(limit, max_header_size);
1505
1506               p_cr = (const char*) memchr(p, CR, limit);
1507               p_lf = (const char*) memchr(p, LF, limit);
1508               if (p_cr != NULL) {
1509                 if (p_lf != NULL && p_cr >= p_lf)
1510                   p = p_lf;
1511                 else
1512                   p = p_cr;
1513               } else if (UNLIKELY(p_lf != NULL)) {
1514                 p = p_lf;
1515               } else {
1516                 p = data + len;
1517               }
1518               --p;
1519               break;
1520             }
1521
1522             case h_connection:
1523             case h_transfer_encoding:
1524               assert(0 && "Shouldn't get here.");
1525               break;
1526
1527             case h_content_length:
1528               if (ch == ' ') break;
1529               h_state = h_content_length_num;
1530               /* fall through */
1531
1532             case h_content_length_num:
1533             {
1534               uint64_t t;
1535
1536               if (ch == ' ') {
1537                 h_state = h_content_length_ws;
1538                 break;
1539               }
1540
1541               if (UNLIKELY(!IS_NUM(ch))) {
1542                 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1543                 parser->header_state = h_state;
1544                 goto error;
1545               }
1546
1547               t = parser->content_length;
1548               t *= 10;
1549               t += ch - '0';
1550
1551               /* Overflow? Test against a conservative limit for simplicity. */
1552               if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
1553                 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1554                 parser->header_state = h_state;
1555                 goto error;
1556               }
1557
1558               parser->content_length = t;
1559               break;
1560             }
1561
1562             case h_content_length_ws:
1563               if (ch == ' ') break;
1564               SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1565               parser->header_state = h_state;
1566               goto error;
1567
1568             /* Transfer-Encoding: chunked */
1569             case h_matching_transfer_encoding_chunked:
1570               parser->index++;
1571               if (parser->index > sizeof(CHUNKED)-1
1572                   || c != CHUNKED[parser->index]) {
1573                 h_state = h_general;
1574               } else if (parser->index == sizeof(CHUNKED)-2) {
1575                 h_state = h_transfer_encoding_chunked;
1576               }
1577               break;
1578
1579             case h_matching_connection_token_start:
1580               /* looking for 'Connection: keep-alive' */
1581               if (c == 'k') {
1582                 h_state = h_matching_connection_keep_alive;
1583               /* looking for 'Connection: close' */
1584               } else if (c == 'c') {
1585                 h_state = h_matching_connection_close;
1586               } else if (c == 'u') {
1587                 h_state = h_matching_connection_upgrade;
1588               } else if (STRICT_TOKEN(c)) {
1589                 h_state = h_matching_connection_token;
1590               } else if (c == ' ' || c == '\t') {
1591                 /* Skip lws */
1592               } else {
1593                 h_state = h_general;
1594               }
1595               break;
1596
1597             /* looking for 'Connection: keep-alive' */
1598             case h_matching_connection_keep_alive:
1599               parser->index++;
1600               if (parser->index > sizeof(KEEP_ALIVE)-1
1601                   || c != KEEP_ALIVE[parser->index]) {
1602                 h_state = h_matching_connection_token;
1603               } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
1604                 h_state = h_connection_keep_alive;
1605               }
1606               break;
1607
1608             /* looking for 'Connection: close' */
1609             case h_matching_connection_close:
1610               parser->index++;
1611               if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
1612                 h_state = h_matching_connection_token;
1613               } else if (parser->index == sizeof(CLOSE)-2) {
1614                 h_state = h_connection_close;
1615               }
1616               break;
1617
1618             /* looking for 'Connection: upgrade' */
1619             case h_matching_connection_upgrade:
1620               parser->index++;
1621               if (parser->index > sizeof(UPGRADE) - 1 ||
1622                   c != UPGRADE[parser->index]) {
1623                 h_state = h_matching_connection_token;
1624               } else if (parser->index == sizeof(UPGRADE)-2) {
1625                 h_state = h_connection_upgrade;
1626               }
1627               break;
1628
1629             case h_matching_connection_token:
1630               if (ch == ',') {
1631                 h_state = h_matching_connection_token_start;
1632                 parser->index = 0;
1633               }
1634               break;
1635
1636             case h_transfer_encoding_chunked:
1637               if (ch != ' ') h_state = h_general;
1638               break;
1639
1640             case h_connection_keep_alive:
1641             case h_connection_close:
1642             case h_connection_upgrade:
1643               if (ch == ',') {
1644                 if (h_state == h_connection_keep_alive) {
1645                   parser->flags |= F_CONNECTION_KEEP_ALIVE;
1646                 } else if (h_state == h_connection_close) {
1647                   parser->flags |= F_CONNECTION_CLOSE;
1648                 } else if (h_state == h_connection_upgrade) {
1649                   parser->flags |= F_CONNECTION_UPGRADE;
1650                 }
1651                 h_state = h_matching_connection_token_start;
1652                 parser->index = 0;
1653               } else if (ch != ' ') {
1654                 h_state = h_matching_connection_token;
1655               }
1656               break;
1657
1658             default:
1659               UPDATE_STATE(s_header_value);
1660               h_state = h_general;
1661               break;
1662           }
1663         }
1664         parser->header_state = h_state;
1665
1666         if (p == data + len)
1667           --p;
1668
1669         COUNT_HEADER_SIZE(p - start);
1670         break;
1671       }
1672
1673       case s_header_almost_done:
1674       {
1675         if (UNLIKELY(ch != LF)) {
1676           SET_ERRNO(HPE_LF_EXPECTED);
1677           goto error;
1678         }
1679
1680         UPDATE_STATE(s_header_value_lws);
1681         break;
1682       }
1683
1684       case s_header_value_lws:
1685       {
1686         if (ch == ' ' || ch == '\t') {
1687           if (parser->header_state == h_content_length_num) {
1688               /* treat obsolete line folding as space */
1689               parser->header_state = h_content_length_ws;
1690           }
1691           UPDATE_STATE(s_header_value_start);
1692           REEXECUTE();
1693         }
1694
1695         /* finished the header */
1696         switch (parser->header_state) {
1697           case h_connection_keep_alive:
1698             parser->flags |= F_CONNECTION_KEEP_ALIVE;
1699             break;
1700           case h_connection_close:
1701             parser->flags |= F_CONNECTION_CLOSE;
1702             break;
1703           case h_transfer_encoding_chunked:
1704             parser->flags |= F_CHUNKED;
1705             break;
1706           case h_connection_upgrade:
1707             parser->flags |= F_CONNECTION_UPGRADE;
1708             break;
1709           default:
1710             break;
1711         }
1712
1713         UPDATE_STATE(s_header_field_start);
1714         REEXECUTE();
1715       }
1716
1717       case s_header_value_discard_ws_almost_done:
1718       {
1719         STRICT_CHECK(ch != LF);
1720         UPDATE_STATE(s_header_value_discard_lws);
1721         break;
1722       }
1723
1724       case s_header_value_discard_lws:
1725       {
1726         if (ch == ' ' || ch == '\t') {
1727           UPDATE_STATE(s_header_value_discard_ws);
1728           break;
1729         } else {
1730           switch (parser->header_state) {
1731             case h_connection_keep_alive:
1732               parser->flags |= F_CONNECTION_KEEP_ALIVE;
1733               break;
1734             case h_connection_close:
1735               parser->flags |= F_CONNECTION_CLOSE;
1736               break;
1737             case h_connection_upgrade:
1738               parser->flags |= F_CONNECTION_UPGRADE;
1739               break;
1740             case h_transfer_encoding_chunked:
1741               parser->flags |= F_CHUNKED;
1742               break;
1743             case h_content_length:
1744               /* do not allow empty content length */
1745               SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1746               goto error;
1747               break;
1748             default:
1749               break;
1750           }
1751
1752           /* header value was empty */
1753           MARK(header_value);
1754           UPDATE_STATE(s_header_field_start);
1755           CALLBACK_DATA_NOADVANCE(header_value);
1756           REEXECUTE();
1757         }
1758       }
1759
1760       case s_headers_almost_done:
1761       {
1762         STRICT_CHECK(ch != LF);
1763
1764         if (parser->flags & F_TRAILING) {
1765           /* End of a chunked request */
1766           UPDATE_STATE(s_message_done);
1767           CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
1768           REEXECUTE();
1769         }
1770
1771         /* Cannot use chunked encoding and a content-length header together
1772            per the HTTP specification. */
1773         if ((parser->flags & F_CHUNKED) &&
1774             (parser->flags & F_CONTENTLENGTH)) {
1775           SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
1776           goto error;
1777         }
1778
1779         UPDATE_STATE(s_headers_done);
1780
1781         /* Set this here so that on_headers_complete() callbacks can see it */
1782         if ((parser->flags & F_UPGRADE) &&
1783             (parser->flags & F_CONNECTION_UPGRADE)) {
1784           /* For responses, "Upgrade: foo" and "Connection: upgrade" are
1785            * mandatory only when it is a 101 Switching Protocols response,
1786            * otherwise it is purely informational, to announce support.
1787            */
1788           parser->upgrade =
1789               (parser->type == HTTP_REQUEST || parser->status_code == 101);
1790         } else {
1791           parser->upgrade = (parser->method == HTTP_CONNECT);
1792         }
1793
1794         /* Here we call the headers_complete callback. This is somewhat
1795          * different than other callbacks because if the user returns 1, we
1796          * will interpret that as saying that this message has no body. This
1797          * is needed for the annoying case of recieving a response to a HEAD
1798          * request.
1799          *
1800          * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1801          * we have to simulate it by handling a change in errno below.
1802          */
1803         if (settings->on_headers_complete) {
1804           switch (settings->on_headers_complete(parser)) {
1805             case 0:
1806               break;
1807
1808             case 2:
1809               parser->upgrade = 1;
1810
1811               /* fall through */
1812             case 1:
1813               parser->flags |= F_SKIPBODY;
1814               break;
1815
1816             default:
1817               SET_ERRNO(HPE_CB_headers_complete);
1818               RETURN(p - data); /* Error */
1819           }
1820         }
1821
1822         if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
1823           RETURN(p - data);
1824         }
1825
1826         REEXECUTE();
1827       }
1828
1829       case s_headers_done:
1830       {
1831         int hasBody;
1832         STRICT_CHECK(ch != LF);
1833
1834         parser->nread = 0;
1835         nread = 0;
1836
1837         hasBody = parser->flags & F_CHUNKED ||
1838           (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
1839         if (parser->upgrade && (parser->method == HTTP_CONNECT ||
1840                                 (parser->flags & F_SKIPBODY) || !hasBody)) {
1841           /* Exit, the rest of the message is in a different protocol. */
1842           UPDATE_STATE(NEW_MESSAGE());
1843           CALLBACK_NOTIFY(message_complete);
1844           RETURN((p - data) + 1);
1845         }
1846
1847         if (parser->flags & F_SKIPBODY) {
1848           UPDATE_STATE(NEW_MESSAGE());
1849           CALLBACK_NOTIFY(message_complete);
1850         } else if (parser->flags & F_CHUNKED) {
1851           /* chunked encoding - ignore Content-Length header */
1852           UPDATE_STATE(s_chunk_size_start);
1853         } else {
1854           if (parser->content_length == 0) {
1855             /* Content-Length header given but zero: Content-Length: 0\r\n */
1856             UPDATE_STATE(NEW_MESSAGE());
1857             CALLBACK_NOTIFY(message_complete);
1858           } else if (parser->content_length != ULLONG_MAX) {
1859             /* Content-Length header given and non-zero */
1860             UPDATE_STATE(s_body_identity);
1861           } else {
1862             if (!http_message_needs_eof(parser)) {
1863               /* Assume content-length 0 - read the next */
1864               UPDATE_STATE(NEW_MESSAGE());
1865               CALLBACK_NOTIFY(message_complete);
1866             } else {
1867               /* Read body until EOF */
1868               UPDATE_STATE(s_body_identity_eof);
1869             }
1870           }
1871         }
1872
1873         break;
1874       }
1875
1876       case s_body_identity:
1877       {
1878         uint64_t to_read = MIN(parser->content_length,
1879                                (uint64_t) ((data + len) - p));
1880
1881         assert(parser->content_length != 0
1882             && parser->content_length != ULLONG_MAX);
1883
1884         /* The difference between advancing content_length and p is because
1885          * the latter will automaticaly advance on the next loop iteration.
1886          * Further, if content_length ends up at 0, we want to see the last
1887          * byte again for our message complete callback.
1888          */
1889         MARK(body);
1890         parser->content_length -= to_read;
1891         p += to_read - 1;
1892
1893         if (parser->content_length == 0) {
1894           UPDATE_STATE(s_message_done);
1895
1896           /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1897            *
1898            * The alternative to doing this is to wait for the next byte to
1899            * trigger the data callback, just as in every other case. The
1900            * problem with this is that this makes it difficult for the test
1901            * harness to distinguish between complete-on-EOF and
1902            * complete-on-length. It's not clear that this distinction is
1903            * important for applications, but let's keep it for now.
1904            */
1905           CALLBACK_DATA_(body, p - body_mark + 1, p - data);
1906           REEXECUTE();
1907         }
1908
1909         break;
1910       }
1911
1912       /* read until EOF */
1913       case s_body_identity_eof:
1914         MARK(body);
1915         p = data + len - 1;
1916
1917         break;
1918
1919       case s_message_done:
1920         UPDATE_STATE(NEW_MESSAGE());
1921         CALLBACK_NOTIFY(message_complete);
1922         if (parser->upgrade) {
1923           /* Exit, the rest of the message is in a different protocol. */
1924           RETURN((p - data) + 1);
1925         }
1926         break;
1927
1928       case s_chunk_size_start:
1929       {
1930         assert(nread == 1);
1931         assert(parser->flags & F_CHUNKED);
1932
1933         unhex_val = unhex[(unsigned char)ch];
1934         if (UNLIKELY(unhex_val == -1)) {
1935           SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1936           goto error;
1937         }
1938
1939         parser->content_length = unhex_val;
1940         UPDATE_STATE(s_chunk_size);
1941         break;
1942       }
1943
1944       case s_chunk_size:
1945       {
1946         uint64_t t;
1947
1948         assert(parser->flags & F_CHUNKED);
1949
1950         if (ch == CR) {
1951           UPDATE_STATE(s_chunk_size_almost_done);
1952           break;
1953         }
1954
1955         unhex_val = unhex[(unsigned char)ch];
1956
1957         if (unhex_val == -1) {
1958           if (ch == ';' || ch == ' ') {
1959             UPDATE_STATE(s_chunk_parameters);
1960             break;
1961           }
1962
1963           SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1964           goto error;
1965         }
1966
1967         t = parser->content_length;
1968         t *= 16;
1969         t += unhex_val;
1970
1971         /* Overflow? Test against a conservative limit for simplicity. */
1972         if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
1973           SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1974           goto error;
1975         }
1976
1977         parser->content_length = t;
1978         break;
1979       }
1980
1981       case s_chunk_parameters:
1982       {
1983         assert(parser->flags & F_CHUNKED);
1984         /* just ignore this shit. TODO check for overflow */
1985         if (ch == CR) {
1986           UPDATE_STATE(s_chunk_size_almost_done);
1987           break;
1988         }
1989         break;
1990       }
1991
1992       case s_chunk_size_almost_done:
1993       {
1994         assert(parser->flags & F_CHUNKED);
1995         STRICT_CHECK(ch != LF);
1996
1997         parser->nread = 0;
1998         nread = 0;
1999
2000         if (parser->content_length == 0) {
2001           parser->flags |= F_TRAILING;
2002           UPDATE_STATE(s_header_field_start);
2003         } else {
2004           UPDATE_STATE(s_chunk_data);
2005         }
2006         CALLBACK_NOTIFY(chunk_header);
2007         break;
2008       }
2009
2010       case s_chunk_data:
2011       {
2012         uint64_t to_read = MIN(parser->content_length,
2013                                (uint64_t) ((data + len) - p));
2014
2015         assert(parser->flags & F_CHUNKED);
2016         assert(parser->content_length != 0
2017             && parser->content_length != ULLONG_MAX);
2018
2019         /* See the explanation in s_body_identity for why the content
2020          * length and data pointers are managed this way.
2021          */
2022         MARK(body);
2023         parser->content_length -= to_read;
2024         p += to_read - 1;
2025
2026         if (parser->content_length == 0) {
2027           UPDATE_STATE(s_chunk_data_almost_done);
2028         }
2029
2030         break;
2031       }
2032
2033       case s_chunk_data_almost_done:
2034         assert(parser->flags & F_CHUNKED);
2035         assert(parser->content_length == 0);
2036         STRICT_CHECK(ch != CR);
2037         UPDATE_STATE(s_chunk_data_done);
2038         CALLBACK_DATA(body);
2039         break;
2040
2041       case s_chunk_data_done:
2042         assert(parser->flags & F_CHUNKED);
2043         STRICT_CHECK(ch != LF);
2044         parser->nread = 0;
2045         nread = 0;
2046         UPDATE_STATE(s_chunk_size_start);
2047         CALLBACK_NOTIFY(chunk_complete);
2048         break;
2049
2050       default:
2051         assert(0 && "unhandled state");
2052         SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
2053         goto error;
2054     }
2055   }
2056
2057   /* Run callbacks for any marks that we have leftover after we ran out of
2058    * bytes. There should be at most one of these set, so it's OK to invoke
2059    * them in series (unset marks will not result in callbacks).
2060    *
2061    * We use the NOADVANCE() variety of callbacks here because 'p' has already
2062    * overflowed 'data' and this allows us to correct for the off-by-one that
2063    * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
2064    * value that's in-bounds).
2065    */
2066
2067   assert(((header_field_mark ? 1 : 0) +
2068           (header_value_mark ? 1 : 0) +
2069           (url_mark ? 1 : 0)  +
2070           (body_mark ? 1 : 0) +
2071           (status_mark ? 1 : 0)) <= 1);
2072
2073   CALLBACK_DATA_NOADVANCE(header_field);
2074   CALLBACK_DATA_NOADVANCE(header_value);
2075   CALLBACK_DATA_NOADVANCE(url);
2076   CALLBACK_DATA_NOADVANCE(body);
2077   CALLBACK_DATA_NOADVANCE(status);
2078
2079   RETURN(len);
2080
2081 error:
2082   if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2083     SET_ERRNO(HPE_UNKNOWN);
2084   }
2085
2086   RETURN(p - data);
2087 }
2088
2089
2090 /* Does the parser need to see an EOF to find the end of the message? */
2091 int
2092 http_message_needs_eof (const http_parser *parser)
2093 {
2094   if (parser->type == HTTP_REQUEST) {
2095     return 0;
2096   }
2097
2098   /* See RFC 2616 section 4.4 */
2099   if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
2100       parser->status_code == 204 ||     /* No Content */
2101       parser->status_code == 304 ||     /* Not Modified */
2102       parser->flags & F_SKIPBODY) {     /* response to a HEAD request */
2103     return 0;
2104   }
2105
2106   if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
2107     return 0;
2108   }
2109
2110   return 1;
2111 }
2112
2113
2114 int
2115 http_should_keep_alive (const http_parser *parser)
2116 {
2117   if (parser->http_major > 0 && parser->http_minor > 0) {
2118     /* HTTP/1.1 */
2119     if (parser->flags & F_CONNECTION_CLOSE) {
2120       return 0;
2121     }
2122   } else {
2123     /* HTTP/1.0 or earlier */
2124     if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2125       return 0;
2126     }
2127   }
2128
2129   return !http_message_needs_eof(parser);
2130 }
2131
2132
2133 const char *
2134 http_method_str (enum http_method m)
2135 {
2136   return ELEM_AT(method_strings, m, "<unknown>");
2137 }
2138
2139 const char *
2140 http_status_str (enum http_status s)
2141 {
2142   switch (s) {
2143 #define XX(num, name, string) case HTTP_STATUS_##name: return #string;
2144     HTTP_STATUS_MAP(XX)
2145 #undef XX
2146     default: return "<unknown>";
2147   }
2148 }
2149
2150 void
2151 http_parser_init (http_parser *parser, enum http_parser_type t)
2152 {
2153   void *data = parser->data; /* preserve application data */
2154   memset(parser, 0, sizeof(*parser));
2155   parser->data = data;
2156   parser->type = t;
2157   parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
2158   parser->http_errno = HPE_OK;
2159 }
2160
2161 void
2162 http_parser_settings_init(http_parser_settings *settings)
2163 {
2164   memset(settings, 0, sizeof(*settings));
2165 }
2166
2167 const char *
2168 http_errno_name(enum http_errno err) {
2169   assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2170   return http_strerror_tab[err].name;
2171 }
2172
2173 const char *
2174 http_errno_description(enum http_errno err) {
2175   assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2176   return http_strerror_tab[err].description;
2177 }
2178
2179 static enum http_host_state
2180 http_parse_host_char(enum http_host_state s, const char ch) {
2181   switch(s) {
2182     case s_http_userinfo:
2183     case s_http_userinfo_start:
2184       if (ch == '@') {
2185         return s_http_host_start;
2186       }
2187
2188       if (IS_USERINFO_CHAR(ch)) {
2189         return s_http_userinfo;
2190       }
2191       break;
2192
2193     case s_http_host_start:
2194       if (ch == '[') {
2195         return s_http_host_v6_start;
2196       }
2197
2198       if (IS_HOST_CHAR(ch)) {
2199         return s_http_host;
2200       }
2201
2202       break;
2203
2204     case s_http_host:
2205       if (IS_HOST_CHAR(ch)) {
2206         return s_http_host;
2207       }
2208
2209     /* fall through */
2210     case s_http_host_v6_end:
2211       if (ch == ':') {
2212         return s_http_host_port_start;
2213       }
2214
2215       break;
2216
2217     case s_http_host_v6:
2218       if (ch == ']') {
2219         return s_http_host_v6_end;
2220       }
2221
2222     /* fall through */
2223     case s_http_host_v6_start:
2224       if (IS_HEX(ch) || ch == ':' || ch == '.') {
2225         return s_http_host_v6;
2226       }
2227
2228       if (s == s_http_host_v6 && ch == '%') {
2229         return s_http_host_v6_zone_start;
2230       }
2231       break;
2232
2233     case s_http_host_v6_zone:
2234       if (ch == ']') {
2235         return s_http_host_v6_end;
2236       }
2237
2238     /* fall through */
2239     case s_http_host_v6_zone_start:
2240       /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
2241       if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
2242           ch == '~') {
2243         return s_http_host_v6_zone;
2244       }
2245       break;
2246
2247     case s_http_host_port:
2248     case s_http_host_port_start:
2249       if (IS_NUM(ch)) {
2250         return s_http_host_port;
2251       }
2252
2253       break;
2254
2255     default:
2256       break;
2257   }
2258   return s_http_host_dead;
2259 }
2260
2261 static int
2262 http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
2263   enum http_host_state s;
2264
2265   const char *p;
2266   size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
2267
2268   assert(u->field_set & (1 << UF_HOST));
2269
2270   u->field_data[UF_HOST].len = 0;
2271
2272   s = found_at ? s_http_userinfo_start : s_http_host_start;
2273
2274   for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
2275     enum http_host_state new_s = http_parse_host_char(s, *p);
2276
2277     if (new_s == s_http_host_dead) {
2278       return 1;
2279     }
2280
2281     switch(new_s) {
2282       case s_http_host:
2283         if (s != s_http_host) {
2284           u->field_data[UF_HOST].off = (uint16_t)(p - buf);
2285         }
2286         u->field_data[UF_HOST].len++;
2287         break;
2288
2289       case s_http_host_v6:
2290         if (s != s_http_host_v6) {
2291           u->field_data[UF_HOST].off = (uint16_t)(p - buf);
2292         }
2293         u->field_data[UF_HOST].len++;
2294         break;
2295
2296       case s_http_host_v6_zone_start:
2297       case s_http_host_v6_zone:
2298         u->field_data[UF_HOST].len++;
2299         break;
2300
2301       case s_http_host_port:
2302         if (s != s_http_host_port) {
2303           u->field_data[UF_PORT].off = (uint16_t)(p - buf);
2304           u->field_data[UF_PORT].len = 0;
2305           u->field_set |= (1 << UF_PORT);
2306         }
2307         u->field_data[UF_PORT].len++;
2308         break;
2309
2310       case s_http_userinfo:
2311         if (s != s_http_userinfo) {
2312           u->field_data[UF_USERINFO].off = (uint16_t)(p - buf);
2313           u->field_data[UF_USERINFO].len = 0;
2314           u->field_set |= (1 << UF_USERINFO);
2315         }
2316         u->field_data[UF_USERINFO].len++;
2317         break;
2318
2319       default:
2320         break;
2321     }
2322     s = new_s;
2323   }
2324
2325   /* Make sure we don't end somewhere unexpected */
2326   switch (s) {
2327     case s_http_host_start:
2328     case s_http_host_v6_start:
2329     case s_http_host_v6:
2330     case s_http_host_v6_zone_start:
2331     case s_http_host_v6_zone:
2332     case s_http_host_port_start:
2333     case s_http_userinfo:
2334     case s_http_userinfo_start:
2335       return 1;
2336     default:
2337       break;
2338   }
2339
2340   return 0;
2341 }
2342
2343 void
2344 http_parser_url_init(struct http_parser_url *u) {
2345   memset(u, 0, sizeof(*u));
2346 }
2347
2348 int
2349 http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2350                       struct http_parser_url *u)
2351 {
2352   enum state s;
2353   const char *p;
2354   enum http_parser_url_fields uf, old_uf;
2355   int found_at = 0;
2356
2357   if (buflen == 0) {
2358     return 1;
2359   }
2360
2361   u->port = u->field_set = 0;
2362   s = is_connect ? s_req_server_start : s_req_spaces_before_url;
2363   old_uf = UF_MAX;
2364
2365   for (p = buf; p < buf + buflen; p++) {
2366     s = parse_url_char(s, *p);
2367
2368     /* Figure out the next field that we're operating on */
2369     switch (s) {
2370       case s_dead:
2371         return 1;
2372
2373       /* Skip delimeters */
2374       case s_req_schema_slash:
2375       case s_req_schema_slash_slash:
2376       case s_req_server_start:
2377       case s_req_query_string_start:
2378       case s_req_fragment_start:
2379         continue;
2380
2381       case s_req_schema:
2382         uf = UF_SCHEMA;
2383         break;
2384
2385       case s_req_server_with_at:
2386         found_at = 1;
2387
2388       /* fall through */
2389       case s_req_server:
2390         uf = UF_HOST;
2391         break;
2392
2393       case s_req_path:
2394         uf = UF_PATH;
2395         break;
2396
2397       case s_req_query_string:
2398         uf = UF_QUERY;
2399         break;
2400
2401       case s_req_fragment:
2402         uf = UF_FRAGMENT;
2403         break;
2404
2405       default:
2406         assert(!"Unexpected state");
2407         return 1;
2408     }
2409
2410     /* Nothing's changed; soldier on */
2411     if (uf == old_uf) {
2412       u->field_data[uf].len++;
2413       continue;
2414     }
2415
2416     u->field_data[uf].off = (uint16_t)(p - buf);
2417     u->field_data[uf].len = 1;
2418
2419     u->field_set |= (1 << uf);
2420     old_uf = uf;
2421   }
2422
2423   /* host must be present if there is a schema */
2424   /* parsing http:///toto will fail */
2425   if ((u->field_set & (1 << UF_SCHEMA)) &&
2426       (u->field_set & (1 << UF_HOST)) == 0) {
2427     return 1;
2428   }
2429
2430   if (u->field_set & (1 << UF_HOST)) {
2431     if (http_parse_host(buf, u, found_at) != 0) {
2432       return 1;
2433     }
2434   }
2435
2436   /* CONNECT requests can only contain "hostname:port" */
2437   if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
2438     return 1;
2439   }
2440
2441   if (u->field_set & (1 << UF_PORT)) {
2442     uint16_t off;
2443     uint16_t len;
2444     const char* p;
2445     const char* end;
2446     unsigned long v;
2447
2448     off = u->field_data[UF_PORT].off;
2449     len = u->field_data[UF_PORT].len;
2450     end = buf + off + len;
2451
2452     /* NOTE: The characters are already validated and are in the [0-9] range */
2453     assert(off + len <= buflen && "Port number overflow");
2454     v = 0;
2455     for (p = buf + off; p < end; p++) {
2456       v *= 10;
2457       v += *p - '0';
2458
2459       /* Ports have a max value of 2^16 */
2460       if (v > 0xffff) {
2461         return 1;
2462       }
2463     }
2464
2465     u->port = (uint16_t) v;
2466   }
2467
2468   return 0;
2469 }
2470
2471 void
2472 http_parser_pause(http_parser *parser, int paused) {
2473   /* Users should only be pausing/unpausing a parser that is not in an error
2474    * state. In non-debug builds, there's not much that we can do about this
2475    * other than ignore it.
2476    */
2477   if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2478       HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2479     uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */
2480     SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2481   } else {
2482     assert(0 && "Attempting to pause parser in error state");
2483   }
2484 }
2485
2486 int
2487 http_body_is_final(const struct http_parser *parser) {
2488     return parser->state == s_message_done;
2489 }
2490
2491 unsigned long
2492 http_parser_version(void) {
2493   return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2494          HTTP_PARSER_VERSION_MINOR * 0x00100 |
2495          HTTP_PARSER_VERSION_PATCH * 0x00001;
2496 }
2497
2498 void
2499 http_parser_set_max_header_size(uint32_t size) {
2500   max_header_size = size;
2501 }