linked list sorted by timeout times

This commit is contained in:
yrutschle 2022-04-24 18:35:09 +02:00
parent cd5d75fed9
commit 449fabba51
6 changed files with 82 additions and 4 deletions

View File

@ -92,6 +92,12 @@ struct queue {
int deferred_data_size;
};
/* Double linked list for timeout management */
typedef struct {
struct connection* head;
struct connection* tail;
} dl_list;
struct connection {
int type; /* SOCK_DGRAM | SOCK_STREAM */
struct sslhcfg_protocols_item* proto; /* Where to connect to */
@ -113,6 +119,9 @@ struct connection {
time_t last_active;
/* double linked list of timeouts */
struct connection *timeout_prev, *timeout_next;
/* We need one local socket for each target server, so we know where to
* forward server responses */
int target_sock;

View File

@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Sun Apr 10 08:52:30 2022.
* on Mon Apr 18 21:21:32 2022.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2021 Yves Rutschle

View File

@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Sun Apr 10 08:52:30 2022.
* on Mon Apr 18 21:21:32 2022.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2021 Yves Rutschle
@ -72,6 +72,7 @@ struct sslhcfg_protocols_item {
T_PROBE* probe;
struct addrinfo* saddr;
void* data;
dl_list timeouts;
};
struct sslhcfg_item {

View File

@ -160,6 +160,9 @@ static void config_protocols()
(const char**) cfg.protocols[i].alpn_protocols,
cfg.protocols[i].alpn_protocols_len);
}
p->timeouts.head = NULL;
p->timeouts.tail = NULL;
}
}

View File

@ -133,7 +133,8 @@ config: {
# Runtime data
{ name: "probe"; type: "runtime"; c_type: "T_PROBE*" },
{ name: "saddr"; type: "runtime"; c_type: "struct addrinfo*" },
{ name: "data"; type: "runtime"; c_type: "void*" }
{ name: "data"; type: "runtime"; c_type: "void*" },
{ name: "timeouts"; type: "runtime"; c_type: "dl_list" }
)
}
)

View File

@ -117,6 +117,61 @@ static int new_source(hash* h, struct connection* new)
}
/* Double linked list utilities: push element at tail of list */
static void list_push(dl_list* list, struct connection* cnx)
{
cnx->timeout_next = NULL;
if (!list->head) {
cnx->timeout_prev = NULL;
list->head = cnx;
}
if (list->tail) {
list->tail->timeout_next = cnx;
cnx->timeout_prev = list->tail;
}
list->tail = cnx;
}
/* Double linked list utilities: remove element */
static void list_remove(dl_list* list, struct connection* cnx)
{
if (list->head == cnx) list->head = cnx->timeout_next;
if (list->tail == cnx) list->tail = cnx->timeout_prev;
if (cnx->timeout_prev)
cnx->timeout_prev->timeout_next = cnx->timeout_next;
if (cnx->timeout_next)
cnx->timeout_next->timeout_prev = cnx->timeout_prev;
}
static void list_dump(void) {
int now = time(NULL);
static int cnt = 0;
if (cnt++ < 1000) {
return;
}
cnt = 0;
FILE * f = fopen("/tmp/list.tmp", "w");
fprintf(f, "time: %d\n", time(NULL));
for (int i = 0; i < cfg.protocols_len; i++) {
struct connection* c = cfg.protocols[i].timeouts.head;
fprintf(f, "p %d %s list %p %p\n", i, cfg.protocols[i].name, cfg.protocols[i].timeouts.head, cfg.protocols[i].timeouts.tail);
while (c) {
fprintf(f, "%p %d(%d) %p %p\n", c, c->last_active, now - c->last_active, c->timeout_prev, c->timeout_next);
c = c->timeout_next;
}
fprintf(f, "/list\n");
}
fclose(f);
rename("/tmp/list.tmp", "/tmp/list");
}
/* Check all connections to see if a UDP connections has timed out, then free
* it. At the same time, keep track of the closest, next timeout. Only do the
@ -152,8 +207,9 @@ void udp_timeouts(struct loop_info* fd_info)
close(cnx->target_sock);
watchers_del_read(fd_info->watchers, i);
watchers_del_write(fd_info->watchers, i);
collection_remove_cnx(fd_info->collection, cnx);
hash_remove(fd_info->hash_sources, cnx);
list_remove(&cnx->proto->timeouts, cnx);
collection_remove_cnx(fd_info->collection, cnx);
} else {
if (timeout < next_timeout) next_timeout = timeout;
}
@ -164,10 +220,18 @@ void udp_timeouts(struct loop_info* fd_info)
fd_info->next_timeout = next_timeout;
}
/* Mark the connection was active */
static void mark_active(struct connection* cnx)
{
cnx->last_active = time(NULL);
dl_list* list = &cnx->proto->timeouts;
list_remove(list, cnx);
list_push(list, cnx);
list_dump();
}