From 59a877dfd91211879c3a01c335ae45221c755ed8 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 12 Oct 2021 09:36:10 +0200 Subject: [PATCH] MINOR: listeners: add clone_listener() to duplicate listeners at boot time This function's purpose will be to duplicate a listener in INIT state. This will be used to ease declaration of listeners spanning multiple groups, which will thus require multiple FDs hence multiple receivers. --- include/haproxy/listener.h | 1 + src/listener.c | 49 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index 5bd60c0247..39dce4cf9f 100644 --- a/include/haproxy/listener.h +++ b/include/haproxy/listener.h @@ -98,6 +98,7 @@ void unbind_listener(struct listener *listener); */ int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss, int portl, int porth, int fd, struct protocol *proto, char **err); +struct listener *clone_listener(struct listener *src); /* Delete a listener from its protocol's list of listeners. The listener's * state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's diff --git a/src/listener.c b/src/listener.c index 112455a66e..044d22390f 100644 --- a/src/listener.c +++ b/src/listener.c @@ -663,6 +663,55 @@ int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss, return 1; } +/* clones listener and returns the new one. All dynamically allocated + * fields are reallocated (name for now). The new listener is inserted before + * the original one in the bind_conf and frontend lists. This allows it to be + * duplicated while iterating over the current list. The original listener must + * only be in the INIT or ASSIGNED states, and the new listener will only be + * placed into the INIT state. The counters are always set to NULL. Maxsock is + * updated. Returns NULL on allocation error. + */ +struct listener *clone_listener(struct listener *src) +{ + struct listener *l; + + l = calloc(1, sizeof(*l)); + if (!l) + goto oom1; + memcpy(l, src, sizeof(*l)); + + if (l->name) { + l->name = strdup(l->name); + if (!l->name) + goto oom2; + } + + l->rx.owner = l; + l->state = LI_INIT; + l->counters = NULL; + l->extra_counters = NULL; + + LIST_APPEND(&src->by_fe, &l->by_fe); + LIST_APPEND(&src->by_bind, &l->by_bind); + + MT_LIST_INIT(&l->wait_queue); + + l->rx.proto->add(l->rx.proto, l); + + HA_SPIN_INIT(&l->lock); + _HA_ATOMIC_INC(&jobs); + _HA_ATOMIC_INC(&listeners); + global.maxsock++; + return l; + + oom3: + free(l->name); + oom2: + free(l); + oom1: + return l; +} + /* Delete a listener from its protocol's list of listeners. The listener's * state is automatically updated from LI_ASSIGNED to LI_INIT. The protocol's * number of listeners is updated, as well as the global number of listeners -- 2.39.5