Mercurial > dovecot > core-2.2
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; }