From 5b00b6a64fb75cdfad2c5f98571c450378700bf5 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Fri, 20 Nov 2009 15:36:55 +0100 Subject: [PATCH] add http_should_keep_alive() --- http_parser.c | 63 +++++++++++++++++++++++++++++++-------------------- http_parser.h | 6 +++++ test.c | 4 ++-- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/http_parser.c b/http_parser.c index 7362c24..e4948f7 100644 --- a/http_parser.c +++ b/http_parser.c @@ -146,7 +146,9 @@ static const uint32_t usual[] = { }; enum state - { s_start_res = 1 /* important that this is > 0 */ + { s_dead = 1 /* important that this is > 0 */ + + , s_start_res , s_res_H , s_res_HT , s_res_HTT @@ -289,6 +291,12 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state ch = *p; switch (state) { + case s_dead: + /* this state is used after a 'Connection: close' message + * the parser will error out if it reads another message + */ + return 0; + case s_start_res: { parser->flags = 0; @@ -1241,7 +1249,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state if (parser->flags & F_TRAILING) { /* End of a chunked request */ CALLBACK2(message_complete); - state = start_state; + state = http_should_keep_alive(parser) ? start_state : s_dead; break; } @@ -1256,32 +1264,18 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state if (parser->content_length == 0) { /* Content-Length header given but zero: Content-Length: 0\r\n */ CALLBACK2(message_complete); - state = start_state; + state = http_should_keep_alive(parser) ? start_state : s_dead; } else if (parser->content_length > 0) { /* Content-Length header given and non-zero */ state = s_body_identity; } else { - /* No Content-Length header, not chunked */ - if (parser->http_major > 0 && parser->http_minor > 0) { - /* HTTP/1.0 or HTTP/1.1 */ - if (parser->flags & F_CONNECTION_CLOSE) { - /* Read body until EOF */ - state = s_body_identity_eof; - } else { - /* Message is done - read the next */ - CALLBACK2(message_complete); - state = start_state; - } + if (http_should_keep_alive(parser)) { + /* Assume content-length 0 - read the next */ + CALLBACK2(message_complete); + state = start_state; } else { - /* HTTP/1.0 or earlier */ - if (parser->flags & F_CONNECTION_KEEP_ALIVE) { - /* Message is done - read the next */ - CALLBACK2(message_complete); - state = start_state; - } else { - /* Read body until EOF */ - state = s_body_identity_eof; - } + /* Read body until EOF */ + state = s_body_identity_eof; } } } @@ -1297,7 +1291,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state parser->body_read += to_read; if (parser->body_read == parser->content_length) { CALLBACK2(message_complete); - state = start_state; + state = http_should_keep_alive(parser) ? start_state : s_dead; } } break; @@ -1440,6 +1434,27 @@ http_parse_responses (http_parser *parser, const char *data, size_t len) } +int +http_should_keep_alive (http_parser *parser) +{ + if (parser->http_major > 0 && parser->http_minor > 0) { + /* HTTP/1.1 */ + if (parser->flags & F_CONNECTION_CLOSE) { + return 0; + } else { + return 1; + } + } else { + /* HTTP/1.0 or earlier */ + if (parser->flags & F_CONNECTION_KEEP_ALIVE) { + return 1; + } else { + return 0; + } + } +} + + void http_parser_init (http_parser *parser) { diff --git a/http_parser.h b/http_parser.h index eaca330..d27c068 100644 --- a/http_parser.h +++ b/http_parser.h @@ -112,6 +112,12 @@ struct http_parser { void http_parser_init(http_parser *parser); size_t http_parse_requests(http_parser *parser, const char *data, size_t len); size_t http_parse_responses(http_parser *parser, const char *data, size_t len); +/* Call this in the on_headers_complete or on_message_complete callback to + * determine if this will be the last message on the connection. + * If you are the server, respond with the "Connection: close" header + * if you are the client, close the connection. + */ +int http_should_keep_alive(http_parser *parser); #ifdef __cplusplus } diff --git a/test.c b/test.c index 62fe943..8658235 100644 --- a/test.c +++ b/test.c @@ -1085,9 +1085,9 @@ main (void) ); printf("request scan 2/3 "); - test_scan( &requests[GET_FUNKY_CONTENT_LENGTH] + test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE] , &requests[POST_IDENTITY_BODY_WORLD] - , &requests[POST_CHUNKED_ALL_YOUR_BASE] + , &requests[GET_FUNKY_CONTENT_LENGTH] ); printf("request scan 3/3 ");