Browse Source

Upgrade http-parser

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
11a784d6da
  1. 21
      deps/http_parser/http_parser.c
  2. 4
      deps/http_parser/http_parser.h
  3. 80
      deps/http_parser/test.c

21
deps/http_parser/http_parser.c

@ -22,7 +22,16 @@
* IN THE SOFTWARE.
*/
#include <http_parser.h>
#ifdef _WIN32
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int16 int32_t;
typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif
#include <assert.h>
#include <stddef.h>
@ -148,7 +157,7 @@ static const uint32_t usual[] = {
enum state
{ s_dead = 1 /* important that this is > 0 */
, s_start_res_or_resp
, s_start_req_or_res
, s_res_or_resp_H
, s_start_res
, s_res_H
@ -315,6 +324,7 @@ size_t http_parser_execute (http_parser *parser,
if (state == s_req_path || state == s_req_schema || state == s_req_schema_slash
|| state == s_req_schema_slash_slash || state == s_req_port
|| state == s_req_query_string_start || state == s_req_query_string
|| state == s_req_host
|| state == s_req_fragment_start || state == s_req_fragment)
url_mark = data;
@ -335,7 +345,7 @@ size_t http_parser_execute (http_parser *parser,
*/
goto error;
case s_start_res_or_resp:
case s_start_req_or_res:
{
if (ch == CR || ch == LF)
break;
@ -1306,7 +1316,7 @@ size_t http_parser_execute (http_parser *parser,
nread = 0;
if (parser->flags & F_UPGRADE) parser->upgrade = 1;
if (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT) parser->upgrade = 1;
/* Here we call the headers_complete callback. This is somewhat
* different than other callbacks because if the user returns 1, we
@ -1329,7 +1339,7 @@ size_t http_parser_execute (http_parser *parser,
}
// Exit, the rest of the connect is in a different protocol.
if (parser->flags & F_UPGRADE) {
if (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT) {
CALLBACK2(message_complete);
return (p - data);
}
@ -1532,7 +1542,8 @@ void
http_parser_init (http_parser *parser, enum http_parser_type t)
{
parser->type = t;
parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_res_or_resp));
parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
parser->nread = 0;
parser->upgrade = 0;
parser->flags = 0;
}

4
deps/http_parser/http_parser.h

@ -27,6 +27,10 @@ extern "C" {
#include <sys/types.h>
#ifdef _WIN32
typedef unsigned int size_t;
typedef int ssize_t;
#endif
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
* faster

80
deps/http_parser/test.c

@ -512,7 +512,7 @@ const struct message requests[] =
,.request_path= ""
,.request_url= "home.netscape.com:443"
,.num_headers= 2
,.upgrade=0
,.upgrade=1
,.headers= { { "User-agent", "Mozilla/1.1N" }
, { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
}
@ -1129,16 +1129,34 @@ print_error (const char *raw, size_t error_location)
void
test_message (const struct message *message)
{
size_t raw_len = strlen(message->raw);
size_t msg1len;
for (msg1len = 0; msg1len < raw_len; msg1len++) {
parser_init(message->type);
size_t read;
const char *msg1 = message->raw;
const char *msg2 = msg1 + msg1len;
size_t msg2len = raw_len - msg1len;
read = parse(message->raw, strlen(message->raw));
if (msg1len) {
read = parse(msg1, msg1len);
if (message->upgrade && parser->upgrade) goto test;
if (read != strlen(message->raw)) {
print_error(message->raw, read);
if (read != msg1len) {
print_error(msg1, read);
exit(1);
}
}
read = parse(msg2, msg2len);
if (message->upgrade && parser->upgrade) goto test;
if (read != msg2len) {
print_error(msg2, read);
exit(1);
}
@ -1151,7 +1169,7 @@ test_message (const struct message *message)
exit(1);
}
test:
test:
if (num_messages != 1) {
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
@ -1161,6 +1179,7 @@ test:
if(!message_eq(0, message)) exit(1);
parser_free();
}
}
void
@ -1388,18 +1407,27 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
buf3[buf3_len] = 0;
read = parse(buf1, buf1_len);
if (r3->upgrade && parser->upgrade) goto test;
if (read != buf1_len) {
print_error(buf1, read);
goto error;
}
read = parse(buf2, buf2_len);
if (r3->upgrade && parser->upgrade) goto test;
if (read != buf2_len) {
print_error(buf2, read);
goto error;
}
read = parse(buf3, buf3_len);
if (r3->upgrade && parser->upgrade) goto test;
if (read != buf3_len) {
print_error(buf3, read);
goto error;
@ -1407,6 +1435,8 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
parse(NULL, 0);
test:
if (3 != num_messages) {
fprintf(stderr, "\n\nParser didn't see 3 messages only %d\n", num_messages);
goto error;
@ -1448,23 +1478,17 @@ char *
create_large_chunked_message (int body_size_in_kb, const char* headers)
{
int i;
size_t needed, wrote = 0;
size_t wrote = 0;
size_t headers_len = strlen(headers);
size_t bufsize = headers_len + 10;
size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6;
char * buf = malloc(bufsize);
strncpy(buf, headers, headers_len);
memcpy(buf, headers, headers_len);
wrote += headers_len;
for (i = 0; i < body_size_in_kb; i++) {
// write 1kb chunk into the body.
needed = 5 + 1024 + 2; // "400\r\nCCCC...CCCC\r\n"
if (bufsize - wrote < needed) {
buf = realloc(buf, bufsize + needed);
bufsize += needed;
}
strcpy(buf + wrote, "400\r\n");
memcpy(buf + wrote, "400\r\n", 5);
wrote += 5;
memset(buf + wrote, 'C', 1024);
wrote += 1024;
@ -1472,15 +1496,9 @@ create_large_chunked_message (int body_size_in_kb, const char* headers)
wrote += 2;
}
needed = 5; // "0\r\n\r\n"
if (bufsize - wrote < needed) {
buf = realloc(buf, bufsize + needed);
bufsize += needed;
}
strcpy(buf + wrote, "0\r\n\r\n");
wrote += 5;
assert(buf[wrote] == 0);
memcpy(buf + wrote, "0\r\n\r\n", 6);
wrote += 6;
assert(wrote == bufsize);
return buf;
}
@ -1588,7 +1606,7 @@ main (void)
"HEAD",
"POST",
"PUT",
"CONNECT",
//"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel
"OPTIONS",
"TRACE",
"COPY",
@ -1675,24 +1693,30 @@ main (void)
}
}
printf("request scan 1/3 ");
printf("request scan 1/4 ");
test_scan( &requests[GET_NO_HEADERS_NO_BODY]
, &requests[GET_ONE_HEADER_NO_BODY]
, &requests[GET_NO_HEADERS_NO_BODY]
);
printf("request scan 2/3 ");
printf("request scan 2/4 ");
test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE]
, &requests[POST_IDENTITY_BODY_WORLD]
, &requests[GET_FUNKY_CONTENT_LENGTH]
);
printf("request scan 3/3 ");
printf("request scan 3/4 ");
test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
, &requests[CHUNKED_W_TRAILING_HEADERS]
, &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]
);
printf("request scan 4/4 ");
test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET]
, &requests[PREFIX_NEWLINE_GET ]
, &requests[CONNECT_REQUEST]
);
puts("requests okay");
return 0;

Loading…
Cancel
Save