Electroneum
http_parser_merged.h
Go to the documentation of this file.
1 /* merged revision: 5b951d74bd66ec9d38448e0a85b1cf8b85d97db3 */
2 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #ifndef CROW_http_parser_h
23 #define CROW_http_parser_h
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 /* Also update SONAME in the Makefile whenever you change these. */
29 #define CROW_HTTP_PARSER_VERSION_MAJOR 2
30 #define CROW_HTTP_PARSER_VERSION_MINOR 3
31 #define CROW_HTTP_PARSER_VERSION_PATCH 0
32 
33 #include <sys/types.h>
34 #if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
35 #include <BaseTsd.h>
36 #include <stddef.h>
37 typedef __int8 int8_t;
38 typedef unsigned __int8 uint8_t;
39 typedef __int16 int16_t;
40 typedef unsigned __int16 uint16_t;
41 typedef __int32 int32_t;
42 typedef unsigned __int32 uint32_t;
43 typedef __int64 int64_t;
44 typedef unsigned __int64 uint64_t;
45 #else
46 #include <stdint.h>
47 #endif
48 
49 /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
50  * faster
51  */
52 #ifndef CROW_HTTP_PARSER_STRICT
53 # define CROW_HTTP_PARSER_STRICT 1
54 #endif
55 
56 /* Maximium header size allowed. If the macro is not defined
57  * before including this header then the default is used. To
58  * change the maximum header size, define the macro in the build
59  * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
60  * the effective limit on the size of the header, define the macro
61  * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
62  */
63 #ifndef CROW_HTTP_MAX_HEADER_SIZE
64 # define CROW_HTTP_MAX_HEADER_SIZE (80*1024)
65 #endif
66 
67 typedef struct http_parser http_parser;
69 
70 
71 /* Callbacks should return non-zero to indicate an error. The parser will
72  * then halt execution.
73  *
74  * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
75  * returning '1' from on_headers_complete will tell the parser that it
76  * should not expect a body. This is used when receiving a response to a
77  * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
78  * chunked' headers that indicate the presence of a body.
79  *
80  * http_data_cb does not return data chunks. It will be call arbitrarally
81  * many times for each string. E.G. you might get 10 callbacks for "on_url"
82  * each providing just a few characters more data.
83  */
84 typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
85 typedef int (*http_cb) (http_parser*);
86 
87 
88 /* Request Methods */
89 #define CROW_HTTP_METHOD_MAP(CROW_XX) \
90  CROW_XX(0, DELETE, DELETE) \
91  CROW_XX(1, GET, GET) \
92  CROW_XX(2, HEAD, HEAD) \
93  CROW_XX(3, POST, POST) \
94  CROW_XX(4, PUT, PUT) \
95  /* pathological */ \
96  CROW_XX(5, CONNECT, CONNECT) \
97  CROW_XX(6, OPTIONS, OPTIONS) \
98  CROW_XX(7, TRACE, TRACE) \
99  /* webdav */ \
100  CROW_XX(8, COPY, COPY) \
101  CROW_XX(9, LOCK, LOCK) \
102  CROW_XX(10, MKCOL, MKCOL) \
103  CROW_XX(11, MOVE, MOVE) \
104  CROW_XX(12, PROPFIND, PROPFIND) \
105  CROW_XX(13, PROPPATCH, PROPPATCH) \
106  CROW_XX(14, SEARCH, SEARCH) \
107  CROW_XX(15, UNLOCK, UNLOCK) \
108  /* subversion */ \
109  CROW_XX(16, REPORT, REPORT) \
110  CROW_XX(17, MKACTIVITY, MKACTIVITY) \
111  CROW_XX(18, CHECKOUT, CHECKOUT) \
112  CROW_XX(19, MERGE, MERGE) \
113  /* upnp */ \
114  CROW_XX(20, MSEARCH, M-SEARCH) \
115  CROW_XX(21, NOTIFY, NOTIFY) \
116  CROW_XX(22, SUBSCRIBE, SUBSCRIBE) \
117  CROW_XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
118  /* RFC-5789 */ \
119  CROW_XX(24, PATCH, PATCH) \
120  CROW_XX(25, PURGE, PURGE) \
121  /* CalDAV */ \
122  CROW_XX(26, MKCALENDAR, MKCALENDAR) \
123 
125  {
126 #define CROW_XX(num, name, string) HTTP_##name = num,
128 #undef CROW_XX
129  };
130 
131 
133 
134 
135 /* Flag values for http_parser.flags field */
136 enum flags
137  { F_CHUNKED = 1 << 0
140  , F_TRAILING = 1 << 3
141  , F_UPGRADE = 1 << 4
142  , F_SKIPBODY = 1 << 5
143  };
144 
145 
146 /* Map for errno-related constants
147  *
148  * The provided argument should be a macro that takes 2 arguments.
149  */
150 #define CROW_HTTP_ERRNO_MAP(CROW_XX) \
151  /* No error */ \
152  CROW_XX(OK, "success") \
153  \
154  /* Callback-related errors */ \
155  CROW_XX(CB_message_begin, "the on_message_begin callback failed") \
156  CROW_XX(CB_url, "the on_url callback failed") \
157  CROW_XX(CB_header_field, "the on_header_field callback failed") \
158  CROW_XX(CB_header_value, "the on_header_value callback failed") \
159  CROW_XX(CB_headers_complete, "the on_headers_complete callback failed") \
160  CROW_XX(CB_body, "the on_body callback failed") \
161  CROW_XX(CB_message_complete, "the on_message_complete callback failed") \
162  CROW_XX(CB_status, "the on_status callback failed") \
163  \
164  /* Parsing-related errors */ \
165  CROW_XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
166  CROW_XX(HEADER_OVERFLOW, \
167  "too many header bytes seen; overflow detected") \
168  CROW_XX(CLOSED_CONNECTION, \
169  "data received after completed connection: close message") \
170  CROW_XX(INVALID_VERSION, "invalid HTTP version") \
171  CROW_XX(INVALID_STATUS, "invalid HTTP status code") \
172  CROW_XX(INVALID_METHOD, "invalid HTTP method") \
173  CROW_XX(INVALID_URL, "invalid URL") \
174  CROW_XX(INVALID_HOST, "invalid host") \
175  CROW_XX(INVALID_PORT, "invalid port") \
176  CROW_XX(INVALID_PATH, "invalid path") \
177  CROW_XX(INVALID_QUERY_STRING, "invalid query string") \
178  CROW_XX(INVALID_FRAGMENT, "invalid fragment") \
179  CROW_XX(LF_EXPECTED, "CROW_LF character expected") \
180  CROW_XX(INVALID_HEADER_TOKEN, "invalid character in header") \
181  CROW_XX(INVALID_CONTENT_LENGTH, \
182  "invalid character in content-length header") \
183  CROW_XX(INVALID_CHUNK_SIZE, \
184  "invalid character in chunk size header") \
185  CROW_XX(INVALID_CONSTANT, "invalid constant string") \
186  CROW_XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
187  CROW_XX(STRICT, "strict mode assertion failed") \
188  CROW_XX(PAUSED, "parser is paused") \
189  CROW_XX(UNKNOWN, "an unknown error occurred")
190 
191 
192 /* Define HPE_* values for each errno value above */
193 #define CROW_HTTP_ERRNO_GEN(n, s) HPE_##n,
196 };
197 #undef CROW_HTTP_ERRNO_GEN
198 
199 
200 /* Get an http_errno value from an http_parser */
201 #define CROW_HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
202 
203 
204 struct http_parser {
206  unsigned int type : 2; /* enum http_parser_type */
207  unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */
208  unsigned int state : 8; /* enum state from http_parser.c */
209  unsigned int header_state : 8; /* enum header_state from http_parser.c */
210  unsigned int index : 8; /* index into current matcher */
211 
212  uint32_t nread; /* # bytes read in various scenarios */
213  uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
214 
216  unsigned short http_major;
217  unsigned short http_minor;
218  unsigned int status_code : 16; /* responses only */
219  unsigned int method : 8; /* requests only */
220  unsigned int http_errno : 7;
221 
222  /* 1 = Upgrade header was present and the parser has exited because of that.
223  * 0 = No upgrade header present.
224  * Should be checked when http_parser_execute() returns in addition to
225  * error checking.
226  */
227  unsigned int upgrade : 1;
228 
230  void *data; /* A pointer to get hook to the "connection" or "socket" object */
231 };
232 
233 
243 };
244 
245 
247  { UF_SCHEMA = 0
248  , UF_HOST = 1
249  , UF_PORT = 2
250  , UF_PATH = 3
251  , UF_QUERY = 4
254  , UF_MAX = 7
255  };
256 
257 
258 /* Result structure for http_parser_parse_url().
259  *
260  * Callers should index into field_data[] with UF_* values iff field_set
261  * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
262  * because we probably have padding left over), we convert any port to
263  * a uint16_t.
264  */
266  uint16_t field_set; /* Bitmask of (1 << UF_*) values */
267  uint16_t port; /* Converted UF_PORT string */
268 
269  struct {
270  uint16_t off; /* Offset into buffer in which field starts */
271  uint16_t len; /* Length of run in buffer */
272  } field_data[UF_MAX];
273 };
274 
275 
276 /* Returns the library version. Bits 16-23 contain the major version number,
277  * bits 8-15 the minor version number and bits 0-7 the patch level.
278  * Usage example:
279  *
280  * unsigned long version = http_parser_version();
281  * unsigned major = (version >> 16) & 255;
282  * unsigned minor = (version >> 8) & 255;
283  * unsigned patch = version & 255;
284  * printf("http_parser v%u.%u.%u\n", major, minor, version);
285  */
286 unsigned long http_parser_version(void);
287 
289 
290 
291 size_t http_parser_execute(http_parser *parser,
292  const http_parser_settings *settings,
293  const char *data,
294  size_t len);
295 
296 
297 /* If http_should_keep_alive() in the on_headers_complete or
298  * on_message_complete callback returns 0, then this should be
299  * the last message on the connection.
300  * If you are the server, respond with the "Connection: close" header.
301  * If you are the client, close the connection.
302  */
303 int http_should_keep_alive(const http_parser *parser);
304 
305 /* Returns a string version of the HTTP method. */
306 const char *http_method_str(enum http_method m);
307 
308 /* Return a string name of the given error */
309 const char *http_errno_name(enum http_errno err);
310 
311 /* Return a string description of the given error */
312 const char *http_errno_description(enum http_errno err);
313 
314 /* Parse a URL; return nonzero on failure */
315 int http_parser_parse_url(const char *buf, size_t buflen,
316  int is_connect,
317  struct http_parser_url *u);
318 
319 /* Pause or un-pause the parser; a nonzero value pauses */
320 void http_parser_pause(http_parser *parser, int paused);
321 
322 /* Checks if this is the final chunk of the body. */
323 int http_body_is_final(const http_parser *parser);
324 
325 /*#include "http_parser.h"*/
326 /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
327  *
328  * Additional changes are licensed under the same terms as NGINX and
329  * copyright Joyent, Inc. and other Node contributors. All rights reserved.
330  *
331  * Permission is hereby granted, free of charge, to any person obtaining a copy
332  * of this software and associated documentation files (the "Software"), to
333  * deal in the Software without restriction, including without limitation the
334  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
335  * sell copies of the Software, and to permit persons to whom the Software is
336  * furnished to do so, subject to the following conditions:
337  *
338  * The above copyright notice and this permission notice shall be included in
339  * all copies or substantial portions of the Software.
340  *
341  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
342  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
343  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
344  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
345  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
346  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
347  * IN THE SOFTWARE.
348  */
349 #include <assert.h>
350 #include <stddef.h>
351 #include <ctype.h>
352 #include <stdlib.h>
353 #include <string.h>
354 #include <limits.h>
355 
356 #ifndef CROW_ULLONG_MAX
357 # define CROW_ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
358 #endif
359 
360 #ifndef CROW_MIN
361 # define CROW_MIN(a,b) ((a) < (b) ? (a) : (b))
362 #endif
363 
364 #ifndef CROW_ARRAY_SIZE
365 # define CROW_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
366 #endif
367 
368 #ifndef CROW_BIT_AT
369 # define CROW_BIT_AT(a, i) \
370  (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
371  (1 << ((unsigned int) (i) & 7))))
372 #endif
373 
374 #ifndef CROW_ELEM_AT
375 # define CROW_ELEM_AT(a, i, v) ((unsigned int) (i) < CROW_ARRAY_SIZE(a) ? (a)[(i)] : (v))
376 #endif
377 
378 #define CROW_SET_ERRNO(e) \
379 do { \
380  parser->http_errno = (e); \
381 } while(0)
382 
383 
384 /* Run the notify callback FOR, returning ER if it fails */
385 #define CROW_CALLBACK_NOTIFY_(FOR, ER) \
386 do { \
387  assert(CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK); \
388  \
389  if (settings->on_##FOR) { \
390  if (0 != settings->on_##FOR(parser)) { \
391  CROW_SET_ERRNO(HPE_CB_##FOR); \
392  } \
393  \
394  /* We either errored above or got paused; get out */ \
395  if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) { \
396  return (ER); \
397  } \
398  } \
399 } while (0)
400 
401 /* Run the notify callback FOR and consume the current byte */
402 #define CROW_CALLBACK_NOTIFY(FOR) CROW_CALLBACK_NOTIFY_(FOR, p - data + 1)
403 
404 /* Run the notify callback FOR and don't consume the current byte */
405 #define CROW_CALLBACK_NOTIFY_NOADVANCE(FOR) CROW_CALLBACK_NOTIFY_(FOR, p - data)
406 
407 /* Run data callback FOR with LEN bytes, returning ER if it fails */
408 #define CROW_CALLBACK_DATA_(FOR, LEN, ER) \
409 do { \
410  assert(CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK); \
411  \
412  if (FOR##_mark) { \
413  if (settings->on_##FOR) { \
414  if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \
415  CROW_SET_ERRNO(HPE_CB_##FOR); \
416  } \
417  \
418  /* We either errored above or got paused; get out */ \
419  if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) { \
420  return (ER); \
421  } \
422  } \
423  FOR##_mark = NULL; \
424  } \
425 } while (0)
426 
427 /* Run the data callback FOR and consume the current byte */
428 #define CROW_CALLBACK_DATA(FOR) \
429  CROW_CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
430 
431 /* Run the data callback FOR and don't consume the current byte */
432 #define CROW_CALLBACK_DATA_NOADVANCE(FOR) \
433  CROW_CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
434 
435 /* Set the mark FOR; non-destructive if mark is already set */
436 #define CROW_MARK(FOR) \
437 do { \
438  if (!FOR##_mark) { \
439  FOR##_mark = p; \
440  } \
441 } while (0)
442 
443 
444 #define CROW_PROXY_CONNECTION "proxy-connection"
445 #define CROW_CONNECTION "connection"
446 #define CROW_CONTENT_LENGTH "content-length"
447 #define CROW_TRANSFER_ENCODING "transfer-encoding"
448 #define CROW_UPGRADE "upgrade"
449 #define CROW_CHUNKED "chunked"
450 #define CROW_KEEP_ALIVE "keep-alive"
451 #define CROW_CLOSE "close"
452 
453 
454 
455 
456 enum state
457  { s_dead = 1 /* important that this is > 0 */
458 
475 
477 
501 
510 
512 
517 
520 
521  /* Important: 's_headers_done' must be the last 'header' state. All
522  * states beyond this must be 'body' states. It is used for overflow
523  * checking. See the CROW_PARSING_HEADER() macro.
524  */
525 
529 
532 
534  };
535 
536 
537 #define CROW_PARSING_HEADER(state) (state <= s_headers_done)
538 
539 
541  { h_general = 0
542  , h_C
545 
551 
556 
560 
564  };
565 
567  {
578 };
579 
580 /* Macros for character classes; depends on strict-mode */
581 #define CROW_CR '\r'
582 #define CROW_LF '\n'
583 #define CROW_LOWER(c) (unsigned char)(c | 0x20)
584 #define CROW_IS_ALPHA(c) (CROW_LOWER(c) >= 'a' && CROW_LOWER(c) <= 'z')
585 #define CROW_IS_NUM(c) ((c) >= '0' && (c) <= '9')
586 #define CROW_IS_ALPHANUM(c) (CROW_IS_ALPHA(c) || CROW_IS_NUM(c))
587 #define CROW_IS_HEX(c) (CROW_IS_NUM(c) || (CROW_LOWER(c) >= 'a' && CROW_LOWER(c) <= 'f'))
588 #define CROW_IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
589  (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
590  (c) == ')')
591 #define CROW_IS_USERINFO_CHAR(c) (CROW_IS_ALPHANUM(c) || CROW_IS_MARK(c) || (c) == '%' || \
592  (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
593  (c) == '$' || (c) == ',')
594 
595 #if CROW_HTTP_PARSER_STRICT
596 #define CROW_TOKEN(c) (tokens[(unsigned char)c])
597 #define CROW_IS_URL_CHAR(c) (CROW_BIT_AT(normal_url_char, (unsigned char)c))
598 #define CROW_IS_HOST_CHAR(c) (CROW_IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
599 #else
600 #define CROW_TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
601 #define CROW_IS_URL_CHAR(c) \
602  (CROW_BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
603 #define CROW_IS_HOST_CHAR(c) \
604  (CROW_IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
605 #endif
606 
607 
608 #define CROW_start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
609 
610 
611 #if CROW_HTTP_PARSER_STRICT
612 # define CROW_STRICT_CHECK(cond) \
613 do { \
614  if (cond) { \
615  CROW_SET_ERRNO(HPE_STRICT); \
616  goto error; \
617  } \
618 } while (0)
619 # define CROW_NEW_MESSAGE() (http_should_keep_alive(parser) ? CROW_start_state : s_dead)
620 #else
621 # define CROW_STRICT_CHECK(cond)
622 # define CROW_NEW_MESSAGE() CROW_start_state
623 #endif
624 
625 
626 
627 int http_message_needs_eof(const http_parser *parser);
628 
629 /* Our URL parser.
630  *
631  * This is designed to be shared by http_parser_execute() for URL validation,
632  * hence it has a state transition + byte-for-byte interface. In addition, it
633  * is meant to be embedded in http_parser_parse_url(), which does the dirty
634  * work of turning state transitions URL components for its API.
635  *
636  * This function should only be invoked with non-space characters. It is
637  * assumed that the caller cares about (and can detect) the transition between
638  * URL and non-URL states by looking for these.
639  */
640 inline enum state
641 parse_url_char(enum state s, const char ch)
642 {
643 #if CROW_HTTP_PARSER_STRICT
644 # define CROW_T(v) 0
645 #else
646 # define CROW_T(v) v
647 #endif
648 
649 
650 static const uint8_t normal_url_char[32] = {
651 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
652  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
653 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
654  0 | CROW_T(2) | 0 | 0 | CROW_T(16) | 0 | 0 | 0,
655 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
656  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
657 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
658  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
659 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
660  0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
661 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
662  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
663 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
664  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
665 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
666  1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
667 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
668  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
669 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
670  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
671 /* 80 P 81 Q 82 R 83 S 84 CROW_T 85 U 86 V 87 W */
672  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
673 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
674  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
675 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
676  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
677 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
678  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
679 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
680  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
681 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
682  1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
683 
684 #undef CROW_T
685 
686  if (ch == ' ' || ch == '\r' || ch == '\n') {
687  return s_dead;
688  }
689 
690 #if CROW_HTTP_PARSER_STRICT
691  if (ch == '\t' || ch == '\f') {
692  return s_dead;
693  }
694 #endif
695 
696  switch (s) {
698  /* Proxied requests are followed by scheme of an absolute URI (alpha).
699  * All methods except CONNECT are followed by '/' or '*'.
700  */
701 
702  if (ch == '/' || ch == '*') {
703  return s_req_path;
704  }
705 
706  if (CROW_IS_ALPHA(ch)) {
707  return s_req_schema;
708  }
709 
710  break;
711 
712  case s_req_schema:
713  if (CROW_IS_ALPHA(ch)) {
714  return s;
715  }
716 
717  if (ch == ':') {
718  return s_req_schema_slash;
719  }
720 
721  break;
722 
723  case s_req_schema_slash:
724  if (ch == '/') {
726  }
727 
728  break;
729 
731  if (ch == '/') {
732  return s_req_server_start;
733  }
734 
735  break;
736 
738  if (ch == '@') {
739  return s_dead;
740  }
741 
742  /* FALLTHROUGH */
743  case s_req_server_start:
744  case s_req_server:
745  if (ch == '/') {
746  return s_req_path;
747  }
748 
749  if (ch == '?') {
751  }
752 
753  if (ch == '@') {
754  return s_req_server_with_at;
755  }
756 
757  if (CROW_IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
758  return s_req_server;
759  }
760 
761  break;
762 
763  case s_req_path:
764  if (CROW_IS_URL_CHAR(ch)) {
765  return s;
766  }
767 
768  switch (ch) {
769  case '?':
771 
772  case '#':
773  return s_req_fragment_start;
774  }
775 
776  break;
777 
779  case s_req_query_string:
780  if (CROW_IS_URL_CHAR(ch)) {
781  return s_req_query_string;
782  }
783 
784  switch (ch) {
785  case '?':
786  /* allow extra '?' in query string */
787  return s_req_query_string;
788 
789  case '#':
790  return s_req_fragment_start;
791  }
792 
793  break;
794 
796  if (CROW_IS_URL_CHAR(ch)) {
797  return s_req_fragment;
798  }
799 
800  switch (ch) {
801  case '?':
802  return s_req_fragment;
803 
804  case '#':
805  return s;
806  }
807 
808  break;
809 
810  case s_req_fragment:
811  if (CROW_IS_URL_CHAR(ch)) {
812  return s;
813  }
814 
815  switch (ch) {
816  case '?':
817  case '#':
818  return s;
819  }
820 
821  break;
822 
823  default:
824  break;
825  }
826 
827  /* We should never fall out of the switch above unless there's an error */
828  return s_dead;
829 }
830 
831 inline size_t http_parser_execute (http_parser *parser,
832  const http_parser_settings *settings,
833  const char *data,
834  size_t len)
835 {
836 static const char *method_strings[] =
837  {
838 #define CROW_XX(num, name, string) #string,
840 #undef CROW_XX
841  };
842 
843 /* Tokens as defined by rfc 2616. Also lowercases them.
844  * token = 1*<any CHAR except CTLs or separators>
845  * separators = "(" | ")" | "<" | ">" | "@"
846  * | "," | ";" | ":" | "\" | <">
847  * | "/" | "[" | "]" | "?" | "="
848  * | "{" | "}" | SP | HT
849  */
850 static const char tokens[256] = {
851 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
852  0, 0, 0, 0, 0, 0, 0, 0,
853 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
854  0, 0, 0, 0, 0, 0, 0, 0,
855 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
856  0, 0, 0, 0, 0, 0, 0, 0,
857 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
858  0, 0, 0, 0, 0, 0, 0, 0,
859 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
860  0, '!', 0, '#', '$', '%', '&', '\'',
861 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
862  0, 0, '*', '+', 0, '-', '.', 0,
863 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
864  '0', '1', '2', '3', '4', '5', '6', '7',
865 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
866  '8', '9', 0, 0, 0, 0, 0, 0,
867 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
868  0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
869 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
870  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
871 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
872  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
873 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
874  'x', 'y', 'z', 0, 0, 0, '^', '_',
875 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
876  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
877 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
878  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
879 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
880  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
881 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
882  'x', 'y', 'z', 0, '|', 0, '~', 0 };
883 
884 
885 static const int8_t unhex[256] =
886  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
887  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
888  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
889  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
890  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
891  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
892  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
893  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
894  };
895 
896 
897 
898  char c, ch;
899  int8_t unhex_val;
900  const char *p = data;
901  const char *header_field_mark = 0;
902  const char *header_value_mark = 0;
903  const char *url_mark = 0;
904  const char *body_mark = 0;
905  const char *status_mark = 0;
906 
907  /* We're in an error state. Don't bother doing anything. */
908  if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) {
909  return 0;
910  }
911 
912  if (len == 0) {
913  switch (parser->state) {
914  case s_body_identity_eof:
915  /* Use of CROW_CALLBACK_NOTIFY() here would erroneously return 1 byte read if
916  * we got paused.
917  */
918  CROW_CALLBACK_NOTIFY_NOADVANCE(message_complete);
919  return 0;
920 
921  case s_dead:
922  case s_start_req_or_res:
923  case s_start_res:
924  case s_start_req:
925  return 0;
926 
927  default:
928  CROW_SET_ERRNO(HPE_INVALID_EOF_STATE);
929  return 1;
930  }
931  }
932 
933 
934  if (parser->state == s_header_field)
935  header_field_mark = data;
936  if (parser->state == s_header_value)
937  header_value_mark = data;
938  switch (parser->state) {
939  case s_req_path:
940  case s_req_schema:
941  case s_req_schema_slash:
943  case s_req_server_start:
944  case s_req_server:
947  case s_req_query_string:
949  case s_req_fragment:
950  url_mark = data;
951  break;
952  case s_res_status:
953  status_mark = data;
954  break;
955  }
956 
957  for (p=data; p != data + len; p++) {
958  ch = *p;
959 
960  if (CROW_PARSING_HEADER(parser->state)) {
961  ++parser->nread;
962  /* Don't allow the total size of the HTTP headers (including the status
963  * line) to exceed CROW_HTTP_MAX_HEADER_SIZE. This check is here to protect
964  * embedders against denial-of-service attacks where the attacker feeds
965  * us a never-ending header that the embedder keeps buffering.
966  *
967  * This check is arguably the responsibility of embedders but we're doing
968  * it on the embedder's behalf because most won't bother and this way we
969  * make the web a little safer. CROW_HTTP_MAX_HEADER_SIZE is still far bigger
970  * than any reasonable request or response so this should never affect
971  * day-to-day operation.
972  */
973  if (parser->nread > (CROW_HTTP_MAX_HEADER_SIZE)) {
974  CROW_SET_ERRNO(HPE_HEADER_OVERFLOW);
975  goto error;
976  }
977  }
978 
979  reexecute_byte:
980  switch (parser->state) {
981 
982  case s_dead:
983  /* this state is used after a 'Connection: close' message
984  * the parser will error out if it reads another message
985  */
986  if (ch == CROW_CR || ch == CROW_LF)
987  break;
988 
989  CROW_SET_ERRNO(HPE_CLOSED_CONNECTION);
990  goto error;
991 
992  case s_start_req_or_res:
993  {
994  if (ch == CROW_CR || ch == CROW_LF)
995  break;
996  parser->flags = 0;
998 
999  if (ch == 'H') {
1000  parser->state = s_res_or_resp_H;
1001 
1002  CROW_CALLBACK_NOTIFY(message_begin);
1003  } else {
1004  parser->type = HTTP_REQUEST;
1005  parser->state = s_start_req;
1006  goto reexecute_byte;
1007  }
1008 
1009  break;
1010  }
1011 
1012  case s_res_or_resp_H:
1013  if (ch == 'T') {
1014  parser->type = HTTP_RESPONSE;
1015  parser->state = s_res_HT;
1016  } else {
1017  if (ch != 'E') {
1018  CROW_SET_ERRNO(HPE_INVALID_CONSTANT);
1019  goto error;
1020  }
1021 
1022  parser->type = HTTP_REQUEST;
1023  parser->method = HTTP_HEAD;
1024  parser->index = 2;
1025  parser->state = s_req_method;
1026  }
1027  break;
1028 
1029  case s_start_res:
1030  {
1031  parser->flags = 0;
1032  parser->content_length = CROW_ULLONG_MAX;
1033 
1034  switch (ch) {
1035  case 'H':
1036  parser->state = s_res_H;
1037  break;
1038 
1039  case CROW_CR:
1040  case CROW_LF:
1041  break;
1042 
1043  default:
1044  CROW_SET_ERRNO(HPE_INVALID_CONSTANT);
1045  goto error;
1046  }
1047 
1048  CROW_CALLBACK_NOTIFY(message_begin);
1049  break;
1050  }
1051 
1052  case s_res_H:
1053  CROW_STRICT_CHECK(ch != 'T');
1054  parser->state = s_res_HT;
1055  break;
1056 
1057  case s_res_HT:
1058  CROW_STRICT_CHECK(ch != 'T');
1059  parser->state = s_res_HTT;
1060  break;
1061 
1062  case s_res_HTT:
1063  CROW_STRICT_CHECK(ch != 'P');
1064  parser->state = s_res_HTTP;
1065  break;
1066 
1067  case s_res_HTTP:
1068  CROW_STRICT_CHECK(ch != '/');
1069  parser->state = s_res_first_http_major;
1070  break;
1071 
1073  if (ch < '0' || ch > '9') {
1074  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1075  goto error;
1076  }
1077 
1078  parser->http_major = ch - '0';
1079  parser->state = s_res_http_major;
1080  break;
1081 
1082  /* major HTTP version or dot */
1083  case s_res_http_major:
1084  {
1085  if (ch == '.') {
1086  parser->state = s_res_first_http_minor;
1087  break;
1088  }
1089 
1090  if (!CROW_IS_NUM(ch)) {
1091  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1092  goto error;
1093  }
1094 
1095  parser->http_major *= 10;
1096  parser->http_major += ch - '0';
1097 
1098  if (parser->http_major > 999) {
1099  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1100  goto error;
1101  }
1102 
1103  break;
1104  }
1105 
1106  /* first digit of minor HTTP version */
1108  if (!CROW_IS_NUM(ch)) {
1109  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1110  goto error;
1111  }
1112 
1113  parser->http_minor = ch - '0';
1114  parser->state = s_res_http_minor;
1115  break;
1116 
1117  /* minor HTTP version or end of request line */
1118  case s_res_http_minor:
1119  {
1120  if (ch == ' ') {
1121  parser->state = s_res_first_status_code;
1122  break;
1123  }
1124 
1125  if (!CROW_IS_NUM(ch)) {
1126  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1127  goto error;
1128  }
1129 
1130  parser->http_minor *= 10;
1131  parser->http_minor += ch - '0';
1132 
1133  if (parser->http_minor > 999) {
1134  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1135  goto error;
1136  }
1137 
1138  break;
1139  }
1140 
1142  {
1143  if (!CROW_IS_NUM(ch)) {
1144  if (ch == ' ') {
1145  break;
1146  }
1147 
1148  CROW_SET_ERRNO(HPE_INVALID_STATUS);
1149  goto error;
1150  }
1151  parser->status_code = ch - '0';
1152  parser->state = s_res_status_code;
1153  break;
1154  }
1155 
1156  case s_res_status_code:
1157  {
1158  if (!CROW_IS_NUM(ch)) {
1159  switch (ch) {
1160  case ' ':
1161  parser->state = s_res_status_start;
1162  break;
1163  case CROW_CR:
1164  parser->state = s_res_line_almost_done;
1165  break;
1166  case CROW_LF:
1167  parser->state = s_header_field_start;
1168  break;
1169  default:
1170  CROW_SET_ERRNO(HPE_INVALID_STATUS);
1171  goto error;
1172  }
1173  break;
1174  }
1175 
1176  parser->status_code *= 10;
1177  parser->status_code += ch - '0';
1178 
1179  if (parser->status_code > 999) {
1180  CROW_SET_ERRNO(HPE_INVALID_STATUS);
1181  goto error;
1182  }
1183 
1184  break;
1185  }
1186 
1187  case s_res_status_start:
1188  {
1189  if (ch == CROW_CR) {
1190  parser->state = s_res_line_almost_done;
1191  break;
1192  }
1193 
1194  if (ch == CROW_LF) {
1195  parser->state = s_header_field_start;
1196  break;
1197  }
1198 
1199  CROW_MARK(status);
1200  parser->state = s_res_status;
1201  parser->index = 0;
1202  break;
1203  }
1204 
1205  case s_res_status:
1206  if (ch == CROW_CR) {
1207  parser->state = s_res_line_almost_done;
1208  CROW_CALLBACK_DATA(status);
1209  break;
1210  }
1211 
1212  if (ch == CROW_LF) {
1213  parser->state = s_header_field_start;
1214  CROW_CALLBACK_DATA(status);
1215  break;
1216  }
1217 
1218  break;
1219 
1221  CROW_STRICT_CHECK(ch != CROW_LF);
1222  parser->state = s_header_field_start;
1223  break;
1224 
1225  case s_start_req:
1226  {
1227  if (ch == CROW_CR || ch == CROW_LF)
1228  break;
1229  parser->flags = 0;
1230  parser->content_length = CROW_ULLONG_MAX;
1231 
1232  if (!CROW_IS_ALPHA(ch)) {
1233  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1234  goto error;
1235  }
1236 
1237  parser->method = (enum http_method) 0;
1238  parser->index = 1;
1239  switch (ch) {
1240  case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
1241  case 'D': parser->method = HTTP_DELETE; break;
1242  case 'G': parser->method = HTTP_GET; break;
1243  case 'H': parser->method = HTTP_HEAD; break;
1244  case 'L': parser->method = HTTP_LOCK; break;
1245  case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
1246  case 'N': parser->method = HTTP_NOTIFY; break;
1247  case 'O': parser->method = HTTP_OPTIONS; break;
1248  case 'P': parser->method = HTTP_POST;
1249  /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
1250  break;
1251  case 'R': parser->method = HTTP_REPORT; break;
1252  case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
1253  case 'T': parser->method = HTTP_TRACE; break;
1254  case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;
1255  default:
1256  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1257  goto error;
1258  }
1259  parser->state = s_req_method;
1260 
1261  CROW_CALLBACK_NOTIFY(message_begin);
1262 
1263  break;
1264  }
1265 
1266  case s_req_method:
1267  {
1268  const char *matcher;
1269  if (ch == '\0') {
1270  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1271  goto error;
1272  }
1273 
1274  matcher = method_strings[parser->method];
1275  if (ch == ' ' && matcher[parser->index] == '\0') {
1276  parser->state = s_req_spaces_before_url;
1277  } else if (ch == matcher[parser->index]) {
1278  ; /* nada */
1279  } else if (parser->method == HTTP_CONNECT) {
1280  if (parser->index == 1 && ch == 'H') {
1281  parser->method = HTTP_CHECKOUT;
1282  } else if (parser->index == 2 && ch == 'P') {
1283  parser->method = HTTP_COPY;
1284  } else {
1285  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1286  goto error;
1287  }
1288  } else if (parser->method == HTTP_MKCOL) {
1289  if (parser->index == 1 && ch == 'O') {
1290  parser->method = HTTP_MOVE;
1291  } else if (parser->index == 1 && ch == 'E') {
1292  parser->method = HTTP_MERGE;
1293  } else if (parser->index == 1 && ch == '-') {
1294  parser->method = HTTP_MSEARCH;
1295  } else if (parser->index == 2 && ch == 'A') {
1296  parser->method = HTTP_MKACTIVITY;
1297  } else if (parser->index == 3 && ch == 'A') {
1298  parser->method = HTTP_MKCALENDAR;
1299  } else {
1300  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1301  goto error;
1302  }
1303  } else if (parser->method == HTTP_SUBSCRIBE) {
1304  if (parser->index == 1 && ch == 'E') {
1305  parser->method = HTTP_SEARCH;
1306  } else {
1307  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1308  goto error;
1309  }
1310  } else if (parser->index == 1 && parser->method == HTTP_POST) {
1311  if (ch == 'R') {
1312  parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
1313  } else if (ch == 'U') {
1314  parser->method = HTTP_PUT; /* or HTTP_PURGE */
1315  } else if (ch == 'A') {
1316  parser->method = HTTP_PATCH;
1317  } else {
1318  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1319  goto error;
1320  }
1321  } else if (parser->index == 2) {
1322  if (parser->method == HTTP_PUT) {
1323  if (ch == 'R') {
1324  parser->method = HTTP_PURGE;
1325  } else {
1326  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1327  goto error;
1328  }
1329  } else if (parser->method == HTTP_UNLOCK) {
1330  if (ch == 'S') {
1331  parser->method = HTTP_UNSUBSCRIBE;
1332  } else {
1333  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1334  goto error;
1335  }
1336  } else {
1337  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1338  goto error;
1339  }
1340  } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
1341  parser->method = HTTP_PROPPATCH;
1342  } else {
1343  CROW_SET_ERRNO(HPE_INVALID_METHOD);
1344  goto error;
1345  }
1346 
1347  ++parser->index;
1348  break;
1349  }
1350 
1352  {
1353  if (ch == ' ') break;
1354 
1355  CROW_MARK(url);
1356  if (parser->method == HTTP_CONNECT) {
1357  parser->state = s_req_server_start;
1358  }
1359 
1360  parser->state = parse_url_char((enum state)parser->state, ch);
1361  if (parser->state == s_dead) {
1362  CROW_SET_ERRNO(HPE_INVALID_URL);
1363  goto error;
1364  }
1365 
1366  break;
1367  }
1368 
1369  case s_req_schema:
1370  case s_req_schema_slash:
1372  case s_req_server_start:
1373  {
1374  switch (ch) {
1375  /* No whitespace allowed here */
1376  case ' ':
1377  case CROW_CR:
1378  case CROW_LF:
1379  CROW_SET_ERRNO(HPE_INVALID_URL);
1380  goto error;
1381  default:
1382  parser->state = parse_url_char((enum state)parser->state, ch);
1383  if (parser->state == s_dead) {
1384  CROW_SET_ERRNO(HPE_INVALID_URL);
1385  goto error;
1386  }
1387  }
1388 
1389  break;
1390  }
1391 
1392  case s_req_server:
1393  case s_req_server_with_at:
1394  case s_req_path:
1396  case s_req_query_string:
1397  case s_req_fragment_start:
1398  case s_req_fragment:
1399  {
1400  switch (ch) {
1401  case ' ':
1402  parser->state = s_req_http_start;
1403  CROW_CALLBACK_DATA(url);
1404  break;
1405  case CROW_CR:
1406  case CROW_LF:
1407  parser->http_major = 0;
1408  parser->http_minor = 9;
1409  parser->state = (ch == CROW_CR) ?
1412  CROW_CALLBACK_DATA(url);
1413  break;
1414  default:
1415  parser->state = parse_url_char((enum state)parser->state, ch);
1416  if (parser->state == s_dead) {
1417  CROW_SET_ERRNO(HPE_INVALID_URL);
1418  goto error;
1419  }
1420  }
1421  break;
1422  }
1423 
1424  case s_req_http_start:
1425  switch (ch) {
1426  case 'H':
1427  parser->state = s_req_http_H;
1428  break;
1429  case ' ':
1430  break;
1431  default:
1432  CROW_SET_ERRNO(HPE_INVALID_CONSTANT);
1433  goto error;
1434  }
1435  break;
1436 
1437  case s_req_http_H:
1438  CROW_STRICT_CHECK(ch != 'T');
1439  parser->state = s_req_http_HT;
1440  break;
1441 
1442  case s_req_http_HT:
1443  CROW_STRICT_CHECK(ch != 'T');
1444  parser->state = s_req_http_HTT;
1445  break;
1446 
1447  case s_req_http_HTT:
1448  CROW_STRICT_CHECK(ch != 'P');
1449  parser->state = s_req_http_HTTP;
1450  break;
1451 
1452  case s_req_http_HTTP:
1453  CROW_STRICT_CHECK(ch != '/');
1454  parser->state = s_req_first_http_major;
1455  break;
1456 
1457  /* first digit of major HTTP version */
1459  if (ch < '1' || ch > '9') {
1460  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1461  goto error;
1462  }
1463 
1464  parser->http_major = ch - '0';
1465  parser->state = s_req_http_major;
1466  break;
1467 
1468  /* major HTTP version or dot */
1469  case s_req_http_major:
1470  {
1471  if (ch == '.') {
1472  parser->state = s_req_first_http_minor;
1473  break;
1474  }
1475 
1476  if (!CROW_IS_NUM(ch)) {
1477  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1478  goto error;
1479  }
1480 
1481  parser->http_major *= 10;
1482  parser->http_major += ch - '0';
1483 
1484  if (parser->http_major > 999) {
1485  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1486  goto error;
1487  }
1488 
1489  break;
1490  }
1491 
1492  /* first digit of minor HTTP version */
1494  if (!CROW_IS_NUM(ch)) {
1495  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1496  goto error;
1497  }
1498 
1499  parser->http_minor = ch - '0';
1500  parser->state = s_req_http_minor;
1501  break;
1502 
1503  /* minor HTTP version or end of request line */
1504  case s_req_http_minor:
1505  {
1506  if (ch == CROW_CR) {
1507  parser->state = s_req_line_almost_done;
1508  break;
1509  }
1510 
1511  if (ch == CROW_LF) {
1512  parser->state = s_header_field_start;
1513  break;
1514  }
1515 
1516  /* XXX allow spaces after digit? */
1517 
1518  if (!CROW_IS_NUM(ch)) {
1519  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1520  goto error;
1521  }
1522 
1523  parser->http_minor *= 10;
1524  parser->http_minor += ch - '0';
1525 
1526  if (parser->http_minor > 999) {
1527  CROW_SET_ERRNO(HPE_INVALID_VERSION);
1528  goto error;
1529  }
1530 
1531  break;
1532  }
1533 
1534  /* end of request line */
1536  {
1537  if (ch != CROW_LF) {
1538  CROW_SET_ERRNO(HPE_LF_EXPECTED);
1539  goto error;
1540  }
1541 
1542  parser->state = s_header_field_start;
1543  break;
1544  }
1545 
1546  case s_header_field_start:
1547  {
1548  if (ch == CROW_CR) {
1549  parser->state = s_headers_almost_done;
1550  break;
1551  }
1552 
1553  if (ch == CROW_LF) {
1554  /* they might be just sending \n instead of \r\n so this would be
1555  * the second \n to denote the end of headers*/
1556  parser->state = s_headers_almost_done;
1557  goto reexecute_byte;
1558  }
1559 
1560  c = CROW_TOKEN(ch);
1561 
1562  if (!c) {
1563  CROW_SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1564  goto error;
1565  }
1566 
1567  CROW_MARK(header_field);
1568 
1569  parser->index = 0;
1570  parser->state = s_header_field;
1571 
1572  switch (c) {
1573  case 'c':
1574  parser->header_state = h_C;
1575  break;
1576 
1577  case 'p':
1579  break;
1580 
1581  case 't':
1583  break;
1584 
1585  case 'u':
1586  parser->header_state = h_matching_upgrade;
1587  break;
1588 
1589  default:
1590  parser->header_state = h_general;
1591  break;
1592  }
1593  break;
1594  }
1595 
1596  case s_header_field:
1597  {
1598  c = CROW_TOKEN(ch);
1599 
1600  if (c) {
1601  switch (parser->header_state) {
1602  case h_general:
1603  break;
1604 
1605  case h_C:
1606  parser->index++;
1607  parser->header_state = (c == 'o' ? h_CO : h_general);
1608  break;
1609 
1610  case h_CO:
1611  parser->index++;
1612  parser->header_state = (c == 'n' ? h_CON : h_general);
1613  break;
1614 
1615  case h_CON:
1616  parser->index++;
1617  switch (c) {
1618  case 'n':
1620  break;
1621  case 't':
1623  break;
1624  default:
1625  parser->header_state = h_general;
1626  break;
1627  }
1628  break;
1629 
1630  /* connection */
1631 
1632  case h_matching_connection:
1633  parser->index++;
1634  if (parser->index > sizeof(CROW_CONNECTION)-1
1635  || c != CROW_CONNECTION[parser->index]) {
1636  parser->header_state = h_general;
1637  } else if (parser->index == sizeof(CROW_CONNECTION)-2) {
1638  parser->header_state = h_connection;
1639  }
1640  break;
1641 
1642  /* proxy-connection */
1643 
1645  parser->index++;
1646  if (parser->index > sizeof(CROW_PROXY_CONNECTION)-1
1647  || c != CROW_PROXY_CONNECTION[parser->index]) {
1648  parser->header_state = h_general;
1649  } else if (parser->index == sizeof(CROW_PROXY_CONNECTION)-2) {
1650  parser->header_state = h_connection;
1651  }
1652  break;
1653 
1654  /* content-length */
1655 
1657  parser->index++;
1658  if (parser->index > sizeof(CROW_CONTENT_LENGTH)-1
1659  || c != CROW_CONTENT_LENGTH[parser->index]) {
1660  parser->header_state = h_general;
1661  } else if (parser->index == sizeof(CROW_CONTENT_LENGTH)-2) {
1662  parser->header_state = h_content_length;
1663  }
1664  break;
1665 
1666  /* transfer-encoding */
1667 
1669  parser->index++;
1670  if (parser->index > sizeof(CROW_TRANSFER_ENCODING)-1
1671  || c != CROW_TRANSFER_ENCODING[parser->index]) {
1672  parser->header_state = h_general;
1673  } else if (parser->index == sizeof(CROW_TRANSFER_ENCODING)-2) {
1675  }
1676  break;
1677 
1678  /* upgrade */
1679 
1680  case h_matching_upgrade:
1681  parser->index++;
1682  if (parser->index > sizeof(CROW_UPGRADE)-1
1683  || c != CROW_UPGRADE[parser->index]) {
1684  parser->header_state = h_general;
1685  } else if (parser->index == sizeof(CROW_UPGRADE)-2) {
1686  parser->header_state = h_upgrade;
1687  }
1688  break;
1689 
1690  case h_connection:
1691  case h_content_length:
1692  case h_transfer_encoding:
1693  case h_upgrade:
1694  if (ch != ' ') parser->header_state = h_general;
1695  break;
1696 
1697  default:
1698  assert(0 && "Unknown header_state");
1699  break;
1700  }
1701  break;
1702  }
1703 
1704  if (ch == ':') {
1705  parser->state = s_header_value_discard_ws;
1706  CROW_CALLBACK_DATA(header_field);
1707  break;
1708  }
1709 
1710  if (ch == CROW_CR) {
1711  parser->state = s_header_almost_done;
1712  CROW_CALLBACK_DATA(header_field);
1713  break;
1714  }
1715 
1716  if (ch == CROW_LF) {
1717  parser->state = s_header_field_start;
1718  CROW_CALLBACK_DATA(header_field);
1719  break;
1720  }
1721 
1722  CROW_SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1723  goto error;
1724  }
1725 
1727  if (ch == ' ' || ch == '\t') break;
1728 
1729  if (ch == CROW_CR) {
1731  break;
1732  }
1733 
1734  if (ch == CROW_LF) {
1736  break;
1737  }
1738 
1739  /* FALLTHROUGH */
1740 
1741  case s_header_value_start:
1742  {
1743  CROW_MARK(header_value);
1744 
1745  parser->state = s_header_value;
1746  parser->index = 0;
1747 
1748  c = CROW_LOWER(ch);
1749 
1750  switch (parser->header_state) {
1751  case h_upgrade:
1752  parser->flags |= F_UPGRADE;
1753  parser->header_state = h_general;
1754  break;
1755 
1756  case h_transfer_encoding:
1757  /* looking for 'Transfer-Encoding: chunked' */
1758  if ('c' == c) {
1760  } else {
1761  parser->header_state = h_general;
1762  }
1763  break;
1764 
1765  case h_content_length:
1766  if (!CROW_IS_NUM(ch)) {
1767  CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1768  goto error;
1769  }
1770 
1771  parser->content_length = ch - '0';
1772  break;
1773 
1774  case h_connection:
1775  /* looking for 'Connection: keep-alive' */
1776  if (c == 'k') {
1778  /* looking for 'Connection: close' */
1779  } else if (c == 'c') {
1781  } else {
1782  parser->header_state = h_general;
1783  }
1784  break;
1785 
1786  default:
1787  parser->header_state = h_general;
1788  break;
1789  }
1790  break;
1791  }
1792 
1793  case s_header_value:
1794  {
1795 
1796  if (ch == CROW_CR) {
1797  parser->state = s_header_almost_done;
1798  CROW_CALLBACK_DATA(header_value);
1799  break;
1800  }
1801 
1802  if (ch == CROW_LF) {
1803  parser->state = s_header_almost_done;
1804  CROW_CALLBACK_DATA_NOADVANCE(header_value);
1805  goto reexecute_byte;
1806  }
1807 
1808  c = CROW_LOWER(ch);
1809 
1810  switch (parser->header_state) {
1811  case h_general:
1812  break;
1813 
1814  case h_connection:
1815  case h_transfer_encoding:
1816  assert(0 && "Shouldn't get here.");
1817  break;
1818 
1819  case h_content_length:
1820  {
1821  uint64_t t;
1822 
1823  if (ch == ' ') break;
1824 
1825  if (!CROW_IS_NUM(ch)) {
1826  CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1827  goto error;
1828  }
1829 
1830  t = parser->content_length;
1831  t *= 10;
1832  t += ch - '0';
1833 
1834  /* Overflow? Test against a conservative limit for simplicity. */
1835  if ((CROW_ULLONG_MAX - 10) / 10 < parser->content_length) {
1836  CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1837  goto error;
1838  }
1839 
1840  parser->content_length = t;
1841  break;
1842  }
1843 
1844  /* Transfer-Encoding: chunked */
1846  parser->index++;
1847  if (parser->index > sizeof(CROW_CHUNKED)-1
1848  || c != CROW_CHUNKED[parser->index]) {
1849  parser->header_state = h_general;
1850  } else if (parser->index == sizeof(CROW_CHUNKED)-2) {
1852  }
1853  break;
1854 
1855  /* looking for 'Connection: keep-alive' */
1857  parser->index++;
1858  if (parser->index > sizeof(CROW_KEEP_ALIVE)-1
1859  || c != CROW_KEEP_ALIVE[parser->index]) {
1860  parser->header_state = h_general;
1861  } else if (parser->index == sizeof(CROW_KEEP_ALIVE)-2) {
1863  }
1864  break;
1865 
1866  /* looking for 'Connection: close' */
1868  parser->index++;
1869  if (parser->index > sizeof(CROW_CLOSE)-1 || c != CROW_CLOSE[parser->index]) {
1870  parser->header_state = h_general;
1871  } else if (parser->index == sizeof(CROW_CLOSE)-2) {
1872  parser->header_state = h_connection_close;
1873  }
1874  break;
1875 
1878  case h_connection_close:
1879  if (ch != ' ') parser->header_state = h_general;
1880  break;
1881 
1882  default:
1883  parser->state = s_header_value;
1884  parser->header_state = h_general;
1885  break;
1886  }
1887  break;
1888  }
1889 
1890  case s_header_almost_done:
1891  {
1892  CROW_STRICT_CHECK(ch != CROW_LF);
1893 
1894  parser->state = s_header_value_lws;
1895  break;
1896  }
1897 
1898  case s_header_value_lws:
1899  {
1900  if (ch == ' ' || ch == '\t') {
1901  parser->state = s_header_value_start;
1902  goto reexecute_byte;
1903  }
1904 
1905  /* finished the header */
1906  switch (parser->header_state) {
1908  parser->flags |= F_CONNECTION_KEEP_ALIVE;
1909  break;
1910  case h_connection_close:
1911  parser->flags |= F_CONNECTION_CLOSE;
1912  break;
1914  parser->flags |= F_CHUNKED;
1915  break;
1916  default:
1917  break;
1918  }
1919 
1920  parser->state = s_header_field_start;
1921  goto reexecute_byte;
1922  }
1923 
1925  {
1926  CROW_STRICT_CHECK(ch != CROW_LF);
1928  break;
1929  }
1930 
1932  {
1933  if (ch == ' ' || ch == '\t') {
1934  parser->state = s_header_value_discard_ws;
1935  break;
1936  } else {
1937  /* header value was empty */
1938  CROW_MARK(header_value);
1939  parser->state = s_header_field_start;
1940  CROW_CALLBACK_DATA_NOADVANCE(header_value);
1941  goto reexecute_byte;
1942  }
1943  }
1944 
1945  case s_headers_almost_done:
1946  {
1947  CROW_STRICT_CHECK(ch != CROW_LF);
1948 
1949  if (parser->flags & F_TRAILING) {
1950  /* End of a chunked request */
1951  parser->state = CROW_NEW_MESSAGE();
1952  CROW_CALLBACK_NOTIFY(message_complete);
1953  break;
1954  }
1955 
1956  parser->state = s_headers_done;
1957 
1958  /* Set this here so that on_headers_complete() callbacks can see it */
1959  parser->upgrade =
1960  (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT);
1961 
1962  /* Here we call the headers_complete callback. This is somewhat
1963  * different than other callbacks because if the user returns 1, we
1964  * will interpret that as saying that this message has no body. This
1965  * is needed for the annoying case of recieving a response to a HEAD
1966  * request.
1967  *
1968  * We'd like to use CROW_CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1969  * we have to simulate it by handling a change in errno below.
1970  */
1971  if (settings->on_headers_complete) {
1972  switch (settings->on_headers_complete(parser)) {
1973  case 0:
1974  break;
1975 
1976  case 1:
1977  parser->flags |= F_SKIPBODY;
1978  break;
1979 
1980  default:
1981  CROW_SET_ERRNO(HPE_CB_headers_complete);
1982  return p - data; /* Error */
1983  }
1984  }
1985 
1986  if (CROW_HTTP_PARSER_ERRNO(parser) != HPE_OK) {
1987  return p - data;
1988  }
1989 
1990  goto reexecute_byte;
1991  }
1992 
1993  case s_headers_done:
1994  {
1995  CROW_STRICT_CHECK(ch != CROW_LF);
1996 
1997  parser->nread = 0;
1998 
1999  /* Exit, the rest of the connect is in a different protocol. */
2000  if (parser->upgrade) {
2001  parser->state = CROW_NEW_MESSAGE();
2002  CROW_CALLBACK_NOTIFY(message_complete);
2003  return (p - data) + 1;
2004  }
2005 
2006  if (parser->flags & F_SKIPBODY) {
2007  parser->state = CROW_NEW_MESSAGE();
2008  CROW_CALLBACK_NOTIFY(message_complete);
2009  } else if (parser->flags & F_CHUNKED) {
2010  /* chunked encoding - ignore Content-Length header */
2011  parser->state = s_chunk_size_start;
2012  } else {
2013  if (parser->content_length == 0) {
2014  /* Content-Length header given but zero: Content-Length: 0\r\n */
2015  parser->state = CROW_NEW_MESSAGE();
2016  CROW_CALLBACK_NOTIFY(message_complete);
2017  } else if (parser->content_length != CROW_ULLONG_MAX) {
2018  /* Content-Length header given and non-zero */
2019  parser->state = s_body_identity;
2020  } else {
2021  if (parser->type == HTTP_REQUEST ||
2022  !http_message_needs_eof(parser)) {
2023  /* Assume content-length 0 - read the next */
2024  parser->state = CROW_NEW_MESSAGE();
2025  CROW_CALLBACK_NOTIFY(message_complete);
2026  } else {
2027  /* Read body until EOF */
2028  parser->state = s_body_identity_eof;
2029  }
2030  }
2031  }
2032 
2033  break;
2034  }
2035 
2036  case s_body_identity:
2037  {
2038  uint64_t to_read = CROW_MIN(parser->content_length,
2039  (uint64_t) ((data + len) - p));
2040 
2041  assert(parser->content_length != 0
2042  && parser->content_length != CROW_ULLONG_MAX);
2043 
2044  /* The difference between advancing content_length and p is because
2045  * the latter will automaticaly advance on the next loop iteration.
2046  * Further, if content_length ends up at 0, we want to see the last
2047  * byte again for our message complete callback.
2048  */
2049  CROW_MARK(body);
2050  parser->content_length -= to_read;
2051  p += to_read - 1;
2052 
2053  if (parser->content_length == 0) {
2054  parser->state = s_message_done;
2055 
2056  /* Mimic CROW_CALLBACK_DATA_NOADVANCE() but with one extra byte.
2057  *
2058  * The alternative to doing this is to wait for the next byte to
2059  * trigger the data callback, just as in every other case. The
2060  * problem with this is that this makes it difficult for the test
2061  * harness to distinguish between complete-on-EOF and
2062  * complete-on-length. It's not clear that this distinction is
2063  * important for applications, but let's keep it for now.
2064  */
2065  CROW_CALLBACK_DATA_(body, p - body_mark + 1, p - data);
2066  goto reexecute_byte;
2067  }
2068 
2069  break;
2070  }
2071 
2072  /* read until EOF */
2073  case s_body_identity_eof:
2074  CROW_MARK(body);
2075  p = data + len - 1;
2076 
2077  break;
2078 
2079  case s_message_done:
2080  parser->state = CROW_NEW_MESSAGE();
2081  CROW_CALLBACK_NOTIFY(message_complete);
2082  break;
2083 
2084  case s_chunk_size_start:
2085  {
2086  assert(parser->nread == 1);
2087  assert(parser->flags & F_CHUNKED);
2088 
2089  unhex_val = unhex[(unsigned char)ch];
2090  if (unhex_val == -1) {
2091  CROW_SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
2092  goto error;
2093  }
2094 
2095  parser->content_length = unhex_val;
2096  parser->state = s_chunk_size;
2097  break;
2098  }
2099 
2100  case s_chunk_size:
2101  {
2102  uint64_t t;
2103 
2104  assert(parser->flags & F_CHUNKED);
2105 
2106  if (ch == CROW_CR) {
2107  parser->state = s_chunk_size_almost_done;
2108  break;
2109  }
2110 
2111  unhex_val = unhex[(unsigned char)ch];
2112 
2113  if (unhex_val == -1) {
2114  if (ch == ';' || ch == ' ') {
2115  parser->state = s_chunk_parameters;
2116  break;
2117  }
2118 
2119  CROW_SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
2120  goto error;
2121  }
2122 
2123  t = parser->content_length;
2124  t *= 16;
2125  t += unhex_val;
2126 
2127  /* Overflow? Test against a conservative limit for simplicity. */
2128  if ((CROW_ULLONG_MAX - 16) / 16 < parser->content_length) {
2129  CROW_SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
2130  goto error;
2131  }
2132 
2133  parser->content_length = t;
2134  break;
2135  }
2136 
2137  case s_chunk_parameters:
2138  {
2139  assert(parser->flags & F_CHUNKED);
2140  /* just ignore this shit. TODO check for overflow */
2141  if (ch == CROW_CR) {
2142  parser->state = s_chunk_size_almost_done;
2143  break;
2144  }
2145  break;
2146  }
2147 
2149  {
2150  assert(parser->flags & F_CHUNKED);
2151  CROW_STRICT_CHECK(ch != CROW_LF);
2152 
2153  parser->nread = 0;
2154 
2155  if (parser->content_length == 0) {
2156  parser->flags |= F_TRAILING;
2157  parser->state = s_header_field_start;
2158  } else {
2159  parser->state = s_chunk_data;
2160  }
2161  break;
2162  }
2163 
2164  case s_chunk_data:
2165  {
2166  uint64_t to_read = CROW_MIN(parser->content_length,
2167  (uint64_t) ((data + len) - p));
2168 
2169  assert(parser->flags & F_CHUNKED);
2170  assert(parser->content_length != 0
2171  && parser->content_length != CROW_ULLONG_MAX);
2172 
2173  /* See the explanation in s_body_identity for why the content
2174  * length and data pointers are managed this way.
2175  */
2176  CROW_MARK(body);
2177  parser->content_length -= to_read;
2178  p += to_read - 1;
2179 
2180  if (parser->content_length == 0) {
2181  parser->state = s_chunk_data_almost_done;
2182  }
2183 
2184  break;
2185  }
2186 
2188  assert(parser->flags & F_CHUNKED);
2189  assert(parser->content_length == 0);
2190  CROW_STRICT_CHECK(ch != CROW_CR);
2191  parser->state = s_chunk_data_done;
2192  CROW_CALLBACK_DATA(body);
2193  break;
2194 
2195  case s_chunk_data_done:
2196  assert(parser->flags & F_CHUNKED);
2197  CROW_STRICT_CHECK(ch != CROW_LF);
2198  parser->nread = 0;
2199  parser->state = s_chunk_size_start;
2200  break;
2201 
2202  default:
2203  assert(0 && "unhandled state");
2204  CROW_SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
2205  goto error;
2206  }
2207  }
2208 
2209  /* Run callbacks for any marks that we have leftover after we ran our of
2210  * bytes. There should be at most one of these set, so it's OK to invoke
2211  * them in series (unset marks will not result in callbacks).
2212  *
2213  * We use the NOADVANCE() variety of callbacks here because 'p' has already
2214  * overflowed 'data' and this allows us to correct for the off-by-one that
2215  * we'd otherwise have (since CROW_CALLBACK_DATA() is meant to be run with a 'p'
2216  * value that's in-bounds).
2217  */
2218 
2219  assert(((header_field_mark ? 1 : 0) +
2220  (header_value_mark ? 1 : 0) +
2221  (url_mark ? 1 : 0) +
2222  (body_mark ? 1 : 0) +
2223  (status_mark ? 1 : 0)) <= 1);
2224 
2225  CROW_CALLBACK_DATA_NOADVANCE(header_field);
2226  CROW_CALLBACK_DATA_NOADVANCE(header_value);
2230 
2231  return len;
2232 
2233 error:
2234  if (CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2235  CROW_SET_ERRNO(HPE_UNKNOWN);
2236  }
2237 
2238  return (p - data);
2239 }
2240 
2241 
2242 /* Does the parser need to see an EOF to find the end of the message? */
2243 inline int
2245 {
2246  if (parser->type == HTTP_REQUEST) {
2247  return 0;
2248  }
2249 
2250  /* See RFC 2616 section 4.4 */
2251  if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
2252  parser->status_code == 204 || /* No Content */
2253  parser->status_code == 304 || /* Not Modified */
2254  parser->flags & F_SKIPBODY) { /* response to a HEAD request */
2255  return 0;
2256  }
2257 
2258  if ((parser->flags & F_CHUNKED) || parser->content_length != CROW_ULLONG_MAX) {
2259  return 0;
2260  }
2261 
2262  return 1;
2263 }
2264 
2265 
2266 inline int
2268 {
2269  if (parser->http_major > 0 && parser->http_minor > 0) {
2270  /* HTTP/1.1 */
2271  if (parser->flags & F_CONNECTION_CLOSE) {
2272  return 0;
2273  }
2274  } else {
2275  /* HTTP/1.0 or earlier */
2276  if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2277  return 0;
2278  }
2279  }
2280 
2281  return !http_message_needs_eof(parser);
2282 }
2283 
2284 
2285 inline const char *
2287 {
2288 static const char *method_strings[] =
2289  {
2290 #define CROW_XX(num, name, string) #string,
2292 #undef CROW_XX
2293  };
2294  return CROW_ELEM_AT(method_strings, m, "<unknown>");
2295 }
2296 
2297 
2298 inline void
2300 {
2301  void *data = parser->data; /* preserve application data */
2302  memset(parser, 0, sizeof(*parser));
2303  parser->data = data;
2304  parser->type = t;
2306  parser->http_errno = HPE_OK;
2307 }
2308 
2309 inline const char *
2311 /* Map errno values to strings for human-readable output */
2312 #define CROW_HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
2313 static struct {
2314  const char *name;
2315  const char *description;
2316 } http_strerror_tab[] = {
2318 };
2319 #undef CROW_HTTP_STRERROR_GEN
2320  assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));
2321  return http_strerror_tab[err].name;
2322 }
2323 
2324 inline const char *
2326 /* Map errno values to strings for human-readable output */
2327 #define CROW_HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
2328 static struct {
2329  const char *name;
2330  const char *description;
2331 } http_strerror_tab[] = {
2333 };
2334 #undef CROW_HTTP_STRERROR_GEN
2335  assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));
2336  return http_strerror_tab[err].description;
2337 }
2338 
2339 inline static enum http_host_state
2341  switch(s) {
2342  case s_http_userinfo:
2343  case s_http_userinfo_start:
2344  if (ch == '@') {
2345  return s_http_host_start;
2346  }
2347 
2348  if (CROW_IS_USERINFO_CHAR(ch)) {
2349  return s_http_userinfo;
2350  }
2351  break;
2352 
2353  case s_http_host_start:
2354  if (ch == '[') {
2355  return s_http_host_v6_start;
2356  }
2357 
2358  if (CROW_IS_HOST_CHAR(ch)) {
2359  return s_http_host;
2360  }
2361 
2362  break;
2363 
2364  case s_http_host:
2365  if (CROW_IS_HOST_CHAR(ch)) {
2366  return s_http_host;
2367  }
2368 
2369  /* FALLTHROUGH */
2370  case s_http_host_v6_end:
2371  if (ch == ':') {
2372  return s_http_host_port_start;
2373  }
2374 
2375  break;
2376 
2377  case s_http_host_v6:
2378  if (ch == ']') {
2379  return s_http_host_v6_end;
2380  }
2381 
2382  /* FALLTHROUGH */
2383  case s_http_host_v6_start:
2384  if (CROW_IS_HEX(ch) || ch == ':' || ch == '.') {
2385  return s_http_host_v6;
2386  }
2387 
2388  break;
2389 
2390  case s_http_host_port:
2392  if (CROW_IS_NUM(ch)) {
2393  return s_http_host_port;
2394  }
2395 
2396  break;
2397 
2398  default:
2399  break;
2400  }
2401  return s_http_host_dead;
2402 }
2403 
2404 inline int
2405 http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
2406  enum http_host_state s;
2407 
2408  const char *p;
2409  size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
2410 
2411  u->field_data[UF_HOST].len = 0;
2412 
2413  s = found_at ? s_http_userinfo_start : s_http_host_start;
2414 
2415  for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
2416  enum http_host_state new_s = http_parse_host_char(s, *p);
2417 
2418  if (new_s == s_http_host_dead) {
2419  return 1;
2420  }
2421 
2422  switch(new_s) {
2423  case s_http_host:
2424  if (s != s_http_host) {
2425  u->field_data[UF_HOST].off = p - buf;
2426  }
2427  u->field_data[UF_HOST].len++;
2428  break;
2429 
2430  case s_http_host_v6:
2431  if (s != s_http_host_v6) {
2432  u->field_data[UF_HOST].off = p - buf;
2433  }
2434  u->field_data[UF_HOST].len++;
2435  break;
2436 
2437  case s_http_host_port:
2438  if (s != s_http_host_port) {
2439  u->field_data[UF_PORT].off = p - buf;
2440  u->field_data[UF_PORT].len = 0;
2441  u->field_set |= (1 << UF_PORT);
2442  }
2443  u->field_data[UF_PORT].len++;
2444  break;
2445 
2446  case s_http_userinfo:
2447  if (s != s_http_userinfo) {
2448  u->field_data[UF_USERINFO].off = p - buf ;
2449  u->field_data[UF_USERINFO].len = 0;
2450  u->field_set |= (1 << UF_USERINFO);
2451  }
2452  u->field_data[UF_USERINFO].len++;
2453  break;
2454 
2455  default:
2456  break;
2457  }
2458  s = new_s;
2459  }
2460 
2461  /* Make sure we don't end somewhere unexpected */
2462  switch (s) {
2463  case s_http_host_start:
2464  case s_http_host_v6_start:
2465  case s_http_host_v6:
2467  case s_http_userinfo:
2468  case s_http_userinfo_start:
2469  return 1;
2470  default:
2471  break;
2472  }
2473 
2474  return 0;
2475 }
2476 
2477 inline int
2478 http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2479  struct http_parser_url *u)
2480 {
2481  enum state s;
2482  const char *p;
2483  enum http_parser_url_fields uf, old_uf;
2484  int found_at = 0;
2485 
2486  u->port = u->field_set = 0;
2487  s = is_connect ? s_req_server_start : s_req_spaces_before_url;
2488  old_uf = UF_MAX;
2489 
2490  for (p = buf; p < buf + buflen; p++) {
2491  s = parse_url_char(s, *p);
2492 
2493  /* Figure out the next field that we're operating on */
2494  switch (s) {
2495  case s_dead:
2496  return 1;
2497 
2498  /* Skip delimeters */
2499  case s_req_schema_slash:
2501  case s_req_server_start:
2503  case s_req_fragment_start:
2504  continue;
2505 
2506  case s_req_schema:
2507  uf = UF_SCHEMA;
2508  break;
2509 
2510  case s_req_server_with_at:
2511  found_at = 1;
2512 
2513  /* FALLTROUGH */
2514  case s_req_server:
2515  uf = UF_HOST;
2516  break;
2517 
2518  case s_req_path:
2519  uf = UF_PATH;
2520  break;
2521 
2522  case s_req_query_string:
2523  uf = UF_QUERY;
2524  break;
2525 
2526  case s_req_fragment:
2527  uf = UF_FRAGMENT;
2528  break;
2529 
2530  default:
2531  assert(!"Unexpected state");
2532  return 1;
2533  }
2534 
2535  /* Nothing's changed; soldier on */
2536  if (uf == old_uf) {
2537  u->field_data[uf].len++;
2538  continue;
2539  }
2540 
2541  u->field_data[uf].off = p - buf;
2542  u->field_data[uf].len = 1;
2543 
2544  u->field_set |= (1 << uf);
2545  old_uf = uf;
2546  }
2547 
2548  /* host must be present if there is a schema */
2549  /* parsing http:///toto will fail */
2550  if ((u->field_set & ((1 << UF_SCHEMA) | (1 << UF_HOST))) != 0) {
2551  if (http_parse_host(buf, u, found_at) != 0) {
2552  return 1;
2553  }
2554  }
2555 
2556  /* CONNECT requests can only contain "hostname:port" */
2557  if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
2558  return 1;
2559  }
2560 
2561  if (u->field_set & (1 << UF_PORT)) {
2562  /* Don't bother with endp; we've already validated the string */
2563  unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
2564 
2565  /* Ports have a max value of 2^16 */
2566  if (v > 0xffff) {
2567  return 1;
2568  }
2569 
2570  u->port = (uint16_t) v;
2571  }
2572 
2573  return 0;
2574 }
2575 
2576 inline void
2577 http_parser_pause(http_parser *parser, int paused) {
2578  /* Users should only be pausing/unpausing a parser that is not in an error
2579  * state. In non-debug builds, there's not much that we can do about this
2580  * other than ignore it.
2581  */
2582  if (CROW_HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2583  CROW_HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2584  CROW_SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2585  } else {
2586  assert(0 && "Attempting to pause parser in error state");
2587  }
2588 }
2589 
2590 inline int
2591 http_body_is_final(const struct http_parser *parser) {
2592  return parser->state == s_message_done;
2593 }
2594 
2595 inline unsigned long
2597  return CROW_HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2598  CROW_HTTP_PARSER_VERSION_MINOR * 0x00100 |
2600 }
2601 
2602 #undef CROW_HTTP_METHOD_MAP
2603 #undef CROW_HTTP_ERRNO_MAP
2604 #undef CROW_SET_ERRNO
2605 #undef CROW_CALLBACK_NOTIFY_
2606 #undef CROW_CALLBACK_NOTIFY
2607 #undef CROW_CALLBACK_NOTIFY_NOADVANCE
2608 #undef CROW_CALLBACK_DATA_
2609 #undef CROW_CALLBACK_DATA
2610 #undef CROW_CALLBACK_DATA_NOADVANCE
2611 #undef CROW_MARK
2612 #undef CROW_PROXY_CONNECTION
2613 #undef CROW_CONNECTION
2614 #undef CROW_CONTENT_LENGTH
2615 #undef CROW_TRANSFER_ENCODING
2616 #undef CROW_UPGRADE
2617 #undef CROW_CHUNKED
2618 #undef CROW_KEEP_ALIVE
2619 #undef CROW_CLOSE
2620 #undef CROW_PARSING_HEADER
2621 #undef CROW_CR
2622 #undef CROW_LF
2623 #undef CROW_LOWER
2624 #undef CROW_IS_ALPHA
2625 #undef CROW_IS_NUM
2626 #undef CROW_IS_ALPHANUM
2627 #undef CROW_IS_HEX
2628 #undef CROW_IS_MARK
2629 #undef CROW_IS_USERINFO_CHAR
2630 #undef CROW_TOKEN
2631 #undef CROW_IS_URL_CHAR
2632 #undef CROW_IS_HOST_CHAR
2633 #undef CROW_start_state
2634 #undef CROW_STRICT_CHECK
2635 #undef CROW_NEW_MESSAGE
2636 
2637 #ifdef __cplusplus
2638 }
2639 #endif
2640 #endif
Definition: http_parser_merged.h:253
Definition: http_parser_merged.h:509
Definition: http_parser_merged.h:139
Definition: http_parser_merged.h:496
#define CROW_CONNECTION
Definition: http_parser_merged.h:445
Definition: http_parser_merged.h:568
Definition: http_parser_merged.h:574
uint32_t nread
Definition: http_parser_merged.h:212
Definition: http_parser_merged.h:464
Definition: http_parser_merged.h:250
int(* http_cb)(http_parser *)
Definition: http_parser_merged.h:85
Definition: http_parser_merged.h:515
Definition: http_parser_merged.h:519
http_errno
Definition: http_parser_merged.h:194
Definition: http_parser_merged.h:204
#define CROW_STRICT_CHECK(cond)
Definition: http_parser_merged.h:612
struct http_parser_url::@13 field_data[UF_MAX]
unsigned int method
Definition: http_parser_merged.h:219
#define CROW_HTTP_ERRNO_GEN(n, s)
Definition: http_parser_merged.h:193
Definition: http_parser_merged.h:553
Definition: http_parser_merged.h:252
Definition: http_parser_merged.h:248
http_data_cb on_header_field
Definition: http_parser_merged.h:238
#define CROW_HTTP_PARSER_ERRNO(p)
Definition: http_parser_merged.h:201
Definition: http_parser_merged.h:487
http_cb on_headers_complete
Definition: http_parser_merged.h:240
#define CROW_TRANSFER_ENCODING
Definition: http_parser_merged.h:447
unsigned short http_minor
Definition: http_parser_merged.h:217
Definition: http_parser_merged.h:471
http_host_state
Definition: http_parser_merged.h:566
Definition: http_parser_merged.h:465
Definition: http_parser_merged.h:478
Definition: http_parser_merged.h:506
Definition: http_parser_merged.h:493
Definition: http_parser_merged.h:505
#define CROW_IS_USERINFO_CHAR(c)
Definition: http_parser_merged.h:591
#define CROW_KEEP_ALIVE
Definition: http_parser_merged.h:450
void http_parser_pause(http_parser *parser, int paused)
Definition: http_parser_merged.h:2577
#define CROW_HTTP_PARSER_VERSION_PATCH
Definition: http_parser_merged.h:31
uint16_t len
Definition: http_parser_merged.h:271
#define CROW_CHUNKED
Definition: http_parser_merged.h:449
#define CROW_PARSING_HEADER(state)
Definition: http_parser_merged.h:537
Definition: http_parser_merged.h:459
unsigned int state
Definition: http_parser_merged.h:208
Definition: http_parser_merged.h:554
#define CROW_HTTP_MAX_HEADER_SIZE
Definition: http_parser_merged.h:64
uint16_t field_set
Definition: http_parser_merged.h:266
Definition: http_parser_merged.h:573
#define CROW_HTTP_METHOD_MAP(CROW_XX)
Definition: http_parser_merged.h:89
#define CROW_CLOSE
Definition: http_parser_merged.h:451
#define CROW_CALLBACK_NOTIFY_NOADVANCE(FOR)
Definition: http_parser_merged.h:405
Definition: http_parser_merged.h:132
Definition: http_parser_merged.h:570
Definition: http_parser_merged.h:527
#define CROW_UPGRADE
Definition: http_parser_merged.h:448
Definition: http_parser_merged.h:499
Definition: http_parser_merged.h:546
Definition: http_parser_merged.h:500
Definition: http_parser_merged.h:497
http_data_cb on_body
Definition: http_parser_merged.h:241
unsigned int status_code
Definition: http_parser_merged.h:218
Definition: http_parser_merged.h:550
const char * http_method_str(enum http_method m)
Definition: http_parser_merged.h:2286
Definition: http_parser_merged.h:503
unsigned int header_state
Definition: http_parser_merged.h:209
http_data_cb on_url
Definition: http_parser_merged.h:236
unsigned int index
Definition: http_parser_merged.h:210
flags
Definition: http_parser_merged.h:136
Definition: http_parser_merged.h:557
Definition: http_parser_merged.h:481
#define CROW_ULLONG_MAX
Definition: http_parser_merged.h:357
#define CROW_IS_URL_CHAR(c)
Definition: http_parser_merged.h:597
const char * http_errno_name(enum http_errno err)
Definition: http_parser_merged.h:2310
unsigned int flags
Definition: http_parser_merged.h:207
#define CROW_NEW_MESSAGE()
Definition: http_parser_merged.h:619
Definition: http_parser_merged.h:254
Definition: http_parser_merged.h:575
Definition: http_parser_merged.h:474
Definition: http_parser_merged.h:249
#define CROW_LF
Definition: http_parser_merged.h:582
header_states
Definition: http_parser_merged.h:540
Definition: http_parser_merged.h:467
Definition: http_parser_merged.h:142
Definition: http_parser_merged.h:547
Definition: http_parser_merged.h:491
#define CROW_HTTP_PARSER_VERSION_MINOR
Definition: http_parser_merged.h:30
Definition: http_parser_merged.h:572
Definition: http_parser_merged.h:234
Definition: http_parser_merged.h:490
Definition: http_parser_merged.h:576
#define CROW_PROXY_CONNECTION
Definition: http_parser_merged.h:444
int http_body_is_final(const http_parser *parser)
Definition: http_parser_merged.h:484
#define CROW_HTTP_PARSER_VERSION_MAJOR
Definition: http_parser_merged.h:29
int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u)
Definition: http_parser_merged.h:2478
Definition: http_parser_merged.h:247
Definition: http_parser_merged.h:549
Definition: http_parser_merged.h:251
const char * http_errno_description(enum http_errno err)
Definition: http_parser_merged.h:2325
Definition: http_parser_merged.h:561
uint64_t content_length
Definition: http_parser_merged.h:213
int(* http_data_cb)(http_parser *, const char *at, size_t length)
Definition: http_parser_merged.h:84
http_parser_url_fields
Definition: http_parser_merged.h:246
#define CROW_HTTP_STRERROR_GEN(n, s)
http_data_cb on_status
Definition: http_parser_merged.h:237
Definition: http_parser_merged.h:472
#define CROW_CALLBACK_DATA(FOR)
Definition: http_parser_merged.h:428
Definition: http_parser_merged.h:479
Definition: http_parser_merged.h:563
#define CROW_HTTP_ERRNO_MAP(CROW_XX)
Definition: http_parser_merged.h:150
size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len)
Definition: http_parser_merged.h:831
unsigned int http_errno
Definition: http_parser_merged.h:220
Definition: http_parser_merged.h:552
Definition: http_parser_merged.h:548
Definition: http_parser_merged.h:492
Definition: http_parser_merged.h:569
Definition: http_parser_merged.h:488
Definition: http_parser_merged.h:559
unsigned short http_major
Definition: http_parser_merged.h:216
Definition: http_parser_merged.h:513
Definition: http_parser_merged.h:480
http_method
Definition: http_parser_merged.h:124
Definition: http_parser_merged.h:508
int http_should_keep_alive(const http_parser *parser)
Definition: http_parser_merged.h:2267
#define CROW_ELEM_AT(a, i, v)
Definition: http_parser_merged.h:375
static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch)
Definition: http_parser_merged.h:2340
Definition: http_parser_merged.h:132
#define CROW_CR
Definition: http_parser_merged.h:581
unsigned long http_parser_version(void)
Definition: http_parser_merged.h:2596
Definition: http_parser_merged.h:511
type
Definition: json.h:74
#define CROW_IS_HOST_CHAR(c)
Definition: http_parser_merged.h:598
#define CROW_SET_ERRNO(e)
Definition: http_parser_merged.h:378
Definition: http_parser_merged.h:577
Definition: http_parser_merged.h:469
#define CROW_LOWER(c)
Definition: http_parser_merged.h:583
Definition: http_parser_merged.h:541
Definition: http_parser_merged.h:468
Definition: http_parser_merged.h:543
#define CROW_T(v)
http_data_cb on_header_value
Definition: http_parser_merged.h:239
Definition: http_parser_merged.h:495
Definition: http_parser_merged.h:504
Definition: http_parser_merged.h:476
#define CROW_MIN(a, b)
Definition: http_parser_merged.h:361
int http_message_needs_eof(const http_parser *parser)
Definition: http_parser_merged.h:2244
Definition: http_parser_merged.h:463
Definition: blake256.h:37
Definition: http_parser_merged.h:138
enum state parse_url_char(enum state s, const char ch)
Definition: http_parser_merged.h:641
Definition: http_parser_merged.h:533
#define CROW_TOKEN(c)
Definition: http_parser_merged.h:596
Definition: http_parser_merged.h:571
void * data
Definition: http_parser_merged.h:230
Definition: http_parser_merged.h:502
Definition: http_parser_merged.h:542
#define CROW_XX(num, name, string)
Definition: http_parser_merged.h:126
Definition: http_parser_merged.h:470
Definition: http_parser_merged.h:473
Definition: http_parser_merged.h:486
Definition: http_parser_merged.h:132
uint16_t off
Definition: http_parser_merged.h:270
Definition: http_parser_merged.h:462
#define CROW_IS_ALPHA(c)
Definition: http_parser_merged.h:584
Definition: http_parser_merged.h:558
Definition: http_parser_merged.h:516
#define CROW_MARK(FOR)
Definition: http_parser_merged.h:436
void http_parser_init(http_parser *parser, enum http_parser_type type)
Definition: http_parser_merged.h:2299
unsigned int upgrade
Definition: http_parser_merged.h:227
Definition: http_parser_merged.h:526
Definition: http_parser_merged.h:489
#define CROW_CONTENT_LENGTH
Definition: http_parser_merged.h:446
Definition: http_parser_merged.h:544
Definition: http_parser_merged.h:518
Definition: http_parser_merged.h:514
Definition: http_parser_merged.h:140
http_cb on_message_begin
Definition: http_parser_merged.h:235
#define CROW_CALLBACK_NOTIFY(FOR)
Definition: http_parser_merged.h:402
const char * name
Definition: simplewallet.cpp:180
Definition: http_parser_merged.h:494
uint16_t port
Definition: http_parser_merged.h:267
Definition: http_parser_merged.h:507
Definition: http_parser_merged.h:531
Definition: http_parser_merged.h:498
Definition: http_parser_merged.h:485
Definition: http_parser_merged.h:528
Definition: http_parser_merged.h:483
Definition: http_parser_merged.h:562
Definition: http_parser_merged.h:461
int http_parse_host(const char *buf, struct http_parser_url *u, int found_at)
Definition: http_parser_merged.h:2405
Definition: http_parser_merged.h:482
unsigned int type
Definition: http_parser_merged.h:206
#define CROW_CALLBACK_DATA_NOADVANCE(FOR)
Definition: http_parser_merged.h:432
Definition: http_parser_merged.h:137
#define s(x, c)
Definition: aesb.c:46
http_parser_type
Definition: http_parser_merged.h:132
http_cb on_message_complete
Definition: http_parser_merged.h:242
Definition: http_parser_merged.h:265
Definition: http_parser_merged.h:457
#define CROW_IS_NUM(c)
Definition: http_parser_merged.h:585
#define CROW_IS_HEX(c)
Definition: http_parser_merged.h:587
Definition: http_parser_merged.h:466
Definition: http_parser_merged.h:141
Definition: http_parser_merged.h:460
Definition: http_parser_merged.h:530
#define CROW_CALLBACK_DATA_(FOR, LEN, ER)
Definition: http_parser_merged.h:408
Definition: http_parser_merged.h:555