37 # define INT64_MAX std::numeric_limits<int64_t>::max() 46 # define MIN(a,b) ((a) < (b) ? (a) : (b)) 51 #define SET_ERRNO(e) \ 53 parser->http_errno = (e); \ 54 parser->error_lineno = __LINE__; \ 57 #define SET_ERRNO(e) \ 59 parser->http_errno = (e); \ 65 parser->state = state; \ 70 #define _CALLBACK_NOTIFY(FOR, ER) \ 72 parser->state = state; \ 73 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ 75 if (0 != settings->on_##FOR(parser)) { \ 76 SET_ERRNO(HPE_CB_##FOR); \ 80 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ 86 #define CALLBACK_NOTIFY(FOR) _CALLBACK_NOTIFY(FOR, p - data + 1) 89 #define CALLBACK_NOTIFY_NOADVANCE(FOR) _CALLBACK_NOTIFY(FOR, p - data) 92 #define _CALLBACK_DATA(FOR, LEN, ER) \ 94 parser->state = state; \ 95 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ 98 if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \ 99 SET_ERRNO(HPE_CB_##FOR); \ 103 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ 106 FOR##_mark = nullptr; \ 111 #define CALLBACK_DATA(FOR) \ 112 _CALLBACK_DATA(FOR, p - FOR##_mark, p - data + 1) 115 #define CALLBACK_DATA_NOADVANCE(FOR) \ 116 _CALLBACK_DATA(FOR, p - FOR##_mark, p - data) 119 #define CALLBACK_SPACE(FOR) \ 121 parser->state = state; \ 122 if (0 != settings->on_##FOR(parser, SPACE, 1)) { \ 123 SET_ERRNO(HPE_CB_##FOR); \ 128 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ 142 #define CONTENT_LENGTH "content-length" 143 #define TRANSFER_ENCODING "transfer-encoding" 144 #define UPGRADE "upgrade" 145 #define CHUNKED "chunked" 186 0, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0,
194 0,
'!', 0,
'#',
'$',
'%',
'&',
'\'',
196 0, 0,
'*',
'+', 0,
'-',
'.', 0,
198 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
200 '8',
'9', 0, 0, 0, 0, 0, 0,
202 0,
'a',
'b',
'c',
'd',
'e',
'f',
'g',
204 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
206 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
208 'x',
'y',
'z', 0, 0, 0,
'^',
'_',
210 '`',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
212 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
214 'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
216 'x',
'y',
'z', 0,
'|', 0,
'~', 0 };
220 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
221 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
222 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
223 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
224 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
225 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
226 ,-1,10,11,12,13,14,15,-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
230 #if HTTP_PARSER_STRICT 238 0, 0, 0, 0, 0, 0, 0, 0,
240 0,
T(1), 0, 0,
T(1), 0, 0, 0,
242 0, 0, 0, 0, 0, 0, 0, 0,
244 0, 0, 0, 0, 0, 0, 0, 0,
246 0, 1, 1, 0, 1, 1, 1, 1,
248 1, 1, 1, 1, 1, 1, 1, 1,
250 1, 1, 1, 1, 1, 1, 1, 1,
252 1, 1, 1, 1, 1, 1, 1, 0,
254 1, 1, 1, 1, 1, 1, 1, 1,
256 1, 1, 1, 1, 1, 1, 1, 1,
258 1, 1, 1, 1, 1, 1, 1, 1,
260 1, 1, 1, 1, 1, 1, 1, 1,
262 1, 1, 1, 1, 1, 1, 1, 1,
264 1, 1, 1, 1, 1, 1, 1, 1,
266 1, 1, 1, 1, 1, 1, 1, 1,
268 1, 1, 1, 1, 1, 1, 1, 0, };
357 #define PARSING_HEADER(state) (state <= s_headers_done) 399 #define LOWER(c) (unsigned char)(c | 0x20) 400 #define TOKEN(c) (tokens[(unsigned char)c]) 401 #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') 402 #define IS_NUM(c) ((c) >= '0' && (c) <= '9') 403 #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) 404 #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) 405 #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ 406 (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ 408 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ 409 (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ 410 (c) == '$' || (c) == ',') 412 #if HTTP_PARSER_STRICT 413 #define IS_URL_CHAR(c) (normal_url_char[(unsigned char) (c)]) 414 #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') 416 #define IS_URL_CHAR(c) \ 417 (normal_url_char[(unsigned char) (c)] || ((c) & 0x80)) 418 #define IS_HOST_CHAR(c) \ 419 (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') 426 #define IS_HEADER_CHAR(ch) \ 427 (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) 429 #define start_state (parser->type == HTTP_REQUEST ? s_pre_start_req : s_pre_start_res) 431 #define STRICT_CHECK(cond) 432 #define NEW_MESSAGE() start_state 435 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, 442 #undef HTTP_STRERROR_GEN 458 if (ch ==
' ' || ch ==
'\r' || ch ==
'\n') {
462 #if HTTP_PARSER_STRICT 463 if (ch ==
'\t' || ch ==
'\f') {
474 if (ch ==
'/' || ch ==
'*') {
610 const char *p =
data;
623 const unsigned int lenient = 0;
653 const char *header_field_mark = 0;
654 const char *header_value_mark = 0;
655 const char *url_mark = 0;
656 const char *reason_mark = 0;
657 const char *body_mark = 0;
660 header_field_mark =
data;
662 header_value_mark =
data;
685 const char* data_or_header_data_start =
data;
687 for (p = data; p != data + len; p++) {
694 if (ch ==
CR || ch ==
LF)
734 if (ch ==
CR || ch ==
LF)
779 if (ch < '0' || ch >
'9') {
915 if (ch ==
CR || ch ==
LF) {
966 const char *matcher = method_strings[parser->
method];
967 if (ch ==
' ' && matcher[parser->
index] ==
'\0') {
969 }
else if (ch == matcher[parser->
index]) {
972 if (parser->
index == 1 && ch ==
'H') {
974 }
else if (parser->
index == 2 && ch ==
'P') {
980 if (parser->
index == 1 && ch ==
'O') {
982 }
else if (parser->
index == 1 && ch ==
'E') {
984 }
else if (parser->
index == 1 && ch ==
'-') {
986 }
else if (parser->
index == 2 && ch ==
'A') {
994 }
else if (ch ==
'U') {
996 }
else if (ch ==
'A') {
1016 if (ch ==
' ')
break;
1022 goto reexecute_byte;
1025 if (ch ==
'/' || ch ==
'*') {
1082 goto reexecute_byte;
1085 if (
IS_HEX(ch) || ch ==
':')
break;
1165 goto reexecute_byte;
1205 goto reexecute_byte;
1240 goto reexecute_byte;
1275 goto reexecute_byte;
1309 goto reexecute_byte;
1356 if (ch < '0' || ch >
'9') {
1415 goto reexecute_byte;
1463 goto reexecute_byte;
1507 #define MOVE_THE_HEAD do { \ 1515 if (data + len - p >= 9) {
1524 }
else if (data + len - p >= 4) {
1575 assert(0 &&
"Unknown header_state");
1586 if (p - header_field_mark > 1 &&
1587 data[p - data - 1] ==
' ') {
1601 if (ch ==
' ' || ch ==
'\t')
break;
1614 if (ch ==
CR || ch ==
LF) {
1690 goto reexecute_byte;
1706 #define MOVE_FAST do { \ 1709 if (ch == CR || ch == LF || ch == QT || \ 1710 ch == BS || !IS_HEADER_CHAR(ch)) { \ 1711 goto cr_or_lf_or_qt; \ 1715 if (data + len - p >= 12) {
1727 }
else if (data + len - p >= 5) {
1739 }
else if (ch ==
BS) {
1757 if (ch ==
' ')
break;
1823 if (ch ==
' ' || ch ==
'\t')
1831 goto reexecute_byte;
1849 goto reexecute_byte;
1867 size_t header_size = p - data + 1;
1885 goto reexecute_byte;
1895 data_or_header_data_start = p;
1923 ((100 <= sc && sc <= 199) || sc == 204 || sc == 304)) {
1965 goto reexecute_byte;
1981 data_or_header_data_start = p;
1993 unhex_val = unhex[(
unsigned char)ch];
1994 if (unhex_val == -1) {
2013 unhex_val = unhex[(
unsigned char)ch];
2015 if (unhex_val == -1) {
2016 if (ch ==
';' || ch ==
' ') {
2100 data_or_header_data_start = p;
2105 assert(0 &&
"unhandled state");
2120 parser->
nread += p - data_or_header_data_start;
2137 assert(((header_field_mark ? 1 : 0) +
2138 (header_value_mark ? 1 : 0) +
2139 (url_mark ? 1 : 0) +
2140 (reason_mark ? 1 : 0) +
2141 (body_mark ? 1 : 0)) <= 1);
2162 return method_strings[
m];
2238 if (
IS_HEX(ch) || ch ==
':' || ch ==
'.') {
2345 for (p = buf; p < buf + buflen; p++) {
2386 assert(!
"Unexpected state");
2441 assert(0 &&
"Attempting to pause parser in error state");
static const int8_t unhex[256]
static struct @0 http_strerror_tab[]
#define HTTP_MAX_HEADER_SIZE
#define IS_HEADER_CHAR(ch)
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)
#define CALLBACK_SPACE(FOR)
unsigned short http_minor
#define PARSING_HEADER(state)
size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len)
#define CALLBACK_DATA(FOR)
static http_parser_settings settings
static http_parser * parser
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
static const uint8_t normal_url_char[256]
unsigned short status_code
#define TRANSFER_ENCODING
#define HTTP_STRERROR_GEN(n, s)
const char * http_method_str(enum http_method m)
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)
#define _CALLBACK_DATA(FOR, LEN, ER)
const char * http_errno_description(enum http_errno err)
unsigned short http_major
static map< string, int > m
http_data_cb on_headers_complete
#define CALLBACK_NOTIFY(FOR)
void http_parser_init(http_parser *parser, enum http_parser_type t)
unsigned char header_state
static enum state parse_url_char(enum state s, const char ch)
#define IS_USERINFO_CHAR(c)
#define STRICT_CHECK(cond)
static constexpr uint64_t data[1]
struct http_parser_url::@1 field_data[UF_MAX]
static const char tokens[256]
static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch)