changeset 21559:7163fa58c41e

lib-http: message parser: Don't allocate a pool for the next message until it is needed. This prevents wasting memory when no message is being parsed.
author Stephan Bosch <stephan.bosch@dovecot.fi>
date Sat, 04 Feb 2017 13:59:10 +0100
parents 390c3ef87cc8
children a304fb6bb606
files src/lib-http/http-message-parser.c src/lib-http/http-message-parser.h src/lib-http/http-request-parser.c src/lib-http/http-response-parser.c
diffstat 4 files changed, 34 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-http/http-message-parser.c	Sat Feb 04 14:11:36 2017 +0100
+++ b/src/lib-http/http-message-parser.c	Sat Feb 04 13:59:10 2017 +0100
@@ -54,15 +54,20 @@
 	if (parser->msg.pool != NULL)
 		pool_unref(&parser->msg.pool);
 	i_zero(&parser->msg);
-	if (pool == NULL) {
-		parser->msg.pool = pool_alloconly_create("http_message", 4096);
-	} else {
+	if (pool != NULL) {
 		parser->msg.pool = pool;
 		pool_ref(pool);
 	}
 	parser->msg.date = (time_t)-1;
 }
 
+pool_t http_message_parser_get_pool(struct http_message_parser *parser)
+{
+	if (parser->msg.pool == NULL)
+		parser->msg.pool = pool_alloconly_create("http_message", 4096);
+	return parser->msg.pool;
+}
+
 int http_message_parse_version(struct http_message_parser *parser)
 {
 	const unsigned char *p = parser->cur;
@@ -130,9 +135,11 @@
 {
 	const struct http_header_field *hdr;
 	struct http_parser hparser;
+	pool_t pool;
 
+	pool = http_message_parser_get_pool(parser);
 	if (parser->msg.header == NULL)
-		parser->msg.header = http_header_create(parser->msg.pool, 32);
+		parser->msg.header = http_header_create(pool, 32);
 	hdr = http_header_field_add(parser->msg.header, name, data, size);
 
 	/* RFC 7230, Section 3.2.2: Field Order
@@ -166,9 +173,9 @@
 				if (strcasecmp(option, "close") == 0)
 					parser->msg.connection_close = TRUE;
 				if (!array_is_created(&parser->msg.connection_options))
-					p_array_init(&parser->msg.connection_options, parser->msg.pool, 4);
+					p_array_init(&parser->msg.connection_options, pool, 4);
 				opt_idx = array_append_space(&parser->msg.connection_options);
-				*opt_idx = p_strdup(parser->msg.pool, option);
+				*opt_idx = p_strdup(pool, option);
 			}
 
 			if (hparser.cur < hparser.end || num_tokens == 0) {
@@ -238,7 +245,7 @@
 	
 			/* Multiple Transfer-Encoding headers are allowed and combined into one */
 			if (!array_is_created(&parser->msg.transfer_encoding))
-				p_array_init(&parser->msg.transfer_encoding, parser->msg.pool, 4);
+				p_array_init(&parser->msg.transfer_encoding, pool, 4);
 
 			/* RFC 7230, Section 3.3.1: Transfer-Encoding
 
@@ -262,7 +269,7 @@
 					bool parse_error;
 
 					coding = array_append_space(&parser->msg.transfer_encoding);
-					coding->name = p_strdup(parser->msg.pool, trenc);
+					coding->name = p_strdup(pool, trenc);
 		
 					/* *( OWS ";" OWS transfer-parameter ) */
 					parse_error = FALSE;
@@ -299,10 +306,10 @@
 						}
 		
 						if (!array_is_created(&coding->parameters))
-							p_array_init(&coding->parameters, parser->msg.pool, 2);
+							p_array_init(&coding->parameters, pool, 2);
 						param = array_append_space(&coding->parameters);
-						param->attribute = p_strdup(parser->msg.pool, attribute);
-						param->value = p_strdup(parser->msg.pool, value);
+						param->attribute = p_strdup(pool, attribute);
+						param->value = p_strdup(pool, value);
 					}
 					if (parse_error)
 						break;
