]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: backend: only allow reuse for reverse server
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 18 Aug 2023 14:02:35 +0000 (16:02 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 24 Aug 2023 12:49:03 +0000 (14:49 +0200)
A reverse server relies solely on its pool of idle connection to
transfer requests which will be populated through a new tcp-request rule
'attach-srv'.

Several changes are required on connect_server() to implement this.
First, reuse mode is forced to always for this type of server. Then, if
no idle connection is found, the request will be aborted. This results
with a 503 HTTP error code, similarly to when no server is available.

include/haproxy/server.h
src/backend.c

index 3829bce2beba6a2d3017930870a2b89057c12915..730493362d1dbc02a1999a7a85487b9cba54db9c 100644 (file)
@@ -33,6 +33,7 @@
 #include <haproxy/task.h>
 #include <haproxy/thread-t.h>
 #include <haproxy/time.h>
+#include <haproxy/tools.h>
 
 
 __decl_thread(extern HA_SPINLOCK_T idle_conn_srv_lock);
@@ -305,6 +306,16 @@ static inline void srv_minmax_conn_apply(struct server *srv)
        }
 }
 
+/* Returns true if server is used as transparent mode. */
+static inline int srv_is_transparent(const struct server *srv)
+{
+       /* A reverse server does not have any address but it is not used as a
+        * transparent one.
+        */
+       return (!is_addr(&srv->addr) && !(srv->flags & SRV_F_REVERSE)) ||
+              (srv->flags & SRV_F_MAPPORTS);
+}
+
 #endif /* _HAPROXY_SERVER_H */
 
 /*
index ef132376b5a94b14d1f760e256102ab0072d3c10..a2deaed47d24679213beb4e3a9f274b364f5eafa 100644 (file)
@@ -1326,7 +1326,7 @@ static int connect_server(struct stream *s)
        struct connection *cli_conn = objt_conn(strm_orig(s));
        struct connection *srv_conn = NULL;
        struct server *srv;
-       const int reuse_mode = s->be->options & PR_O_REUSE_MASK;
+       int reuse_mode = s->be->options & PR_O_REUSE_MASK;
        int reuse = 0;
        int init_mux = 0;
        int err;
@@ -1342,6 +1342,10 @@ static int connect_server(struct stream *s)
         * it can be NULL for dispatch mode or transparent backend */
        srv = objt_server(s->target);
 
+       /* Override reuse-mode if reverse-connect is used. */
+       if (srv && srv->flags & SRV_F_REVERSE)
+               reuse_mode = PR_O_REUSE_ALWS;
+
        err = alloc_dst_address(&s->scb->dst, srv, s);
        if (err != SRV_STATUS_OK)
                return SF_ERR_INTERNAL;
@@ -1393,7 +1397,7 @@ static int connect_server(struct stream *s)
 #endif /* USE_OPENSSL */
 
        /* 3. destination address */
-       if (srv && (!is_addr(&srv->addr) || srv->flags & SRV_F_MAPPORTS))
+       if (srv && srv_is_transparent(srv))
                hash_params.dst_addr = s->scb->dst;
 
        /* 4. source address */
@@ -1587,6 +1591,12 @@ static int connect_server(struct stream *s)
 skip_reuse:
        /* no reuse or failed to reuse the connection above, pick a new one */
        if (!srv_conn) {
+               if (srv && (srv->flags & SRV_F_REVERSE)) {
+                       DBG_TRACE_USER("cannot open a new connection for reverse server", STRM_EV_STRM_PROC|STRM_EV_CS_ST, s);
+                       s->conn_err_type = STRM_ET_CONN_ERR;
+                       return SF_ERR_INTERNAL;
+               }
+
                srv_conn = conn_new(s->target);
                if (srv_conn) {
                        DBG_TRACE_STATE("alloc new be connection", STRM_EV_STRM_PROC|STRM_EV_CS_ST, s);