MINOR: connection: implement alpn registration of muxes
Selecting a mux based on ALPN and the proxy mode will quickly become a
pain. This commit provides new functions to register/lookup a mux based
on the ALPN string and the proxy mode to make this easier. Given that
we're not supposed to support a wide range of muxes, the lookup should
not have any measurable performance impact.
diff --git a/include/proto/connection.h b/include/proto/connection.h
index 72f793a..fbb3790 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -23,6 +23,7 @@
#define _PROTO_CONNECTION_H
#include <common/config.h>
+#include <common/ist.h>
#include <common/memory.h>
#include <types/connection.h>
#include <types/listener.h>
@@ -31,6 +32,7 @@
extern struct pool_head *pool2_connection;
extern struct xprt_ops *registered_xprt[XPRT_ENTRIES];
+extern struct alpn_mux_list alpn_mux_list;
/* perform minimal intializations, report 0 in case of error, 1 if OK. */
int init_connection();
@@ -702,6 +704,72 @@
return conn->xprt->get_alpn(conn, str, len);
}
+/* registers alpn mux list <list>. Modifies the list element! */
+static inline void alpn_register_mux(struct alpn_mux_list *list)
+{
+ LIST_ADDQ(&alpn_mux_list.list, &list->list);
+}
+
+/* unregisters alpn mux list <list> */
+static inline void alpn_unregister_mux(struct alpn_mux_list *list)
+{
+ LIST_DEL(&list->list);
+ LIST_INIT(&list->list);
+}
+
+/* returns the first mux in the list matching the exact same token and
+ * compatible with the proxy's mode (http or tcp). Mode "health" has to be
+ * considered as TCP here. Ie passing "px->mode == PR_MODE_HTTP" is fine. Will
+ * fall back to the first compatible mux with empty ALPN name. May return null
+ * if the code improperly registered the default mux to use as a fallback.
+ */
+static inline const struct mux_ops *alpn_get_mux(const struct ist token, int http_mode)
+{
+ struct alpn_mux_list *item;
+ const struct mux_ops *fallback = NULL;
+
+ http_mode = 1 << !!http_mode;
+
+ list_for_each_entry(item, &alpn_mux_list.list, list) {
+ if (!(item->mode & http_mode))
+ continue;
+ if (isteq(token, item->token))
+ return item->mux;
+ if (!istlen(item->token))
+ fallback = item->mux;
+ }
+ return fallback;
+}
+
+/* finds the best mux for incoming connection <conn> and mode <http_mode> for
+ * the proxy. Null cannot be returned unless there's a serious bug somewhere
+ * else (no fallback mux registered).
+ */
+static inline const struct mux_ops *conn_find_best_mux(struct connection *conn, int http_mode)
+{
+ const char *alpn_str;
+ int alpn_len;
+
+ if (!conn_get_alpn(conn, &alpn_str, &alpn_len))
+ alpn_len = 0;
+
+ return alpn_get_mux(ist2(alpn_str, alpn_len), http_mode);
+}
+
+/* finds the best mux for incoming connection <conn>, a proxy in and http mode
+ * <mode>, and installs it on the connection for direction <dir> (MUX_INBOUND/
+ * MUX_OUTBOUND). Returns < 0 on error.
+ */
+static inline int conn_install_best_mux(struct connection *conn, int mode, enum mux_dir dir)
+{
+ const struct mux_ops *mux_ops;
+
+ mux_ops = conn_find_best_mux(conn, mode);
+ if (!mux_ops)
+ return -1;
+ return conn_install_mux(conn, mux_ops, dir);
+}
+
#endif /* _PROTO_CONNECTION_H */
/*
diff --git a/include/types/connection.h b/include/types/connection.h
index f720601..b925f65 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -26,6 +26,7 @@
#include <sys/socket.h>
#include <common/config.h>
+#include <common/ist.h>
#include <types/listener.h>
#include <types/obj_type.h>
@@ -331,6 +332,21 @@
} addr; /* addresses of the remote side, client for producer and server for consumer */
};
+/* ALPN token registration */
+enum alpn_proxy_mode {
+ ALPN_MODE_NONE = 0,
+ ALPN_MODE_TCP = 1 << 0, // must not be changed!
+ ALPN_MODE_HTTP = 1 << 1, // must not be changed!
+ ALPN_MODE_ANY = ALPN_MODE_TCP | ALPN_MODE_HTTP,
+};
+
+struct alpn_mux_list {
+ const struct ist token; /* token name and length. Empty is catch-all */
+ enum alpn_proxy_mode mode;
+ const struct mux_ops *mux;
+ struct list list;
+};
+
/* proxy protocol v2 definitions */
#define PP2_SIGNATURE "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
#define PP2_SIGNATURE_LEN 12
diff --git a/src/connection.c b/src/connection.c
index 129c741..43ec328 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -30,6 +30,11 @@
struct pool_head *pool2_connection;
struct xprt_ops *registered_xprt[XPRT_ENTRIES] = { NULL, };
+/* List head of all known muxes for ALPN */
+struct alpn_mux_list alpn_mux_list = {
+ .list = LIST_HEAD_INIT(alpn_mux_list.list)
+};
+
/* perform minimal intializations, report 0 in case of error, 1 if OK. */
int init_connection()
{