MAJOR: backend: initial work towards connection reuse

In connect_server(), if we don't have a connection attached to the
stream-int, we first look into the server's idle_conns list and we
pick the first one there, we detach it from its owner if it had one.
If we used to have a connection, we close it.

This mechanism works well but doesn't scale : as servers increase,
the likeliness that the connection attached to the stream interface
doesn't match the server and gets closed increases.
diff --git a/src/backend.c b/src/backend.c
index 3c00acf..b31061a 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1034,6 +1034,33 @@
 	if (srv_conn)
 		reuse = s->target == srv_conn->target;
 
+	if (srv && !reuse) {
+		if (srv_conn) {
+			srv_conn->owner = NULL;
+			si_release_endpoint(&s->si[1]);
+			srv_conn = NULL;
+		}
+
+		if ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS &&
+		    !LIST_ISEMPTY(&srv->idle_conns)) {
+			/* We're going to have to pick the first connection
+			 * from this pool and use it for our purposes. We may
+			 * have to get rid of the current idle connection. It
+			 * may move to another pool, but we know we're not
+			 * interested in it.
+			 */
+			/* pick first connection. We know there's at least one */
+			srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
+
+			LIST_DEL(&srv_conn->list);
+			LIST_INIT(&srv_conn->list);
+
+			si_detach_endpoint(srv_conn->owner);
+			si_attach_conn(&s->si[1], srv_conn);
+			reuse = 1;
+		}
+	}
+
 	if (reuse) {
 		/* Disable connection reuse if a dynamic source is used.
 		 * As long as we don't share connections between servers,
diff --git a/src/proto_http.c b/src/proto_http.c
index fb831b9..02ff485 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5189,7 +5189,13 @@
 	/* we're in keep-alive with an idle connection, monitor it */
 	if (srv_conn) {
 		srv = objt_server(srv_conn->target);
-		si_idle_conn(&s->si[1], srv ? &srv->priv_conns : NULL);
+		if (!srv)
+			si_idle_conn(&s->si[1], NULL);
+		else if ((srv_conn->flags & CO_FL_PRIVATE) ||
+			 ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR))
+			si_idle_conn(&s->si[1], &srv->priv_conns);
+		else
+			si_idle_conn(&s->si[1], &srv->idle_conns);
 	}
 
 	s->req.analysers = strm_li(s)->analysers;