Update http-parser to 8d9e5db981b623fffc93657abacdc80270cbee58

This commit is contained in:
Tatsuhiro Tsujikawa 2014-05-16 00:23:03 +09:00
parent 694cd07f1d
commit 3b5b5ce254
10 changed files with 253 additions and 84 deletions

View File

@ -972,7 +972,7 @@ int htp_msg_begincb(http_parser *htp)
} // namespace
namespace {
int htp_status_completecb(http_parser *htp)
int htp_statuscb(http_parser *htp, const char *at, size_t length)
{
auto client = static_cast<HttpClient*>(htp->data);
client->upgrade_response_status_code = htp->status_code;
@ -993,7 +993,7 @@ namespace {
http_parser_settings htp_hooks = {
htp_msg_begincb, // http_cb on_message_begin;
nullptr, // http_data_cb on_url;
htp_status_completecb, // http_cb on_status_complete;
htp_statuscb, // http_data_cb on_status;
nullptr, // http_data_cb on_header_field;
nullptr, // http_data_cb on_header_value;
nullptr, // http_cb on_headers_complete;

View File

@ -529,7 +529,7 @@ namespace {
http_parser_settings htp_hooks = {
nullptr, // http_cb on_message_begin;
nullptr, // http_data_cb on_url;
nullptr, // http_cb on_status_complete;
nullptr, // http_data_cb on_status;
nullptr, // http_data_cb on_header_field;
nullptr, // http_data_cb on_header_value;
htp_hdrs_completecb, // http_cb on_headers_complete;

View File

@ -490,7 +490,7 @@ namespace {
http_parser_settings htp_hooks = {
nullptr, // http_cb on_message_begin;
nullptr, // http_data_cb on_url;
nullptr, // http_cb on_status_complete;
nullptr, // http_data_cb on_status;
htp_hdr_keycb, // http_data_cb on_header_field;
htp_hdr_valcb, // http_data_cb on_header_value;
htp_hdrs_completecb, // http_cb on_headers_complete;

View File

@ -248,7 +248,7 @@ namespace {
http_parser_settings htp_hooks = {
htp_msg_begin, // http_cb on_message_begin;
htp_uricb, // http_data_cb on_url;
nullptr, // http_cb on_status_complete;
nullptr, // http_data_cb on_status;
htp_hdr_keycb, // http_data_cb on_header_field;
htp_hdr_valcb, // http_data_cb on_header_value;
htp_hdrs_completecb, // http_cb on_headers_complete;

View File

@ -39,3 +39,12 @@ BogDan Vatra <bogdan@kde.org>
Peter Faiman <peter@thepicard.org>
Corey Richardson <corey@octayn.net>
Tóth Tamás <tomika_nospam@freemail.hu>
Patrik Stutz <patrik.stutz@gmail.com>
Cam Swords <cam.swords@gmail.com>
Chris Dickinson <christopher.s.dickinson@gmail.com>
Uli Köhler <ukoehler@btronik.de>
Charlie Somerville <charlie@charliesomerville.com>
Fedor Indutny <fedor.indutny@gmail.com>
runner <runner.mei@gmail.com>
Alexis Campailla <alexis@janeasystems.com>
David Wragg <david@wragg.org>

View File

@ -61,7 +61,7 @@ if (recved < 0) {
}
/* Start up / continue the parser.
* Note we pass recved==0 to signal that EOF has been recieved.
* Note we pass recved==0 to signal that EOF has been received.
*/
nparsed = http_parser_execute(parser, &settings, buf, recved);

View File

@ -111,14 +111,14 @@ int main(int argc, char* argv[]) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
perror("fopen");
return EXIT_FAILURE;
goto fail;
}
fseek(file, 0, SEEK_END);
long file_length = ftell(file);
if (file_length == -1) {
perror("ftell");
return EXIT_FAILURE;
goto fail;
}
fseek(file, 0, SEEK_SET);
@ -126,7 +126,7 @@ int main(int argc, char* argv[]) {
if (fread(data, 1, file_length, file) != (size_t)file_length) {
fprintf(stderr, "couldn't read entire file\n");
free(data);
return EXIT_FAILURE;
goto fail;
}
http_parser_settings settings;
@ -149,8 +149,12 @@ int main(int argc, char* argv[]) {
"Error: %s (%s)\n",
http_errno_description(HTTP_PARSER_ERRNO(&parser)),
http_errno_name(HTTP_PARSER_ERRNO(&parser)));
return EXIT_FAILURE;
goto fail;
}
return EXIT_SUCCESS;
fail:
fclose(file);
return EXIT_FAILURE;
}

View File

@ -248,6 +248,7 @@ enum state
, s_res_http_minor
, s_res_first_status_code
, s_res_status_code
, s_res_status_start
, s_res_status
, s_res_line_almost_done
@ -279,6 +280,9 @@ enum state
, s_header_field_start
, s_header_field
, s_header_value_discard_ws
, s_header_value_discard_ws_almost_done
, s_header_value_discard_lws
, s_header_value_start
, s_header_value
, s_header_value_lws
@ -581,6 +585,7 @@ size_t http_parser_execute (http_parser *parser,
const char *header_value_mark = 0;
const char *url_mark = 0;
const char *body_mark = 0;
const char *status_mark = 0;
/* We're in an error state. Don't bother doing anything. */
if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
@ -627,6 +632,9 @@ size_t http_parser_execute (http_parser *parser,
case s_req_fragment:
url_mark = data;
break;
case s_res_status:
status_mark = data;
break;
}
for (p=data; p != data + len; p++) {
@ -645,7 +653,7 @@ size_t http_parser_execute (http_parser *parser,
* than any reasonable request or response so this should never affect
* day-to-day operation.
*/
if (parser->nread > HTTP_MAX_HEADER_SIZE) {
if (parser->nread > (HTTP_MAX_HEADER_SIZE)) {
SET_ERRNO(HPE_HEADER_OVERFLOW);
goto error;
}
@ -833,7 +841,7 @@ size_t http_parser_execute (http_parser *parser,
if (!IS_NUM(ch)) {
switch (ch) {
case ' ':
parser->state = s_res_status;
parser->state = s_res_status_start;
break;
case CR:
parser->state = s_res_line_almost_done;
@ -859,9 +867,8 @@ size_t http_parser_execute (http_parser *parser,
break;
}
case s_res_status:
/* the human readable status. e.g. "NOT FOUND"
* we are not humans so just ignore this */
case s_res_status_start:
{
if (ch == CR) {
parser->state = s_res_line_almost_done;
break;
@ -871,12 +878,31 @@ size_t http_parser_execute (http_parser *parser,
parser->state = s_header_field_start;
break;
}
MARK(status);
parser->state = s_res_status;
parser->index = 0;
break;
}
case s_res_status:
if (ch == CR) {
parser->state = s_res_line_almost_done;
CALLBACK_DATA(status);
break;
}
if (ch == LF) {
parser->state = s_header_field_start;
CALLBACK_DATA(status);
break;
}
break;
case s_res_line_almost_done:
STRICT_CHECK(ch != LF);
parser->state = s_header_field_start;
CALLBACK_NOTIFY(status_complete);
break;
case s_start_req:
@ -1357,7 +1383,7 @@ size_t http_parser_execute (http_parser *parser,
}
if (ch == ':') {
parser->state = s_header_value_start;
parser->state = s_header_value_discard_ws;
CALLBACK_DATA(header_field);
break;
}
@ -1378,28 +1404,28 @@ size_t http_parser_execute (http_parser *parser,
goto error;
}
case s_header_value_start:
{
case s_header_value_discard_ws:
if (ch == ' ' || ch == '\t') break;
MARK(header_value);
parser->state = s_header_value;
parser->index = 0;
if (ch == CR) {
parser->header_state = h_general;
parser->state = s_header_almost_done;
CALLBACK_DATA(header_value);
parser->state = s_header_value_discard_ws_almost_done;
break;
}
if (ch == LF) {
parser->state = s_header_field_start;
CALLBACK_DATA(header_value);
parser->state = s_header_value_discard_lws;
break;
}
/* FALLTHROUGH */
case s_header_value_start:
{
MARK(header_value);
parser->state = s_header_value;
parser->index = 0;
c = LOWER(ch);
switch (parser->header_state) {
@ -1486,8 +1512,8 @@ size_t http_parser_execute (http_parser *parser,
t *= 10;
t += ch - '0';
/* Overflow? */
if (t < parser->content_length || t == ULLONG_MAX) {
/* Overflow? Test against a conservative limit for simplicity. */
if ((ULLONG_MAX - 10) / 10 < parser->content_length) {
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
goto error;
}
@ -1547,7 +1573,17 @@ size_t http_parser_execute (http_parser *parser,
STRICT_CHECK(ch != LF);
parser->state = s_header_value_lws;
break;
}
case s_header_value_lws:
{
if (ch == ' ' || ch == '\t') {
parser->state = s_header_value_start;
goto reexecute_byte;
}
/* finished the header */
switch (parser->header_state) {
case h_connection_keep_alive:
parser->flags |= F_CONNECTION_KEEP_ALIVE;
@ -1562,19 +1598,29 @@ size_t http_parser_execute (http_parser *parser,
break;
}
parser->state = s_header_field_start;
goto reexecute_byte;
}
case s_header_value_discard_ws_almost_done:
{
STRICT_CHECK(ch != LF);
parser->state = s_header_value_discard_lws;
break;
}
case s_header_value_lws:
case s_header_value_discard_lws:
{
if (ch == ' ' || ch == '\t')
parser->state = s_header_value_start;
else
{
if (ch == ' ' || ch == '\t') {
parser->state = s_header_value_discard_ws;
break;
} else {
/* header value was empty */
MARK(header_value);
parser->state = s_header_field_start;
CALLBACK_DATA_NOADVANCE(header_value);
goto reexecute_byte;
}
break;
}
case s_headers_almost_done:
@ -1759,8 +1805,8 @@ size_t http_parser_execute (http_parser *parser,
t *= 16;
t += unhex_val;
/* Overflow? */
if (t < parser->content_length || t == ULLONG_MAX) {
/* Overflow? Test against a conservative limit for simplicity. */
if ((ULLONG_MAX - 16) / 16 < parser->content_length) {
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
goto error;
}
@ -1854,12 +1900,14 @@ size_t http_parser_execute (http_parser *parser,
assert(((header_field_mark ? 1 : 0) +
(header_value_mark ? 1 : 0) +
(url_mark ? 1 : 0) +
(body_mark ? 1 : 0)) <= 1);
(body_mark ? 1 : 0) +
(status_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);
return len;
@ -2094,7 +2142,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
u->port = u->field_set = 0;
s = is_connect ? s_req_server_start : s_req_spaces_before_url;
old_uf = UF_MAX;
uf = old_uf = UF_MAX;
for (p = buf; p < buf + buflen; p++) {
s = parse_url_char(s, *p);

View File

@ -26,7 +26,7 @@ extern "C" {
/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 1
#define HTTP_PARSER_VERSION_MINOR 3
#define HTTP_PARSER_VERSION_PATCH 0
#include <sys/types.h>
@ -52,9 +52,16 @@ typedef unsigned __int64 uint64_t;
# define HTTP_PARSER_STRICT 1
#endif
/* Maximium header size allowed */
#define HTTP_MAX_HEADER_SIZE (80*1024)
/* Maximium header size allowed. If the macro is not defined
* before including this header then the default is used. To
* change the maximum header size, define the macro in the build
* environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
* the effective limit on the size of the header, define the macro
* to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
*/
#ifndef HTTP_MAX_HEADER_SIZE
# define HTTP_MAX_HEADER_SIZE (80*1024)
#endif
typedef struct http_parser http_parser;
typedef struct http_parser_settings http_parser_settings;
@ -143,13 +150,13 @@ enum flags
\
/* Callback-related errors */ \
XX(CB_message_begin, "the on_message_begin callback failed") \
XX(CB_status_complete, "the on_status_complete callback failed") \
XX(CB_url, "the on_url callback failed") \
XX(CB_header_field, "the on_header_field callback failed") \
XX(CB_header_value, "the on_header_value callback failed") \
XX(CB_headers_complete, "the on_headers_complete callback failed") \
XX(CB_body, "the on_body callback failed") \
XX(CB_message_complete, "the on_message_complete callback failed") \
XX(CB_status, "the on_status callback failed") \
\
/* Parsing-related errors */ \
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
@ -193,11 +200,11 @@ enum http_errno {
struct http_parser {
/** PRIVATE **/
unsigned char type : 2; /* enum http_parser_type */
unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
unsigned char state; /* enum state from http_parser.c */
unsigned char header_state; /* enum header_state from http_parser.c */
unsigned char index; /* index into current matcher */
unsigned int type : 2; /* enum http_parser_type */
unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */
unsigned int state : 8; /* enum state from http_parser.c */
unsigned int header_state : 8; /* enum header_state from http_parser.c */
unsigned int index : 8; /* index into current matcher */
uint32_t nread; /* # bytes read in various scenarios */
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
@ -205,16 +212,16 @@ struct http_parser {
/** READ-ONLY **/
unsigned short http_major;
unsigned short http_minor;
unsigned short status_code; /* responses only */
unsigned char method; /* requests only */
unsigned char http_errno : 7;
unsigned int status_code : 16; /* responses only */
unsigned int method : 8; /* requests only */
unsigned int http_errno : 7;
/* 1 = Upgrade header was present and the parser has exited because of that.
* 0 = No upgrade header present.
* Should be checked when http_parser_execute() returns in addition to
* error checking.
*/
unsigned char upgrade : 1;
unsigned int upgrade : 1;
/** PUBLIC **/
void *data; /* A pointer to get hook to the "connection" or "socket" object */
@ -224,7 +231,7 @@ struct http_parser {
struct http_parser_settings {
http_cb on_message_begin;
http_data_cb on_url;
http_cb on_status_complete;
http_data_cb on_status;
http_data_cb on_header_field;
http_data_cb on_header_value;
http_cb on_headers_complete;

View File

@ -26,6 +26,12 @@
#include <string.h>
#include <stdarg.h>
#if defined(__APPLE__)
# undef strlcat
# undef strlncpy
# undef strlcpy
#endif /* defined(__APPLE__) */
#undef TRUE
#define TRUE 1
#undef FALSE
@ -44,6 +50,7 @@ struct message {
enum http_parser_type type;
enum http_method method;
int status_code;
char response_status[MAX_ELEMENT_SIZE];
char request_path[MAX_ELEMENT_SIZE];
char request_url[MAX_ELEMENT_SIZE];
char fragment[MAX_ELEMENT_SIZE];
@ -601,8 +608,14 @@ const struct message requests[] =
" mno \r\n"
"\t \tqrs\r\n"
"Line2: \t line2\t\r\n"
"Line3:\r\n"
" line3\r\n"
"Line4: \r\n"
" \r\n"
"Connection:\r\n"
" close\r\n"
"\r\n"
,.should_keep_alive= TRUE
,.should_keep_alive= FALSE
,.message_complete_on_eof= FALSE
,.http_major= 1
,.http_minor= 1
@ -611,9 +624,12 @@ const struct message requests[] =
,.fragment= ""
,.request_path= "/"
,.request_url= "/"
,.num_headers= 2
,.headers= { { "Line1", "abcdefghijklmno qrs" }
,.num_headers= 5
,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
, { "Line2", "line2\t" }
, { "Line3", "line3" }
, { "Line4", "" }
, { "Connection", "close" },
}
,.body= ""
}
@ -897,6 +913,43 @@ const struct message requests[] =
,.body= ""
}
#define LINE_FOLDING_IN_HEADER_WITH_LF 34
, {.name= "line folding in header value"
,.type= HTTP_REQUEST
,.raw= "GET / HTTP/1.1\n"
"Line1: abc\n"
"\tdef\n"
" ghi\n"
"\t\tjkl\n"
" mno \n"
"\t \tqrs\n"
"Line2: \t line2\t\n"
"Line3:\n"
" line3\n"
"Line4: \n"
" \n"
"Connection:\n"
" close\n"
"\n"
,.should_keep_alive= FALSE
,.message_complete_on_eof= FALSE
,.http_major= 1
,.http_minor= 1
,.method= HTTP_GET
,.query_string= ""
,.fragment= ""
,.request_path= "/"
,.request_url= "/"
,.num_headers= 5
,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
, { "Line2", "line2\t" }
, { "Line3", "line3" }
, { "Line4", "" }
, { "Connection", "close" },
}
,.body= ""
}
, {.name= NULL } /* sentinel */
};
@ -927,6 +980,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 301
,.response_status= "Moved Permanently"
,.num_headers= 8
,.headers=
{ { "Location", "http://www.google.com/" }
@ -975,6 +1029,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 5
,.headers=
{ { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
@ -1003,6 +1058,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 404
,.response_status= "Not Found"
,.num_headers= 0
,.headers= {}
,.body_size= 0
@ -1018,6 +1074,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 301
,.response_status= ""
,.num_headers= 0
,.headers= {}
,.body= ""
@ -1043,6 +1100,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 2
,.headers=
{ {"Content-Type", "text/plain" }
@ -1068,6 +1126,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 2
,.headers=
{ {"Content-Type", "text/html; charset=utf-8" }
@ -1091,6 +1150,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 4
,.headers=
{ {"Content-Type", "text/html; charset=UTF-8" }
@ -1116,6 +1176,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 4
,.headers=
{ {"Server", "DCLK-AdSvr" }
@ -1148,6 +1209,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 0
,.status_code= 301
,.response_status= "Moved Permanently"
,.num_headers= 9
,.headers=
{ { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }
@ -1186,6 +1248,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 11
,.headers=
{ { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }
@ -1217,6 +1280,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 500
,.response_status= "Oriëntatieprobleem"
,.num_headers= 3
,.headers=
{ { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }
@ -1237,6 +1301,7 @@ const struct message responses[] =
,.http_major= 0
,.http_minor= 9
,.status_code= 200
,.response_status= "OK"
,.num_headers= 0
,.headers=
{}
@ -1259,6 +1324,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 1
,.headers=
{ { "Content-Type", "text/plain" }
@ -1277,6 +1343,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 0
,.status_code= 200
,.response_status= "OK"
,.num_headers= 1
,.headers=
{ { "Connection", "keep-alive" }
@ -1296,6 +1363,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 0
,.status_code= 204
,.response_status= "No content"
,.num_headers= 1
,.headers=
{ { "Connection", "keep-alive" }
@ -1314,6 +1382,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 0
,.headers={}
,.body_size= 0
@ -1330,6 +1399,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 204
,.response_status= "No content"
,.num_headers= 0
,.headers={}
,.body_size= 0
@ -1347,6 +1417,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 204
,.response_status= "No content"
,.num_headers= 1
,.headers=
{ { "Connection", "close" }
@ -1368,6 +1439,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 1
,.headers=
{ { "Transfer-Encoding", "chunked" }
@ -1396,6 +1468,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= "OK"
,.num_headers= 7
,.headers=
{ { "Server", "Microsoft-IIS/6.0" }
@ -1433,6 +1506,7 @@ const struct message responses[] =
,.http_major= 1
,.http_minor= 1
,.status_code= 301
,.response_status= "MovedPermanently"
,.num_headers= 9
,.headers= { { "Date", "Wed, 15 May 2013 17:06:33 GMT" }
, { "Server", "Server" }
@ -1447,6 +1521,22 @@ const struct message responses[] =
,.body= "\n"
}
#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
, {.name= "empty reason phrase after space"
,.type= HTTP_RESPONSE
,.raw= "HTTP/1.1 200 \r\n"
"\r\n"
,.should_keep_alive= FALSE
,.message_complete_on_eof= TRUE
,.http_major= 1
,.http_minor= 1
,.status_code= 200
,.response_status= ""
,.num_headers= 0
,.headers= {}
,.body= ""
}
, {.name= NULL } /* sentinel */
};
@ -1528,13 +1618,6 @@ request_url_cb (http_parser *p, const char *buf, size_t len)
return 0;
}
int
status_complete_cb (http_parser *p) {
assert(p == parser);
p->data++;
return 0;
}
int
header_field_cb (http_parser *p, const char *buf, size_t len)
{
@ -1660,6 +1743,17 @@ message_complete_cb (http_parser *p)
return 0;
}
int
response_status_cb (http_parser *p, const char *buf, size_t len)
{
assert(p == parser);
strlncat(messages[num_messages].response_status,
sizeof(messages[num_messages].response_status),
buf,
len);
return 0;
}
/* These dontcall_* callbacks exist so that we can verify that when we're
* paused, no additional callbacks are invoked */
int
@ -1720,11 +1814,20 @@ dontcall_message_complete_cb (http_parser *p)
abort();
}
int
dontcall_response_status_cb (http_parser *p, const char *buf, size_t len)
{
if (p || buf || len) { } // gcc
fprintf(stderr, "\n\n*** on_status() called on paused parser ***\n\n");
abort();
}
static http_parser_settings settings_dontcall =
{.on_message_begin = dontcall_message_begin_cb
,.on_header_field = dontcall_header_field_cb
,.on_header_value = dontcall_header_value_cb
,.on_url = dontcall_request_url_cb
,.on_status = dontcall_response_status_cb
,.on_body = dontcall_body_cb
,.on_headers_complete = dontcall_headers_complete_cb
,.on_message_complete = dontcall_message_complete_cb
@ -1790,11 +1893,20 @@ pause_message_complete_cb (http_parser *p)
return message_complete_cb(p);
}
int
pause_response_status_cb (http_parser *p, const char *buf, size_t len)
{
http_parser_pause(p, 1);
*current_pause_parser = settings_dontcall;
return response_status_cb(p, buf, len);
}
static http_parser_settings settings_pause =
{.on_message_begin = pause_message_begin_cb
,.on_header_field = pause_header_field_cb
,.on_header_value = pause_header_value_cb
,.on_url = pause_request_url_cb
,.on_status = pause_response_status_cb
,.on_body = pause_body_cb
,.on_headers_complete = pause_headers_complete_cb
,.on_message_complete = pause_message_complete_cb
@ -1805,6 +1917,7 @@ static http_parser_settings settings =
,.on_header_field = header_field_cb
,.on_header_value = header_value_cb
,.on_url = request_url_cb
,.on_status = response_status_cb
,.on_body = body_cb
,.on_headers_complete = headers_complete_cb
,.on_message_complete = message_complete_cb
@ -1815,6 +1928,7 @@ static http_parser_settings settings_count_body =
,.on_header_field = header_field_cb
,.on_header_value = header_value_cb
,.on_url = request_url_cb
,.on_status = response_status_cb
,.on_body = count_body_cb
,.on_headers_complete = headers_complete_cb
,.on_message_complete = message_complete_cb
@ -1825,6 +1939,7 @@ static http_parser_settings settings_null =
,.on_header_field = 0
,.on_header_value = 0
,.on_url = 0
,.on_status = 0
,.on_body = 0
,.on_headers_complete = 0
,.on_message_complete = 0
@ -1948,6 +2063,7 @@ message_eq (int index, const struct message *expected)
MESSAGE_CHECK_NUM_EQ(expected, m, method);
} else {
MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
MESSAGE_CHECK_STR_EQ(expected, m, response_status);
}
MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);
@ -2868,7 +2984,7 @@ test_header_content_length_overflow_error (void)
"HTTP/1.1 200 OK\r\n" \
"Content-Length: " #size "\r\n" \
"\r\n"
const char a[] = X(18446744073709551614); /* 2^64-2 */
const char a[] = X(1844674407370955160); /* 2^64 / 10 - 1 */
const char b[] = X(18446744073709551615); /* 2^64-1 */
const char c[] = X(18446744073709551616); /* 2^64 */
#undef X
@ -2886,7 +3002,7 @@ test_chunk_content_length_overflow_error (void)
"\r\n" \
#size "\r\n" \
"..."
const char a[] = X(FFFFFFFFFFFFFFFE); /* 2^64-2 */
const char a[] = X(FFFFFFFFFFFFFFE); /* 2^64 / 16 - 1 */
const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */
const char c[] = X(10000000000000000); /* 2^64 */
#undef X
@ -3133,20 +3249,6 @@ create_large_chunked_message (int body_size_in_kb, const char* headers)
return buf;
}
void
test_status_complete (void)
{
parser_init(HTTP_RESPONSE);
parser->data = 0;
http_parser_settings settings = settings_null;
settings.on_status_complete = status_complete_cb;
char *response = "don't mind me, just a simple response";
http_parser_execute(parser, &settings, response, strlen(response));
assert(parser->data == (void*)0); // the status_complete callback was never called
assert(parser->http_errno == HPE_INVALID_CONSTANT); // the errno for an invalid status line
}
/* Verify that we can pause parsing at any of the bytes in the
* message and still get the result that we're expecting. */
void
@ -3280,6 +3382,7 @@ main (void)
,.http_major= 1
,.http_minor= 0
,.status_code= 200
,.response_status= "OK"
,.num_headers= 2
,.headers=
{ { "Transfer-Encoding", "chunked" }
@ -3468,8 +3571,6 @@ main (void)
, &requests[CONNECT_REQUEST]
);
test_status_complete();
puts("requests okay");
return 0;