"Fossies" - the Fresh Open Source Software Archive

Member "tcpflow-1.6.1/src/http-parser/http_parser.c" (19 Feb 2021, 69864 Bytes) of package /linux/misc/tcpflow-1.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "http_parser.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.4.5_vs_1.5.0.

    1 /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
    2  *
    3  * Additional changes are licensed under the same terms as NGINX and
    4  * copyright Joyent, Inc. and other Node contributors. All rights reserved.
    5  *
    6  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7  * of this software and associated documentation files (the "Software"), to
    8  * deal in the Software without restriction, including without limitation the
    9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   10  * sell copies of the Software, and to permit persons to whom the Software is
   11  * furnished to do so, subject to the following conditions:
   12  *
   13  * The above copyright notice and this permission notice shall be included in
   14  * all copies or substantial portions of the Software.
   15  *
   16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   22  * IN THE SOFTWARE.
   23  */
   24 #include "http_parser.h"
   25 #include <assert.h>
   26 #include <stddef.h>
   27 #include <ctype.h>
   28 #include <stdlib.h>
   29 #include <string.h>
   30 #include <limits.h>
   31 
   32 #ifndef ULLONG_MAX
   33 # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
   34 #endif
   35 
   36 #ifndef MIN
   37 # define MIN(a,b) ((a) < (b) ? (a) : (b))
   38 #endif
   39 
   40 #ifndef ARRAY_SIZE
   41 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
   42 #endif
   43 
   44 #ifndef BIT_AT
   45 # define BIT_AT(a, i)                                                \
   46   (!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
   47    (1 << ((unsigned int) (i) & 7))))
   48 #endif
   49 
   50 #ifndef ELEM_AT
   51 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
   52 #endif
   53 
   54 #define SET_ERRNO(e)                                                 \
   55 do {                                                                 \
   56   parser->http_errno = (e);                                          \
   57 } while(0)
   58 
   59 #define CURRENT_STATE() p_state
   60 #define UPDATE_STATE(V) p_state = (enum state) (V);
   61 #define RETURN(V)                                                    \
   62 do {                                                                 \
   63   parser->state = CURRENT_STATE();                                   \
   64   return (V);                                                        \
   65 } while (0);
   66 #define REEXECUTE()                                                  \
   67   goto reexecute;                                                    \
   68 
   69 
   70 #ifdef __GNUC__
   71 # define LIKELY(X) __builtin_expect(!!(X), 1)
   72 # define UNLIKELY(X) __builtin_expect(!!(X), 0)
   73 #else
   74 # define LIKELY(X) (X)
   75 # define UNLIKELY(X) (X)
   76 #endif
   77 
   78 
   79 /* Run the notify callback FOR, returning ER if it fails */
   80 #define CALLBACK_NOTIFY_(FOR, ER)                                    \
   81 do {                                                                 \
   82   assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \
   83                                                                      \
   84   if (LIKELY(settings->on_##FOR)) {                                  \
   85     parser->state = CURRENT_STATE();                                 \
   86     if (UNLIKELY(0 != settings->on_##FOR(parser))) {                 \
   87       SET_ERRNO(HPE_CB_##FOR);                                       \
   88     }                                                                \
   89     UPDATE_STATE(parser->state);                                     \
   90                                                                      \
   91     /* We either errored above or got paused; get out */             \
   92     if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {             \
   93       return (ER);                                                   \
   94     }                                                                \
   95   }                                                                  \
   96 } while (0)
   97 
   98 /* Run the notify callback FOR and consume the current byte */
   99 #define CALLBACK_NOTIFY(FOR)            CALLBACK_NOTIFY_(FOR, p - data + 1)
  100 
  101 /* Run the notify callback FOR and don't consume the current byte */
  102 #define CALLBACK_NOTIFY_NOADVANCE(FOR)  CALLBACK_NOTIFY_(FOR, p - data)
  103 
  104 /* Run data callback FOR with LEN bytes, returning ER if it fails */
  105 #define CALLBACK_DATA_(FOR, LEN, ER)                                 \
  106 do {                                                                 \
  107   assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \
  108                                                                      \
  109   if (FOR##_mark) {                                                  \
  110     if (LIKELY(settings->on_##FOR)) {                                \
  111       parser->state = CURRENT_STATE();                               \
  112       if (UNLIKELY(0 !=                                              \
  113                    settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
  114         SET_ERRNO(HPE_CB_##FOR);                                     \
  115       }                                                              \
  116       UPDATE_STATE(parser->state);                                   \
  117                                                                      \
  118       /* We either errored above or got paused; get out */           \
  119       if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {           \
  120         return (ER);                                                 \
  121       }                                                              \
  122     }                                                                \
  123     FOR##_mark = NULL;                                               \
  124   }                                                                  \
  125 } while (0)
  126 
  127 /* Run the data callback FOR and consume the current byte */
  128 #define CALLBACK_DATA(FOR)                                           \
  129     CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
  130 
  131 /* Run the data callback FOR and don't consume the current byte */
  132 #define CALLBACK_DATA_NOADVANCE(FOR)                                 \
  133     CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
  134 
  135 /* Set the mark FOR; non-destructive if mark is already set */
  136 #define MARK(FOR)                                                    \
  137 do {                                                                 \
  138   if (!FOR##_mark) {                                                 \
  139     FOR##_mark = p;                                                  \
  140   }                                                                  \
  141 } while (0)
  142 
  143 /* Don't allow the total size of the HTTP headers (including the status
  144  * line) to exceed HTTP_MAX_HEADER_SIZE.  This check is here to protect
  145  * embedders against denial-of-service attacks where the attacker feeds
  146  * us a never-ending header that the embedder keeps buffering.
  147  *
  148  * This check is arguably the responsibility of embedders but we're doing
  149  * it on the embedder's behalf because most won't bother and this way we
  150  * make the web a little safer.  HTTP_MAX_HEADER_SIZE is still far bigger
  151  * than any reasonable request or response so this should never affect
  152  * day-to-day operation.
  153  */
  154 #define COUNT_HEADER_SIZE(V)                                         \
  155 do {                                                                 \
  156   parser->nread += (V);                                              \
  157   if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) {            \
  158     SET_ERRNO(HPE_HEADER_OVERFLOW);                                  \
  159     goto error;                                                      \
  160   }                                                                  \
  161 } while (0)
  162 
  163 
  164 #define PROXY_CONNECTION "proxy-connection"
  165 #define CONNECTION "connection"
  166 #define CONTENT_LENGTH "content-length"
  167 #define TRANSFER_ENCODING "transfer-encoding"
  168 #define UPGRADE "upgrade"
  169 #define CHUNKED "chunked"
  170 #define KEEP_ALIVE "keep-alive"
  171 #define CLOSE "close"
  172 
  173 
  174 static const char *method_strings[] =
  175   {
  176 #define XX(num, name, string) #string,
  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,      '!',      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_major
  320   , s_req_http_dot
  321   , s_req_http_minor
  322   , s_req_http_end
  323   , s_req_line_almost_done
  324 
  325   , s_header_field_start
  326   , s_header_field
  327   , s_header_value_discard_ws
  328   , s_header_value_discard_ws_almost_done
  329   , s_header_value_discard_lws
  330   , s_header_value_start
  331   , s_header_value
  332   , s_header_value_lws
  333 
  334   , s_header_almost_done
  335 
  336   , s_chunk_size_start
  337   , s_chunk_size
  338   , s_chunk_parameters
  339   , s_chunk_size_almost_done
  340 
  341   , s_headers_almost_done
  342   , s_headers_done
  343 
  344   /* Important: 's_headers_done' must be the last 'header' state. All
  345    * states beyond this must be 'body' states. It is used for overflow
  346    * checking. See the PARSING_HEADER() macro.
  347    */
  348 
  349   , s_chunk_data
  350   , s_chunk_data_almost_done
  351   , s_chunk_data_done
  352 
  353   , s_body_identity
  354   , s_body_identity_eof
  355 
  356   , s_message_done
  357   };
  358 
  359 
  360 #define PARSING_HEADER(state) (state <= s_headers_done)
  361 
  362 
  363 enum header_states
  364   { h_general = 0
  365   , h_C
  366   , h_CO
  367   , h_CON
  368 
  369   , h_matching_connection
  370   , h_matching_proxy_connection
  371   , h_matching_content_length
  372   , h_matching_transfer_encoding
  373   , h_matching_upgrade
  374 
  375   , h_connection
  376   , h_content_length
  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)     (tokens[(unsigned char)c])
  425 
  426 #if HTTP_PARSER_STRICT
  427 #define TOKEN(c)            (tokens[(unsigned char)c])
  428 #define IS_URL_CHAR(c)      (BIT_AT(normal_url_char, (unsigned char)c))
  429 #define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
  430 #else
  431 #define TOKEN(c)            ((c == ' ') ? ' ' : tokens[(unsigned char)c])
  432 #define IS_URL_CHAR(c)                                                         \
  433   (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
  434 #define IS_HOST_CHAR(c)                                                        \
  435   (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
  436 #endif
  437 
  438 /**
  439  * Verify that a char is a valid visible (printable) US-ASCII
  440  * character or %x80-FF
  441  **/
  442 #define IS_HEADER_CHAR(ch)                                                     \
  443   (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
  444 
  445 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
  446 
  447 
  448 #if HTTP_PARSER_STRICT
  449 # define STRICT_CHECK(cond)                                          \
  450 do {                                                                 \
  451   if (cond) {                                                        \
  452     SET_ERRNO(HPE_STRICT);                                           \
  453     goto error;                                                      \
  454   }                                                                  \
  455 } while (0)
  456 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
  457 #else
  458 # define STRICT_CHECK(cond)
  459 # define NEW_MESSAGE() start_state
  460 #endif
  461 
  462 
  463 /* Map errno values to strings for human-readable output */
  464 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
  465 static struct {
  466   const char *name;
  467   const char *description;
  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     /* FALLTHROUGH */
  546     case s_req_server_start:
  547     case s_req_server:
  548       if (ch == '/') {
  549         return s_req_path;
  550       }
  551 
  552       if (ch == '?') {
  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 
  650   /* We're in an error state. Don't bother doing anything. */
  651   if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
  652     return 0;
  653   }
  654 
  655   if (len == 0) {
  656     switch (CURRENT_STATE()) {
  657       case s_body_identity_eof:
  658         /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
  659          * we got paused.
  660          */
  661         CALLBACK_NOTIFY_NOADVANCE(message_complete);
  662         return 0;
  663 
  664       case s_dead:
  665       case s_start_req_or_res:
  666       case s_start_res:
  667       case s_start_req:
  668         return 0;
  669 
  670       default:
  671         SET_ERRNO(HPE_INVALID_EOF_STATE);
  672         return 1;
  673     }
  674   }
  675 
  676 
  677   if (CURRENT_STATE() == s_header_field)
  678     header_field_mark = data;
  679   if (CURRENT_STATE() == s_header_value)
  680     header_value_mark = data;
  681   switch (CURRENT_STATE()) {
  682   case s_req_path:
  683   case s_req_schema:
  684   case s_req_schema_slash:
  685   case s_req_schema_slash_slash:
  686   case s_req_server_start:
  687   case s_req_server:
  688   case s_req_server_with_at:
  689   case s_req_query_string_start:
  690   case s_req_query_string:
  691   case s_req_fragment_start:
  692   case s_req_fragment:
  693     url_mark = data;
  694     break;
  695   case s_res_status:
  696     status_mark = data;
  697     break;
  698   default:
  699     break;
  700   }
  701 
  702   for (p=data; p != data + len; p++) {
  703     ch = *p;
  704 
  705     if (PARSING_HEADER(CURRENT_STATE()))
  706       COUNT_HEADER_SIZE(1);
  707 
  708 reexecute:
  709     switch (CURRENT_STATE()) {
  710 
  711       case s_dead:
  712         /* this state is used after a 'Connection: close' message
  713          * the parser will error out if it reads another message
  714          */
  715         if (LIKELY(ch == CR || ch == LF))
  716           break;
  717 
  718         SET_ERRNO(HPE_CLOSED_CONNECTION);
  719         goto error;
  720 
  721       case s_start_req_or_res:
  722       {
  723         if (ch == CR || ch == LF)
  724           break;
  725         parser->flags = 0;
  726         parser->content_length = ULLONG_MAX;
  727 
  728         if (ch == 'H') {
  729           UPDATE_STATE(s_res_or_resp_H);
  730 
  731           CALLBACK_NOTIFY(message_begin);
  732         } else {
  733           parser->type = HTTP_REQUEST;
  734           UPDATE_STATE(s_start_req);
  735           REEXECUTE();
  736         }
  737 
  738         break;
  739       }
  740 
  741       case s_res_or_resp_H:
  742         if (ch == 'T') {
  743           parser->type = HTTP_RESPONSE;
  744           UPDATE_STATE(s_res_HT);
  745         } else {
  746           if (UNLIKELY(ch != 'E')) {
  747             SET_ERRNO(HPE_INVALID_CONSTANT);
  748             goto error;
  749           }
  750 
  751           parser->type = HTTP_REQUEST;
  752           parser->method = HTTP_HEAD;
  753           parser->index = 2;
  754           UPDATE_STATE(s_req_method);
  755         }
  756         break;
  757 
  758       case s_start_res:
  759       {
  760         parser->flags = 0;
  761         parser->content_length = ULLONG_MAX;
  762 
  763         switch (ch) {
  764           case 'H':
  765             UPDATE_STATE(s_res_H);
  766             break;
  767 
  768           case CR:
  769           case LF:
  770             break;
  771 
  772           default:
  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 */ 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(REPORT,    2, 'B', REBIND)
  996             XX(PROPFIND,  4, 'P', PROPPATCH)
  997             XX(LOCK,      1, 'I', LINK)
  998             XX(UNLOCK,    2, 'S', UNSUBSCRIBE)
  999             XX(UNLOCK,    2, 'B', UNBIND)
 1000             XX(UNLOCK,    3, 'I', UNLINK)
 1001 #undef XX
 1002             default:
 1003               SET_ERRNO(HPE_INVALID_METHOD);
 1004               goto error;
 1005           }
 1006         } else {
 1007           SET_ERRNO(HPE_INVALID_METHOD);
 1008           goto error;
 1009         }
 1010 
 1011         ++parser->index;
 1012         break;
 1013       }
 1014 
 1015       case s_req_spaces_before_url:
 1016       {
 1017         if (ch == ' ') break;
 1018 
 1019         MARK(url);
 1020         if (parser->method == HTTP_CONNECT) {
 1021           UPDATE_STATE(s_req_server_start);
 1022         }
 1023 
 1024         UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
 1025         if (UNLIKELY(CURRENT_STATE() == s_dead)) {
 1026           SET_ERRNO(HPE_INVALID_URL);
 1027           goto error;
 1028         }
 1029 
 1030         break;
 1031       }
 1032 
 1033       case s_req_schema:
 1034       case s_req_schema_slash:
 1035       case s_req_schema_slash_slash:
 1036       case s_req_server_start:
 1037       {
 1038         switch (ch) {
 1039           /* No whitespace allowed here */
 1040           case ' ':
 1041           case CR:
 1042           case LF:
 1043             SET_ERRNO(HPE_INVALID_URL);
 1044             goto error;
 1045           default:
 1046             UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
 1047             if (UNLIKELY(CURRENT_STATE() == s_dead)) {
 1048               SET_ERRNO(HPE_INVALID_URL);
 1049               goto error;
 1050             }
 1051         }
 1052 
 1053         break;
 1054       }
 1055 
 1056       case s_req_server:
 1057       case s_req_server_with_at:
 1058       case s_req_path:
 1059       case s_req_query_string_start:
 1060       case s_req_query_string:
 1061       case s_req_fragment_start:
 1062       case s_req_fragment:
 1063       {
 1064         switch (ch) {
 1065           case ' ':
 1066             UPDATE_STATE(s_req_http_start);
 1067             CALLBACK_DATA(url);
 1068             break;
 1069           case CR:
 1070           case LF:
 1071             parser->http_major = 0;
 1072             parser->http_minor = 9;
 1073             UPDATE_STATE((ch == CR) ?
 1074               s_req_line_almost_done :
 1075               s_header_field_start);
 1076             CALLBACK_DATA(url);
 1077             break;
 1078           default:
 1079             UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
 1080             if (UNLIKELY(CURRENT_STATE() == s_dead)) {
 1081               SET_ERRNO(HPE_INVALID_URL);
 1082               goto error;
 1083             }
 1084         }
 1085         break;
 1086       }
 1087 
 1088       case s_req_http_start:
 1089         switch (ch) {
 1090           case 'H':
 1091             UPDATE_STATE(s_req_http_H);
 1092             break;
 1093           case ' ':
 1094             break;
 1095           default:
 1096             SET_ERRNO(HPE_INVALID_CONSTANT);
 1097             goto error;
 1098         }
 1099         break;
 1100 
 1101       case s_req_http_H:
 1102         STRICT_CHECK(ch != 'T');
 1103         UPDATE_STATE(s_req_http_HT);
 1104         break;
 1105 
 1106       case s_req_http_HT:
 1107         STRICT_CHECK(ch != 'T');
 1108         UPDATE_STATE(s_req_http_HTT);
 1109         break;
 1110 
 1111       case s_req_http_HTT:
 1112         STRICT_CHECK(ch != 'P');
 1113         UPDATE_STATE(s_req_http_HTTP);
 1114         break;
 1115 
 1116       case s_req_http_HTTP:
 1117         STRICT_CHECK(ch != '/');
 1118         UPDATE_STATE(s_req_http_major);
 1119         break;
 1120 
 1121       case s_req_http_major:
 1122         if (UNLIKELY(!IS_NUM(ch))) {
 1123           SET_ERRNO(HPE_INVALID_VERSION);
 1124           goto error;
 1125         }
 1126 
 1127         parser->http_major = ch - '0';
 1128         UPDATE_STATE(s_req_http_dot);
 1129         break;
 1130 
 1131       case s_req_http_dot:
 1132       {
 1133         if (UNLIKELY(ch != '.')) {
 1134           SET_ERRNO(HPE_INVALID_VERSION);
 1135           goto error;
 1136         }
 1137 
 1138         UPDATE_STATE(s_req_http_minor);
 1139         break;
 1140       }
 1141 
 1142       case s_req_http_minor:
 1143         if (UNLIKELY(!IS_NUM(ch))) {
 1144           SET_ERRNO(HPE_INVALID_VERSION);
 1145           goto error;
 1146         }
 1147 
 1148         parser->http_minor = ch - '0';
 1149         UPDATE_STATE(s_req_http_end);
 1150         break;
 1151 
 1152       case s_req_http_end:
 1153       {
 1154         if (ch == CR) {
 1155           UPDATE_STATE(s_req_line_almost_done);
 1156           break;
 1157         }
 1158 
 1159         if (ch == LF) {
 1160           UPDATE_STATE(s_header_field_start);
 1161           break;
 1162         }
 1163 
 1164         SET_ERRNO(HPE_INVALID_VERSION);
 1165         goto error;
 1166         break;
 1167       }
 1168 
 1169       /* end of request line */
 1170       case s_req_line_almost_done:
 1171       {
 1172         if (UNLIKELY(ch != LF)) {
 1173           SET_ERRNO(HPE_LF_EXPECTED);
 1174           goto error;
 1175         }
 1176 
 1177         UPDATE_STATE(s_header_field_start);
 1178         break;
 1179       }
 1180 
 1181       case s_header_field_start:
 1182       {
 1183         if (ch == CR) {
 1184           UPDATE_STATE(s_headers_almost_done);
 1185           break;
 1186         }
 1187 
 1188         if (ch == LF) {
 1189           /* they might be just sending \n instead of \r\n so this would be
 1190            * the second \n to denote the end of headers*/
 1191           UPDATE_STATE(s_headers_almost_done);
 1192           REEXECUTE();
 1193         }
 1194 
 1195         c = TOKEN(ch);
 1196 
 1197         if (UNLIKELY(!c)) {
 1198           SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
 1199           goto error;
 1200         }
 1201 
 1202         MARK(header_field);
 1203 
 1204         parser->index = 0;
 1205         UPDATE_STATE(s_header_field);
 1206 
 1207         switch (c) {
 1208           case 'c':
 1209             parser->header_state = h_C;
 1210             break;
 1211 
 1212           case 'p':
 1213             parser->header_state = h_matching_proxy_connection;
 1214             break;
 1215 
 1216           case 't':
 1217             parser->header_state = h_matching_transfer_encoding;
 1218             break;
 1219 
 1220           case 'u':
 1221             parser->header_state = h_matching_upgrade;
 1222             break;
 1223 
 1224           default:
 1225             parser->header_state = h_general;
 1226             break;
 1227         }
 1228         break;
 1229       }
 1230 
 1231       case s_header_field:
 1232       {
 1233         const char* start = p;
 1234         for (; p != data + len; p++) {
 1235           ch = *p;
 1236           c = TOKEN(ch);
 1237 
 1238           if (!c)
 1239             break;
 1240 
 1241           switch (parser->header_state) {
 1242             case h_general:
 1243               break;
 1244 
 1245             case h_C:
 1246               parser->index++;
 1247               parser->header_state = (c == 'o' ? h_CO : h_general);
 1248               break;
 1249 
 1250             case h_CO:
 1251               parser->index++;
 1252               parser->header_state = (c == 'n' ? h_CON : h_general);
 1253               break;
 1254 
 1255             case h_CON:
 1256               parser->index++;
 1257               switch (c) {
 1258                 case 'n':
 1259                   parser->header_state = h_matching_connection;
 1260                   break;
 1261                 case 't':
 1262                   parser->header_state = h_matching_content_length;
 1263                   break;
 1264                 default:
 1265                   parser->header_state = h_general;
 1266                   break;
 1267               }
 1268               break;
 1269 
 1270             /* connection */
 1271 
 1272             case h_matching_connection:
 1273               parser->index++;
 1274               if (parser->index > sizeof(CONNECTION)-1
 1275                   || c != CONNECTION[parser->index]) {
 1276                 parser->header_state = h_general;
 1277               } else if (parser->index == sizeof(CONNECTION)-2) {
 1278                 parser->header_state = h_connection;
 1279               }
 1280               break;
 1281 
 1282             /* proxy-connection */
 1283 
 1284             case h_matching_proxy_connection:
 1285               parser->index++;
 1286               if (parser->index > sizeof(PROXY_CONNECTION)-1
 1287                   || c != PROXY_CONNECTION[parser->index]) {
 1288                 parser->header_state = h_general;
 1289               } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
 1290                 parser->header_state = h_connection;
 1291               }
 1292               break;
 1293 
 1294             /* content-length */
 1295 
 1296             case h_matching_content_length:
 1297               parser->index++;
 1298               if (parser->index > sizeof(CONTENT_LENGTH)-1
 1299                   || c != CONTENT_LENGTH[parser->index]) {
 1300                 parser->header_state = h_general;
 1301               } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
 1302                 parser->header_state = h_content_length;
 1303               }
 1304               break;
 1305 
 1306             /* transfer-encoding */
 1307 
 1308             case h_matching_transfer_encoding:
 1309               parser->index++;
 1310               if (parser->index > sizeof(TRANSFER_ENCODING)-1
 1311                   || c != TRANSFER_ENCODING[parser->index]) {
 1312                 parser->header_state = h_general;
 1313               } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
 1314                 parser->header_state = h_transfer_encoding;
 1315               }
 1316               break;
 1317 
 1318             /* upgrade */
 1319 
 1320             case h_matching_upgrade:
 1321               parser->index++;
 1322               if (parser->index > sizeof(UPGRADE)-1
 1323                   || c != UPGRADE[parser->index]) {
 1324                 parser->header_state = h_general;
 1325               } else if (parser->index == sizeof(UPGRADE)-2) {
 1326                 parser->header_state = h_upgrade;
 1327               }
 1328               break;
 1329 
 1330             case h_connection:
 1331             case h_content_length:
 1332             case h_transfer_encoding:
 1333             case h_upgrade:
 1334               if (ch != ' ') parser->header_state = h_general;
 1335               break;
 1336 
 1337             default:
 1338               assert(0 && "Unknown header_state");
 1339               break;
 1340           }
 1341         }
 1342 
 1343         COUNT_HEADER_SIZE(p - start);
 1344 
 1345         if (p == data + len) {
 1346           --p;
 1347           break;
 1348         }
 1349 
 1350         if (ch == ':') {
 1351           UPDATE_STATE(s_header_value_discard_ws);
 1352           CALLBACK_DATA(header_field);
 1353           break;
 1354         }
 1355 
 1356         SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
 1357         goto error;
 1358       }
 1359 
 1360       case s_header_value_discard_ws:
 1361         if (ch == ' ' || ch == '\t') break;
 1362 
 1363         if (ch == CR) {
 1364           UPDATE_STATE(s_header_value_discard_ws_almost_done);
 1365           break;
 1366         }
 1367 
 1368         if (ch == LF) {
 1369           UPDATE_STATE(s_header_value_discard_lws);
 1370           break;
 1371         }
 1372 
 1373         /* FALLTHROUGH */
 1374 
 1375       case s_header_value_start:
 1376       {
 1377         MARK(header_value);
 1378 
 1379         UPDATE_STATE(s_header_value);
 1380         parser->index = 0;
 1381 
 1382         c = LOWER(ch);
 1383 
 1384         switch (parser->header_state) {
 1385           case h_upgrade:
 1386             parser->flags |= F_UPGRADE;
 1387             parser->header_state = h_general;
 1388             break;
 1389 
 1390           case h_transfer_encoding:
 1391             /* looking for 'Transfer-Encoding: chunked' */
 1392             if ('c' == c) {
 1393               parser->header_state = h_matching_transfer_encoding_chunked;
 1394             } else {
 1395               parser->header_state = h_general;
 1396             }
 1397             break;
 1398 
 1399           case h_content_length:
 1400             if (UNLIKELY(!IS_NUM(ch))) {
 1401               SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
 1402               goto error;
 1403             }
 1404 
 1405             if (parser->flags & F_CONTENTLENGTH) {
 1406               SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
 1407               goto error;
 1408             }
 1409 
 1410             parser->flags |= F_CONTENTLENGTH;
 1411             parser->content_length = ch - '0';
 1412             break;
 1413 
 1414           case h_connection:
 1415             /* looking for 'Connection: keep-alive' */
 1416             if (c == 'k') {
 1417               parser->header_state = h_matching_connection_keep_alive;
 1418             /* looking for 'Connection: close' */
 1419             } else if (c == 'c') {
 1420               parser->header_state = h_matching_connection_close;
 1421             } else if (c == 'u') {
 1422               parser->header_state = h_matching_connection_upgrade;
 1423             } else {
 1424               parser->header_state = h_matching_connection_token;
 1425             }
 1426             break;
 1427 
 1428           /* Multi-value `Connection` header */
 1429           case h_matching_connection_token_start:
 1430             break;
 1431 
 1432           default:
 1433             parser->header_state = h_general;
 1434             break;
 1435         }
 1436         break;
 1437       }
 1438 
 1439       case s_header_value:
 1440       {
 1441         const char* start = p;
 1442         enum header_states h_state = (enum header_states) parser->header_state;
 1443         for (; p != data + len; p++) {
 1444           ch = *p;
 1445           if (ch == CR) {
 1446             UPDATE_STATE(s_header_almost_done);
 1447             parser->header_state = h_state;
 1448             CALLBACK_DATA(header_value);
 1449             break;
 1450           }
 1451 
 1452           if (ch == LF) {
 1453             UPDATE_STATE(s_header_almost_done);
 1454             COUNT_HEADER_SIZE(p - start);
 1455             parser->header_state = h_state;
 1456             CALLBACK_DATA_NOADVANCE(header_value);
 1457             REEXECUTE();
 1458           }
 1459 
 1460           if (!lenient && !IS_HEADER_CHAR(ch)) {
 1461             SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
 1462             goto error;
 1463           }
 1464 
 1465           c = LOWER(ch);
 1466 
 1467           switch (h_state) {
 1468             case h_general:
 1469             {
 1470               const char* p_cr;
 1471               const char* p_lf;
 1472               size_t limit = data + len - p;
 1473 
 1474               limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
 1475 
 1476               p_cr = (const char*) memchr(p, CR, limit);
 1477               p_lf = (const char*) memchr(p, LF, limit);
 1478               if (p_cr != NULL) {
 1479                 if (p_lf != NULL && p_cr >= p_lf)
 1480                   p = p_lf;
 1481                 else
 1482                   p = p_cr;
 1483               } else if (UNLIKELY(p_lf != NULL)) {
 1484                 p = p_lf;
 1485               } else {
 1486                 p = data + len;
 1487               }
 1488               --p;
 1489 
 1490               break;
 1491             }
 1492 
 1493             case h_connection:
 1494             case h_transfer_encoding:
 1495               assert(0 && "Shouldn't get here.");
 1496               break;
 1497 
 1498             case h_content_length:
 1499             {
 1500               uint64_t t;
 1501 
 1502               if (ch == ' ') break;
 1503 
 1504               if (UNLIKELY(!IS_NUM(ch))) {
 1505                 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
 1506                 parser->header_state = h_state;
 1507                 goto error;
 1508               }
 1509 
 1510               t = parser->content_length;
 1511               t *= 10;
 1512               t += ch - '0';
 1513 
 1514               /* Overflow? Test against a conservative limit for simplicity. */
 1515               if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
 1516                 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
 1517                 parser->header_state = h_state;
 1518                 goto error;
 1519               }
 1520 
 1521               parser->content_length = t;
 1522               break;
 1523             }
 1524 
 1525             /* Transfer-Encoding: chunked */
 1526             case h_matching_transfer_encoding_chunked:
 1527               parser->index++;
 1528               if (parser->index > sizeof(CHUNKED)-1
 1529                   || c != CHUNKED[parser->index]) {
 1530                 h_state = h_general;
 1531               } else if (parser->index == sizeof(CHUNKED)-2) {
 1532                 h_state = h_transfer_encoding_chunked;
 1533               }
 1534               break;
 1535 
 1536             case h_matching_connection_token_start:
 1537               /* looking for 'Connection: keep-alive' */
 1538               if (c == 'k') {
 1539                 h_state = h_matching_connection_keep_alive;
 1540               /* looking for 'Connection: close' */
 1541               } else if (c == 'c') {
 1542                 h_state = h_matching_connection_close;
 1543               } else if (c == 'u') {
 1544                 h_state = h_matching_connection_upgrade;
 1545               } else if (STRICT_TOKEN(c)) {
 1546                 h_state = h_matching_connection_token;
 1547               } else if (c == ' ' || c == '\t') {
 1548                 /* Skip lws */
 1549               } else {
 1550                 h_state = h_general;
 1551               }
 1552               break;
 1553 
 1554             /* looking for 'Connection: keep-alive' */
 1555             case h_matching_connection_keep_alive:
 1556               parser->index++;
 1557               if (parser->index > sizeof(KEEP_ALIVE)-1
 1558                   || c != KEEP_ALIVE[parser->index]) {
 1559                 h_state = h_matching_connection_token;
 1560               } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
 1561                 h_state = h_connection_keep_alive;
 1562               }
 1563               break;
 1564 
 1565             /* looking for 'Connection: close' */
 1566             case h_matching_connection_close:
 1567               parser->index++;
 1568               if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
 1569                 h_state = h_matching_connection_token;
 1570               } else if (parser->index == sizeof(CLOSE)-2) {
 1571                 h_state = h_connection_close;
 1572               }
 1573               break;
 1574 
 1575             /* looking for 'Connection: upgrade' */
 1576             case h_matching_connection_upgrade:
 1577               parser->index++;
 1578               if (parser->index > sizeof(UPGRADE) - 1 ||
 1579                   c != UPGRADE[parser->index]) {
 1580                 h_state = h_matching_connection_token;
 1581               } else if (parser->index == sizeof(UPGRADE)-2) {
 1582                 h_state = h_connection_upgrade;
 1583               }
 1584               break;
 1585 
 1586             case h_matching_connection_token:
 1587               if (ch == ',') {
 1588                 h_state = h_matching_connection_token_start;
 1589                 parser->index = 0;
 1590               }
 1591               break;
 1592 
 1593             case h_transfer_encoding_chunked:
 1594               if (ch != ' ') h_state = h_general;
 1595               break;
 1596 
 1597             case h_connection_keep_alive:
 1598             case h_connection_close:
 1599             case h_connection_upgrade:
 1600               if (ch == ',') {
 1601                 if (h_state == h_connection_keep_alive) {
 1602                   parser->flags |= F_CONNECTION_KEEP_ALIVE;
 1603                 } else if (h_state == h_connection_close) {
 1604                   parser->flags |= F_CONNECTION_CLOSE;
 1605                 } else if (h_state == h_connection_upgrade) {
 1606                   parser->flags |= F_CONNECTION_UPGRADE;
 1607                 }
 1608                 h_state = h_matching_connection_token_start;
 1609                 parser->index = 0;
 1610               } else if (ch != ' ') {
 1611                 h_state = h_matching_connection_token;
 1612               }
 1613               break;
 1614 
 1615             default:
 1616               UPDATE_STATE(s_header_value);
 1617               h_state = h_general;
 1618               break;
 1619           }
 1620         }
 1621         parser->header_state = h_state;
 1622 
 1623         COUNT_HEADER_SIZE(p - start);
 1624 
 1625         if (p == data + len)
 1626           --p;
 1627         break;
 1628       }
 1629 
 1630       case s_header_almost_done:
 1631       {
 1632         if (UNLIKELY(ch != LF)) {
 1633           SET_ERRNO(HPE_LF_EXPECTED);
 1634           goto error;
 1635         }
 1636 
 1637         UPDATE_STATE(s_header_value_lws);
 1638         break;
 1639       }
 1640 
 1641       case s_header_value_lws:
 1642       {
 1643         if (ch == ' ' || ch == '\t') {
 1644           UPDATE_STATE(s_header_value_start);
 1645           REEXECUTE();
 1646         }
 1647 
 1648         /* finished the header */
 1649         switch (parser->header_state) {
 1650           case h_connection_keep_alive:
 1651             parser->flags |= F_CONNECTION_KEEP_ALIVE;
 1652             break;
 1653           case h_connection_close:
 1654             parser->flags |= F_CONNECTION_CLOSE;
 1655             break;
 1656           case h_transfer_encoding_chunked:
 1657             parser->flags |= F_CHUNKED;
 1658             break;
 1659           case h_connection_upgrade:
 1660             parser->flags |= F_CONNECTION_UPGRADE;
 1661             break;
 1662           default:
 1663             break;
 1664         }
 1665 
 1666         UPDATE_STATE(s_header_field_start);
 1667         REEXECUTE();
 1668       }
 1669 
 1670       case s_header_value_discard_ws_almost_done:
 1671       {
 1672         STRICT_CHECK(ch != LF);
 1673         UPDATE_STATE(s_header_value_discard_lws);
 1674         break;
 1675       }
 1676 
 1677       case s_header_value_discard_lws:
 1678       {
 1679         if (ch == ' ' || ch == '\t') {
 1680           UPDATE_STATE(s_header_value_discard_ws);
 1681           break;
 1682         } else {
 1683           switch (parser->header_state) {
 1684             case h_connection_keep_alive:
 1685               parser->flags |= F_CONNECTION_KEEP_ALIVE;
 1686               break;
 1687             case h_connection_close:
 1688               parser->flags |= F_CONNECTION_CLOSE;
 1689               break;
 1690             case h_connection_upgrade:
 1691               parser->flags |= F_CONNECTION_UPGRADE;
 1692               break;
 1693             case h_transfer_encoding_chunked:
 1694               parser->flags |= F_CHUNKED;
 1695               break;
 1696             default:
 1697               break;
 1698           }
 1699 
 1700           /* header value was empty */
 1701           MARK(header_value);
 1702           UPDATE_STATE(s_header_field_start);
 1703           CALLBACK_DATA_NOADVANCE(header_value);
 1704           REEXECUTE();
 1705         }
 1706       }
 1707 
 1708       case s_headers_almost_done:
 1709       {
 1710         STRICT_CHECK(ch != LF);
 1711 
 1712         if (parser->flags & F_TRAILING) {
 1713           /* End of a chunked request */
 1714           UPDATE_STATE(s_message_done);
 1715           CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
 1716           REEXECUTE();
 1717         }
 1718 
 1719         /* Cannot use chunked encoding and a content-length header together
 1720            per the HTTP specification. */
 1721         if ((parser->flags & F_CHUNKED) &&
 1722             (parser->flags & F_CONTENTLENGTH)) {
 1723           SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
 1724           goto error;
 1725         }
 1726 
 1727         UPDATE_STATE(s_headers_done);
 1728 
 1729         /* Set this here so that on_headers_complete() callbacks can see it */
 1730         if ((parser->flags & F_UPGRADE) &&
 1731             (parser->flags & F_CONNECTION_UPGRADE)) {
 1732           /* For responses, "Upgrade: foo" and "Connection: upgrade" are
 1733            * mandatory only when it is a 101 Switching Protocols response,
 1734            * otherwise it is purely informational, to announce support.
 1735            */
 1736           parser->upgrade =
 1737               (parser->type == HTTP_REQUEST || parser->status_code == 101);
 1738         } else {
 1739           parser->upgrade = (parser->method == HTTP_CONNECT);
 1740         }
 1741 
 1742         /* Here we call the headers_complete callback. This is somewhat
 1743          * different than other callbacks because if the user returns 1, we
 1744          * will interpret that as saying that this message has no body. This
 1745          * is needed for the annoying case of recieving a response to a HEAD
 1746          * request.
 1747          *
 1748          * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
 1749          * we have to simulate it by handling a change in errno below.
 1750          */
 1751         if (settings->on_headers_complete) {
 1752           switch (settings->on_headers_complete(parser)) {
 1753             case 0:
 1754               break;
 1755 
 1756             case 2:
 1757               parser->upgrade = 1;
 1758 
 1759             /* FALLTHROUGH */
 1760             case 1:
 1761               parser->flags |= F_SKIPBODY;
 1762               break;
 1763 
 1764             default:
 1765               SET_ERRNO(HPE_CB_headers_complete);
 1766               RETURN(p - data); /* Error */
 1767           }
 1768         }
 1769 
 1770         if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
 1771           RETURN(p - data);
 1772         }
 1773 
 1774         REEXECUTE();
 1775       }
 1776 
 1777       case s_headers_done:
 1778       {
 1779         int hasBody;
 1780         STRICT_CHECK(ch != LF);
 1781 
 1782         parser->nread = 0;
 1783 
 1784         hasBody = parser->flags & F_CHUNKED ||
 1785           (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
 1786         if (parser->upgrade && (parser->method == HTTP_CONNECT ||
 1787                                 (parser->flags & F_SKIPBODY) || !hasBody)) {
 1788           /* Exit, the rest of the message is in a different protocol. */
 1789           UPDATE_STATE(NEW_MESSAGE());
 1790           CALLBACK_NOTIFY(message_complete);
 1791           RETURN((p - data) + 1);
 1792         }
 1793 
 1794         if (parser->flags & F_SKIPBODY) {
 1795           UPDATE_STATE(NEW_MESSAGE());
 1796           CALLBACK_NOTIFY(message_complete);
 1797         } else if (parser->flags & F_CHUNKED) {
 1798           /* chunked encoding - ignore Content-Length header */
 1799           UPDATE_STATE(s_chunk_size_start);
 1800         } else {
 1801           if (parser->content_length == 0) {
 1802             /* Content-Length header given but zero: Content-Length: 0\r\n */
 1803             UPDATE_STATE(NEW_MESSAGE());
 1804             CALLBACK_NOTIFY(message_complete);
 1805           } else if (parser->content_length != ULLONG_MAX) {
 1806             /* Content-Length header given and non-zero */
 1807             UPDATE_STATE(s_body_identity);
 1808           } else {
 1809             if (!http_message_needs_eof(parser)) {
 1810               /* Assume content-length 0 - read the next */
 1811               UPDATE_STATE(NEW_MESSAGE());
 1812               CALLBACK_NOTIFY(message_complete);
 1813             } else {
 1814               /* Read body until EOF */
 1815               UPDATE_STATE(s_body_identity_eof);
 1816             }
 1817           }
 1818         }
 1819 
 1820         break;
 1821       }
 1822 
 1823       case s_body_identity:
 1824       {
 1825         uint64_t to_read = MIN(parser->content_length,
 1826                                (uint64_t) ((data + len) - p));
 1827 
 1828         assert(parser->content_length != 0
 1829             && parser->content_length != ULLONG_MAX);
 1830 
 1831         /* The difference between advancing content_length and p is because
 1832          * the latter will automaticaly advance on the next loop iteration.
 1833          * Further, if content_length ends up at 0, we want to see the last
 1834          * byte again for our message complete callback.
 1835          */
 1836         MARK(body);
 1837         parser->content_length -= to_read;
 1838         p += to_read - 1;
 1839 
 1840         if (parser->content_length == 0) {
 1841           UPDATE_STATE(s_message_done);
 1842 
 1843           /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
 1844            *
 1845            * The alternative to doing this is to wait for the next byte to
 1846            * trigger the data callback, just as in every other case. The
 1847            * problem with this is that this makes it difficult for the test
 1848            * harness to distinguish between complete-on-EOF and
 1849            * complete-on-length. It's not clear that this distinction is
 1850            * important for applications, but let's keep it for now.
 1851            */
 1852           CALLBACK_DATA_(body, p - body_mark + 1, p - data);
 1853           REEXECUTE();
 1854         }
 1855 
 1856         break;
 1857       }
 1858 
 1859       /* read until EOF */
 1860       case s_body_identity_eof:
 1861         MARK(body);
 1862         p = data + len - 1;
 1863 
 1864         break;
 1865 
 1866       case s_message_done:
 1867         UPDATE_STATE(NEW_MESSAGE());
 1868         CALLBACK_NOTIFY(message_complete);
 1869         if (parser->upgrade) {
 1870           /* Exit, the rest of the message is in a different protocol. */
 1871           RETURN((p - data) + 1);
 1872         }
 1873         break;
 1874 
 1875       case s_chunk_size_start:
 1876       {
 1877         assert(parser->nread == 1);
 1878         assert(parser->flags & F_CHUNKED);
 1879 
 1880         unhex_val = unhex[(unsigned char)ch];
 1881         if (UNLIKELY(unhex_val == -1)) {
 1882           SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
 1883           goto error;
 1884         }
 1885 
 1886         parser->content_length = unhex_val;
 1887         UPDATE_STATE(s_chunk_size);
 1888         break;
 1889       }
 1890 
 1891       case s_chunk_size:
 1892       {
 1893         uint64_t t;
 1894 
 1895         assert(parser->flags & F_CHUNKED);
 1896 
 1897         if (ch == CR) {
 1898           UPDATE_STATE(s_chunk_size_almost_done);
 1899           break;
 1900         }
 1901 
 1902         unhex_val = unhex[(unsigned char)ch];
 1903 
 1904         if (unhex_val == -1) {
 1905           if (ch == ';' || ch == ' ') {
 1906             UPDATE_STATE(s_chunk_parameters);
 1907             break;
 1908           }
 1909 
 1910           SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
 1911           goto error;
 1912         }
 1913 
 1914         t = parser->content_length;
 1915         t *= 16;
 1916         t += unhex_val;
 1917 
 1918         /* Overflow? Test against a conservative limit for simplicity. */
 1919         if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
 1920           SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
 1921           goto error;
 1922         }
 1923 
 1924         parser->content_length = t;
 1925         break;
 1926       }
 1927 
 1928       case s_chunk_parameters:
 1929       {
 1930         assert(parser->flags & F_CHUNKED);
 1931         /* just ignore this shit. TODO check for overflow */
 1932         if (ch == CR) {
 1933           UPDATE_STATE(s_chunk_size_almost_done);
 1934           break;
 1935         }
 1936         break;
 1937       }
 1938 
 1939       case s_chunk_size_almost_done:
 1940       {
 1941         assert(parser->flags & F_CHUNKED);
 1942         STRICT_CHECK(ch != LF);
 1943 
 1944         parser->nread = 0;
 1945 
 1946         if (parser->content_length == 0) {
 1947           parser->flags |= F_TRAILING;
 1948           UPDATE_STATE(s_header_field_start);
 1949         } else {
 1950           UPDATE_STATE(s_chunk_data);
 1951         }
 1952         CALLBACK_NOTIFY(chunk_header);
 1953         break;
 1954       }
 1955 
 1956       case s_chunk_data:
 1957       {
 1958         uint64_t to_read = MIN(parser->content_length,
 1959                                (uint64_t) ((data + len) - p));
 1960 
 1961         assert(parser->flags & F_CHUNKED);
 1962         assert(parser->content_length != 0
 1963             && parser->content_length != ULLONG_MAX);
 1964 
 1965         /* See the explanation in s_body_identity for why the content
 1966          * length and data pointers are managed this way.
 1967          */
 1968         MARK(body);
 1969         parser->content_length -= to_read;
 1970         p += to_read - 1;
 1971 
 1972         if (parser->content_length == 0) {
 1973           UPDATE_STATE(s_chunk_data_almost_done);
 1974         }
 1975 
 1976         break;
 1977       }
 1978 
 1979       case s_chunk_data_almost_done:
 1980         assert(parser->flags & F_CHUNKED);
 1981         assert(parser->content_length == 0);
 1982         STRICT_CHECK(ch != CR);
 1983         UPDATE_STATE(s_chunk_data_done);
 1984         CALLBACK_DATA(body);
 1985         break;
 1986 
 1987       case s_chunk_data_done:
 1988         assert(parser->flags & F_CHUNKED);
 1989         STRICT_CHECK(ch != LF);
 1990         parser->nread = 0;
 1991         UPDATE_STATE(s_chunk_size_start);
 1992         CALLBACK_NOTIFY(chunk_complete);
 1993         break;
 1994 
 1995       default:
 1996         assert(0 && "unhandled state");
 1997         SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
 1998         goto error;
 1999     }
 2000   }
 2001 
 2002   /* Run callbacks for any marks that we have leftover after we ran our of
 2003    * bytes. There should be at most one of these set, so it's OK to invoke
 2004    * them in series (unset marks will not result in callbacks).
 2005    *
 2006    * We use the NOADVANCE() variety of callbacks here because 'p' has already
 2007    * overflowed 'data' and this allows us to correct for the off-by-one that
 2008    * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
 2009    * value that's in-bounds).
 2010    */
 2011 
 2012   assert(((header_field_mark ? 1 : 0) +
 2013           (header_value_mark ? 1 : 0) +
 2014           (url_mark ? 1 : 0)  +
 2015           (body_mark ? 1 : 0) +
 2016           (status_mark ? 1 : 0)) <= 1);
 2017 
 2018   CALLBACK_DATA_NOADVANCE(header_field);
 2019   CALLBACK_DATA_NOADVANCE(header_value);
 2020   CALLBACK_DATA_NOADVANCE(url);
 2021   CALLBACK_DATA_NOADVANCE(body);
 2022   CALLBACK_DATA_NOADVANCE(status);
 2023 
 2024   RETURN(len);
 2025 
 2026 error:
 2027   if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
 2028     SET_ERRNO(HPE_UNKNOWN);
 2029   }
 2030 
 2031   RETURN(p - data);
 2032 }
 2033 
 2034 
 2035 /* Does the parser need to see an EOF to find the end of the message? */
 2036 int
 2037 http_message_needs_eof (const http_parser *parser)
 2038 {
 2039   if (parser->type == HTTP_REQUEST) {
 2040     return 0;
 2041   }
 2042 
 2043   /* See RFC 2616 section 4.4 */
 2044   if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
 2045       parser->status_code == 204 ||     /* No Content */
 2046       parser->status_code == 304 ||     /* Not Modified */
 2047       parser->flags & F_SKIPBODY) {     /* response to a HEAD request */
 2048     return 0;
 2049   }
 2050 
 2051   if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
 2052     return 0;
 2053   }
 2054 
 2055   return 1;
 2056 }
 2057 
 2058 
 2059 int
 2060 http_should_keep_alive (const http_parser *parser)
 2061 {
 2062   if (parser->http_major > 0 && parser->http_minor > 0) {
 2063     /* HTTP/1.1 */
 2064     if (parser->flags & F_CONNECTION_CLOSE) {
 2065       return 0;
 2066     }
 2067   } else {
 2068     /* HTTP/1.0 or earlier */
 2069     if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
 2070       return 0;
 2071     }
 2072   }
 2073 
 2074   return !http_message_needs_eof(parser);
 2075 }
 2076 
 2077 
 2078 const char *
 2079 http_method_str (enum http_method m)
 2080 {
 2081   return ELEM_AT(method_strings, m, "<unknown>");
 2082 }
 2083 
 2084 
 2085 void
 2086 http_parser_init (http_parser *parser, enum http_parser_type t)
 2087 {
 2088   void *data = parser->data; /* preserve application data */
 2089   memset(parser, 0, sizeof(*parser));
 2090   parser->data = data;
 2091   parser->type = t;
 2092   parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
 2093   parser->http_errno = HPE_OK;
 2094 }
 2095 
 2096 void
 2097 http_parser_settings_init(http_parser_settings *settings)
 2098 {
 2099   memset(settings, 0, sizeof(*settings));
 2100 }
 2101 
 2102 const char *
 2103 http_errno_name(enum http_errno err) {
 2104   assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
 2105   return http_strerror_tab[err].name;
 2106 }
 2107 
 2108 const char *
 2109 http_errno_description(enum http_errno err) {
 2110   assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
 2111   return http_strerror_tab[err].description;
 2112 }
 2113 
 2114 static enum http_host_state
 2115 http_parse_host_char(enum http_host_state s, const char ch) {
 2116   switch(s) {
 2117     case s_http_userinfo:
 2118     case s_http_userinfo_start:
 2119       if (ch == '@') {
 2120         return s_http_host_start;
 2121       }
 2122 
 2123       if (IS_USERINFO_CHAR(ch)) {
 2124         return s_http_userinfo;
 2125       }
 2126       break;
 2127 
 2128     case s_http_host_start:
 2129       if (ch == '[') {
 2130         return s_http_host_v6_start;
 2131       }
 2132 
 2133       if (IS_HOST_CHAR(ch)) {
 2134         return s_http_host;
 2135       }
 2136 
 2137       break;
 2138 
 2139     case s_http_host:
 2140       if (IS_HOST_CHAR(ch)) {
 2141         return s_http_host;
 2142       }
 2143 
 2144     /* FALLTHROUGH */
 2145     case s_http_host_v6_end:
 2146       if (ch == ':') {
 2147         return s_http_host_port_start;
 2148       }
 2149 
 2150       break;
 2151 
 2152     case s_http_host_v6:
 2153       if (ch == ']') {
 2154         return s_http_host_v6_end;
 2155       }
 2156 
 2157     /* FALLTHROUGH */
 2158     case s_http_host_v6_start:
 2159       if (IS_HEX(ch) || ch == ':' || ch == '.') {
 2160         return s_http_host_v6;
 2161       }
 2162 
 2163       if (s == s_http_host_v6 && ch == '%') {
 2164         return s_http_host_v6_zone_start;
 2165       }
 2166       break;
 2167 
 2168     case s_http_host_v6_zone:
 2169       if (ch == ']') {
 2170         return s_http_host_v6_end;
 2171       }
 2172 
 2173     /* FALLTHROUGH */
 2174     case s_http_host_v6_zone_start:
 2175       /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
 2176       if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
 2177           ch == '~') {
 2178         return s_http_host_v6_zone;
 2179       }
 2180       break;
 2181 
 2182     case s_http_host_port:
 2183     case s_http_host_port_start:
 2184       if (IS_NUM(ch)) {
 2185         return s_http_host_port;
 2186       }
 2187 
 2188       break;
 2189 
 2190     default:
 2191       break;
 2192   }
 2193   return s_http_host_dead;
 2194 }
 2195 
 2196 static int
 2197 http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
 2198   enum http_host_state s;
 2199 
 2200   const char *p;
 2201   size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
 2202 
 2203   assert(u->field_set & (1 << UF_HOST));
 2204 
 2205   u->field_data[UF_HOST].len = 0;
 2206 
 2207   s = found_at ? s_http_userinfo_start : s_http_host_start;
 2208 
 2209   for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
 2210     enum http_host_state new_s = http_parse_host_char(s, *p);
 2211 
 2212     if (new_s == s_http_host_dead) {
 2213       return 1;
 2214     }
 2215 
 2216     switch(new_s) {
 2217       case s_http_host:
 2218         if (s != s_http_host) {
 2219           u->field_data[UF_HOST].off = p - buf;
 2220         }
 2221         u->field_data[UF_HOST].len++;
 2222         break;
 2223 
 2224       case s_http_host_v6:
 2225         if (s != s_http_host_v6) {
 2226           u->field_data[UF_HOST].off = p - buf;
 2227         }
 2228         u->field_data[UF_HOST].len++;
 2229         break;
 2230 
 2231       case s_http_host_v6_zone_start:
 2232       case s_http_host_v6_zone:
 2233         u->field_data[UF_HOST].len++;
 2234         break;
 2235 
 2236       case s_http_host_port:
 2237         if (s != s_http_host_port) {
 2238           u->field_data[UF_PORT].off = p - buf;
 2239           u->field_data[UF_PORT].len = 0;
 2240           u->field_set |= (1 << UF_PORT);
 2241         }
 2242         u->field_data[UF_PORT].len++;
 2243         break;
 2244 
 2245       case s_http_userinfo:
 2246         if (s != s_http_userinfo) {
 2247           u->field_data[UF_USERINFO].off = p - buf ;
 2248           u->field_data[UF_USERINFO].len = 0;
 2249           u->field_set |= (1 << UF_USERINFO);
 2250         }
 2251         u->field_data[UF_USERINFO].len++;
 2252         break;
 2253 
 2254       default:
 2255         break;
 2256     }
 2257     s = new_s;
 2258   }
 2259 
 2260   /* Make sure we don't end somewhere unexpected */
 2261   switch (s) {
 2262     case s_http_host_start:
 2263     case s_http_host_v6_start:
 2264     case s_http_host_v6:
 2265     case s_http_host_v6_zone_start:
 2266     case s_http_host_v6_zone:
 2267     case s_http_host_port_start:
 2268     case s_http_userinfo:
 2269     case s_http_userinfo_start:
 2270       return 1;
 2271     default:
 2272       break;
 2273   }
 2274 
 2275   return 0;
 2276 }
 2277 
 2278 void
 2279 http_parser_url_init(struct http_parser_url *u) {
 2280   memset(u, 0, sizeof(*u));
 2281 }
 2282 
 2283 int
 2284 http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
 2285                       struct http_parser_url *u)
 2286 {
 2287   enum state s;
 2288   const char *p;
 2289   enum http_parser_url_fields uf, old_uf;
 2290   int found_at = 0;
 2291 
 2292   u->port = u->field_set = 0;
 2293   s = is_connect ? s_req_server_start : s_req_spaces_before_url;
 2294   old_uf = UF_MAX;
 2295 
 2296   for (p = buf; p < buf + buflen; p++) {
 2297     s = parse_url_char(s, *p);
 2298 
 2299     /* Figure out the next field that we're operating on */
 2300     switch (s) {
 2301       case s_dead:
 2302         return 1;
 2303 
 2304       /* Skip delimeters */
 2305       case s_req_schema_slash:
 2306       case s_req_schema_slash_slash:
 2307       case s_req_server_start:
 2308       case s_req_query_string_start:
 2309       case s_req_fragment_start:
 2310         continue;
 2311 
 2312       case s_req_schema:
 2313         uf = UF_SCHEMA;
 2314         break;
 2315 
 2316       case s_req_server_with_at:
 2317         found_at = 1;
 2318 
 2319       /* FALLTHROUGH */
 2320       case s_req_server:
 2321         uf = UF_HOST;
 2322         break;
 2323 
 2324       case s_req_path:
 2325         uf = UF_PATH;
 2326         break;
 2327 
 2328       case s_req_query_string:
 2329         uf = UF_QUERY;
 2330         break;
 2331 
 2332       case s_req_fragment:
 2333         uf = UF_FRAGMENT;
 2334         break;
 2335 
 2336       default:
 2337         assert(!"Unexpected state");
 2338         return 1;
 2339     }
 2340 
 2341     /* Nothing's changed; soldier on */
 2342     if (uf == old_uf) {
 2343       u->field_data[uf].len++;
 2344       continue;
 2345     }
 2346 
 2347     u->field_data[uf].off = p - buf;
 2348     u->field_data[uf].len = 1;
 2349 
 2350     u->field_set |= (1 << uf);
 2351     old_uf = uf;
 2352   }
 2353 
 2354   /* host must be present if there is a schema */
 2355   /* parsing http:///toto will fail */
 2356   if ((u->field_set & (1 << UF_SCHEMA)) &&
 2357       (u->field_set & (1 << UF_HOST)) == 0) {
 2358     return 1;
 2359   }
 2360 
 2361   if (u->field_set & (1 << UF_HOST)) {
 2362     if (http_parse_host(buf, u, found_at) != 0) {
 2363       return 1;
 2364     }
 2365   }
 2366 
 2367   /* CONNECT requests can only contain "hostname:port" */
 2368   if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
 2369     return 1;
 2370   }
 2371 
 2372   if (u->field_set & (1 << UF_PORT)) {
 2373     /* Don't bother with endp; we've already validated the string */
 2374     unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
 2375 
 2376     /* Ports have a max value of 2^16 */
 2377     if (v > 0xffff) {
 2378       return 1;
 2379     }
 2380 
 2381     u->port = (uint16_t) v;
 2382   }
 2383 
 2384   return 0;
 2385 }
 2386 
 2387 void
 2388 http_parser_pause(http_parser *parser, int paused) {
 2389   /* Users should only be pausing/unpausing a parser that is not in an error
 2390    * state. In non-debug builds, there's not much that we can do about this
 2391    * other than ignore it.
 2392    */
 2393   if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
 2394       HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
 2395     SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
 2396   } else {
 2397     assert(0 && "Attempting to pause parser in error state");
 2398   }
 2399 }
 2400 
 2401 int
 2402 http_body_is_final(const struct http_parser *parser) {
 2403     return parser->state == s_message_done;
 2404 }
 2405 
 2406 unsigned long
 2407 http_parser_version(void) {
 2408   return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
 2409          HTTP_PARSER_VERSION_MINOR * 0x00100 |
 2410          HTTP_PARSER_VERSION_PATCH * 0x00001;
 2411 }