@@ -355,11 +362,13 @@
 	while ((ret=http_header_parse_next_field(parser->header_parser,
 		&field_name, &field_data, &field_size, &error)) > 0) {
 		if (field_name == NULL) {
+			pool_t pool;
 			/* EOH */
 
 			/* Create empty header if there is none */
+			pool = http_message_parser_get_pool(parser);
 			if (parser->msg.header == NULL)
-				parser->msg.header = http_header_create(parser->msg.pool, 1);
+				parser->msg.header = http_header_create(pool, 1);
 
 			/* handle HTTP/1.0 persistence */
 			if (msg->version_major == 1 && msg->version_minor == 0 &&
--- a/src/lib-http/http-message-parser.h	Sat Feb 04 14:11:36 2017 +0100
+++ b/src/lib-http/http-message-parser.h	Sat Feb 04 13:59:10 2017 +0100
@@ -62,6 +62,8 @@
 void http_message_parser_restart(struct http_message_parser *parser,
 	pool_t pool);
 
+pool_t http_message_parser_get_pool(struct http_message_parser *parser);
+
 int http_message_parse_finish_payload(struct http_message_parser *parser);
 int http_message_parse_version(struct http_message_parser *parser);
 int http_message_parse_headers(struct http_message_parser *parser);
--- a/src/lib-http/http-request-parser.c	Sat Feb 04 14:11:36 2017 +0100
+++ b/src/lib-http/http-request-parser.c	Sat Feb 04 13:59:10 2017 +0100
@@ -92,6 +92,7 @@
 static int http_request_parse_method(struct http_request_parser *parser)
 {
 	const unsigned char *p = parser->parser.cur;
+	pool_t pool;
 
 	/* method         = token
 	 */
@@ -105,8 +106,9 @@
 	}
 	if (p == parser->parser.end)
 		return 0;
+	pool = http_message_parser_get_pool(&parser->parser);
 	parser->request_method =
-		p_strdup_until(parser->parser.msg.pool, parser->parser.cur, p);
+		p_strdup_until(pool, parser->parser.cur, p);
 	parser->parser.cur = p;
 	return 1;
 }
@@ -115,6 +117,7 @@
 {
 	struct http_message_parser *_parser = &parser->parser;
 	const unsigned char *p = parser->parser.cur;
+	pool_t pool;
 
 	/* We'll just parse anything up to the first SP or a control char.
 	   We could also implement workarounds for buggy HTTP clients and
@@ -138,7 +141,8 @@
 	}
 	if (p == _parser->end)
 		return 0;
-	parser->request_target = p_strdup_until(_parser->msg.pool, _parser->cur, p);
+	pool = http_message_parser_get_pool(_parser);
+	parser->request_target = p_strdup_until(pool, _parser->cur, p);
 	parser->parser.cur = p;
 	return 1;
 }
@@ -574,8 +578,9 @@
 
 	i_zero(request);
 
+	pool = http_message_parser_get_pool(&parser->parser);
 	if (http_url_request_target_parse(parser->request_target, hdr->value,
-		parser->parser.msg.pool, &request->target, &error) < 0) {
+		pool, &request->target, &error) < 0) {
 		*error_code_r = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST;
 		*error_r = t_strdup_printf("Bad request target `%s': %s",
 			parser->request_target, error);
--- a/src/lib-http/http-response-parser.c	Sat Feb 04 14:11:36 2017 +0100
+++ b/src/lib-http/http-response-parser.c	Sat Feb 04 13:59:10 2017 +0100
@@ -83,6 +83,7 @@
 static int http_response_parse_reason(struct http_response_parser *parser)
 {
 	const unsigned char *p = parser->parser.cur;
+	pool_t pool;
 
 	/* reason-phrase = *( HTAB / SP / VCHAR / obs-text )
 	 */
@@ -92,8 +93,9 @@
 
 	if (p == parser->parser.end)
 		return 0;
+	pool = http_message_parser_get_pool(&parser->parser);
 	parser->response_reason =
-		p_strdup_until(parser->parser.msg.pool, parser->parser.cur, p);
+		p_strdup_until(pool, parser->parser.cur, p);
 	parser->parser.cur = p;
 	return 1;
 }