]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - vendor/http_parser/http_parser.c
Fix the <wsorigin> example.
[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 left = data + len - p;
1261               const char* pe = p + MIN(left, max_header_size);
1262               while (p+1 < pe && 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                 size_t left = data + len - p;
1501                 const char* pe = p + MIN(left, max_header_size);
1502
1503                 for (; p != pe; p++) {
1504                   ch = *p;
1505                   if (ch == CR || ch == LF) {
1506                     --p;
1507                     break;
1508                   }
1509                   if (!lenient && !IS_HEADER_CHAR(ch)) {
1510                     SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1511                     goto error;
1512                   }
1513                 }
1514                 if (p == data + len)
1515                   --p;
1516                 break;
1517               }
1518
1519             case h_connection:
1520             case h_transfer_encoding:
1521               assert(0 && "Shouldn't get here.");
1522               break;
1523
1524             case h_content_length:
1525               if (ch == ' ') break;
1526               h_state = h_content_length_num;
1527               /* fall through */
1528
1529             case h_content_length_num:
1530             {
1531               uint64_t t;
1532
1533               if (ch == ' ') {
1534                 h_state = h_content_length_ws;
1535                 break;
1536               }
1537
1538               if (UNLIKELY(!IS_NUM(ch))) {
1539                 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1540                 parser->header_state = h_state;
1541                 goto error;
1542               }
1543
1544               t = parser->content_length;
1545               t *= 10;
1546               t += ch - '0';
1547
1548               /* Overflow? Test against a conservative limit for simplicity. */
1549               if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
1550                 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1551                 parser->header_state = h_state;
1552                 goto error;
1553               }
1554
1555               parser->content_length = t;
1556               break;
1557             }
1558
1559             case h_content_length_ws:
1560               if (ch == ' ') break;
1561               SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1562               parser->header_state = h_state;
1563               goto error;
1564
1565             /* Transfer-Encoding: chunked */
1566             case h_matching_transfer_encoding_chunked:
1567               parser->index++;
1568               if (parser->index > sizeof(CHUNKED)-1
1569                   || c != CHUNKED[parser->index]) {
1570                 h_state = h_general;
1571               } else if (parser->index == sizeof(CHUNKED)-2) {
1572                 h_state = h_transfer_encoding_chunked;
1573               }
1574               break;
1575
1576             case h_matching_connection_token_start:
1577               /* looking for 'Connection: keep-alive' */
1578               if (c == 'k') {
1579                 h_state = h_matching_connection_keep_alive;
1580               /* looking for 'Connection: close' */
1581               } else if (c == 'c') {
1582                 h_state = h_matching_connection_close;
1583               } else if (c == 'u') {
1584                 h_state = h_matching_connection_upgrade;
1585               } else if (STRICT_TOKEN(c)) {
1586                 h_state = h_matching_connection_token;
1587               } else if (c == ' ' || c == '\t') {
1588                 /* Skip lws */
1589               } else {
1590                 h_state = h_general;
1591               }
1592               break;
1593
1594             /* looking for 'Connection: keep-alive' */
1595             case h_matching_connection_keep_alive:
1596               parser->index++;
1597               if (parser->index > sizeof(KEEP_ALIVE)-1
1598                   || c != KEEP_ALIVE[parser->index]) {
1599                 h_state = h_matching_connection_token;
1600               } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
1601                 h_state = h_connection_keep_alive;
1602               }
1603               break;
1604
1605             /* looking for 'Connection: close' */
1606             case h_matching_connection_close:
1607               parser->index++;
1608               if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
1609                 h_state = h_matching_connection_token;
1610               } else if (parser->index == sizeof(CLOSE)-2) {
1611                 h_state = h_connection_close;
1612               }
1613               break;
1614
1615             /* looking for 'Connection: upgrade' */
1616             case h_matching_connection_upgrade:
1617               parser->index++;
1618               if (parser->index > sizeof(UPGRADE) - 1 ||
1619                   c != UPGRADE[parser->index]) {
1620                 h_state = h_matching_connection_token;
1621               } else if (parser->index == sizeof(UPGRADE)-2) {
1622                 h_state = h_connection_upgrade;
1623               }
1624               break;
1625
1626             case h_matching_connection_token:
1627               if (ch == ',') {
1628                 h_state = h_matching_connection_token_start;
1629                 parser->index = 0;
1630               }
1631               break;
1632
1633             case h_transfer_encoding_chunked:
1634               if (ch != ' ') h_state = h_general;
1635               break;
1636
1637             case h_connection_keep_alive:
1638             case h_connection_close:
1639             case h_connection_upgrade:
1640               if (ch == ',') {
1641                 if (h_state == h_connection_keep_alive) {
1642                   parser->flags |= F_CONNECTION_KEEP_ALIVE;
1643                 } else if (h_state == h_connection_close) {
1644                   parser->flags |= F_CONNECTION_CLOSE;
1645                 } else if (h_state == h_connection_upgrade) {
1646                   parser->flags |= F_CONNECTION_UPGRADE;
1647                 }
1648                 h_state = h_matching_connection_token_start;
1649                 parser->index = 0;
1650               } else if (ch != ' ') {
1651                 h_state = h_matching_connection_token;
1652               }
1653               break;
1654
1655             default:
1656               UPDATE_STATE(s_header_value);
1657               h_state = h_general;
1658               break;
1659           }
1660         }
1661         parser->header_state = h_state;
1662
1663         if (p == data + len)
1664           --p;
1665
1666         COUNT_HEADER_SIZE(p - start);
1667         break;
1668       }
1669
1670       case s_header_almost_done:
1671       {
1672         if (UNLIKELY(ch != LF)) {
1673           SET_ERRNO(HPE_LF_EXPECTED);
1674           goto error;
1675         }
1676
1677         UPDATE_STATE(s_header_value_lws);
1678         break;
1679       }
1680
1681       case s_header_value_lws:
1682       {
1683         if (ch == ' ' || ch == '\t') {
1684           if (parser->header_state == h_content_length_num) {
1685               /* treat obsolete line folding as space */
1686               parser->header_state = h_content_length_ws;
1687           }
1688           UPDATE_STATE(s_header_value_start);
1689           REEXECUTE();
1690         }
1691
1692         /* finished the header */
1693         switch (parser->header_state) {
1694           case h_connection_keep_alive:
1695             parser->flags |= F_CONNECTION_KEEP_ALIVE;
1696             break;
1697           case h_connection_close:
1698             parser->flags |= F_CONNECTION_CLOSE;
1699             break;
1700           case h_transfer_encoding_chunked:
1701             parser->flags |= F_CHUNKED;
1702             break;
1703           case h_connection_upgrade:
1704             parser->flags |= F_CONNECTION_UPGRADE;
1705             break;
1706           default:
1707             break;
1708         }
1709
1710         UPDATE_STATE(s_header_field_start);
1711         REEXECUTE();
1712       }
1713
1714       case s_header_value_discard_ws_almost_done:
1715       {
1716         STRICT_CHECK(ch != LF);
1717         UPDATE_STATE(s_header_value_discard_lws);
1718         break;
1719       }
1720
1721       case s_header_value_discard_lws:
1722       {
1723         if (ch == ' ' || ch == '\t') {
1724           UPDATE_STATE(s_header_value_discard_ws);
1725           break;
1726         } else {
1727           switch (parser->header_state) {
1728             case h_connection_keep_alive:
1729               parser->flags |= F_CONNECTION_KEEP_ALIVE;
1730               break;
1731             case h_connection_close:
1732               parser->flags |= F_CONNECTION_CLOSE;
1733               break;
1734             case h_connection_upgrade:
1735               parser->flags |= F_CONNECTION_UPGRADE;
1736               break;
1737             case h_transfer_encoding_chunked:
1738               parser->flags |= F_CHUNKED;
1739               break;
1740             case h_content_length:
1741               /* do not allow empty content length */
1742               SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1743               goto error;
1744               break;
1745             default:
1746               break;
1747           }
1748
1749           /* header value was empty */
1750           MARK(header_value);
1751           UPDATE_STATE(s_header_field_start);
1752           CALLBACK_DATA_NOADVANCE(header_value);
1753           REEXECUTE();
1754         }
1755       }
1756
1757       case s_headers_almost_done:
1758       {
1759         STRICT_CHECK(ch != LF);
1760
1761         if (parser->flags & F_TRAILING) {
1762           /* End of a chunked request */
1763           UPDATE_STATE(s_message_done);
1764           CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
1765           REEXECUTE();
1766         }
1767
1768         /* Cannot use chunked encoding and a content-length header together
1769            per the HTTP specification. */
1770         if ((parser->flags & F_CHUNKED) &&
1771             (parser->flags & F_CONTENTLENGTH)) {
1772           SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
1773           goto error;
1774         }
1775
1776         UPDATE_STATE(s_headers_done);
1777
1778         /* Set this here so that on_headers_complete() callbacks can see it */
1779         if ((parser->flags & F_UPGRADE) &&
1780             (parser->flags & F_CONNECTION_UPGRADE)) {
1781           /* For responses, "Upgrade: foo" and "Connection: upgrade" are
1782            * mandatory only when it is a 101 Switching Protocols response,
1783            * otherwise it is purely informational, to announce support.
1784            */
1785           parser->upgrade =
1786               (parser->type == HTTP_REQUEST || parser->status_code == 101);
1787         } else {
1788           parser->upgrade = (parser->method == HTTP_CONNECT);
1789         }
1790
1791         /* Here we call the headers_complete callback. This is somewhat
1792          * different than other callbacks because if the user returns 1, we
1793          * will interpret that as saying that this message has no body. This
1794          * is needed for the annoying case of recieving a response to a HEAD
1795          * request.
1796          *
1797          * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1798          * we have to simulate it by handling a change in errno below.
1799          */
1800         if (settings->on_headers_complete) {
1801           switch (settings->on_headers_complete(parser)) {
1802             case 0:
1803               break;
1804
1805             case 2:
1806               parser->upgrade = 1;
1807
1808               /* fall through */
1809             case 1:
1810               parser->flags |= F_SKIPBODY;
1811               break;
1812
1813             default:
1814               SET_ERRNO(HPE_CB_headers_complete);
1815               RETURN(p - data); /* Error */
1816           }
1817         }
1818
1819         if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
1820           RETURN(p - data);
1821         }
1822
1823         REEXECUTE();
1824       }
1825
1826       case s_headers_done:
1827       {
1828         int hasBody;
1829         STRICT_CHECK(ch != LF);
1830
1831         parser->nread = 0;
1832         nread = 0;
1833
1834         hasBody = parser->flags & F_CHUNKED ||
1835           (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
1836         if (parser->upgrade && (parser->method == HTTP_CONNECT ||
1837                                 (parser->flags & F_SKIPBODY) || !hasBody)) {
1838           /* Exit, the rest of the message is in a different protocol. */
1839           UPDATE_STATE(NEW_MESSAGE());
1840           CALLBACK_NOTIFY(message_complete);
1841           RETURN((p - data) + 1);
1842         }
1843
1844         if (parser->flags & F_SKIPBODY) {
1845           UPDATE_STATE(NEW_MESSAGE());
1846           CALLBACK_NOTIFY(message_complete);
1847         } else if (parser->flags & F_CHUNKED) {
1848           /* chunked encoding - ignore Content-Length header */
1849           UPDATE_STATE(s_chunk_size_start);
1850         } else {
1851           if (parser->content_length == 0) {
1852             /* Content-Length header given but zero: Content-Length: 0\r\n */
1853             UPDATE_STATE(NEW_MESSAGE());
1854             CALLBACK_NOTIFY(message_complete);
1855           } else if (parser->content_length != ULLONG_MAX) {
1856             /* Content-Length header given and non-zero */
1857             UPDATE_STATE(s_body_identity);
1858           } else {
1859             if (!http_message_needs_eof(parser)) {
1860               /* Assume content-length 0 - read the next */
1861               UPDATE_STATE(NEW_MESSAGE());
1862               CALLBACK_NOTIFY(message_complete);
1863             } else {
1864               /* Read body until EOF */
1865               UPDATE_STATE(s_body_identity_eof);
1866             }
1867           }
1868         }
1869
1870         break;
1871       }
1872
1873       case s_body_identity:
1874       {
1875         uint64_t to_read = MIN(parser->content_length,
1876                                (uint64_t) ((data + len) - p));
1877
1878         assert(parser->content_length != 0
1879             && parser->content_length != ULLONG_MAX);
1880
1881         /* The difference between advancing content_length and p is because
1882          * the latter will automaticaly advance on the next loop iteration.
1883          * Further, if content_length ends up at 0, we want to see the last
1884          * byte again for our message complete callback.
1885          */
1886         MARK(body);
1887         parser->content_length -= to_read;
1888         p += to_read - 1;
1889
1890         if (parser->content_length == 0) {
1891           UPDATE_STATE(s_message_done);
1892
1893           /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1894            *
1895            * The alternative to doing this is to wait for the next byte to
1896            * trigger the data callback, just as in every other case. The
1897            * problem with this is that this makes it difficult for the test
1898            * harness to distinguish between complete-on-EOF and
1899            * complete-on-length. It's not clear that this distinction is
1900            * important for applications, but let's keep it for now.
1901            */
1902           CALLBACK_DATA_(body, p - body_mark + 1, p - data);
1903           REEXECUTE();
1904         }
1905
1906         break;
1907       }
1908
1909       /* read until EOF */
1910       case s_body_identity_eof:
1911         MARK(body);
1912         p = data + len - 1;
1913
1914         break;
1915
1916       case s_message_done:
1917         UPDATE_STATE(NEW_MESSAGE());
1918         CALLBACK_NOTIFY(message_complete);
1919         if (parser->upgrade) {
1920           /* Exit, the rest of the message is in a different protocol. */
1921           RETURN((p - data) + 1);
1922         }
1923         break;
1924
1925       case s_chunk_size_start:
1926       {
1927         assert(nread == 1);
1928         assert(parser->flags & F_CHUNKED);
1929
1930         unhex_val = unhex[(unsigned char)ch];
1931         if (UNLIKELY(unhex_val == -1)) {
1932           SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1933           goto error;
1934         }
1935
1936         parser->content_length = unhex_val;
1937         UPDATE_STATE(s_chunk_size);
1938         break;
1939       }
1940
1941       case s_chunk_size:
1942       {
1943         uint64_t t;
1944
1945         assert(parser->flags & F_CHUNKED);
1946
1947         if (ch == CR) {
1948           UPDATE_STATE(s_chunk_size_almost_done);
1949           break;
1950         }
1951
1952         unhex_val = unhex[(unsigned char)ch];
1953
1954         if (unhex_val == -1) {
1955           if (ch == ';' || ch == ' ') {
1956             UPDATE_STATE(s_chunk_parameters);
1957             break;
1958           }
1959
1960           SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
1961           goto error;
1962         }
1963
1964         t = parser->content_length;
1965         t *= 16;
1966         t += unhex_val;
1967
1968         /* Overflow? Test against a conservative limit for simplicity. */
1969         if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
1970           SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1971           goto error;
1972         }
1973
1974         parser->content_length = t;
1975         break;
1976       }
1977
1978       case s_chunk_parameters:
1979       {
1980         assert(parser->flags & F_CHUNKED);
1981         /* just ignore this shit. TODO check for overflow */
1982         if (ch == CR) {
1983           UPDATE_STATE(s_chunk_size_almost_done);
1984           break;
1985         }
1986         break;
1987       }
1988
1989       case s_chunk_size_almost_done:
1990       {
1991         assert(parser->flags & F_CHUNKED);
1992         STRICT_CHECK(ch != LF);
1993
1994         parser->nread = 0;
1995         nread = 0;
1996
1997         if (parser->content_length == 0) {
1998           parser->flags |= F_TRAILING;
1999           UPDATE_STATE(s_header_field_start);
2000         } else {
2001           UPDATE_STATE(s_chunk_data);
2002         }
2003         CALLBACK_NOTIFY(chunk_header);
2004         break;
2005       }
2006
2007       case s_chunk_data:
2008       {
2009         uint64_t to_read = MIN(parser->content_length,
2010                                (uint64_t) ((data + len) - p));
2011
2012         assert(parser->flags & F_CHUNKED);
2013         assert(parser->content_length != 0
2014             && parser->content_length != ULLONG_MAX);
2015
2016         /* See the explanation in s_body_identity for why the content
2017          * length and data pointers are managed this way.
2018          */
2019         MARK(body);
2020         parser->content_length -= to_read;
2021         p += to_read - 1;
2022
2023         if (parser->content_length == 0) {
2024           UPDATE_STATE(s_chunk_data_almost_done);
2025         }
2026
2027         break;
2028       }
2029
2030       case s_chunk_data_almost_done:
2031         assert(parser->flags & F_CHUNKED);
2032         assert(parser->content_length == 0);
2033         STRICT_CHECK(ch != CR);
2034         UPDATE_STATE(s_chunk_data_done);
2035         CALLBACK_DATA(body);
2036         break;
2037
2038       case s_chunk_data_done:
2039         assert(parser->flags & F_CHUNKED);
2040         STRICT_CHECK(ch != LF);
2041         parser->nread = 0;
2042         nread = 0;
2043         UPDATE_STATE(s_chunk_size_start);
2044         CALLBACK_NOTIFY(chunk_complete);
2045         break;
2046
2047       default:
2048         assert(0 && "unhandled state");
2049         SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
2050         goto error;
2051     }
2052   }
2053
2054   /* Run callbacks for any marks that we have leftover after we ran out of
2055    * bytes. There should be at most one of these set, so it's OK to invoke
2056    * them in series (unset marks will not result in callbacks).
2057    *
2058    * We use the NOADVANCE() variety of callbacks here because 'p' has already
2059    * overflowed 'data' and this allows us to correct for the off-by-one that
2060    * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
2061    * value that's in-bounds).
2062    */
2063
2064   assert(((header_field_mark ? 1 : 0) +
2065           (header_value_mark ? 1 : 0) +
2066           (url_mark ? 1 : 0)  +
2067           (body_mark ? 1 : 0) +
2068           (status_mark ? 1 : 0)) <= 1);
2069
2070   CALLBACK_DATA_NOADVANCE(header_field);
2071   CALLBACK_DATA_NOADVANCE(header_value);
2072   CALLBACK_DATA_NOADVANCE(url);
2073   CALLBACK_DATA_NOADVANCE(body);
2074   CALLBACK_DATA_NOADVANCE(status);
2075
2076   RETURN(len);
2077
2078 error:
2079   if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2080     SET_ERRNO(HPE_UNKNOWN);
2081   }
2082
2083   RETURN(p - data);
2084 }
2085
2086
2087 /* Does the parser need to see an EOF to find the end of the message? */
2088 int
2089 http_message_needs_eof (const http_parser *parser)
2090 {
2091   if (parser->type == HTTP_REQUEST) {
2092     return 0;
2093   }
2094
2095   /* See RFC 2616 section 4.4 */
2096   if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
2097       parser->status_code == 204 ||     /* No Content */
2098       parser->status_code == 304 ||     /* Not Modified */
2099       parser->flags & F_SKIPBODY) {     /* response to a HEAD request */
2100     return 0;
2101   }
2102
2103   if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
2104     return 0;
2105   }
2106
2107   return 1;
2108 }
2109
2110
2111 int
2112 http_should_keep_alive (const http_parser *parser)
2113 {
2114   if (parser->http_major > 0 && parser->http_minor > 0) {
2115     /* HTTP/1.1 */
2116     if (parser->flags & F_CONNECTION_CLOSE) {
2117       return 0;
2118     }
2119   } else {
2120     /* HTTP/1.0 or earlier */
2121     if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2122       return 0;
2123     }
2124   }
2125
2126   return !http_message_needs_eof(parser);
2127 }
2128
2129
2130 const char *
2131 http_method_str (enum http_method m)
2132 {
2133   return ELEM_AT(method_strings, m, "<unknown>");
2134 }
2135
2136 const char *
2137 http_status_str (enum http_status s)
2138 {
2139   switch (s) {
2140 #define XX(num, name, string) case HTTP_STATUS_##name: return #string;
2141     HTTP_STATUS_MAP(XX)
2142 #undef XX
2143     default: return "<unknown>";
2144   }
2145 }
2146
2147 void
2148 http_parser_init (http_parser *parser, enum http_parser_type t)
2149 {
2150   void *data = parser->data; /* preserve application data */
2151   memset(parser, 0, sizeof(*parser));
2152   parser->data = data;
2153   parser->type = t;
2154   parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
2155   parser->http_errno = HPE_OK;
2156 }
2157
2158 void
2159 http_parser_settings_init(http_parser_settings *settings)
2160 {
2161   memset(settings, 0, sizeof(*settings));
2162 }
2163
2164 const char *
2165 http_errno_name(enum http_errno err) {
2166   assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2167   return http_strerror_tab[err].name;
2168 }
2169
2170 const char *
2171 http_errno_description(enum http_errno err) {
2172   assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2173   return http_strerror_tab[err].description;
2174 }
2175
2176 static enum http_host_state
2177 http_parse_host_char(enum http_host_state s, const char ch) {
2178   switch(s) {
2179     case s_http_userinfo:
2180     case s_http_userinfo_start:
2181       if (ch == '@') {
2182         return s_http_host_start;
2183       }
2184
2185       if (IS_USERINFO_CHAR(ch)) {
2186         return s_http_userinfo;
2187       }
2188       break;
2189
2190     case s_http_host_start:
2191       if (ch == '[') {
2192         return s_http_host_v6_start;
2193       }
2194
2195       if (IS_HOST_CHAR(ch)) {
2196         return s_http_host;
2197       }
2198
2199       break;
2200
2201     case s_http_host:
2202       if (IS_HOST_CHAR(ch)) {
2203         return s_http_host;
2204       }
2205
2206     /* fall through */
2207     case s_http_host_v6_end:
2208       if (ch == ':') {
2209         return s_http_host_port_start;
2210       }
2211
2212       break;
2213
2214     case s_http_host_v6:
2215       if (ch == ']') {
2216         return s_http_host_v6_end;
2217       }
2218
2219     /* fall through */
2220     case s_http_host_v6_start:
2221       if (IS_HEX(ch) || ch == ':' || ch == '.') {
2222         return s_http_host_v6;
2223       }
2224
2225       if (s == s_http_host_v6 && ch == '%') {
2226         return s_http_host_v6_zone_start;
2227       }
2228       break;
2229
2230     case s_http_host_v6_zone:
2231       if (ch == ']') {
2232         return s_http_host_v6_end;
2233       }
2234
2235     /* fall through */
2236     case s_http_host_v6_zone_start:
2237       /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
2238       if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
2239           ch == '~') {
2240         return s_http_host_v6_zone;
2241       }
2242       break;
2243
2244     case s_http_host_port:
2245     case s_http_host_port_start:
2246       if (IS_NUM(ch)) {
2247         return s_http_host_port;
2248       }
2249
2250       break;
2251
2252     default:
2253       break;
2254   }
2255   return s_http_host_dead;
2256 }
2257
2258 static int
2259 http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
2260   enum http_host_state s;
2261
2262   const char *p;
2263   size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
2264
2265   assert(u->field_set & (1 << UF_HOST));
2266
2267   u->field_data[UF_HOST].len = 0;
2268
2269   s = found_at ? s_http_userinfo_start : s_http_host_start;
2270
2271   for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
2272     enum http_host_state new_s = http_parse_host_char(s, *p);
2273
2274     if (new_s == s_http_host_dead) {
2275       return 1;
2276     }
2277
2278     switch(new_s) {
2279       case s_http_host:
2280         if (s != s_http_host) {
2281           u->field_data[UF_HOST].off = (uint16_t)(p - buf);
2282         }
2283         u->field_data[UF_HOST].len++;
2284         break;
2285
2286       case s_http_host_v6:
2287         if (s != s_http_host_v6) {
2288           u->field_data[UF_HOST].off = (uint16_t)(p - buf);
2289         }
2290         u->field_data[UF_HOST].len++;
2291         break;
2292
2293       case s_http_host_v6_zone_start:
2294       case s_http_host_v6_zone:
2295         u->field_data[UF_HOST].len++;
2296         break;
2297
2298       case s_http_host_port:
2299         if (s != s_http_host_port) {
2300           u->field_data[UF_PORT].off = (uint16_t)(p - buf);
2301           u->field_data[UF_PORT].len = 0;
2302           u->field_set |= (1 << UF_PORT);
2303         }
2304         u->field_data[UF_PORT].len++;
2305         break;
2306
2307       case s_http_userinfo:
2308         if (s != s_http_userinfo) {
2309           u->field_data[UF_USERINFO].off = (uint16_t)(p - buf);
2310           u->field_data[UF_USERINFO].len = 0;
2311           u->field_set |= (1 << UF_USERINFO);
2312         }
2313         u->field_data[UF_USERINFO].len++;
2314         break;
2315
2316       default:
2317         break;
2318     }
2319     s = new_s;
2320   }
2321
2322   /* Make sure we don't end somewhere unexpected */
2323   switch (s) {
2324     case s_http_host_start:
2325     case s_http_host_v6_start:
2326     case s_http_host_v6:
2327     case s_http_host_v6_zone_start:
2328     case s_http_host_v6_zone:
2329     case s_http_host_port_start:
2330     case s_http_userinfo:
2331     case s_http_userinfo_start:
2332       return 1;
2333     default:
2334       break;
2335   }
2336
2337   return 0;
2338 }
2339
2340 void
2341 http_parser_url_init(struct http_parser_url *u) {
2342   memset(u, 0, sizeof(*u));
2343 }
2344
2345 int
2346 http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2347                       struct http_parser_url *u)
2348 {
2349   enum state s;
2350   const char *p;
2351   enum http_parser_url_fields uf, old_uf;
2352   int found_at = 0;
2353
2354   if (buflen == 0) {
2355     return 1;
2356   }
2357
2358   u->port = u->field_set = 0;
2359   s = is_connect ? s_req_server_start : s_req_spaces_before_url;
2360   old_uf = UF_MAX;
2361
2362   for (p = buf; p < buf + buflen; p++) {
2363     s = parse_url_char(s, *p);
2364
2365     /* Figure out the next field that we're operating on */
2366     switch (s) {
2367       case s_dead:
2368         return 1;
2369
2370       /* Skip delimeters */
2371       case s_req_schema_slash:
2372       case s_req_schema_slash_slash:
2373       case s_req_server_start:
2374       case s_req_query_string_start:
2375       case s_req_fragment_start:
2376         continue;
2377
2378       case s_req_schema:
2379         uf = UF_SCHEMA;
2380         break;
2381
2382       case s_req_server_with_at:
2383         found_at = 1;
2384
2385       /* fall through */
2386       case s_req_server:
2387         uf = UF_HOST;
2388         break;
2389
2390       case s_req_path:
2391         uf = UF_PATH;
2392         break;
2393
2394       case s_req_query_string:
2395         uf = UF_QUERY;
2396         break;
2397
2398       case s_req_fragment:
2399         uf = UF_FRAGMENT;
2400         break;
2401
2402       default:
2403         assert(!"Unexpected state");
2404         return 1;
2405     }
2406
2407     /* Nothing's changed; soldier on */
2408     if (uf == old_uf) {
2409       u->field_data[uf].len++;
2410       continue;
2411     }
2412
2413     u->field_data[uf].off = (uint16_t)(p - buf);
2414     u->field_data[uf].len = 1;
2415
2416     u->field_set |= (1 << uf);
2417     old_uf = uf;
2418   }
2419
2420   /* host must be present if there is a schema */
2421   /* parsing http:///toto will fail */
2422   if ((u->field_set & (1 << UF_SCHEMA)) &&
2423       (u->field_set & (1 << UF_HOST)) == 0) {
2424     return 1;
2425   }
2426
2427   if (u->field_set & (1 << UF_HOST)) {
2428     if (http_parse_host(buf, u, found_at) != 0) {
2429       return 1;
2430     }
2431   }
2432
2433   /* CONNECT requests can only contain "hostname:port" */
2434   if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
2435     return 1;
2436   }
2437
2438   if (u->field_set & (1 << UF_PORT)) {
2439     uint16_t off;
2440     uint16_t len;
2441     const char* p;
2442     const char* end;
2443     unsigned long v;
2444
2445     off = u->field_data[UF_PORT].off;
2446     len = u->field_data[UF_PORT].len;
2447     end = buf + off + len;
2448
2449     /* NOTE: The characters are already validated and are in the [0-9] range */
2450     assert(off + len <= buflen && "Port number overflow");
2451     v = 0;
2452     for (p = buf + off; p < end; p++) {
2453       v *= 10;
2454       v += *p - '0';
2455
2456       /* Ports have a max value of 2^16 */
2457       if (v > 0xffff) {
2458         return 1;
2459       }
2460     }
2461
2462     u->port = (uint16_t) v;
2463   }
2464
2465   return 0;
2466 }
2467
2468 void
2469 http_parser_pause(http_parser *parser, int paused) {
2470   /* Users should only be pausing/unpausing a parser that is not in an error
2471    * state. In non-debug builds, there's not much that we can do about this
2472    * other than ignore it.
2473    */
2474   if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2475       HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2476     uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */
2477     SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2478   } else {
2479     assert(0 && "Attempting to pause parser in error state");
2480   }
2481 }
2482
2483 int
2484 http_body_is_final(const struct http_parser *parser) {
2485     return parser->state == s_message_done;
2486 }
2487
2488 unsigned long
2489 http_parser_version(void) {
2490   return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2491          HTTP_PARSER_VERSION_MINOR * 0x00100 |
2492          HTTP_PARSER_VERSION_PATCH * 0x00001;
2493 }
2494
2495 void
2496 http_parser_set_max_header_size(uint32_t size) {
2497   max_header_size = size;
2498 }