|
|
|
@ -22,6 +22,7 @@
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h> /* rand */
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
@ -35,7 +36,8 @@
|
|
|
|
|
|
|
|
|
|
enum message_type { REQUEST, RESPONSE };
|
|
|
|
|
|
|
|
|
|
static http_parser parser;
|
|
|
|
|
static http_parser *parser;
|
|
|
|
|
|
|
|
|
|
struct message {
|
|
|
|
|
const char *name; // for debugging purposes
|
|
|
|
|
const char *raw;
|
|
|
|
@ -67,8 +69,8 @@ inline size_t parse (enum message_type t, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
size_t nparsed;
|
|
|
|
|
currently_parsing_eof = (len == 0);
|
|
|
|
|
nparsed = (t == REQUEST ? http_parse_requests(&parser, buf, len)
|
|
|
|
|
: http_parse_responses(&parser, buf, len));
|
|
|
|
|
nparsed = (t == REQUEST ? http_parse_requests(parser, buf, len)
|
|
|
|
|
: http_parse_responses(parser, buf, len));
|
|
|
|
|
return nparsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -581,47 +583,47 @@ const struct message responses[] =
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
request_path_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
request_path_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
strncat(messages[num_messages].request_path, p, len);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
strncat(messages[num_messages].request_path, buf, len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
request_url_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
strncat(messages[num_messages].request_url, p, len);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
strncat(messages[num_messages].request_url, buf, len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
query_string_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
query_string_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
strncat(messages[num_messages].query_string, p, len);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
strncat(messages[num_messages].query_string, buf, len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
fragment_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
fragment_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
strncat(messages[num_messages].fragment, p, len);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
strncat(messages[num_messages].fragment, buf, len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
header_field_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
struct message *m = &messages[num_messages];
|
|
|
|
|
|
|
|
|
|
if (m->last_header_element != FIELD)
|
|
|
|
|
m->num_headers++;
|
|
|
|
|
|
|
|
|
|
strncat(m->headers[m->num_headers-1][0], p, len);
|
|
|
|
|
strncat(m->headers[m->num_headers-1][0], buf, len);
|
|
|
|
|
|
|
|
|
|
m->last_header_element = FIELD;
|
|
|
|
|
|
|
|
|
@ -629,12 +631,12 @@ header_field_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
header_value_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
struct message *m = &messages[num_messages];
|
|
|
|
|
|
|
|
|
|
strncat(m->headers[m->num_headers-1][1], p, len);
|
|
|
|
|
strncat(m->headers[m->num_headers-1][1], buf, len);
|
|
|
|
|
|
|
|
|
|
m->last_header_element = VALUE;
|
|
|
|
|
|
|
|
|
@ -642,25 +644,26 @@ header_value_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
body_cb (http_parser *parser, const char *p, size_t len)
|
|
|
|
|
body_cb (http_parser *p, const char *buf, size_t len)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
strncat(messages[num_messages].body, p, len);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
strncat(messages[num_messages].body, buf, len);
|
|
|
|
|
// printf("body_cb: '%s'\n", requests[num_messages].body);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
message_begin_cb (http_parser *parser)
|
|
|
|
|
message_begin_cb (http_parser *p)
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
assert(p == parser);
|
|
|
|
|
messages[num_messages].message_begin_cb_called = TRUE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
headers_complete_cb (http_parser *parser)
|
|
|
|
|
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;
|
|
|
|
@ -671,9 +674,9 @@ headers_complete_cb (http_parser *parser)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
message_complete_cb (http_parser *parser)
|
|
|
|
|
message_complete_cb (http_parser *p)
|
|
|
|
|
{
|
|
|
|
|
assert(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 "
|
|
|
|
@ -695,20 +698,32 @@ parser_init ()
|
|
|
|
|
{
|
|
|
|
|
num_messages = 0;
|
|
|
|
|
|
|
|
|
|
http_parser_init(&parser);
|
|
|
|
|
assert(parser == NULL);
|
|
|
|
|
|
|
|
|
|
parser = malloc(sizeof(http_parser));
|
|
|
|
|
|
|
|
|
|
http_parser_init(parser);
|
|
|
|
|
|
|
|
|
|
memset(&messages, 0, sizeof messages);
|
|
|
|
|
|
|
|
|
|
parser.on_message_begin = message_begin_cb;
|
|
|
|
|
parser.on_header_field = header_field_cb;
|
|
|
|
|
parser.on_header_value = header_value_cb;
|
|
|
|
|
parser.on_path = request_path_cb;
|
|
|
|
|
parser.on_url = request_url_cb;
|
|
|
|
|
parser.on_fragment = fragment_cb;
|
|
|
|
|
parser.on_query_string = query_string_cb;
|
|
|
|
|
parser.on_body = body_cb;
|
|
|
|
|
parser.on_headers_complete = headers_complete_cb;
|
|
|
|
|
parser.on_message_complete = message_complete_cb;
|
|
|
|
|
parser->on_message_begin = message_begin_cb;
|
|
|
|
|
parser->on_header_field = header_field_cb;
|
|
|
|
|
parser->on_header_value = header_value_cb;
|
|
|
|
|
parser->on_path = request_path_cb;
|
|
|
|
|
parser->on_url = request_url_cb;
|
|
|
|
|
parser->on_fragment = fragment_cb;
|
|
|
|
|
parser->on_query_string = query_string_cb;
|
|
|
|
|
parser->on_body = body_cb;
|
|
|
|
|
parser->on_headers_complete = headers_complete_cb;
|
|
|
|
|
parser->on_message_complete = message_complete_cb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
parser_free ()
|
|
|
|
|
{
|
|
|
|
|
assert(parser);
|
|
|
|
|
free(parser);
|
|
|
|
|
parser = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
@ -855,9 +870,11 @@ test_message (const struct message *message)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!message_eq(0, message)) exit(1);
|
|
|
|
|
|
|
|
|
|
parser_free();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
void
|
|
|
|
|
test_error (const char *buf)
|
|
|
|
|
{
|
|
|
|
|
parser_init();
|
|
|
|
@ -865,14 +882,16 @@ test_error (const char *buf)
|
|
|
|
|
size_t parsed;
|
|
|
|
|
|
|
|
|
|
parsed = parse(REQUEST, buf, strlen(buf));
|
|
|
|
|
if (parsed != strlen(buf)) return 1;
|
|
|
|
|
if (parsed != strlen(buf)) goto out;
|
|
|
|
|
parsed = parse(REQUEST, NULL, 0);
|
|
|
|
|
if (parsed != 0) return 1;
|
|
|
|
|
if (parsed != 0) goto out;
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "\n*** Error expected but none found ***\n\n%s", buf);
|
|
|
|
|
exit(1);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
out:
|
|
|
|
|
parser_free();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -913,6 +932,8 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct
|
|
|
|
|
if (!message_eq(0, r1)) exit(1);
|
|
|
|
|
if (!message_eq(1, r2)) exit(1);
|
|
|
|
|
if (!message_eq(2, r3)) exit(1);
|
|
|
|
|
|
|
|
|
|
parser_free();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* SCAN through every possible breaking to make sure the
|
|
|
|
@ -1003,6 +1024,8 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
|
|
|
fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parser_free();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
puts("\b\b\b\b100%");
|
|
|
|
@ -1019,6 +1042,7 @@ error:
|
|
|
|
|
int
|
|
|
|
|
main (void)
|
|
|
|
|
{
|
|
|
|
|
parser = NULL;
|
|
|
|
|
int i, j, k;
|
|
|
|
|
int request_count;
|
|
|
|
|
int response_count;
|
|
|
|
@ -1028,7 +1052,7 @@ main (void)
|
|
|
|
|
for (request_count = 0; requests[request_count].name; request_count++);
|
|
|
|
|
for (response_count = 0; responses[response_count].name; response_count++);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
//// RESPONSES
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < response_count; i++) {
|
|
|
|
@ -1052,6 +1076,7 @@ main (void)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
puts("responses okay");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// REQUESTS
|
|
|
|
|