From 62e97967ca9356b2645b6090512ab3dbac83e8ed Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Fri, 4 Oct 2019 02:10:02 -0400 Subject: [PATCH] [core] prefer uint32_t to size_t in base.h even 2 billion is way larger than even extreme operating values expected for the members in base.h include some structs directly in struct server, rather than by ptr --- src/CMakeLists.txt | 2 +- src/Makefile.am | 4 +-- src/SConscript | 2 +- src/base.h | 27 +++++++------- src/configfile-glue.c | 10 ++---- src/connections-glue.c | 13 +++++++ src/connections.c | 43 ++++++++++------------ src/connections.h | 3 ++ src/gw_backend.c | 1 - src/joblist.c | 58 ------------------------------ src/joblist.h | 14 -------- src/meson.build | 1 - src/mod_cgi.c | 1 - src/mod_evasive.c | 6 ++-- src/mod_status.c | 38 +++++++++----------- src/mod_wstunnel.c | 6 ++-- src/network.c | 23 ++++++------ src/plugin.c | 52 +++++++++++---------------- src/response.c | 2 +- src/server.c | 81 +++++++++++++++++------------------------- 20 files changed, 142 insertions(+), 245 deletions(-) delete mode 100644 src/joblist.c delete mode 100644 src/joblist.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1bdef070..935de648 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -638,7 +638,7 @@ set(COMMON_SRC base64.c buffer.c burl.c log.c http_header.c http_kv.c keyvalue.c chunk.c http_chunk.c stream.c fdevent.c gw_backend.c - stat_cache.c plugin.c joblist.c etag.c array.c + stat_cache.c plugin.c etag.c array.c data_string.c data_array.c data_integer.c algo_sha1.c md5.c vector.c diff --git a/src/Makefile.am b/src/Makefile.am index 8440254e..096d828c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,7 +76,7 @@ CLEANFILES = versionstamp.h versionstamp.h.tmp lemon$(BUILD_EXEEXT) common_src=base64.c buffer.c burl.c log.c \ http_header.c http_kv.c keyvalue.c chunk.c \ http_chunk.c stream.c fdevent.c gw_backend.c \ - stat_cache.c plugin.c joblist.c etag.c array.c \ + stat_cache.c plugin.c etag.c array.c \ data_string.c data_array.c \ data_integer.c algo_sha1.c md5.c \ vector.c \ @@ -426,7 +426,7 @@ hdr = base64.h buffer.h burl.h network.h log.h http_kv.h keyvalue.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 \ plugin.h \ - etag.h joblist.h array.h vector.h crc32.h \ + etag.h array.h vector.h crc32.h \ fdevent_impl.h network_write.h configfile.h \ mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \ configparser.h mod_ssi_exprparser.h \ diff --git a/src/SConscript b/src/SConscript index d181ce5a..2a0d55bc 100644 --- a/src/SConscript +++ b/src/SConscript @@ -58,7 +58,7 @@ def GatherLibs(env, *libs): common_src = Split("base64.c buffer.c burl.c log.c \ http_header.c http_kv.c keyvalue.c chunk.c \ http_chunk.c stream.c fdevent.c gw_backend.c \ - stat_cache.c plugin.c joblist.c etag.c array.c \ + stat_cache.c plugin.c etag.c array.c \ data_string.c data_array.c \ data_integer.c algo_sha1.c md5.c \ vector.c \ diff --git a/src/base.h b/src/base.h index 9ed7779d..465cbc4b 100644 --- a/src/base.h +++ b/src/base.h @@ -205,8 +205,8 @@ struct connection { time_t request_start; struct timespec request_start_hp; - size_t request_count; /* number of requests handled in this connection */ - size_t loops_per_request; /* to catch endless loops in a single request + uint32_t request_count; /* number of requests handled in this connection */ + uint32_t loops_per_request; /* to catch endless loops in a single request * * used by mod_rewrite, mod_fastcgi, ... and others * this is self-protection @@ -249,7 +249,7 @@ struct connection { physical physical; response response; - size_t header_len; + uint32_t header_len; array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */ @@ -283,8 +283,8 @@ struct connection { typedef struct { connection **ptr; - size_t size; - size_t used; + uint32_t size; + uint32_t used; } connections; typedef struct { @@ -294,8 +294,8 @@ typedef struct { typedef struct { void *ptr; - size_t used; - size_t size; + uint32_t used; + uint32_t size; } buffer_plugin; typedef struct { @@ -363,8 +363,8 @@ typedef struct server_socket { typedef struct { server_socket **ptr; - size_t size; - size_t used; + uint32_t size; + uint32_t used; } server_socket_array; struct server { @@ -385,10 +385,9 @@ struct server { int max_fds_lowat;/* low watermark */ int max_fds_hiwat;/* high watermark */ int cur_fds; /* currently used fds */ - int want_fds; /* waiting fds */ int sockets_disabled; - size_t max_conns; + uint32_t max_conns; /* buffers */ buffer *parse_full_path; @@ -427,9 +426,9 @@ struct server { short int config_deprecated; short int config_unsupported; - connections *conns; - connections *joblist; - connections *fdwaitqueue; + connections conns; + connections joblist; + connections fdwaitqueue; struct stat_cache *stat_cache; diff --git a/src/configfile-glue.c b/src/configfile-glue.c index 94c8909a..2375c6c8 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -543,9 +543,7 @@ static void config_cond_clear_node(server *srv, connection *con, data_config *dc * if the item is COND_LAST_ELEMENT we reset all items */ void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item) { - size_t i; - - for (i = 0; i < srv->config_context->used; i++) { + for (uint32_t i = 0; i < srv->config_context->used; ++i) { data_config *dc = (data_config *)srv->config_context->data[i]; if (item == dc->comp) { @@ -561,17 +559,15 @@ void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item) * reset the config cache to its initial state at connection start */ void config_cond_cache_reset(server *srv, connection *con) { - size_t i; - /* resetting all entries; no need to follow children as in config_cond_cache_reset_item */ - for (i = 0; i < srv->config_context->used; i++) { + for (uint32_t i = 0; i < srv->config_context->used; ++i) { con->cond_cache[i].result = COND_RESULT_UNSET; con->cond_cache[i].local_result = COND_RESULT_UNSET; con->cond_cache[i].patterncount = 0; con->cond_cache[i].comp_value = NULL; } - for (i = 0; i < COMP_LAST_ELEMENT; i++) { + for (int i = 0; i < COMP_LAST_ELEMENT; ++i) { con->conditional_is_valid[i] = 0; } } diff --git a/src/connections-glue.c b/src/connections-glue.c index f37f50fc..4c6eb5ff 100644 --- a/src/connections-glue.c +++ b/src/connections-glue.c @@ -9,6 +9,7 @@ #include "response.h" #include +#include #include const char *connection_get_state(connection_state_t state) { @@ -45,6 +46,18 @@ const char *connection_get_short_state(connection_state_t state) { } } +__attribute_cold__ +static void connection_list_resize(connections *conns) { + conns->size += 16; + conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size); + force_assert(NULL != conns->ptr); +} + +void connection_list_append(connections *conns, connection *con) { + if (conns->used == conns->size) connection_list_resize(conns); + conns->ptr[conns->used++] = con; +} + static int connection_handle_read_post_cq_compact(chunkqueue *cq) { /* combine first mem chunk with next non-empty mem chunk * (loop if next chunk is empty) */ diff --git a/src/connections.c b/src/connections.c index c6cb84ce..9567076e 100644 --- a/src/connections.c +++ b/src/connections.c @@ -14,7 +14,6 @@ #include "network.h" #include "http_chunk.h" #include "stat_cache.h" -#include "joblist.h" #include "plugin.h" @@ -48,7 +47,7 @@ static int connection_reset(server *srv, connection *con); static connection *connections_get_new_connection(server *srv) { - connections *conns = srv->conns; + connections * const conns = &srv->conns; size_t i; if (conns->size == conns->used) { @@ -68,7 +67,7 @@ static connection *connections_get_new_connection(server *srv) { static int connection_del(server *srv, connection *con) { size_t i; - connections *conns = srv->conns; + connections * const conns = &srv->conns; connection *temp; if (con == NULL) return -1; @@ -140,7 +139,7 @@ static int connection_close(server *srv, connection *con) { con->is_ssl_sock = 0; /* plugins should have cleaned themselves up */ - for (size_t i = 0; i < srv->plugins.used; ++i) { + for (uint32_t i = 0; i < srv->plugins.used; ++i) { plugin *p = ((plugin **)(srv->plugins.ptr))[i]; plugin_data *pd = p->data; if (!pd || NULL == con->plugin_ctx[pd->id]) continue; @@ -219,6 +218,11 @@ static void connection_handle_shutdown(server *srv, connection *con) { } } +__attribute_cold__ +static void connection_fdwaitqueue_append(server *srv, connection *con) { + connection_list_append(&srv->fdwaitqueue, con); +} + static void connection_handle_response_end_state(server *srv, connection *con) { /* log the request */ /* (even if error, connection dropped, still write to access log if http_status) */ @@ -503,8 +507,7 @@ static void connection_handle_write_state(server *srv, connection *con) { case HANDLER_GO_ON: break; case HANDLER_WAIT_FOR_FD: - srv->want_fds++; - fdwaitqueue_append(srv, con); + connection_fdwaitqueue_append(srv, con); break; case HANDLER_COMEBACK: default: @@ -588,12 +591,8 @@ static connection *connection_init(server *srv) { } void connections_free(server *srv) { - connections *conns = srv->conns; - size_t i; - - if (NULL == conns) return; - - for (i = 0; i < conns->size; i++) { + connections * const conns = &srv->conns; + for (uint32_t i = 0; i < conns->size; ++i) { connection *con = conns->ptr[i]; connection_reset(srv, con); @@ -637,8 +636,7 @@ void connections_free(server *srv) { } free(conns->ptr); - free(conns); - srv->conns = NULL; + conns->ptr = NULL; } @@ -731,14 +729,14 @@ static chunk * connection_read_header_more(connection *con, chunkqueue *cq, chun } __attribute_hot__ -static size_t connection_read_header_hoff(const char *n, const size_t clen, unsigned short hoff[8192]) { +static uint32_t connection_read_header_hoff(const char *n, const size_t clen, unsigned short hoff[8192]) { size_t hlen = 0; for (const char *b; (n = memchr((b = n),'\n',clen-hlen)); ++n) { size_t x = (size_t)(n - b + 1); hlen += x; if (x <= 2 && (x == 1 || n[-1] == '\r')) { hoff[hoff[0]+1] = hlen; - return hlen; + return hlen <= UINT32_MAX ? (uint32_t)hlen : 0; } if (++hoff[0] >= /*sizeof(hoff)/sizeof(hoff[0])-1*/ 8192-1) break; hoff[hoff[0]] = hlen; @@ -840,7 +838,7 @@ static int connection_handle_read_state(server * const srv, connection * const c if (con->conf.log_request_header) { log_error(con->errh, __FILE__, __LINE__, - "fd: %d request-len: %zu\n%.*s", con->fd, con->header_len, + "fd: %d request-len: %d\n%.*s", con->fd, (int)con->header_len, (int)con->header_len, hdrs); } @@ -960,7 +958,7 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { * see #1216 */ - if (srv->conns->used >= srv->max_conns) { + if (srv->conns.used >= srv->max_conns) { return NULL; } @@ -1215,10 +1213,7 @@ static int connection_handle_request(server *srv, connection *con) { connection_set_state(con, CON_STATE_RESPONSE_START); break; case HANDLER_WAIT_FOR_FD: - srv->want_fds++; - - fdwaitqueue_append(srv, con); - + connection_fdwaitqueue_append(srv, con); break; case HANDLER_COMEBACK: return 1; @@ -1468,14 +1463,14 @@ static void connection_check_timeout (server * const srv, const time_t cur_ts, c void connection_periodic_maint (server * const srv, const time_t cur_ts) { /* check all connections for timeouts */ - connections * const conns = srv->conns; + connections * const conns = &srv->conns; for (size_t ndx = 0; ndx < conns->used; ++ndx) { connection_check_timeout(srv, cur_ts, conns->ptr[ndx]); } } void connection_graceful_shutdown_maint (server *srv) { - connections *conns = srv->conns; + connections * const conns = &srv->conns; for (size_t ndx = 0; ndx < conns->used; ++ndx) { connection * const con = conns->ptr[ndx]; int changed = 0; diff --git a/src/connections.h b/src/connections.h index caa310e6..8c5fe967 100644 --- a/src/connections.h +++ b/src/connections.h @@ -23,4 +23,7 @@ handler_t connection_handle_read_post_error(server *srv, connection *con, int ht int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *c, off_t max_bytes); void connection_response_reset(server *srv, connection *con); +#define joblist_append(srv, con) connection_list_append(&(srv)->joblist, (con)) +void connection_list_append(connections *conns, connection *con); + #endif diff --git a/src/gw_backend.c b/src/gw_backend.c index 2020111d..bd1fee6d 100644 --- a/src/gw_backend.c +++ b/src/gw_backend.c @@ -1043,7 +1043,6 @@ static void gw_restart_dead_procs(server *srv, gw_host *host, int debug, int tri #include "base.h" #include "connections.h" -#include "joblist.h" #include "response.h" diff --git a/src/joblist.c b/src/joblist.c deleted file mode 100644 index 5a137a9e..00000000 --- a/src/joblist.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "first.h" - -#include "base.h" -#include "joblist.h" - -#include -#include - -int joblist_append(server *srv, connection *con) { - if (srv->joblist->used == srv->joblist->size) { - srv->joblist->size += 16; - srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size); - force_assert(NULL != srv->joblist->ptr); - } - - srv->joblist->ptr[srv->joblist->used++] = con; - - return 0; -} - -void joblist_free(server *srv, connections *joblist) { - UNUSED(srv); - - free(joblist->ptr); - free(joblist); -} - -connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) { - connection *con; - UNUSED(srv); - - - if (fdwaitqueue->used == 0) return NULL; - - con = fdwaitqueue->ptr[0]; - - memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr))); - - return con; -} - -int fdwaitqueue_append(server *srv, connection *con) { - if (srv->fdwaitqueue->used == srv->fdwaitqueue->size) { - srv->fdwaitqueue->size += 16; - srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size); - force_assert(NULL != srv->fdwaitqueue->ptr); - } - - srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con; - - return 0; -} - -void fdwaitqueue_free(server *srv, connections *fdwaitqueue) { - UNUSED(srv); - free(fdwaitqueue->ptr); - free(fdwaitqueue); -} diff --git a/src/joblist.h b/src/joblist.h deleted file mode 100644 index 78c40e53..00000000 --- a/src/joblist.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _JOB_LIST_H_ -#define _JOB_LIST_H_ -#include "first.h" - -#include "base_decls.h" - -int joblist_append(server *srv, connection *con); -void joblist_free(server *srv, connections *joblist); - -int fdwaitqueue_append(server *srv, connection *con); -void fdwaitqueue_free(server *srv, connections *fdwaitqueue); -connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue); - -#endif diff --git a/src/meson.build b/src/meson.build index b6432712..c6abbd39 100644 --- a/src/meson.build +++ b/src/meson.build @@ -603,7 +603,6 @@ common_src = [ 'http_kv.c', 'http_vhostdb.c', 'http-header-glue.c', - 'joblist.c', 'keyvalue.c', 'log.c', 'md5.c', diff --git a/src/mod_cgi.c b/src/mod_cgi.c index 45116600..c49f522e 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -5,7 +5,6 @@ #include "http_kv.h" #include "log.h" #include "connections.h" -#include "joblist.h" #include "response.h" #include "http_chunk.h" #include "http_header.h" diff --git a/src/mod_evasive.c b/src/mod_evasive.c index 3505b3a6..3857973d 100644 --- a/src/mod_evasive.c +++ b/src/mod_evasive.c @@ -148,8 +148,6 @@ static int mod_evasive_patch_connection(server *srv, connection *con, plugin_dat URIHANDLER_FUNC(mod_evasive_uri_handler) { plugin_data *p = p_d; - size_t conns_by_ip = 0; - size_t j; if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON; @@ -158,8 +156,8 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { /* no limit set, nothing to block */ if (p->conf.max_conns == 0) return HANDLER_GO_ON; - for (j = 0; j < srv->conns->used; j++) { - connection *c = srv->conns->ptr[j]; + for (uint32_t i = 0, conns_by_ip = 0; i < srv->conns.used; ++i) { + connection *c = srv->conns.ptr[i]; /* check if other connections are already actively serving data for the same IP * we can only ban connections which are already behind the 'read request' state diff --git a/src/mod_status.c b/src/mod_status.c index 256b1336..bd020408 100644 --- a/src/mod_status.c +++ b/src/mod_status.c @@ -199,8 +199,8 @@ static int mod_status_get_multiplier(double *avg, char *multiplier, int size) { static handler_t mod_status_handle_server_status_html(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; buffer *b = chunkqueue_append_buffer_open(con->write_queue); - size_t j; double avg; + uint32_t j; char multiplier = '\0'; char buf[32]; time_t ts; @@ -456,11 +456,11 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c buffer_append_string_len(b, CONST_STR_LEN("
\n
\n"));
 
 	buffer_append_string_len(b, CONST_STR_LEN(""));
-	buffer_append_int(b, srv->conns->used);
+	buffer_append_int(b, srv->conns.used);
 	buffer_append_string_len(b, CONST_STR_LEN(" connections\n"));
 
-	for (j = 0; j < srv->conns->used; j++) {
-		connection *c = srv->conns->ptr[j];
+	for (j = 0; j < srv->conns.used; ++j) {
+		connection *c = srv->conns.ptr[j];
 		const char *state;
 
 		if (CON_STATE_READ == c->state && !buffer_string_is_empty(c->request.orig_uri)) {
@@ -508,8 +508,8 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c
 	mod_status_header_append_sort(b, p_d, "File");
 	buffer_append_string_len(b, CONST_STR_LEN("\n"));
 
-	for (j = 0; j < srv->conns->used; j++) {
-		connection *c = srv->conns->ptr[j];
+	for (j = 0; j < srv->conns.used; ++j) {
+		connection *c = srv->conns.ptr[j];
 
 		buffer_append_string_len(b, CONST_STR_LEN(""));
 
@@ -599,8 +599,6 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c
 	double avg;
 	time_t ts;
 	char buf[32];
-	unsigned int k;
-	unsigned int l;
 
 	/* output total number of requests */
 	buffer_append_string_len(b, CONST_STR_LEN("Total Accesses: "));
@@ -624,24 +622,24 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c
 
 	/* output busy servers */
 	buffer_append_string_len(b, CONST_STR_LEN("BusyServers: "));
-	buffer_append_int(b, srv->conns->used);
+	buffer_append_int(b, srv->conns.used);
 	buffer_append_string_len(b, CONST_STR_LEN("\n"));
 
 	buffer_append_string_len(b, CONST_STR_LEN("IdleServers: "));
-	buffer_append_int(b, srv->conns->size - srv->conns->used);
+	buffer_append_int(b, srv->conns.size - srv->conns.used);
 	buffer_append_string_len(b, CONST_STR_LEN("\n"));
 
 	/* output scoreboard */
 	buffer_append_string_len(b, CONST_STR_LEN("Scoreboard: "));
-	for (k = 0; k < srv->conns->used; k++) {
-		connection *c = srv->conns->ptr[k];
+	for (uint32_t i = 0; i < srv->conns.used; ++i) {
+		connection *c = srv->conns.ptr[i];
 		const char *state =
 		  (CON_STATE_READ == c->state && !buffer_string_is_empty(c->request.orig_uri))
 		    ? "k"
 		    : connection_get_short_state(c->state);
 		buffer_append_string_len(b, state, 1);
 	}
-	for (l = 0; l < srv->conns->size - srv->conns->used; l++) {
+	for (uint32_t i = 0; i < srv->conns.size - srv->conns.used; ++i) {
 		buffer_append_string_len(b, CONST_STR_LEN("_"));
 	}
 	buffer_append_string_len(b, CONST_STR_LEN("\n"));
@@ -661,7 +659,7 @@ static handler_t mod_status_handle_server_status_json(server *srv, connection *c
 	double avg;
 	time_t ts;
 	char buf[32];
-	size_t j;
+	uint32_t j;
 	unsigned int jsonp = 0;
 
 	if (buffer_string_length(con->uri.query) >= sizeof("jsonp=")-1
@@ -701,11 +699,11 @@ static handler_t mod_status_handle_server_status_json(server *srv, connection *c
 
 	/* output busy servers */
 	buffer_append_string_len(b, CONST_STR_LEN("\t\"BusyServers\": "));
-	buffer_append_int(b, srv->conns->used);
+	buffer_append_int(b, srv->conns.used);
 	buffer_append_string_len(b, CONST_STR_LEN(",\n"));
 
 	buffer_append_string_len(b, CONST_STR_LEN("\t\"IdleServers\": "));
-	buffer_append_int(b, srv->conns->size - srv->conns->used);
+	buffer_append_int(b, srv->conns.size - srv->conns.used);
 	buffer_append_string_len(b, CONST_STR_LEN(",\n"));
 
 	for (j = 0, avg = 0; j < 5; j++) {
@@ -795,7 +793,6 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v
 	plugin_data *p = p_d;
 	buffer *b = chunkqueue_append_buffer_open(con->write_queue);
 	buffer *m = p->module_list;
-	size_t i;
 
 	buffer_copy_string_len(b, CONST_STR_LEN(
 			   "\n"
@@ -824,7 +821,7 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v
 
 	mod_status_header_append(b, "Config-File-Settings");
 
-	for (i = 0; i < srv->plugins.used; i++) {
+	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
 		plugin **ps = srv->plugins.ptr;
 
 		plugin *pl = ps[i];
@@ -917,11 +914,10 @@ static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
 
 TRIGGER_FUNC(mod_status_trigger) {
 	plugin_data *p = p_d;
-	size_t i;
 
 	/* check all connections */
-	for (i = 0; i < srv->conns->used; i++) {
-		connection *c = srv->conns->ptr[i];
+	for (uint32_t i = 0; i < srv->conns.used; ++i) {
+		connection *c = srv->conns.ptr[i];
 
 		p->bytes_written += c->bytes_written_cur_second;
 	}
diff --git a/src/mod_wstunnel.c b/src/mod_wstunnel.c
index c0864719..00532b57 100644
--- a/src/mod_wstunnel.c
+++ b/src/mod_wstunnel.c
@@ -89,8 +89,8 @@
 #include "chunk.h"
 #include "fdevent.h"
 #include "http_header.h"
-#include "joblist.h"
 #include "log.h"
+#include "connections.h"
 
 #define MOD_WEBSOCKET_LOG_NONE  0
 #define MOD_WEBSOCKET_LOG_ERR   1
@@ -603,8 +603,8 @@ TRIGGER_FUNC(mod_wstunnel_handle_trigger) {
 
     gw_handle_trigger(srv, p_d);
 
-    for (size_t i = 0; i < srv->conns->used; ++i) {
-        connection *con = srv->conns->ptr[i];
+    for (uint32_t i = 0; i < srv->conns.used; ++i) {
+        connection *con = srv->conns.ptr[i];
         handler_ctx *hctx = con->plugin_ctx[p->id];
         if (NULL == hctx || con->mode != p->id)
             continue;
diff --git a/src/network.c b/src/network.c
index dc55169a..14d329a5 100644
--- a/src/network.c
+++ b/src/network.c
@@ -61,8 +61,8 @@ static handler_t network_server_handle_fdevent(server *srv, void *context, int r
 	/* accept()s at most 100 connections directly
 	 *
 	 * we jump out after 100 to give the waiting connections a chance */
-	if (srv->conns->used >= srv->max_conns) return HANDLER_GO_ON;
-	loops = (int)(srv->max_conns - srv->conns->used + 1);
+	if (srv->conns.used >= srv->max_conns) return HANDLER_GO_ON;
+	loops = (int)(srv->max_conns - srv->conns.used + 1);
 	if (loops > 100) loops = 101;
 
 	while (--loops && NULL != (con = connection_accept(srv, srv_socket)))
@@ -154,7 +154,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int
 	/* check if we already know this socket, and if yes, don't init it
 	 * (optimization: check strings here to filter out exact matches;
 	 *  binary addresses are matched further below) */
-	for (size_t i = 0; i < srv->srv_sockets.used; ++i) {
+	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
 		if (buffer_is_equal(srv->srv_sockets.ptr[i]->srv_token, host_token)) {
 			buffer_copy_buffer(host_token, srv->srv_sockets.ptr[i]->srv_token);
 			return 0;
@@ -198,7 +198,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int
 	}
 
 	/* check if we already know this socket (after potential DNS resolution), and if yes, don't init it */
-	for (size_t i = 0; i < srv->srv_sockets.used; ++i) {
+	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
 		if (0 == memcmp(&srv->srv_sockets.ptr[i]->addr, &addr, sizeof(addr))) {
 			return 0;
 		}
@@ -219,7 +219,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int
 	}
 
 	if (srv->srvconf.systemd_socket_activation) {
-		for (size_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
+		for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
 			if (0 != memcmp(&srv->srv_sockets_inherited.ptr[i]->addr, &srv_socket->addr, addr_len)) continue;
 			if ((unsigned short)~0u == srv->srv_sockets_inherited.ptr[i]->sidx) {
 				srv->srv_sockets_inherited.ptr[i]->sidx = sidx;
@@ -362,8 +362,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int
 }
 
 int network_close(server *srv) {
-	size_t i;
-	for (i = 0; i < srv->srv_sockets.used; i++) {
+	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
 		server_socket *srv_socket = srv->srv_sockets.ptr[i];
 		if (srv_socket->fd != -1) {
 			network_unregister_sock(srv, srv_socket);
@@ -380,7 +379,7 @@ int network_close(server *srv) {
 	srv->srv_sockets.used = 0;
 	srv->srv_sockets.size = 0;
 
-	for (i = 0; i < srv->srv_sockets_inherited.used; i++) {
+	for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
 		server_socket *srv_socket = srv->srv_sockets_inherited.ptr[i];
 		if (srv_socket->fd != -1 && srv_socket->sidx != (unsigned short)~0u) {
 			close(srv_socket->fd);
@@ -451,7 +450,7 @@ int network_init(server *srv, int stdin_fd) {
 	if (0 != network_write_init(srv)) return -1;
 
 	if (srv->srvconf.systemd_socket_activation) {
-		for (size_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
+		for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
 		        srv->srv_sockets_inherited.ptr[i]->sidx = (unsigned short)~0u;
 		}
 		if (0 != network_socket_activation_from_env(srv)) return -1;
@@ -503,7 +502,7 @@ int network_init(server *srv, int stdin_fd) {
 	if (srv->srvconf.systemd_socket_activation) {
 		/* activate any inherited sockets not explicitly listed in config file */
 		server_socket *srv_socket;
-		for (size_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
+		for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
 		        if ((unsigned short)~0u != srv->srv_sockets_inherited.ptr[i]->sidx) continue;
 		        srv->srv_sockets_inherited.ptr[i]->sidx = 0;
 			srv_socket = calloc(1, sizeof(server_socket));
@@ -525,8 +524,6 @@ void network_unregister_sock(server *srv, server_socket *srv_socket) {
 }
 
 int network_register_fdevents(server *srv) {
-	size_t i;
-
 	if (-1 == fdevent_reset(srv->ev)) {
 		return -1;
 	}
@@ -534,7 +531,7 @@ int network_register_fdevents(server *srv) {
 	if (srv->sockets_disabled) return 0; /* lighttpd -1 (one-shot mode) */
 
 	/* register fdevents after reset */
-	for (i = 0; i < srv->srv_sockets.used; i++) {
+	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
 		server_socket *srv_socket = srv->srv_sockets.ptr[i];
 
 		srv_socket->fdn = fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
diff --git a/src/plugin.c b/src/plugin.c
index f38718fa..26a8cf45 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -293,11 +293,11 @@ int plugins_load(server *srv) {
 #define PLUGIN_TO_SLOT(x, y) \
 	handler_t plugins_call_##y(server *srv, connection *con) {\
 		plugin ** const slot = ((plugin ***)(srv->plugin_slots))[x];\
-		const size_t used = srv->plugins.used;\
+		const uint32_t used = srv->plugins.used;\
 		handler_t rc = HANDLER_GO_ON;\
 		if (slot) {\
 			const plugin *p;\
-			for (size_t i = 0; i < used && (p = slot[i]) && (rc = p->y(srv, con, p->data)) == HANDLER_GO_ON; ++i) ;\
+			for (uint32_t i = 0; i < used && (p = slot[i]) && (rc = p->y(srv, con, p->data)) == HANDLER_GO_ON; ++i) ;\
 		}\
 		return rc;\
 	}
@@ -329,11 +329,11 @@ PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset)
 #define PLUGIN_TO_SLOT(x, y) \
 	handler_t plugins_call_##y(server *srv) {\
 		plugin ** const slot = ((plugin ***)(srv->plugin_slots))[x];\
-		const size_t used = srv->plugins.used; \
+		const uint32_t used = srv->plugins.used; \
 		handler_t rc = HANDLER_GO_ON;\
 		if (slot) {\
 			const plugin *p;\
-			for (size_t i = 0; i < used && (p = slot[i]) && (rc = p->y(srv, p->data)) == HANDLER_GO_ON; ++i) ;\
+			for (uint32_t i = 0; i < used && (p = slot[i]) && (rc = p->y(srv, p->data)) == HANDLER_GO_ON; ++i) ;\
 		}\
 		return rc;\
 	}
@@ -357,7 +357,7 @@ handler_t plugins_call_handle_waitpid(server *srv, pid_t pid, int status) {
 	plugin ** const slot =
 	  ((plugin ***)(srv->plugin_slots))[PLUGIN_FUNC_HANDLE_WAITPID];
 	if (!slot) return HANDLER_GO_ON;
-	for (size_t i = 0; i < srv->plugins.used && slot[i]; ++i) {
+	for (uint32_t i = 0; i < srv->plugins.used && slot[i]; ++i) {
 		plugin *p = slot[i];
 		handler_t r = p->handle_waitpid(srv, p->data, pid, status);
 		if (r != HANDLER_GO_ON) return r;
@@ -372,12 +372,8 @@ handler_t plugins_call_handle_waitpid(server *srv, pid_t pid, int status) {
  *
  */
 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
-	size_t i;
-	plugin **ps;
-
-	ps = srv->plugins.ptr;
-
-	for (i = 0; i < srv->plugins.used; i++) {
+	plugin ** const ps = srv->plugins.ptr;
+	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
 		plugin *p = ps[i];
 		if (p->handle_fdevent) {
 			handler_t r;
@@ -408,18 +404,14 @@ handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
  */
 
 handler_t plugins_call_init(server *srv) {
-	size_t i;
-	plugin **ps;
-
-	ps = srv->plugins.ptr;
+	plugin ** const ps = srv->plugins.ptr;
 
 	/* fill slots */
 
 	srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
 	force_assert(NULL != srv->plugin_slots);
 
-	for (i = 0; i < srv->plugins.used; i++) {
-		size_t j;
+	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
 		/* check which calls are supported */
 
 		plugin *p = ps[i];
@@ -432,7 +424,7 @@ handler_t plugins_call_init(server *srv) {
 			force_assert(NULL != slot); \
 			((plugin ***)(srv->plugin_slots))[x] = slot; \
 		} \
-		for (j = 0; j < srv->plugins.used; j++) { \
+		for (uint32_t j = 0; j < srv->plugins.used; ++j) { \
 			if (slot[j]) continue;\
 			slot[j] = p;\
 			break;\
@@ -489,25 +481,23 @@ handler_t plugins_call_init(server *srv) {
 }
 
 void plugins_free(server *srv) {
-	size_t i;
-	if (srv->plugin_slots) plugins_call_cleanup(srv);
+	if (srv->plugin_slots) {
+		plugins_call_cleanup(srv);
+		for (int i = 0; i < PLUGIN_FUNC_SIZEOF; ++i) {
+			plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
+			if (slot) free(slot);
+		}
+		free(srv->plugin_slots);
+		srv->plugin_slots = NULL;
+	}
 
-	for (i = 0; i < srv->plugins.used; i++) {
+	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
 		plugin *p = ((plugin **)srv->plugins.ptr)[i];
 
 		plugin_free(p);
 	}
-
-	for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
-		plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
-
-		if (slot) free(slot);
-	}
-
-	free(srv->plugin_slots);
-	srv->plugin_slots = NULL;
-
 	free(srv->plugins.ptr);
 	srv->plugins.ptr = NULL;
 	srv->plugins.used = 0;
+	srv->plugins.size = 0;
 }
diff --git a/src/response.c b/src/response.c
index 9682f3e9..ad48fea7 100644
--- a/src/response.c
+++ b/src/response.c
@@ -352,7 +352,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
 		} else {
 			char *qstr;
 			if (con->conf.http_parseopts & HTTP_PARSEOPT_URL_NORMALIZE) {
-				/*size_t len = buffer_string_length(con->request.uri);*/
+				/*uint32_t len = (uint32_t)buffer_string_length(con->request.uri);*/
 				int qs = burl_normalize(con->request.uri, srv->tmp_buf, con->conf.http_parseopts);
 				if (-2 == qs) {
 					log_error_write(srv, __FILE__, __LINE__, "sb",
diff --git a/src/server.c b/src/server.c
index cce5b63c..487d525c 100644
--- a/src/server.c
+++ b/src/server.c
@@ -15,7 +15,6 @@
 #include "stat_cache.h"
 #include "configfile.h"
 #include "plugin.h"
-#include "joblist.h"
 #include "network_write.h"
 
 #ifdef HAVE_VERSIONSTAMP_H
@@ -228,7 +227,6 @@ static int daemonize(void) {
 
 __attribute_cold__
 static server *server_init(void) {
-	int i;
 	server *srv = calloc(1, sizeof(*srv));
 	force_assert(srv);
 #define CLEAN(x) \
@@ -263,7 +261,7 @@ static server *server_init(void) {
 	CLEAN(status);
 #undef CLEAN
 
-	for (i = 0; i < FILE_CACHE_MAX; i++) {
+	for (int i = 0; i < FILE_CACHE_MAX; ++i) {
 		srv->mtime_cache[i].mtime = (time_t)-1;
 		srv->mtime_cache[i].str = buffer_init();
 	}
@@ -273,15 +271,6 @@ static server *server_init(void) {
 	srv->cur_ts = time(NULL);
 	srv->startup_ts = srv->cur_ts;
 
-	srv->conns = calloc(1, sizeof(*srv->conns));
-	force_assert(srv->conns);
-
-	srv->joblist = calloc(1, sizeof(*srv->joblist));
-	force_assert(srv->joblist);
-
-	srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
-	force_assert(srv->fdwaitqueue);
-
 	srv->errh = log_error_st_init(&srv->cur_ts, &srv->last_generated_debug_ts);
 
 	srv->srvconf.modules = array_init();
@@ -313,9 +302,7 @@ static server *server_init(void) {
 
 __attribute_cold__
 static void server_free(server *srv) {
-	size_t i;
-
-	for (i = 0; i < FILE_CACHE_MAX; i++) {
+	for (int i = 0; i < FILE_CACHE_MAX; ++i) {
 		buffer_free(srv->mtime_cache[i].str);
 	}
 
@@ -352,10 +339,8 @@ static void server_free(server *srv) {
 
 	fdevent_free(srv->ev);
 
-	free(srv->conns);
-
 	if (srv->config_storage) {
-		for (i = 0; i < srv->config_context->used; i++) {
+		for (uint32_t i = 0; i < srv->config_context->used; ++i) {
 			specific_config *s = srv->config_storage[i];
 
 			if (!s) continue;
@@ -383,8 +368,8 @@ static void server_free(server *srv) {
 	CLEAN(srvconf.upload_tempdirs);
 #undef CLEAN
 
-	joblist_free(srv, srv->joblist);
-	fdwaitqueue_free(srv, srv->fdwaitqueue);
+	free(srv->joblist.ptr);
+	free(srv->fdwaitqueue.ptr);
 
 	if (srv->stat_cache) {
 		stat_cache_free(srv->stat_cache);
@@ -433,8 +418,7 @@ static void remove_pid_file(server *srv) {
 __attribute_cold__
 static server_socket * server_oneshot_getsock(server *srv, sock_addr *cnt_addr) {
 	server_socket *srv_socket, *srv_socket_wild = NULL;
-	size_t i;
-	for (i = 0; i < srv->srv_sockets.used; ++i) {
+	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
 		srv_socket = srv->srv_sockets.ptr[i];
 		if (!sock_addr_is_port_eq(&srv_socket->addr,cnt_addr)) continue;
 		if (sock_addr_is_addr_eq(&srv_socket->addr,cnt_addr)) return srv_socket;
@@ -719,8 +703,7 @@ static int log_error_open(server *srv) {
            ,{ "local6",   LOG_LOCAL6 }
            ,{ "local7",   LOG_LOCAL7 }
         };
-        unsigned int i;
-        for (i = 0; i < sizeof(facility_names)/sizeof(facility_names[0]); ++i) {
+        for (unsigned int i = 0; i < sizeof(facility_names)/sizeof(facility_names[0]); ++i) {
             const struct facility_name_st *f = facility_names+i;
             if (0 == strcmp(srv->srvconf.syslog_facility->ptr, f->name)) {
                 facility = f->val;
@@ -877,7 +860,7 @@ static void server_sockets_restore (server *srv) { /* graceful_restart */
 __attribute_cold__
 static int server_sockets_set_nb_cloexec (server *srv) {
     if (srv->sockets_disabled) return 0; /* lighttpd -1 (one-shot mode) */
-    for (size_t i = 0; i < srv->srv_sockets.used; ++i) {
+    for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
         server_socket *srv_socket = srv->srv_sockets.ptr[i];
         if (-1 == fdevent_fcntl_set_nb_cloexec_sock(srv->ev, srv_socket->fd)) {
             log_error_write(srv, __FILE__, __LINE__, "ss",
@@ -890,7 +873,7 @@ static int server_sockets_set_nb_cloexec (server *srv) {
 
 __attribute_cold__
 static void server_sockets_set_event (server *srv, int event) {
-    for (size_t i = 0; i < srv->srv_sockets.used; ++i) {
+    for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
         server_socket *srv_socket = srv->srv_sockets.ptr[i];
         fdevent_fdnode_event_set(srv->ev, srv_socket->fdn, event);
     }
@@ -900,7 +883,7 @@ __attribute_cold__
 static void server_sockets_unregister (server *srv) {
     if (2 == srv->sockets_disabled) return;
     srv->sockets_disabled = 2;
-    for (size_t i = 0; i < srv->srv_sockets.used; ++i)
+    for (uint32_t i = 0; i < srv->srv_sockets.used; ++i)
         network_unregister_sock(srv, srv->srv_sockets.ptr[i]);
 }
 
@@ -912,7 +895,7 @@ static void server_sockets_close (server *srv) {
      * than started by lighttpd via "bin-path")
      */
     if (3 == srv->sockets_disabled) return;
-    for (size_t i = 0; i < srv->srv_sockets.used; ++i) {
+    for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
         server_socket *srv_socket = srv->srv_sockets.ptr[i];
         if (-1 == srv_socket->fd) continue;
         if (2 != srv->sockets_disabled) network_unregister_sock(srv,srv_socket);
@@ -963,35 +946,39 @@ static void server_sockets_disable (server *srv) {
     server_sockets_set_event(srv, 0);
     srv->sockets_disabled = 1;
     log_error_write(srv, __FILE__, __LINE__, "s",
-                    (srv->conns->used >= srv->max_conns)
+                    (srv->conns.used >= srv->max_conns)
                     ? "[note] sockets disabled, connection limit reached"
                     : "[note] sockets disabled, out-of-fds");
 }
 
 __attribute_cold__
 static void server_overload_check (server *srv) {
-    if (srv->cur_fds + srv->want_fds < srv->max_fds_lowat
-        && srv->conns->used <= srv->max_conns * 9 / 10) {
+    if (srv->cur_fds + (int)srv->fdwaitqueue.used < srv->max_fds_lowat
+        && srv->conns.used <= srv->max_conns * 9 / 10) {
 
         server_sockets_enable(srv);
     }
 }
 
 static void server_load_check (server *srv) {
-    if (srv->cur_fds + srv->want_fds > srv->max_fds_hiwat  /* out of fds */
-        || srv->conns->used >= srv->max_conns) {   /* out of connections */
+    /* check if hit limits for num fds used or num connections */
+    if (srv->cur_fds + (int)srv->fdwaitqueue.used > srv->max_fds_hiwat
+        || srv->conns.used >= srv->max_conns) {
 
         server_sockets_disable(srv);
     }
 }
 
 __attribute_cold__
-static void server_process_want_fds (server *srv) {
+static void server_process_fdwaitqueue (server *srv) {
+    connections * const fdwaitqueue = &srv->fdwaitqueue;
+    uint32_t i = 0;
     for (int n = srv->max_fds - srv->cur_fds - 16; n > 0; --n) {
-        connection *con = fdwaitqueue_unshift(srv, srv->fdwaitqueue);
-        if (NULL == con) break;
-        connection_state_machine(srv, con);
-        --srv->want_fds;
+        if (i == fdwaitqueue->used) break;
+        connection_state_machine(srv, fdwaitqueue->ptr[i++]);
+    }
+    if (i > 0 && 0 != (fdwaitqueue->used -= i)) {
+	memmove(fdwaitqueue->ptr, fdwaitqueue->ptr+i, fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
     }
 }
 
@@ -1004,7 +991,7 @@ static int server_main (server * const srv, int argc, char **argv) {
 #ifdef HAVE_FORK
 	int num_childs = 0;
 #endif
-	size_t i;
+	uint32_t i;
 #ifdef HAVE_SIGACTION
 	struct sigaction act;
 #endif
@@ -1501,9 +1488,7 @@ static int server_main (server * const srv, int argc, char **argv) {
 	/* dump unused config-keys */
 	for (i = 0; i < srv->config_context->used; i++) {
 		array *config = ((data_config *)srv->config_context->data[i])->value;
-		size_t j;
-
-		for (j = 0; config && j < config->used; j++) {
+		for (uint32_t j = 0; config && j < config->used; ++j) {
 			data_unset *du = config->data[j];
 
 			/* all var.* is known as user defined variable */
@@ -1837,7 +1822,7 @@ static void server_handle_sigalrm (server * const srv, time_t min_ts, time_t las
 				/* cleanup stat-cache */
 				stat_cache_trigger_cleanup(srv);
 				/* reset global/aggregate rate limit counters */
-				for (size_t i = 0; i < srv->config_context->used; ++i) {
+				for (uint32_t i = 0; i < srv->config_context->used; ++i) {
 					srv->config_storage[i]->global_bytes_per_second_cnt = 0;
 				}
 				/* if graceful_shutdown, accelerate cleanup of recently completed request/responses */
@@ -1868,7 +1853,7 @@ static void server_handle_sigchld (server * const srv) {
 __attribute_hot__
 __attribute_noinline__
 static int server_main_loop (server * const srv) {
-	connections * const joblist = srv->joblist;
+	connections * const joblist = &srv->joblist;
 	time_t last_active_ts = time(NULL);
 
 	while (!srv_shutdown) {
@@ -1898,7 +1883,7 @@ static int server_main_loop (server * const srv) {
 
 		if (graceful_shutdown) {
 			server_graceful_state(srv);
-			if (srv->conns->used == 0) {
+			if (0 == srv->conns.used) {
 				/* we are in graceful shutdown phase and all connections are closed
 				 * we are ready to terminate without harming anyone */
 				srv_shutdown = 1;
@@ -1910,15 +1895,15 @@ static int server_main_loop (server * const srv) {
 			server_load_check(srv);
 		}
 
-		if (srv->want_fds) {
-			server_process_want_fds(srv);
+		if (srv->fdwaitqueue.used) {
+			server_process_fdwaitqueue(srv);
 		}
 
 		if (fdevent_poll(srv->ev, 1000) > 0) {
 			last_active_ts = srv->cur_ts;
 		}
 
-		for (size_t ndx = 0; ndx < joblist->used; ++ndx) {
+		for (uint32_t ndx = 0; ndx < joblist->used; ++ndx) {
 			connection *con = joblist->ptr[ndx];
 			connection_state_machine(srv, con);
 		}