MAJOR: sessions: Store multiple outgoing connections in the session.

Instead of just storing the last connection in the session, store all of
the connections, for at most MAX_SRV_LIST (currently 5) targets.
That way we can do keepalive on more than 1 outgoing connection when the
client uses HTTP/2.
diff --git a/include/proto/connection.h b/include/proto/connection.h
index a1b979e..3f48b15 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -662,13 +662,8 @@
 /* Releases a connection previously allocated by conn_new() */
 static inline void conn_free(struct connection *conn)
 {
-	struct session *sess, *sess_back;
-
-	list_for_each_entry_safe(sess, sess_back, &conn->session_list, conn_list) {
-		sess->srv_conn = NULL;
-		LIST_DEL(&sess->conn_list);
-		LIST_INIT(&sess->conn_list);
-	}
+	/* Remove ourself from the session's connections list, if any. */
+	LIST_DEL(&conn->session_list);
 	/* If we temporarily stored the connection as the stream_interface's
 	 * end point, remove it.
 	 */
diff --git a/include/proto/session.h b/include/proto/session.h
index 68f5c0d..bc5498a 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -71,6 +71,46 @@
 	}
 }
 
+static inline void session_add_conn(struct session *sess, struct connection *conn, void *target)
+{
+	int avail = -1;
+	int i;
+
+	for (i = 0; i < MAX_SRV_LIST; i++) {
+		if (sess->srv_list[i].target == target) {
+			avail = i;
+			break;
+		}
+		if (LIST_ISEMPTY(&sess->srv_list[i].list) && avail == -1)
+			avail = i;
+	}
+	if (avail == -1) {
+		struct connection *conn, *conn_back;
+		int count = 0;
+		/* We have no slot free, let's free the one with the fewer connections */
+		for (i = 0; i < MAX_SRV_LIST; i++) {
+			int count_list = 0;
+			list_for_each_entry(conn, &sess->srv_list[i].list, session_list)
+			    count_list++;
+			if (count == 0 || count_list < count) {
+				count = count_list;
+				avail = i;
+			}
+		}
+		/* Now unown all the connections */
+		list_for_each_entry_safe(conn, conn_back, &sess->srv_list[avail].list, session_list) {
+			conn->owner = NULL;
+			LIST_DEL(&conn->session_list);
+			LIST_INIT(&conn->session_list);
+			if (conn->mux)
+				conn->mux->destroy(conn);
+		}
+
+	}
+	sess->srv_list[avail].target = target;
+	LIST_ADDQ(&sess->srv_list[avail].list, &conn->session_list);
+}
+
 
 #endif /* _PROTO_SESSION_H */
 
diff --git a/include/types/connection.h b/include/types/connection.h
index dbf985b..85afca0 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -414,7 +414,7 @@
 	struct wait_event *send_wait; /* Task to wake when we're ready to send */
 	struct wait_event *recv_wait; /* Task to wake when we're ready to recv */
 	struct list list;             /* attach point to various connection lists (idle, ...) */
-	struct list session_list;     /* List of all sessions attached to this connection */
+	struct list session_list;     /* List of attached connections to a session */
 	int xprt_st;                  /* transport layer state, initialized to zero */
 	int tmp_early_data;           /* 1st byte of early data, if any */
 	int sent_early_data;          /* Amount of early data we sent so far */
diff --git a/include/types/session.h b/include/types/session.h
index e0e1455..334a071 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -37,6 +37,13 @@
 #include <types/task.h>
 #include <types/vars.h>
 
+struct sess_srv_list {
+	void *target;
+	struct list list;
+};
+
+#define MAX_SRV_LIST	5
+
 struct session {
 	struct proxy *fe;               /* the proxy this session depends on for the client side */
 	struct listener *listener;      /* the listener by which the request arrived */
@@ -47,8 +54,7 @@
 	struct vars vars;               /* list of variables for the session scope. */
 	struct task *task;              /* handshake timeout processing */
 	long t_handshake;               /* handshake duration, -1 = not completed */
-	struct connection *srv_conn;    /* Server connection we last used */
-	struct list conn_list;          /* List element for the session list in each connection */
+	struct sess_srv_list srv_list[MAX_SRV_LIST]; /* List of servers and the connections the session is currently responsible for */
 };
 
 #endif /* _TYPES_SESSION_H */