]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: protocol: store the socket and control type in the protocol array
authorWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 19:28:15 +0000 (21:28 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 16 Sep 2020 20:08:08 +0000 (22:08 +0200)
The protocol array used to be only indexed by socket family, which is very
problematic with UDP (requiring an extra family) and with the forthcoming
QUIC (also requiring an extra family), especially since that binds them to
certain families, prevents them from supporting dgram UNIX sockets etc.

In order to address this, we now start to register the protocols with more
info, namely the socket type and the control type (either stream or dgram).
This is sufficient for the protocols we have to deal with, but could also
be extended further if multiple protocol variants were needed. But as is,
it still fits nicely in an array, which is convenient for lookups that are
instant.

include/haproxy/protocol.h
src/protocol.c

index 3a3da90b538db1d404d1b7cfc26b27548c2847a7..ac331c78d6ecc8234c895511a13f1ee192e7a6c1 100644 (file)
@@ -26,7 +26,8 @@
 #include <haproxy/protocol-t.h>
 #include <haproxy/thread.h>
 
-extern struct protocol *__protocol_by_family[AF_CUST_MAX];
+/* [AF][sock_dgram][ctrl_dgram] */
+extern struct protocol *__protocol_by_family[AF_CUST_MAX][2][2];
 __decl_thread(extern HA_SPINLOCK_T proto_lock);
 
 /* Registers the protocol <proto> */
@@ -55,11 +56,24 @@ int protocol_unbind_all(void);
  */
 int protocol_enable_all(void);
 
-/* returns the protocol associated to family <family> or NULL if not found */
+/* returns the protocol associated to family <family> with sock_type and
+ * ctrl_type of SOCK_STREAM, or NULL if not found
+ */
 static inline struct protocol *protocol_by_family(int family)
 {
        if (family >= 0 && family < AF_CUST_MAX)
-               return __protocol_by_family[family];
+               return __protocol_by_family[family][0][0];
+       return NULL;
+}
+
+/* returns the protocol associated to family <family> with sock_type and
+ * ctrl_type of either SOCK_STREAM or SOCK_DGRAM depending on the requested
+ * values, or NULL if not found.
+ */
+static inline struct protocol *protocol_lookup(int family, int sock_dgram, int ctrl_dgram)
+{
+       if (family >= 0 && family < AF_CUST_MAX)
+               return __protocol_by_family[family][!!sock_dgram][!!ctrl_dgram];
        return NULL;
 }
 
index 74858702523ba4694d2cc6f574e8d7b28fc8502f..48bce766b6dab11394ed7c9aa0f2b1a2537c8b89 100644 (file)
@@ -24,7 +24,7 @@
 
 /* List head of all registered protocols */
 static struct list protocols = LIST_HEAD_INIT(protocols);
-struct protocol *__protocol_by_family[AF_CUST_MAX] = { };
+struct protocol *__protocol_by_family[AF_CUST_MAX][2][2] = { };
 
 /* This is the global spinlock we may need to register/unregister listeners or
  * protocols. Its main purpose is in fact to serialize the rare stop/deinit()
@@ -38,7 +38,9 @@ void protocol_register(struct protocol *proto)
        HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
        LIST_ADDQ(&protocols, &proto->list);
        if (proto->sock_domain >= 0 && proto->sock_domain < AF_CUST_MAX)
-               __protocol_by_family[proto->sock_domain] = proto;
+               __protocol_by_family[proto->sock_domain]
+                       [proto->sock_type == SOCK_DGRAM]
+                       [proto->ctrl_type == SOCK_DGRAM] = proto;
        HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
 }