MINOR: listeners: new function create_listeners
This function is used to create a series of listeners for a specific
address and a port range. It automatically calls the matching protocol
handlers to add them to the relevant lists. This way cfgparse doesn't
need to manipulate listeners anymore. As an added bonus, the memory
allocation is checked.
diff --git a/include/proto/listener.h b/include/proto/listener.h
index 0ad0beb..7fdb1cf 100644
--- a/include/proto/listener.h
+++ b/include/proto/listener.h
@@ -78,6 +78,17 @@
*/
int unbind_all_listeners(struct protocol *proto);
+
+/* creates one or multiple listeners for bind_conf <bc> on sockaddr <ss> on port
+ * range <portl> to <porth>, and possibly attached to fd <fd> (or -1 for auto
+ * allocation). The address family is taken from ss->ss_family. The number of
+ * jobs and listeners is automatically increased by the number of listeners
+ * created. It returns non-zero on success, zero on error with the error message
+ * set in <err>.
+ */
+int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
+ int portl, int porth, int fd, char **err);
+
/* 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. Note that the listener must have previously
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 759d407..9b91b90 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -220,14 +220,13 @@
*/
int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
{
- struct listener *l;
char *next, *dupstr;
int port, end;
next = dupstr = strdup(str);
while (next && *next) {
- struct sockaddr_storage ss, *ss2;
+ struct sockaddr_storage *ss2;
int fd = -1;
str = next;
@@ -283,31 +282,10 @@
}
/* OK the address looks correct */
- memcpy(&ss, ss2, sizeof(ss));
-
- for (; port <= end; port++) {
- struct protocol *proto = protocol_by_family(ss.ss_family);
-
- if (!proto) {
- memprintf(err, "unsupported protocol family %d for address '%s'.\n", ss.ss_family, str);
- goto fail;
- }
-
- l = calloc(1, sizeof(*l));
- l->obj_type = OBJ_TYPE_LISTENER;
- LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
- LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
- l->bind_conf = bind_conf;
-
- l->fd = fd;
- memcpy(&l->addr, &ss, sizeof(ss));
- l->state = LI_INIT;
-
- proto->add(l, port);
-
- jobs++;
- listeners++;
- } /* end for(port) */
+ if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
+ memprintf(err, "%s for address '%s'.\n", *err, str);
+ goto fail;
+ }
} /* end while(next) */
free(dupstr);
return 1;
diff --git a/src/listener.c b/src/listener.c
index abedd2f..47bed17 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -33,6 +33,7 @@
#include <proto/freq_ctr.h>
#include <proto/log.h>
#include <proto/listener.h>
+#include <proto/protocol.h>
#include <proto/sample.h>
#include <proto/stream.h>
#include <proto/task.h>
@@ -298,6 +299,48 @@
return ERR_NONE;
}
+/* creates one or multiple listeners for bind_conf <bc> on sockaddr <ss> on port
+ * range <portl> to <porth>, and possibly attached to fd <fd> (or -1 for auto
+ * allocation). The address family is taken from ss->ss_family. The number of
+ * jobs and listeners is automatically increased by the number of listeners
+ * created. It returns non-zero on success, zero on error with the error message
+ * set in <err>.
+ */
+int create_listeners(struct bind_conf *bc, const struct sockaddr_storage *ss,
+ int portl, int porth, int fd, char **err)
+{
+ struct protocol *proto = protocol_by_family(ss->ss_family);
+ struct listener *l;
+ int port;
+
+ if (!proto) {
+ memprintf(err, "unsupported protocol family %d", ss->ss_family);
+ return 0;
+ }
+
+ for (port = portl; port <= porth; port++) {
+ l = calloc(1, sizeof(*l));
+ if (!l) {
+ memprintf(err, "out of memory");
+ return 0;
+ }
+ l->obj_type = OBJ_TYPE_LISTENER;
+ LIST_ADDQ(&bc->frontend->conf.listeners, &l->by_fe);
+ LIST_ADDQ(&bc->listeners, &l->by_bind);
+ l->bind_conf = bc;
+
+ l->fd = fd;
+ memcpy(&l->addr, ss, sizeof(*ss));
+ l->state = LI_INIT;
+
+ proto->add(l, port);
+
+ jobs++;
+ listeners++;
+ }
+ return 1;
+}
+
/* 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. Note that the listener must have previously