Skip to content
This repository has been archived by the owner on Nov 6, 2022. It is now read-only.

Chunk extensions callbacks #430

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions http_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ size_t http_parser_execute (http_parser *parser,
const char *url_mark = 0;
const char *body_mark = 0;
const char *status_mark = 0;
const char *chunk_extensions_mark = 0;
enum state p_state = (enum state) parser->state;
const unsigned int lenient = parser->lenient_http_headers;

Expand Down Expand Up @@ -676,6 +677,8 @@ size_t http_parser_execute (http_parser *parser,
header_field_mark = data;
if (CURRENT_STATE() == s_header_value)
header_value_mark = data;
if (CURRENT_STATE() == s_chunk_parameters)
chunk_extensions_mark = data;
switch (CURRENT_STATE()) {
case s_req_path:
case s_req_schema:
Expand Down Expand Up @@ -1917,10 +1920,11 @@ size_t http_parser_execute (http_parser *parser,

if (unhex_val == -1) {
if (ch == ';' || ch == ' ') {
/* Parse chunk extensions */
MARK(chunk_extensions);
UPDATE_STATE(s_chunk_parameters);
break;
}

SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
goto error;
}
Expand All @@ -1945,6 +1949,7 @@ size_t http_parser_execute (http_parser *parser,
/* just ignore this shit. TODO check for overflow */
if (ch == CR) {
UPDATE_STATE(s_chunk_size_almost_done);
CALLBACK_DATA(chunk_extensions);
break;
}
break;
Expand Down Expand Up @@ -2027,13 +2032,15 @@ size_t http_parser_execute (http_parser *parser,
(header_value_mark ? 1 : 0) +
(url_mark ? 1 : 0) +
(body_mark ? 1 : 0) +
(status_mark ? 1 : 0)) <= 1);
(status_mark ? 1 : 0) +
(chunk_extensions_mark ? 1 : 0)) <= 1);

CALLBACK_DATA_NOADVANCE(header_field);
CALLBACK_DATA_NOADVANCE(header_value);
CALLBACK_DATA_NOADVANCE(url);
CALLBACK_DATA_NOADVANCE(body);
CALLBACK_DATA_NOADVANCE(status);
CALLBACK_DATA_NOADVANCE(chunk_extensions);

RETURN(len);

Expand Down
2 changes: 2 additions & 0 deletions http_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ enum flags
XX(CB_status, "the on_status callback failed") \
XX(CB_chunk_header, "the on_chunk_header callback failed") \
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
XX(CB_chunk_extensions, "the on_chunk_extensions callback failed") \
\
/* Parsing-related errors */ \
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
Expand Down Expand Up @@ -335,6 +336,7 @@ struct http_parser_settings {
*/
http_cb on_chunk_header;
http_cb on_chunk_complete;
http_data_cb on_chunk_extensions;
};


Expand Down
44 changes: 44 additions & 0 deletions test.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct message {
int num_chunks;
int num_chunks_complete;
int chunk_lengths[MAX_CHUNKS];
char chunk_extensions[MAX_CHUNKS][MAX_ELEMENT_SIZE];

const char *upgrade; // upgraded body

Expand Down Expand Up @@ -397,6 +398,10 @@ const struct message requests[] =
,.body= "hello world"
,.num_chunks_complete= 3
,.chunk_lengths= { 5, 6 }
,.chunk_extensions =
{ "; ihatew3;whatthefuck=aretheseparametersfor"
, "; blahblah; blah"
}
}

#define WITH_QUOTES 12
Expand Down Expand Up @@ -1333,6 +1338,7 @@ const struct message responses[] =
"and this is the second one\r\n"
,.num_chunks_complete= 3
,.chunk_lengths= { 0x25, 0x1c }
,.chunk_extensions = { " ", "" , " " }
}

#define NO_CARRIAGE_RET 5
Expand Down Expand Up @@ -2186,6 +2192,20 @@ chunk_complete_cb (http_parser *p)
return 0;
}

int
chunk_extensions_cb (http_parser *p, const char *buf, size_t len)
{
assert(p == parser);

struct message *m = &messages[num_messages];
strlncat(m->chunk_extensions[m->num_chunks],
sizeof(m->chunk_extensions[m->num_chunks]),
buf,
len);

return 0;
}

/* These dontcall_* callbacks exist so that we can verify that when we're
* paused, no additional callbacks are invoked */
int
Expand Down Expand Up @@ -2271,6 +2291,15 @@ dontcall_chunk_complete_cb (http_parser *p)
exit(1);
}

int
dontcall_chunk_extensions_cb (http_parser *p, const char *buf, size_t len)
{
if (p || buf || len) { } // gcc
fprintf(stderr, "\n\n*** on_chunk_extensions() "
"called on paused parser ***\n\n");
exit(1);
}

static http_parser_settings settings_dontcall =
{.on_message_begin = dontcall_message_begin_cb
,.on_header_field = dontcall_header_field_cb
Expand All @@ -2282,6 +2311,7 @@ static http_parser_settings settings_dontcall =
,.on_message_complete = dontcall_message_complete_cb
,.on_chunk_header = dontcall_chunk_header_cb
,.on_chunk_complete = dontcall_chunk_complete_cb
,.on_chunk_extensions = dontcall_chunk_extensions_cb
};

/* These pause_* callbacks always pause the parser and just invoke the regular
Expand Down Expand Up @@ -2368,6 +2398,14 @@ pause_chunk_complete_cb (http_parser *p)
return chunk_complete_cb(p);
}

int
pause_chunk_extensions_cb (http_parser *p, const char *buf, size_t len)
{
http_parser_pause(p, 1);
*current_pause_parser = settings_dontcall;
return chunk_extensions_cb(p, buf, len);
}

int
connect_headers_complete_cb (http_parser *p)
{
Expand All @@ -2393,6 +2431,7 @@ static http_parser_settings settings_pause =
,.on_message_complete = pause_message_complete_cb
,.on_chunk_header = pause_chunk_header_cb
,.on_chunk_complete = pause_chunk_complete_cb
,.on_chunk_extensions = pause_chunk_extensions_cb
};

static http_parser_settings settings =
Expand All @@ -2406,6 +2445,7 @@ static http_parser_settings settings =
,.on_message_complete = message_complete_cb
,.on_chunk_header = chunk_header_cb
,.on_chunk_complete = chunk_complete_cb
,.on_chunk_extensions = chunk_extensions_cb
};

static http_parser_settings settings_count_body =
Expand All @@ -2419,6 +2459,7 @@ static http_parser_settings settings_count_body =
,.on_message_complete = message_complete_cb
,.on_chunk_header = chunk_header_cb
,.on_chunk_complete = chunk_complete_cb
,.on_chunk_extensions = chunk_extensions_cb
};

static http_parser_settings settings_connect =
Expand All @@ -2432,6 +2473,7 @@ static http_parser_settings settings_connect =
,.on_message_complete = connect_message_complete_cb
,.on_chunk_header = chunk_header_cb
,.on_chunk_complete = chunk_complete_cb
,.on_chunk_extensions = chunk_extensions_cb
};

static http_parser_settings settings_null =
Expand All @@ -2445,6 +2487,7 @@ static http_parser_settings settings_null =
,.on_message_complete = 0
,.on_chunk_header = 0
,.on_chunk_complete = 0
,.on_chunk_extensions = 0
};

void
Expand Down Expand Up @@ -2633,6 +2676,7 @@ message_eq (int index, int connect, const struct message *expected)
MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete);
for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) {
MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]);
MESSAGE_CHECK_STR_EQ(expected, m, chunk_extensions[i]);
}
}

Expand Down