diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a943f721..662d541a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -762,6 +762,7 @@ add_executable(lighttpd server.c response.c connections.c + reqpool.c inet_ntop_cache.c network.c network_write.c diff --git a/src/Makefile.am b/src/Makefile.am index 4ecc91d4..72523ff5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -97,7 +97,7 @@ common_src=base64.c buffer.c burl.c log.c \ splaytree.c \ safe_memclear.c -src = server.c response.c connections.c \ +src = server.c response.c connections.c reqpool.c \ inet_ntop_cache.c \ network.c \ network_write.c \ @@ -450,7 +450,7 @@ mod_wstunnel_la_LIBADD = $(common_libadd) $(CRYPTO_LIB) hdr = base64.h buffer.h burl.h network.h log.h http_kv.h keyvalue.h \ - response.h request.h fastcgi.h chunk.h \ + response.h request.h reqpool.h fastcgi.h chunk.h \ first.h http_chunk.h \ algo_sha1.h md5.h http_auth.h http_header.h http_vhostdb.h stream.h \ fdevent.h gw_backend.h connections.h base.h base_decls.h stat_cache.h \ diff --git a/src/SConscript b/src/SConscript index d18a84b3..94110d4e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -78,7 +78,7 @@ common_src = Split("base64.c buffer.c burl.c log.c \ safe_memclear.c \ ") -src = Split("server.c response.c connections.c \ +src = Split("server.c response.c connections.c reqpool.c \ inet_ntop_cache.c \ network.c \ network_write.c \ diff --git a/src/connections.c b/src/connections.c index 48b90330..bb83f9ab 100644 --- a/src/connections.c +++ b/src/connections.c @@ -9,6 +9,7 @@ #include "fdevent.h" #include "http_header.h" +#include "reqpool.h" #include "request.h" #include "response.h" #include "network.h" @@ -228,8 +229,6 @@ static void connection_fdwaitqueue_append(connection *con) { connection_list_append(&con->srv->fdwaitqueue, con); } -static void request_reset (request_st * const r); - static void connection_handle_response_end_state(request_st * const r, connection * const con) { /* call request_done hook if http_status set (e.g. to log request) */ /* (even if error, connection dropped, as long as http_status is set) */ @@ -245,6 +244,7 @@ static void connection_handle_response_end_state(request_st * const r, connectio if (r->keep_alive) { request_reset(r); + config_reset_config(r); con->is_readable = 1; /* potentially trigger optimistic read */ /*(accounting used by mod_accesslog for HTTP/1.0 and HTTP/1.1)*/ r->bytes_read_ckpt = con->bytes_read; @@ -587,37 +587,6 @@ static void connection_handle_write_state(request_st * const r, connection * con } -__attribute_cold__ -static void -request_init (request_st * const r, connection * const con, server * const srv) -{ - r->write_queue = chunkqueue_init(); - r->read_queue = chunkqueue_init(); - r->reqbody_queue = chunkqueue_init(); - - r->resp_header_len = 0; - r->loops_per_request = 0; - r->con = con; - r->tmp_buf = srv->tmp_buf; - - /* init plugin-specific per-request structures */ - r->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *)); - force_assert(NULL != r->plugin_ctx); - - r->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t)); - force_assert(NULL != r->cond_cache); - - #ifdef HAVE_PCRE_H - if (srv->config_context->used > 1) {/*(save 128b per con if no conditions)*/ - r->cond_match = - calloc(srv->config_context->used, sizeof(cond_match_t)); - force_assert(NULL != r->cond_match); - } - #endif - - config_reset_config(r); -} - __attribute_cold__ static connection *connection_init(server *srv) { connection * const con = calloc(1, sizeof(*con)); @@ -635,6 +604,7 @@ static connection *connection_init(server *srv) { request_st * const r = &con->request; request_init(r, con, srv); + config_reset_config(r); con->write_queue = r->write_queue; con->read_queue = r->read_queue; @@ -646,40 +616,6 @@ static connection *connection_init(server *srv) { } -static void -request_free (request_st * const r) -{ - chunkqueue_free(r->reqbody_queue); - chunkqueue_free(r->write_queue); - chunkqueue_free(r->read_queue); - array_free_data(&r->rqst_headers); - array_free_data(&r->resp_headers); - array_free_data(&r->env); - - free(r->target.ptr); - free(r->target_orig.ptr); - - free(r->uri.scheme.ptr); - free(r->uri.authority.ptr); - free(r->uri.path.ptr); - free(r->uri.query.ptr); - - free(r->physical.doc_root.ptr); - free(r->physical.path.ptr); - free(r->physical.basedir.ptr); - free(r->physical.etag.ptr); - free(r->physical.rel_path.ptr); - - free(r->pathinfo.ptr); - free(r->server_name_buf.ptr); - - free(r->plugin_ctx); - free(r->cond_cache); - free(r->cond_match); - - /* note: r is not zeroed here and r is not freed here */ -} - void connections_free(server *srv) { connections * const conns = &srv->conns; for (uint32_t i = 0; i < conns->size; ++i) { @@ -704,72 +640,10 @@ void connections_free(server *srv) { } -static void -request_reset (request_st * const r) { - plugins_call_handle_request_reset(r); - - connection_response_reset(r); - - r->resp_header_len = 0; - r->loops_per_request = 0; - - r->http_method = HTTP_METHOD_UNSET; - r->http_version = HTTP_VERSION_UNSET; - - /*con->proto_default_port = 80;*//*set to default in connection_accepted()*/ - - r->http_host = NULL; - r->reqbody_length = 0; - r->te_chunked = 0; - r->rqst_htags = 0; - - buffer_clear(&r->uri.scheme); - - if (r->rqst_header_len <= BUFFER_MAX_REUSE_SIZE) { - r->rqst_headers.used = 0; - /* (Note: total header size not recalculated on HANDLER_COMEBACK - * even if other request headers changed during processing) - * (While this might delay release of larger buffers, it is not - * expected to be the general case. For those systems where it - * is a typical case, the larger buffers are likely to be reused) */ - buffer_clear(&r->target); - buffer_clear(&r->pathinfo); - /*buffer_clear(&r->target_orig);*/ /* reset later; used by mod_status*/ - /*buffer_clear(&r->uri.path);*/ /* reset later; used by mod_status*/ - /*buffer_clear(&r->uri.query);*/ /* reset later; used by mod_status*/ - /*buffer_clear(&r->uri.authority);*//* reset later; used by mod_status*/ - /*buffer_clear(&r->server_name_buf);*//* reset when used */ - } - else { - buffer_reset(&r->target); - buffer_reset(&r->pathinfo); - /*buffer_reset(&r->target_orig);*/ /* reset later; used by mod_status*/ - /*buffer_reset(&r->uri.path);*/ /* reset later; used by mod_status*/ - /*buffer_reset(&r->uri.query);*/ /* reset later; used by mod_status*/ - /*buffer_clear(&r->uri.authority);*//* reset later; used by mod_status*/ - /*buffer_clear(&r->server_name_buf);*//* reset when used */ - array_reset_data_strings(&r->rqst_headers); - } - r->rqst_header_len = 0; - if (0 != r->env.used) - array_reset_data_strings(&r->env); - - chunkqueue_reset(r->reqbody_queue); - - /* The cond_cache gets reset in response.c */ - /* config_cond_cache_reset(r); */ - - r->async_callback = 0; - r->error_handler_saved_status = 0; - /*r->error_handler_saved_method = HTTP_METHOD_UNSET;*/ - /*(error_handler_saved_method value is not valid unless error_handler_saved_status is set)*/ - - config_reset_config(r); -} - static void connection_reset(connection *con) { request_st * const r = &con->request; request_reset(r); + config_reset_config(r); r->bytes_read_ckpt = 0; r->bytes_written_ckpt = 0; con->is_readable = 1; diff --git a/src/meson.build b/src/meson.build index 07060b0f..fc91e3a5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -685,6 +685,7 @@ main_src = [ 'configfile.c', 'connections.c', 'data_config.c', + 'reqpool.c', 'inet_ntop_cache.c', 'network_write.c', 'network.c', diff --git a/src/reqpool.c b/src/reqpool.c new file mode 100644 index 00000000..074c5e40 --- /dev/null +++ b/src/reqpool.c @@ -0,0 +1,146 @@ +/* + * reqpool - request objects + * + * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com All rights reserved + * License: BSD 3-clause (same as lighttpd) + */ +#include "first.h" +#include "reqpool.h" + +#include + +#include "base.h" +#include "buffer.h" +#include "connections.h"/* connection_response_reset() */ +#include "chunk.h" +#include "plugin.h" +#include "plugin_config.h" +#include "request.h" + + +void +request_init (request_st * const r, connection * const con, server * const srv) +{ + r->write_queue = chunkqueue_init(); + r->read_queue = chunkqueue_init(); + r->reqbody_queue = chunkqueue_init(); + + r->resp_header_len = 0; + r->loops_per_request = 0; + r->con = con; + r->tmp_buf = srv->tmp_buf; + + /* init plugin-specific per-request structures */ + r->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *)); + force_assert(NULL != r->plugin_ctx); + + r->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t)); + force_assert(NULL != r->cond_cache); + + #ifdef HAVE_PCRE_H + if (srv->config_context->used > 1) {/*(save 128b per con if no conditions)*/ + r->cond_match = + calloc(srv->config_context->used, sizeof(cond_match_t)); + force_assert(NULL != r->cond_match); + } + #endif +} + + +void +request_reset (request_st * const r) +{ + plugins_call_handle_request_reset(r); + + connection_response_reset(r); + + r->resp_header_len = 0; + r->loops_per_request = 0; + + r->http_method = HTTP_METHOD_UNSET; + r->http_version = HTTP_VERSION_UNSET; + + /*con->proto_default_port = 80;*//*set to default in connection_accepted()*/ + + r->http_host = NULL; + r->reqbody_length = 0; + r->te_chunked = 0; + r->rqst_htags = 0; + + r->async_callback = 0; + r->error_handler_saved_status = 0; + /*r->error_handler_saved_method = HTTP_METHOD_UNSET;*/ + /*(error_handler_saved_method value is not valid + * unless error_handler_saved_status is set)*/ + + buffer_clear(&r->uri.scheme); + + if (r->rqst_header_len <= BUFFER_MAX_REUSE_SIZE) { + r->rqst_headers.used = 0; + /* (Note: total header size not recalculated on HANDLER_COMEBACK + * even if other request headers changed during processing) + * (While this might delay release of larger buffers, it is not + * expected to be the general case. For those systems where it + * is a typical case, the larger buffers are likely to be reused) */ + buffer_clear(&r->target); + buffer_clear(&r->pathinfo); + /*buffer_clear(&r->target_orig);*/ /* reset later; used by mod_status*/ + /*buffer_clear(&r->uri.path);*/ /* reset later; used by mod_status*/ + /*buffer_clear(&r->uri.query);*/ /* reset later; used by mod_status*/ + /*buffer_clear(&r->uri.authority);*//* reset later; used by mod_status*/ + /*buffer_clear(&r->server_name_buf);*//* reset when used */ + } + else { + buffer_reset(&r->target); + buffer_reset(&r->pathinfo); + /*buffer_reset(&r->target_orig);*/ /* reset later; used by mod_status*/ + /*buffer_reset(&r->uri.path);*/ /* reset later; used by mod_status*/ + /*buffer_reset(&r->uri.query);*/ /* reset later; used by mod_status*/ + /*buffer_clear(&r->uri.authority);*//* reset later; used by mod_status*/ + /*buffer_clear(&r->server_name_buf);*//* reset when used */ + array_reset_data_strings(&r->rqst_headers); + } + r->rqst_header_len = 0; + if (0 != r->env.used) + array_reset_data_strings(&r->env); + + chunkqueue_reset(r->reqbody_queue); + + /* The cond_cache gets reset in response.c */ + /* config_cond_cache_reset(r); */ +} + + +void +request_free (request_st * const r) +{ + chunkqueue_free(r->reqbody_queue); + chunkqueue_free(r->write_queue); + chunkqueue_free(r->read_queue); + array_free_data(&r->rqst_headers); + array_free_data(&r->resp_headers); + array_free_data(&r->env); + + free(r->target.ptr); + free(r->target_orig.ptr); + + free(r->uri.scheme.ptr); + free(r->uri.authority.ptr); + free(r->uri.path.ptr); + free(r->uri.query.ptr); + + free(r->physical.doc_root.ptr); + free(r->physical.path.ptr); + free(r->physical.basedir.ptr); + free(r->physical.etag.ptr); + free(r->physical.rel_path.ptr); + + free(r->pathinfo.ptr); + free(r->server_name_buf.ptr); + + free(r->plugin_ctx); + free(r->cond_cache); + free(r->cond_match); + + /* note: r is not zeroed here and r is not freed here */ +} diff --git a/src/reqpool.h b/src/reqpool.h new file mode 100644 index 00000000..32a1351c --- /dev/null +++ b/src/reqpool.h @@ -0,0 +1,11 @@ +#ifndef LI_REQPOOL_H +#define LI_REQPOOL_H +#include "first.h" + +#include "base_decls.h" + +void request_init (request_st *r, connection *con, server *srv); +void request_reset (request_st *r); +void request_free (request_st *r); + +#endif