52 # define ULLONG_MAX ((uint64_t) -1)
56 # define MIN(a,b) ((a) < (b) ? (a) : (b))
60 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
64 # define BIT_AT(a, i) \
65 (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
66 (1 << ((unsigned int) (i) & 7))))
70 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
73 #define SET_ERRNO(e) \
75 parser->http_errno = (e); \
78 #define CURRENT_STATE() p_state
79 #define UPDATE_STATE(V) p_state = (enum state) (V);
82 parser->state = CURRENT_STATE(); \
90 # define LIKELY(X) __builtin_expect(!!(X), 1)
91 # define UNLIKELY(X) __builtin_expect(!!(X), 0)
93 # define LIKELY(X) (X)
94 # define UNLIKELY(X) (X)
99 #define CALLBACK_NOTIFY_(FOR, ER) \
101 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
103 if (LIKELY(settings->on_##FOR)) { \
104 parser->state = CURRENT_STATE(); \
105 if (UNLIKELY(0 != settings->on_##FOR(parser))) { \
106 SET_ERRNO(HPE_CB_##FOR); \
108 UPDATE_STATE(parser->state); \
111 if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
118 #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
121 #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
124 #define CALLBACK_DATA_(FOR, LEN, ER) \
126 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
129 if (LIKELY(settings->on_##FOR)) { \
130 parser->state = CURRENT_STATE(); \
132 settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
133 SET_ERRNO(HPE_CB_##FOR); \
135 UPDATE_STATE(parser->state); \
138 if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \
147 #define CALLBACK_DATA(FOR) \
148 CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
151 #define CALLBACK_DATA_NOADVANCE(FOR) \
152 CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
173 #define COUNT_HEADER_SIZE(V) \
175 parser->nread += (V); \
176 if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \
177 SET_ERRNO(HPE_HEADER_OVERFLOW); \
183 #define PROXY_CONNECTION "proxy-connection"
184 #define CONNECTION "connection"
185 #define CONTENT_LENGTH "content-length"
186 #define TRANSFER_ENCODING "transfer-encoding"
187 #define UPGRADE "upgrade"
188 #define CHUNKED "chunked"
189 #define KEEP_ALIVE "keep-alive"
190 #define CLOSE "close"
195 #define XX(num, name, string) #string,
210 0, 0, 0, 0, 0, 0, 0, 0,
212 0, 0, 0, 0, 0, 0, 0, 0,
214 0, 0, 0, 0, 0, 0, 0, 0,
216 0, 0, 0, 0, 0, 0, 0, 0,
218 0,
'!', 0,
'#',
'$',
'%',
'&',
'\'',
220 0, 0,
'*',
'+', 0,
'-',
'.', 0,
222 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
224 '8',
'9', 0, 0, 0, 0, 0, 0,
226 0,
'a',
'b',
'c',
'd',
'e',
'f',
'g',
228 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
230 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
232 'x',
'y',
'z', 0, 0, 0,
'^',
'_',
234 '`',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
236 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
238 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
240 'x',
'y',
'z', 0,
'|', 0,
'~', 0 };
244 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
245 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
246 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
247 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
248 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
249 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
250 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
251 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
255 #if HTTP_PARSER_STRICT
264 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
266 0 |
T(2) | 0 | 0 |
T(16) | 0 | 0 | 0,
268 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
270 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
272 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
274 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
276 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
278 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
280 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
282 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
284 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
286 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
288 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
290 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
292 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
294 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
379 #define PARSING_HEADER(state) (state <= s_headers_done)
431 #define LOWER(c) (unsigned char)(c | 0x20)
432 #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
433 #define IS_NUM(c) ((c) >= '0' && (c) <= '9')
434 #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
435 #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
436 #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
437 (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
439 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
440 (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
441 (c) == '$' || (c) == ',')
443 #define STRICT_TOKEN(c) (tokens[(unsigned char)c])
445 #if HTTP_PARSER_STRICT
446 #define TOKEN(c) (tokens[(unsigned char)c])
447 #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
448 #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
450 #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
451 #define IS_URL_CHAR(c) \
452 (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
453 #define IS_HOST_CHAR(c) \
454 (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
461 #define IS_HEADER_CHAR(ch) \
462 (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
464 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
467 #if HTTP_PARSER_STRICT
468 # define STRICT_CHECK(cond) \
471 SET_ERRNO(HPE_STRICT); \
475 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
477 # define STRICT_CHECK(cond)
478 # define NEW_MESSAGE() start_state
483 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
490 #undef HTTP_STRERROR_GEN
508 if (ch ==
' ' || ch ==
'\r' || ch ==
'\n') {
512 #if HTTP_PARSER_STRICT
513 if (ch ==
'\t' || ch ==
'\f') {
524 if (ch ==
'/' || ch ==
'*') {
660 const char *p = data;
661 const char *header_field_mark = 0;
662 const char *header_value_mark = 0;
663 const char *url_mark = 0;
664 const char *body_mark = 0;
665 const char *status_mark = 0;
697 header_field_mark = data;
699 header_value_mark = data;
721 for (p=data; p != data + len; p++) {
742 if (ch ==
CR || ch ==
LF)
771 parser->
method = HTTP_HEAD;
913 if (ch ==
CR || ch ==
LF)
941 if (ch ==
CR || ch ==
LF)
954 case 'A': parser->
method = HTTP_ACL;
break;
955 case 'B': parser->
method = HTTP_BIND;
break;
956 case 'C': parser->
method = HTTP_CONNECT;
break;
957 case 'D': parser->
method = HTTP_DELETE;
break;
958 case 'G': parser->
method = HTTP_GET;
break;
959 case 'H': parser->
method = HTTP_HEAD;
break;
960 case 'L': parser->
method = HTTP_LOCK;
break;
961 case 'M': parser->
method = HTTP_MKCOL;
break;
962 case 'N': parser->
method = HTTP_NOTIFY;
break;
963 case 'O': parser->
method = HTTP_OPTIONS;
break;
964 case 'P': parser->
method = HTTP_POST;
967 case 'R': parser->
method = HTTP_REPORT;
break;
968 case 'S': parser->
method = HTTP_SUBSCRIBE;
break;
969 case 'T': parser->
method = HTTP_TRACE;
break;
970 case 'U': parser->
method = HTTP_UNLOCK;
break;
991 if (ch ==
' ' && matcher[parser->
index] ==
'\0') {
993 }
else if (ch == matcher[parser->
index]) {
995 }
else if ((ch >=
'A' && ch <=
'Z') || ch ==
'-') {
997 switch (parser->
method << 16 | parser->
index << 8 | ch) {
998 #define XX(meth, pos, ch, new_meth) \
999 case (HTTP_##meth << 16 | pos << 8 | ch): \
1000 parser->method = HTTP_##new_meth; break;
1002 XX(POST, 1,
'U', PUT)
1003 XX(POST, 1,
'A', PATCH)
1004 XX(POST, 1,
'R', PROPFIND)
1005 XX(PUT, 2,
'R', PURGE)
1006 XX(CONNECT, 1,
'H', CHECKOUT)
1007 XX(CONNECT, 2,
'P', COPY)
1008 XX(MKCOL, 1,
'O', MOVE)
1009 XX(MKCOL, 1,
'E', MERGE)
1010 XX(MKCOL, 1,
'-', MSEARCH)
1011 XX(MKCOL, 2,
'A', MKACTIVITY)
1012 XX(MKCOL, 3,
'A', MKCALENDAR)
1013 XX(SUBSCRIBE, 1,
'E', SEARCH)
1014 XX(REPORT, 2,
'B', REBIND)
1015 XX(PROPFIND, 4,
'P', PROPPATCH)
1016 XX(LOCK, 1,
'I', LINK)
1017 XX(UNLOCK, 2,
'S', UNSUBSCRIBE)
1018 XX(UNLOCK, 2,
'B', UNBIND)
1019 XX(UNLOCK, 3,
'I', UNLINK)
1036 if (ch ==
' ')
break;
1039 if (parser->
method == HTTP_CONNECT) {
1252 const char* start = p;
1253 for (; p != data + len; p++) {
1357 assert(0 &&
"Unknown header_state");
1364 if (p == data + len) {
1380 if (ch ==
' ' || ch ==
'\t')
break;
1438 }
else if (c ==
'c') {
1440 }
else if (c ==
'u') {
1460 const char* start = p;
1462 for (; p != data + len; p++) {
1491 size_t limit = data + len - p;
1495 p_cr = (
const char*) memchr(p,
CR, limit);
1496 p_lf = (
const char*) memchr(p,
LF, limit);
1498 if (p_lf != NULL && p_cr >= p_lf)
1502 }
else if (
UNLIKELY(p_lf != NULL)) {
1514 assert(0 &&
"Shouldn't get here.");
1521 if (ch ==
' ')
break;
1560 }
else if (c ==
'c') {
1562 }
else if (c ==
'u') {
1566 }
else if (c ==
' ' || c ==
'\t') {
1589 }
else if (parser->
index ==
sizeof(
CLOSE)-2) {
1629 }
else if (ch !=
' ') {
1644 if (p == data + len)
1662 if (ch ==
' ' || ch ==
'\t') {
1698 if (ch ==
' ' || ch ==
'\t') {
1845 (uint64_t) ((data + len) - p));
1896 assert(parser->
nread == 1);
1899 unhex_val =
unhex[(
unsigned char)ch];
1921 unhex_val =
unhex[(
unsigned char)ch];
1923 if (unhex_val == -1) {
1924 if (ch ==
';' || ch ==
' ') {
1978 (uint64_t) ((data + len) - p));
2015 assert(0 &&
"unhandled state");
2031 assert(((header_field_mark ? 1 : 0) +
2032 (header_value_mark ? 1 : 0) +
2033 (url_mark ? 1 : 0) +
2034 (body_mark ? 1 : 0) +
2035 (status_mark ? 1 : 0)) <= 1);
2107 void *data = parser->
data;
2108 memset(parser, 0,
sizeof(*parser));
2109 parser->
data = data;
2118 memset(settings, 0,
sizeof(*settings));
2178 if (
IS_HEX(ch) || ch ==
':' || ch ==
'.') {
2195 if (
IS_ALPHANUM(ch) || ch ==
'%' || ch ==
'.' || ch ==
'-' || ch ==
'_' ||
2299 memset(u, 0,
sizeof(*u));
2315 for (p = buf; p < buf + buflen; p++) {
2356 assert(!
"Unexpected state");
2400 u->
port = (uint16_t) v;
2416 assert(0 &&
"Attempting to pause parser in error state");
static const int8_t unhex[256]
static struct @0 http_strerror_tab[]
static const uint8_t normal_url_char[32]
#define HTTP_MAX_HEADER_SIZE
void http_parser_url_init(struct http_parser_url *u)
#define IS_HEADER_CHAR(ch)
Verify that a char is a valid visible (printable) US-ASCII character or x80-FF.
static int http_parse_host(const char *buf, struct http_parser_url *u, int found_at)
#define HTTP_ERRNO_MAP(XX)
#define CALLBACK_NOTIFY_NOADVANCE(FOR)
const char * http_errno_name(enum http_errno err)
#define CALLBACK_DATA_NOADVANCE(FOR)
http_cb on_headers_complete
unsigned short http_minor
#define HTTP_PARSER_VERSION_MAJOR
#define PARSING_HEADER(state)
#define HTTP_METHOD_MAP(XX)
size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len)
#define CALLBACK_DATA(FOR)
void http_parser_settings_init(http_parser_settings *settings)
unsigned int header_state
#define HTTP_PARSER_VERSION_PATCH
#define TRANSFER_ENCODING
#define HTTP_STRERROR_GEN(n, s)
const char * http_method_str(enum http_method m)
unsigned int lenient_http_headers
void http_parser_pause(http_parser *parser, int paused)
#define HTTP_PARSER_ERRNO(p)
static const char * method_strings[]
int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u)
int http_should_keep_alive(const http_parser *parser)
#define HTTP_PARSER_VERSION_MINOR
int http_body_is_final(const struct http_parser *parser)
const char * http_errno_description(enum http_errno err)
unsigned short http_major
READ-ONLY.
#define COUNT_HEADER_SIZE(V)
#define CALLBACK_NOTIFY(FOR)
int http_message_needs_eof(const http_parser *parser)
void http_parser_init(http_parser *parser, enum http_parser_type t)
#define XX(num, name, string)
unsigned long http_parser_version(void)
static enum state parse_url_char(enum state s, const char ch)
#define IS_USERINFO_CHAR(c)
#define STRICT_CHECK(cond)
char * name
Name for the msu type.
#define CALLBACK_DATA_(FOR, LEN, ER)
struct http_parser_url::@1 field_data[UF_MAX]
unsigned int type
PRIVATE.
static const char tokens[256]
static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch)