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