MEDIUM: stream-int: queue idle connections at the server

Now we get a per-server list of all idle connections. That way we'll
be able to reclaim them upon shortage later.
diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h
index 6e4cfe8..09c2a4e 100644
--- a/include/proto/stream_interface.h
+++ b/include/proto/stream_interface.h
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 
 #include <common/config.h>
+#include <types/server.h>
 #include <types/stream.h>
 #include <types/stream_interface.h>
 #include <proto/applet.h>
@@ -154,6 +155,7 @@
 		return;
 
 	if ((conn = objt_conn(si->end))) {
+		LIST_DEL(&conn->list);
 		conn_force_close(conn);
 		conn_free(conn);
 	}
@@ -167,15 +169,19 @@
 
 /* Turn a possibly existing connection endpoint of stream interface <si> to
  * idle mode, which means that the connection will be polled for incoming events
- * and might be killed by the underlying I/O handler.
+ * and might be killed by the underlying I/O handler. If <pool> is not null, the
+ * connection will also be added at the head of this list.
  */
-static inline void si_idle_conn(struct stream_interface *si)
+static inline void si_idle_conn(struct stream_interface *si, struct list *pool)
 {
 	struct connection *conn = objt_conn(si->end);
 
 	if (!conn)
 		return;
 
+	if (pool)
+		LIST_ADD(pool, &conn->list);
+
 	conn_attach(conn, si, &si_idle_conn_cb);
 	conn_data_want_recv(conn);
 }
diff --git a/src/backend.c b/src/backend.c
index f8185d7..bbe9573 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1052,6 +1052,11 @@
 
 	if (!reuse)
 		srv_conn = si_alloc_conn(&s->si[1]);
+	else {
+		/* reusing our connection, take it out of the idle list */
+		LIST_DEL(&srv_conn->list);
+		LIST_INIT(&srv_conn->list);
+	}
 
 	if (!srv_conn)
 		return SF_ERR_RESOURCE;
diff --git a/src/proto_http.c b/src/proto_http.c
index 161939a..352dd75 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5030,12 +5030,15 @@
 {
 	int prev_status = s->txn->status;
 	struct proxy *fe = strm_fe(s);
+	struct connection *srv_conn;
+	struct server *srv;
 
 	/* FIXME: We need a more portable way of releasing a backend's and a
 	 * server's connections. We need a safer way to reinitialize buffer
 	 * flags. We also need a more accurate method for computing per-request
 	 * data.
 	 */
+	srv_conn = objt_conn(s->si[1].end);
 
 	/* unless we're doing keep-alive, we want to quickly close the connection
 	 * to the server.
@@ -5125,6 +5128,7 @@
 	if (((s->txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
 	    !si_conn_ready(&s->si[1])) {
 		si_release_endpoint(&s->si[1]);
+		srv_conn = NULL;
 	}
 
 	s->si[1].state     = s->si[1].prev_state = SI_ST_INI;
@@ -5182,7 +5186,11 @@
 	channel_auto_close(&s->res);
 
 	/* we're in keep-alive with an idle connection, monitor it */
-	si_idle_conn(&s->si[1]);
+	srv = NULL;
+	if (srv_conn)
+		srv = objt_server(srv_conn->target);
+
+	si_idle_conn(&s->si[1], srv ? &srv->priv_conns : NULL);
 
 	s->req.analysers = strm_li(s)->analysers;
 	s->res.analysers = 0;
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 4b8d924..2ea59c7 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -515,6 +515,7 @@
 
 	if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) {
 		/* warning, we can't do anything on <conn> after this call ! */
+		LIST_DEL(&conn->list);
 		conn_force_close(conn);
 		conn_free(conn);
 		si->end = NULL;