|
@@ -43,7 +43,7 @@
|
|
|
|
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
|
|
|
|
|
-static http_parser *parser;
|
|
|
|
|
|
+static http_parser parser;
|
|
|
|
|
|
struct message {
|
|
struct message {
|
|
const char *name; // for debugging purposes
|
|
const char *name; // for debugging purposes
|
|
@@ -153,10 +153,10 @@ const struct message requests[] =
|
|
,.body= ""
|
|
,.body= ""
|
|
}
|
|
}
|
|
|
|
|
|
-#define DUMBFUCK 2
|
|
|
|
-, {.name= "dumbfuck"
|
|
|
|
|
|
+#define DUMBLUCK 2
|
|
|
|
+, {.name= "dumbluck"
|
|
,.type= HTTP_REQUEST
|
|
,.type= HTTP_REQUEST
|
|
- ,.raw= "GET /dumbfuck HTTP/1.1\r\n"
|
|
|
|
|
|
+ ,.raw= "GET /dumbluck HTTP/1.1\r\n"
|
|
"aaaaaaaaaaaaa:++++++++++\r\n"
|
|
"aaaaaaaaaaaaa:++++++++++\r\n"
|
|
"\r\n"
|
|
"\r\n"
|
|
,.should_keep_alive= TRUE
|
|
,.should_keep_alive= TRUE
|
|
@@ -166,8 +166,8 @@ const struct message requests[] =
|
|
,.method= HTTP_GET
|
|
,.method= HTTP_GET
|
|
,.query_string= ""
|
|
,.query_string= ""
|
|
,.fragment= ""
|
|
,.fragment= ""
|
|
- ,.request_path= "/dumbfuck"
|
|
|
|
- ,.request_url= "/dumbfuck"
|
|
|
|
|
|
+ ,.request_path= "/dumbluck"
|
|
|
|
+ ,.request_url= "/dumbluck"
|
|
,.num_headers= 1
|
|
,.num_headers= 1
|
|
,.headers=
|
|
,.headers=
|
|
{ { "aaaaaaaaaaaaa", "++++++++++" }
|
|
{ { "aaaaaaaaaaaaa", "++++++++++" }
|
|
@@ -371,13 +371,13 @@ const struct message requests[] =
|
|
,.chunk_lengths= { 5, 6 }
|
|
,.chunk_lengths= { 5, 6 }
|
|
}
|
|
}
|
|
|
|
|
|
-#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
|
|
|
|
-, {.name= "with bullshit after the length"
|
|
|
|
|
|
+#define CHUNKED_W_NONSENSE_AFTER_LENGTH 11
|
|
|
|
+, {.name= "with nonsense after the length"
|
|
,.type= HTTP_REQUEST
|
|
,.type= HTTP_REQUEST
|
|
- ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
|
|
|
|
|
|
+ ,.raw= "POST /chunked_w_nonsense_after_length HTTP/1.1\r\n"
|
|
"Transfer-Encoding: chunked\r\n"
|
|
"Transfer-Encoding: chunked\r\n"
|
|
"\r\n"
|
|
"\r\n"
|
|
- "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
|
|
|
|
|
|
+ "5; ilovew3;whattheluck=aretheseparametersfor\r\nhello\r\n"
|
|
"6; blahblah; blah\r\n world\r\n"
|
|
"6; blahblah; blah\r\n world\r\n"
|
|
"0\r\n"
|
|
"0\r\n"
|
|
"\r\n"
|
|
"\r\n"
|
|
@@ -388,8 +388,8 @@ const struct message requests[] =
|
|
,.method= HTTP_POST
|
|
,.method= HTTP_POST
|
|
,.query_string= ""
|
|
,.query_string= ""
|
|
,.fragment= ""
|
|
,.fragment= ""
|
|
- ,.request_path= "/chunked_w_bullshit_after_length"
|
|
|
|
- ,.request_url= "/chunked_w_bullshit_after_length"
|
|
|
|
|
|
+ ,.request_path= "/chunked_w_nonsense_after_length"
|
|
|
|
+ ,.request_url= "/chunked_w_nonsense_after_length"
|
|
,.num_headers= 1
|
|
,.num_headers= 1
|
|
,.headers=
|
|
,.headers=
|
|
{ { "Transfer-Encoding", "chunked" }
|
|
{ { "Transfer-Encoding", "chunked" }
|
|
@@ -1173,6 +1173,26 @@ const struct message requests[] =
|
|
,.headers= { { "Host", "example.com" } }
|
|
,.headers= { { "Host", "example.com" } }
|
|
,.body= ""
|
|
,.body= ""
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+#define SOURCE_ICE_REQUEST 42
|
|
|
|
+, {.name = "source request"
|
|
|
|
+ ,.type= HTTP_REQUEST
|
|
|
|
+ ,.raw= "SOURCE /music/sweet/music ICE/1.0\r\n"
|
|
|
|
+ "Host: example.com\r\n"
|
|
|
|
+ "\r\n"
|
|
|
|
+ ,.should_keep_alive= FALSE
|
|
|
|
+ ,.message_complete_on_eof= FALSE
|
|
|
|
+ ,.http_major= 1
|
|
|
|
+ ,.http_minor= 0
|
|
|
|
+ ,.method= HTTP_SOURCE
|
|
|
|
+ ,.request_path= "/music/sweet/music"
|
|
|
|
+ ,.request_url= "/music/sweet/music"
|
|
|
|
+ ,.query_string= ""
|
|
|
|
+ ,.fragment= ""
|
|
|
|
+ ,.num_headers= 1
|
|
|
|
+ ,.headers= { { "Host", "example.com" } }
|
|
|
|
+ ,.body= ""
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
/* * R E S P O N S E S * */
|
|
/* * R E S P O N S E S * */
|
|
@@ -2010,7 +2030,7 @@ strlncpy(char *dst, size_t len, const char *src, size_t n)
|
|
int
|
|
int
|
|
request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
strlncat(messages[num_messages].request_url,
|
|
strlncat(messages[num_messages].request_url,
|
|
sizeof(messages[num_messages].request_url),
|
|
sizeof(messages[num_messages].request_url),
|
|
buf,
|
|
buf,
|
|
@@ -2021,7 +2041,7 @@ request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
int
|
|
int
|
|
header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
struct message *m = &messages[num_messages];
|
|
struct message *m = &messages[num_messages];
|
|
|
|
|
|
if (m->last_header_element != FIELD)
|
|
if (m->last_header_element != FIELD)
|
|
@@ -2040,7 +2060,7 @@ header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
int
|
|
int
|
|
header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
struct message *m = &messages[num_messages];
|
|
struct message *m = &messages[num_messages];
|
|
|
|
|
|
strlncat(m->headers[m->num_headers-1][1],
|
|
strlncat(m->headers[m->num_headers-1][1],
|
|
@@ -2069,7 +2089,7 @@ check_body_is_final (const http_parser *p)
|
|
int
|
|
int
|
|
body_cb (http_parser *p, const char *buf, size_t len)
|
|
body_cb (http_parser *p, const char *buf, size_t len)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
strlncat(messages[num_messages].body,
|
|
strlncat(messages[num_messages].body,
|
|
sizeof(messages[num_messages].body),
|
|
sizeof(messages[num_messages].body),
|
|
buf,
|
|
buf,
|
|
@@ -2083,7 +2103,7 @@ body_cb (http_parser *p, const char *buf, size_t len)
|
|
int
|
|
int
|
|
count_body_cb (http_parser *p, const char *buf, size_t len)
|
|
count_body_cb (http_parser *p, const char *buf, size_t len)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
assert(buf);
|
|
assert(buf);
|
|
messages[num_messages].body_size += len;
|
|
messages[num_messages].body_size += len;
|
|
check_body_is_final(p);
|
|
check_body_is_final(p);
|
|
@@ -2093,7 +2113,8 @@ count_body_cb (http_parser *p, const char *buf, size_t len)
|
|
int
|
|
int
|
|
message_begin_cb (http_parser *p)
|
|
message_begin_cb (http_parser *p)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
|
|
+ assert(!messages[num_messages].message_begin_cb_called);
|
|
messages[num_messages].message_begin_cb_called = TRUE;
|
|
messages[num_messages].message_begin_cb_called = TRUE;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -2101,21 +2122,22 @@ message_begin_cb (http_parser *p)
|
|
int
|
|
int
|
|
headers_complete_cb (http_parser *p)
|
|
headers_complete_cb (http_parser *p)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
- messages[num_messages].method = parser->method;
|
|
|
|
- messages[num_messages].status_code = parser->status_code;
|
|
|
|
- messages[num_messages].http_major = parser->http_major;
|
|
|
|
- messages[num_messages].http_minor = parser->http_minor;
|
|
|
|
|
|
+ assert(p == &parser);
|
|
|
|
+ messages[num_messages].method = parser.method;
|
|
|
|
+ messages[num_messages].status_code = parser.status_code;
|
|
|
|
+ messages[num_messages].http_major = parser.http_major;
|
|
|
|
+ messages[num_messages].http_minor = parser.http_minor;
|
|
messages[num_messages].headers_complete_cb_called = TRUE;
|
|
messages[num_messages].headers_complete_cb_called = TRUE;
|
|
- messages[num_messages].should_keep_alive = http_should_keep_alive(parser);
|
|
|
|
|
|
+ messages[num_messages].should_keep_alive = http_should_keep_alive(&parser);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
int
|
|
message_complete_cb (http_parser *p)
|
|
message_complete_cb (http_parser *p)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
- if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser))
|
|
|
|
|
|
+ assert(p == &parser);
|
|
|
|
+ if (messages[num_messages].should_keep_alive !=
|
|
|
|
+ http_should_keep_alive(&parser))
|
|
{
|
|
{
|
|
fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same "
|
|
fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same "
|
|
"value in both on_message_complete and on_headers_complete "
|
|
"value in both on_message_complete and on_headers_complete "
|
|
@@ -2146,7 +2168,7 @@ message_complete_cb (http_parser *p)
|
|
int
|
|
int
|
|
response_status_cb (http_parser *p, const char *buf, size_t len)
|
|
response_status_cb (http_parser *p, const char *buf, size_t len)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
|
|
|
|
messages[num_messages].status_cb_called = TRUE;
|
|
messages[num_messages].status_cb_called = TRUE;
|
|
|
|
|
|
@@ -2160,7 +2182,7 @@ response_status_cb (http_parser *p, const char *buf, size_t len)
|
|
int
|
|
int
|
|
chunk_header_cb (http_parser *p)
|
|
chunk_header_cb (http_parser *p)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
int chunk_idx = messages[num_messages].num_chunks;
|
|
int chunk_idx = messages[num_messages].num_chunks;
|
|
messages[num_messages].num_chunks++;
|
|
messages[num_messages].num_chunks++;
|
|
if (chunk_idx < MAX_CHUNKS) {
|
|
if (chunk_idx < MAX_CHUNKS) {
|
|
@@ -2173,7 +2195,7 @@ chunk_header_cb (http_parser *p)
|
|
int
|
|
int
|
|
chunk_complete_cb (http_parser *p)
|
|
chunk_complete_cb (http_parser *p)
|
|
{
|
|
{
|
|
- assert(p == parser);
|
|
|
|
|
|
+ assert(p == &parser);
|
|
|
|
|
|
/* Here we want to verify that each chunk_header_cb is matched by a
|
|
/* Here we want to verify that each chunk_header_cb is matched by a
|
|
* chunk_complete_cb, so not only should the total number of calls to
|
|
* chunk_complete_cb, so not only should the total number of calls to
|
|
@@ -2378,7 +2400,7 @@ connect_headers_complete_cb (http_parser *p)
|
|
int
|
|
int
|
|
connect_message_complete_cb (http_parser *p)
|
|
connect_message_complete_cb (http_parser *p)
|
|
{
|
|
{
|
|
- messages[num_messages].should_keep_alive = http_should_keep_alive(parser);
|
|
|
|
|
|
+ messages[num_messages].should_keep_alive = http_should_keep_alive(&parser);
|
|
return message_complete_cb(p);
|
|
return message_complete_cb(p);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2451,30 +2473,15 @@ void
|
|
parser_init (enum http_parser_type type)
|
|
parser_init (enum http_parser_type type)
|
|
{
|
|
{
|
|
num_messages = 0;
|
|
num_messages = 0;
|
|
-
|
|
|
|
- assert(parser == NULL);
|
|
|
|
-
|
|
|
|
- parser = malloc(sizeof(http_parser));
|
|
|
|
-
|
|
|
|
- http_parser_init(parser, type);
|
|
|
|
-
|
|
|
|
|
|
+ http_parser_init(&parser, type);
|
|
memset(&messages, 0, sizeof messages);
|
|
memset(&messages, 0, sizeof messages);
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void
|
|
|
|
-parser_free ()
|
|
|
|
-{
|
|
|
|
- assert(parser);
|
|
|
|
- free(parser);
|
|
|
|
- parser = NULL;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
size_t parse (const char *buf, size_t len)
|
|
size_t parse (const char *buf, size_t len)
|
|
{
|
|
{
|
|
size_t nparsed;
|
|
size_t nparsed;
|
|
currently_parsing_eof = (len == 0);
|
|
currently_parsing_eof = (len == 0);
|
|
- nparsed = http_parser_execute(parser, &settings, buf, len);
|
|
|
|
|
|
+ nparsed = http_parser_execute(&parser, &settings, buf, len);
|
|
return nparsed;
|
|
return nparsed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2482,7 +2489,7 @@ size_t parse_count_body (const char *buf, size_t len)
|
|
{
|
|
{
|
|
size_t nparsed;
|
|
size_t nparsed;
|
|
currently_parsing_eof = (len == 0);
|
|
currently_parsing_eof = (len == 0);
|
|
- nparsed = http_parser_execute(parser, &settings_count_body, buf, len);
|
|
|
|
|
|
+ nparsed = http_parser_execute(&parser, &settings_count_body, buf, len);
|
|
return nparsed;
|
|
return nparsed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2493,7 +2500,7 @@ size_t parse_pause (const char *buf, size_t len)
|
|
|
|
|
|
currently_parsing_eof = (len == 0);
|
|
currently_parsing_eof = (len == 0);
|
|
current_pause_parser = &s;
|
|
current_pause_parser = &s;
|
|
- nparsed = http_parser_execute(parser, current_pause_parser, buf, len);
|
|
|
|
|
|
+ nparsed = http_parser_execute(&parser, current_pause_parser, buf, len);
|
|
return nparsed;
|
|
return nparsed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2501,7 +2508,7 @@ size_t parse_connect (const char *buf, size_t len)
|
|
{
|
|
{
|
|
size_t nparsed;
|
|
size_t nparsed;
|
|
currently_parsing_eof = (len == 0);
|
|
currently_parsing_eof = (len == 0);
|
|
- nparsed = http_parser_execute(parser, &settings_connect, buf, len);
|
|
|
|
|
|
+ nparsed = http_parser_execute(&parser, &settings_connect, buf, len);
|
|
return nparsed;
|
|
return nparsed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2721,7 +2728,7 @@ static void
|
|
print_error (const char *raw, size_t error_location)
|
|
print_error (const char *raw, size_t error_location)
|
|
{
|
|
{
|
|
fprintf(stderr, "\n*** %s ***\n\n",
|
|
fprintf(stderr, "\n*** %s ***\n\n",
|
|
- http_errno_description(HTTP_PARSER_ERRNO(parser)));
|
|
|
|
|
|
+ http_errno_description(HTTP_PARSER_ERRNO(&parser)));
|
|
|
|
|
|
int this_line = 0, char_len = 0;
|
|
int this_line = 0, char_len = 0;
|
|
size_t i, j, len = strlen(raw), error_location_line = 0;
|
|
size_t i, j, len = strlen(raw), error_location_line = 0;
|
|
@@ -3264,6 +3271,24 @@ const struct url_test url_tests[] =
|
|
,.rv=1 /* s_dead */
|
|
,.rv=1 /* s_dead */
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+, {.name="empty url"
|
|
|
|
+ ,.url=""
|
|
|
|
+ ,.is_connect=0
|
|
|
|
+ ,.rv=1
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+, {.name="NULL url"
|
|
|
|
+ ,.url=NULL
|
|
|
|
+ ,.is_connect=0
|
|
|
|
+ ,.rv=1
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+, {.name="full of spaces url"
|
|
|
|
+ ,.url=" "
|
|
|
|
+ ,.is_connect=0
|
|
|
|
+ ,.rv=1
|
|
|
|
+ }
|
|
|
|
+
|
|
#if HTTP_PARSER_STRICT
|
|
#if HTTP_PARSER_STRICT
|
|
|
|
|
|
, {.name="tab in URL"
|
|
, {.name="tab in URL"
|
|
@@ -3348,7 +3373,7 @@ test_parse_url (void)
|
|
memset(&u, 0, sizeof(u));
|
|
memset(&u, 0, sizeof(u));
|
|
|
|
|
|
rv = http_parser_parse_url(test->url,
|
|
rv = http_parser_parse_url(test->url,
|
|
- strlen(test->url),
|
|
|
|
|
|
+ test->url ? strlen(test->url) : 0,
|
|
test->is_connect,
|
|
test->is_connect,
|
|
&u);
|
|
&u);
|
|
|
|
|
|
@@ -3389,6 +3414,14 @@ test_method_str (void)
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
void
|
|
|
|
+test_status_str (void)
|
|
|
|
+{
|
|
|
|
+ assert(0 == strcmp("OK", http_status_str(HTTP_STATUS_OK)));
|
|
|
|
+ assert(0 == strcmp("Not Found", http_status_str(HTTP_STATUS_NOT_FOUND)));
|
|
|
|
+ assert(0 == strcmp("<unknown>", http_status_str(1337)));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
test_message (const struct message *message)
|
|
test_message (const struct message *message)
|
|
{
|
|
{
|
|
size_t raw_len = strlen(message->raw);
|
|
size_t raw_len = strlen(message->raw);
|
|
@@ -3402,9 +3435,18 @@ test_message (const struct message *message)
|
|
size_t msg2len = raw_len - msg1len;
|
|
size_t msg2len = raw_len - msg1len;
|
|
|
|
|
|
if (msg1len) {
|
|
if (msg1len) {
|
|
|
|
+ assert(num_messages == 0);
|
|
|
|
+ messages[0].headers_complete_cb_called = FALSE;
|
|
|
|
+
|
|
read = parse(msg1, msg1len);
|
|
read = parse(msg1, msg1len);
|
|
|
|
|
|
- if (message->upgrade && parser->upgrade && num_messages > 0) {
|
|
|
|
|
|
+ if (!messages[0].headers_complete_cb_called && parser.nread != read) {
|
|
|
|
+ assert(parser.nread == read);
|
|
|
|
+ print_error(msg1, read);
|
|
|
|
+ abort();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (message->upgrade && parser.upgrade && num_messages > 0) {
|
|
messages[num_messages - 1].upgrade = msg1 + read;
|
|
messages[num_messages - 1].upgrade = msg1 + read;
|
|
goto test;
|
|
goto test;
|
|
}
|
|
}
|
|
@@ -3418,7 +3460,7 @@ test_message (const struct message *message)
|
|
|
|
|
|
read = parse(msg2, msg2len);
|
|
read = parse(msg2, msg2len);
|
|
|
|
|
|
- if (message->upgrade && parser->upgrade) {
|
|
|
|
|
|
+ if (message->upgrade && parser.upgrade) {
|
|
messages[num_messages - 1].upgrade = msg2 + read;
|
|
messages[num_messages - 1].upgrade = msg2 + read;
|
|
goto test;
|
|
goto test;
|
|
}
|
|
}
|
|
@@ -3443,8 +3485,6 @@ test_message (const struct message *message)
|
|
}
|
|
}
|
|
|
|
|
|
if(!message_eq(0, 0, message)) abort();
|
|
if(!message_eq(0, 0, message)) abort();
|
|
-
|
|
|
|
- parser_free();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3480,8 +3520,6 @@ test_message_count_body (const struct message *message)
|
|
}
|
|
}
|
|
|
|
|
|
if(!message_eq(0, 0, message)) abort();
|
|
if(!message_eq(0, 0, message)) abort();
|
|
-
|
|
|
|
- parser_free();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
void
|
|
@@ -3494,11 +3532,9 @@ test_simple_type (const char *buf,
|
|
enum http_errno err;
|
|
enum http_errno err;
|
|
|
|
|
|
parse(buf, strlen(buf));
|
|
parse(buf, strlen(buf));
|
|
- err = HTTP_PARSER_ERRNO(parser);
|
|
|
|
|
|
+ err = HTTP_PARSER_ERRNO(&parser);
|
|
parse(NULL, 0);
|
|
parse(NULL, 0);
|
|
|
|
|
|
- parser_free();
|
|
|
|
-
|
|
|
|
/* In strict mode, allow us to pass with an unexpected HPE_STRICT as
|
|
/* In strict mode, allow us to pass with an unexpected HPE_STRICT as
|
|
* long as the caller isn't expecting success.
|
|
* long as the caller isn't expecting success.
|
|
*/
|
|
*/
|
|
@@ -3838,7 +3874,7 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct
|
|
|
|
|
|
read = parse(total, strlen(total));
|
|
read = parse(total, strlen(total));
|
|
|
|
|
|
- if (parser->upgrade) {
|
|
|
|
|
|
+ if (parser.upgrade) {
|
|
upgrade_message_fix(total, read, 3, r1, r2, r3);
|
|
upgrade_message_fix(total, read, 3, r1, r2, r3);
|
|
goto test;
|
|
goto test;
|
|
}
|
|
}
|
|
@@ -3865,8 +3901,6 @@ test:
|
|
if (!message_eq(0, 0, r1)) abort();
|
|
if (!message_eq(0, 0, r1)) abort();
|
|
if (message_count > 1 && !message_eq(1, 0, r2)) abort();
|
|
if (message_count > 1 && !message_eq(1, 0, r2)) abort();
|
|
if (message_count > 2 && !message_eq(2, 0, r3)) abort();
|
|
if (message_count > 2 && !message_eq(2, 0, r3)) abort();
|
|
-
|
|
|
|
- parser_free();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* SCAN through every possible breaking to make sure the
|
|
/* SCAN through every possible breaking to make sure the
|
|
@@ -3920,9 +3954,17 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
strlncpy(buf3, sizeof(buf1), total+j, buf3_len);
|
|
strlncpy(buf3, sizeof(buf1), total+j, buf3_len);
|
|
buf3[buf3_len] = 0;
|
|
buf3[buf3_len] = 0;
|
|
|
|
|
|
|
|
+ assert(num_messages == 0);
|
|
|
|
+ messages[0].headers_complete_cb_called = FALSE;
|
|
|
|
+
|
|
read = parse(buf1, buf1_len);
|
|
read = parse(buf1, buf1_len);
|
|
|
|
|
|
- if (parser->upgrade) goto test;
|
|
|
|
|
|
+ if (!messages[0].headers_complete_cb_called && parser.nread != read) {
|
|
|
|
+ print_error(buf1, read);
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (parser.upgrade) goto test;
|
|
|
|
|
|
if (read != buf1_len) {
|
|
if (read != buf1_len) {
|
|
print_error(buf1, read);
|
|
print_error(buf1, read);
|
|
@@ -3931,7 +3973,7 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
|
|
|
|
read += parse(buf2, buf2_len);
|
|
read += parse(buf2, buf2_len);
|
|
|
|
|
|
- if (parser->upgrade) goto test;
|
|
|
|
|
|
+ if (parser.upgrade) goto test;
|
|
|
|
|
|
if (read != buf1_len + buf2_len) {
|
|
if (read != buf1_len + buf2_len) {
|
|
print_error(buf2, read);
|
|
print_error(buf2, read);
|
|
@@ -3940,7 +3982,7 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
|
|
|
|
read += parse(buf3, buf3_len);
|
|
read += parse(buf3, buf3_len);
|
|
|
|
|
|
- if (parser->upgrade) goto test;
|
|
|
|
|
|
+ if (parser.upgrade) goto test;
|
|
|
|
|
|
if (read != buf1_len + buf2_len + buf3_len) {
|
|
if (read != buf1_len + buf2_len + buf3_len) {
|
|
print_error(buf3, read);
|
|
print_error(buf3, read);
|
|
@@ -3950,7 +3992,7 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
parse(NULL, 0);
|
|
parse(NULL, 0);
|
|
|
|
|
|
test:
|
|
test:
|
|
- if (parser->upgrade) {
|
|
|
|
|
|
+ if (parser.upgrade) {
|
|
upgrade_message_fix(total, read, 3, r1, r2, r3);
|
|
upgrade_message_fix(total, read, 3, r1, r2, r3);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3974,8 +4016,6 @@ test:
|
|
fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
|
|
fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
-
|
|
|
|
- parser_free();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -4039,7 +4079,7 @@ test_message_pause (const struct message *msg)
|
|
// completion callback.
|
|
// completion callback.
|
|
if (messages[0].message_complete_cb_called &&
|
|
if (messages[0].message_complete_cb_called &&
|
|
msg->upgrade &&
|
|
msg->upgrade &&
|
|
- parser->upgrade) {
|
|
|
|
|
|
+ parser.upgrade) {
|
|
messages[0].upgrade = buf + nread;
|
|
messages[0].upgrade = buf + nread;
|
|
goto test;
|
|
goto test;
|
|
}
|
|
}
|
|
@@ -4047,17 +4087,16 @@ test_message_pause (const struct message *msg)
|
|
if (nread < buflen) {
|
|
if (nread < buflen) {
|
|
|
|
|
|
// Not much do to if we failed a strict-mode check
|
|
// Not much do to if we failed a strict-mode check
|
|
- if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) {
|
|
|
|
- parser_free();
|
|
|
|
|
|
+ if (HTTP_PARSER_ERRNO(&parser) == HPE_STRICT) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED);
|
|
|
|
|
|
+ assert (HTTP_PARSER_ERRNO(&parser) == HPE_PAUSED);
|
|
}
|
|
}
|
|
|
|
|
|
buf += nread;
|
|
buf += nread;
|
|
buflen -= nread;
|
|
buflen -= nread;
|
|
- http_parser_pause(parser, 0);
|
|
|
|
|
|
+ http_parser_pause(&parser, 0);
|
|
} while (buflen > 0);
|
|
} while (buflen > 0);
|
|
|
|
|
|
nread = parse_pause(NULL, 0);
|
|
nread = parse_pause(NULL, 0);
|
|
@@ -4070,8 +4109,6 @@ test:
|
|
}
|
|
}
|
|
|
|
|
|
if(!message_eq(0, 0, msg)) abort();
|
|
if(!message_eq(0, 0, msg)) abort();
|
|
-
|
|
|
|
- parser_free();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* Verify that body and next message won't be parsed in responses to CONNECT */
|
|
/* Verify that body and next message won't be parsed in responses to CONNECT */
|
|
@@ -4091,14 +4128,11 @@ test_message_connect (const struct message *msg)
|
|
}
|
|
}
|
|
|
|
|
|
if(!message_eq(0, 1, msg)) abort();
|
|
if(!message_eq(0, 1, msg)) abort();
|
|
-
|
|
|
|
- parser_free();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
int
|
|
main (void)
|
|
main (void)
|
|
{
|
|
{
|
|
- parser = NULL;
|
|
|
|
unsigned i, j, k;
|
|
unsigned i, j, k;
|
|
unsigned long version;
|
|
unsigned long version;
|
|
unsigned major;
|
|
unsigned major;
|
|
@@ -4117,6 +4151,7 @@ main (void)
|
|
test_preserve_data();
|
|
test_preserve_data();
|
|
test_parse_url();
|
|
test_parse_url();
|
|
test_method_str();
|
|
test_method_str();
|
|
|
|
+ test_status_str();
|
|
|
|
|
|
//// NREAD
|
|
//// NREAD
|
|
test_header_nread_value();
|
|
test_header_nread_value();
|
|
@@ -4149,6 +4184,13 @@ main (void)
|
|
|
|
|
|
test_simple_type(
|
|
test_simple_type(
|
|
"POST / HTTP/1.1\r\n"
|
|
"POST / HTTP/1.1\r\n"
|
|
|
|
+ "Content-Length:\r\n" // empty
|
|
|
|
+ "\r\n",
|
|
|
|
+ HPE_INVALID_CONTENT_LENGTH,
|
|
|
|
+ HTTP_REQUEST);
|
|
|
|
+
|
|
|
|
+ test_simple_type(
|
|
|
|
+ "POST / HTTP/1.1\r\n"
|
|
"Content-Length: 42 \r\n" // Note the surrounding whitespace.
|
|
"Content-Length: 42 \r\n" // Note the surrounding whitespace.
|
|
"\r\n",
|
|
"\r\n",
|
|
HPE_OK,
|
|
HPE_OK,
|
|
@@ -4168,6 +4210,20 @@ main (void)
|
|
HPE_INVALID_CONTENT_LENGTH,
|
|
HPE_INVALID_CONTENT_LENGTH,
|
|
HTTP_REQUEST);
|
|
HTTP_REQUEST);
|
|
|
|
|
|
|
|
+ test_simple_type(
|
|
|
|
+ "POST / HTTP/1.1\r\n"
|
|
|
|
+ "Content-Length: 42\r\n"
|
|
|
|
+ " Hello world!\r\n",
|
|
|
|
+ HPE_INVALID_CONTENT_LENGTH,
|
|
|
|
+ HTTP_REQUEST);
|
|
|
|
+
|
|
|
|
+ test_simple_type(
|
|
|
|
+ "POST / HTTP/1.1\r\n"
|
|
|
|
+ "Content-Length: 42\r\n"
|
|
|
|
+ " \r\n",
|
|
|
|
+ HPE_OK,
|
|
|
|
+ HTTP_REQUEST);
|
|
|
|
+
|
|
//// RESPONSES
|
|
//// RESPONSES
|
|
|
|
|
|
test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
@@ -4175,6 +4231,7 @@ main (void)
|
|
test_simple_type("HTTP/11.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
test_simple_type("HTTP/11.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
test_simple_type("HTTP/1.01 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
test_simple_type("HTTP/1.01 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
test_simple_type("HTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
test_simple_type("HTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
|
|
+ test_simple_type("\rHTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(responses); i++) {
|
|
for (i = 0; i < ARRAY_SIZE(responses); i++) {
|
|
test_message(&responses[i]);
|
|
test_message(&responses[i]);
|
|
@@ -4252,11 +4309,16 @@ main (void)
|
|
|
|
|
|
/// REQUESTS
|
|
/// REQUESTS
|
|
|
|
|
|
|
|
+ test_simple("GET / IHTTP/1.0\r\n\r\n", HPE_INVALID_CONSTANT);
|
|
|
|
+ test_simple("GET / ICE/1.0\r\n\r\n", HPE_INVALID_CONSTANT);
|
|
test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTTP/01.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTTP/01.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION);
|
|
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION);
|
|
|
|
|
|
|
|
+ test_simple("GET / HTTP/1.0\r\nHello: w\1rld\r\n\r\n", HPE_INVALID_HEADER_TOKEN);
|
|
|
|
+ test_simple("GET / HTTP/1.0\r\nHello: woooo\2rld\r\n\r\n", HPE_INVALID_HEADER_TOKEN);
|
|
|
|
+
|
|
// Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js
|
|
// Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js
|
|
test_simple("GET / HTTP/1.1\r\n"
|
|
test_simple("GET / HTTP/1.1\r\n"
|
|
"Test: Düsseldorf\r\n",
|
|
"Test: Düsseldorf\r\n",
|
|
@@ -4339,9 +4401,9 @@ main (void)
|
|
"\r\n",
|
|
"\r\n",
|
|
HPE_INVALID_HEADER_TOKEN);
|
|
HPE_INVALID_HEADER_TOKEN);
|
|
|
|
|
|
- const char *dumbfuck2 =
|
|
|
|
|
|
+ const char *dumbluck2 =
|
|
"GET / HTTP/1.1\r\n"
|
|
"GET / HTTP/1.1\r\n"
|
|
- "X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n"
|
|
|
|
|
|
+ "X-SSL-Nonsense: -----BEGIN CERTIFICATE-----\r\n"
|
|
"\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"
|
|
"\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"
|
|
"\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"
|
|
"\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"
|
|
"\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"
|
|
"\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"
|
|
@@ -4374,7 +4436,7 @@ main (void)
|
|
"\tRA==\r\n"
|
|
"\tRA==\r\n"
|
|
"\t-----END CERTIFICATE-----\r\n"
|
|
"\t-----END CERTIFICATE-----\r\n"
|
|
"\r\n";
|
|
"\r\n";
|
|
- test_simple(dumbfuck2, HPE_OK);
|
|
|
|
|
|
+ test_simple(dumbluck2, HPE_OK);
|
|
|
|
|
|
const char *corrupted_connection =
|
|
const char *corrupted_connection =
|
|
"GET / HTTP/1.1\r\n"
|
|
"GET / HTTP/1.1\r\n"
|
|
@@ -4441,7 +4503,7 @@ main (void)
|
|
printf("request scan 3/4 ");
|
|
printf("request scan 3/4 ");
|
|
test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
|
|
test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
|
|
, &requests[CHUNKED_W_TRAILING_HEADERS]
|
|
, &requests[CHUNKED_W_TRAILING_HEADERS]
|
|
- , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]
|
|
|
|
|
|
+ , &requests[CHUNKED_W_NONSENSE_AFTER_LENGTH]
|
|
);
|
|
);
|
|
|
|
|
|
printf("request scan 4/4 ");
|
|
printf("request scan 4/4 ");
|