mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-13 23:14:46 +00:00
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.
This commit is contained in:
parent
53a4766e40
commit
2386be64ba
@ -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 @@ static inline int conn_get_alpn(const struct connection *conn, const char **str,
|
||||
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 */
|
||||
|
||||
/*
|
||||
|
@ -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 @@ struct connection {
|
||||
} 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
|
||||
|
@ -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()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user