Further refine dropout-candidates over response-type and progress - quark - qua… | |
git clone git://git.suckless.org/quark | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 2920ba56d92b461c39f3c7c9c5a264f38b899fd7 | |
parent 6d7c7b6ff701fafc2a649b21a66a92a9ab626221 | |
Author: Laslo Hunhold <[email protected]> | |
Date: Sat, 13 Feb 2021 11:46:59 +0100 | |
Further refine dropout-candidates over response-type and progress | |
There might not only be scenarios where the server is under attack | |
by a single entity, but possibly a botnet of hundreds of computers with | |
a few connections each. | |
An honest client connecting to the server with a few connections that | |
might include a long-running download might end up as the client with | |
the most simultaneous connections (e.g. 6 over the respective 5 | |
of each botnet-member). | |
If we end up dropping one of the honest client's connections, we don't | |
want it to be the long-running-download, but lower-priority things | |
(directory listings, error responses, not-far-advanced downloads; in | |
increasing order of importance). Among similar types, we drop those | |
that are not as far advanced in absolute terms. The reasoning behind | |
this (and against relative progress) is that it's worse to drop a | |
download at 50% when the requested file is 300MB compared to | |
dropping another connection at 75% when the requested file is merely | |
a few kB large. | |
Signed-off-by: Laslo Hunhold <[email protected]> | |
Diffstat: | |
M data.c | 2 +- | |
M http.h | 2 +- | |
M main.c | 48 ++++++++++++++++++++++++++---… | |
3 files changed, 43 insertions(+), 9 deletions(-) | |
--- | |
diff --git a/data.c b/data.c | |
@@ -13,9 +13,9 @@ | |
enum status (* const data_fct[])(const struct response *, | |
struct buffer *, size_t *) = { | |
+ [RESTYPE_DIRLISTING] = data_prepare_dirlisting_buf, | |
[RESTYPE_ERROR] = data_prepare_error_buf, | |
[RESTYPE_FILE] = data_prepare_file_buf, | |
- [RESTYPE_DIRLISTING] = data_prepare_dirlisting_buf, | |
}; | |
static int | |
diff --git a/http.h b/http.h | |
@@ -65,9 +65,9 @@ enum res_field { | |
extern const char *res_field_str[]; | |
enum res_type { | |
+ RESTYPE_DIRLISTING, | |
RESTYPE_ERROR, | |
RESTYPE_FILE, | |
- RESTYPE_DIRLISTING, | |
NUM_RES_TYPES, | |
}; | |
diff --git a/main.c b/main.c | |
@@ -181,8 +181,12 @@ get_connection_drop_candidate(struct connection *connectio… | |
*/ | |
for (i = 0, minc = NULL, maxcnt = 0; i < nslots; i++) { | |
/* | |
- * the c is used to minimize in regard to importance | |
- * within the same-address-group | |
+ * we determine how many connections have the same | |
+ * in-address as connection[i], but also minimize over | |
+ * that set with other criteria, yielding a general | |
+ * minimizer c. We first set it to connection[i] and | |
+ * update it, if a better candidate shows up, in the inner | |
+ * loop | |
*/ | |
c = &connection[i]; | |
@@ -193,16 +197,46 @@ get_connection_drop_candidate(struct connection *connecti… | |
} | |
cnt++; | |
+ /* minimize over state */ | |
if (connection[j].state < c->state) { | |
- /* | |
- * we have found a connection with an | |
- * even lower state and thus lower | |
- * importance | |
- */ | |
c = &connection[j]; | |
+ } else if (connection[j].state == c->state) { | |
+ /* minimize over progress */ | |
+ if (c->state == C_SEND_BODY && | |
+ connection[i].res.type != c->res.type) { | |
+ /* | |
+ * mixed response types; progress | |
+ * is not comparable | |
+ * | |
+ * the res-type-enum is ordered as | |
+ * DIRLISTING, ERROR, FILE, i.e. | |
+ * in rising priority, because a | |
+ * file transfer is most important, | |
+ * followed by error-messages. | |
+ * Dirlistings as an "interactive" | |
+ * feature (that take up lots of | |
+ * resources) have the lowest | |
+ * priority | |
+ */ | |
+ if (connection[i].res.type < | |
+ c->res.type) { | |
+ c = &connection[j]; | |
+ } | |
+ } else if (connection[j].progress < | |
+ c->progress) { | |
+ /* | |
+ * for C_SEND_BODY with same response | |
+ * type, C_RECV_HEADER and C_SEND_BODY | |
+ * it is sufficient to compare the | |
+ * raw progress | |
+ */ | |
+ c = &connection[j]; | |
+ } | |
} | |
} | |
+ | |
if (cnt > maxcnt) { | |
+ /* this run yielded an even greedier in-address */ | |
minc = c; | |
maxcnt = cnt; | |
} |