MEDIUM: vars: move the session variables to the session, not the stream

It's important that the session-wide variables are in the session and not
in the stream.
diff --git a/include/proto/vars.h b/include/proto/vars.h
index e1092c7..4c85825 100644
--- a/include/proto/vars.h
+++ b/include/proto/vars.h
@@ -5,6 +5,7 @@
 
 void vars_init(struct vars *vars, enum vars_scope scope);
 void vars_prune(struct vars *vars, struct stream *strm);
+void vars_prune_per_sess(struct vars *vars);
 int vars_get_by_name(const char *name, size_t len, struct stream *strm, struct sample *smp);
 void vars_set_by_name(const char *name, size_t len, struct stream *strm, struct sample *smp);
 int vars_check_arg(struct arg *arg, char **err);
diff --git a/include/types/session.h b/include/types/session.h
index d02e57f..62c3a95 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -35,6 +35,7 @@
 #include <types/proxy.h>
 #include <types/stick_table.h>
 #include <types/task.h>
+#include <types/vars.h>
 
 struct session {
 	struct proxy *fe;               /* the proxy this session depends on for the client side */
@@ -43,6 +44,7 @@
 	struct timeval accept_date;     /* date of the session's accept() in user date */
 	struct timeval tv_accept;       /* date of the session's accept() in internal date (monotonic) */
 	struct stkctr stkctr[MAX_SESS_STKCTR];  /* stick counters for tcp-connection */
+	struct vars vars;               /* list of variables for the session scope. */
 };
 
 #endif /* _TYPES_SESSION_H */
diff --git a/src/session.c b/src/session.c
index 7189fbe..44fccbf 100644
--- a/src/session.c
+++ b/src/session.c
@@ -27,6 +27,7 @@
 #include <proto/raw_sock.h>
 #include <proto/session.h>
 #include <proto/stream.h>
+#include <proto/vars.h>
 
 struct pool_head *pool2_session;
 
@@ -59,6 +60,7 @@
 		sess->accept_date = date; /* user-visible date for logging */
 		sess->tv_accept   = now;  /* corrected date for internal use */
 		memset(sess->stkctr, 0, sizeof(sess->stkctr));
+		vars_init(&sess->vars, SCOPE_SESS);
 	}
 	return sess;
 }
@@ -66,6 +68,7 @@
 void session_free(struct session *sess)
 {
 	session_store_counters(sess);
+	vars_prune_per_sess(&sess->vars);
 	pool_free2(pool2_session, sess);
 }
 
diff --git a/src/stream.c b/src/stream.c
index 0a38f2e..1003826 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -137,10 +137,9 @@
 	s->req_cap = NULL;
 	s->res_cap = NULL;
 
-	/* Initialise alle the variable context even if will not use.
-	 * This permits to prune these context without errors.
+	/* Initialise all the variables contexts even if not used.
+	 * This permits to prune these contexts without errors.
 	 */
-	vars_init(&s->vars_sess,   SCOPE_SESS);
 	vars_init(&s->vars_txn,    SCOPE_TXN);
 	vars_init(&s->vars_reqres, SCOPE_REQ);
 
@@ -302,7 +301,6 @@
 	}
 
 	/* Cleanup all variable contexts. */
-	vars_prune(&s->vars_sess, s);
 	vars_prune(&s->vars_txn, s);
 	vars_prune(&s->vars_reqres, s);
 
diff --git a/src/vars.c b/src/vars.c
index 9662abe..fa521f3 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -10,6 +10,7 @@
 #include <proto/proto_tcp.h>
 #include <proto/sample.h>
 #include <proto/stream.h>
+#include <proto/vars.h>
 
 /* This contains a pool of struct vars */
 static struct pool_head *var_pool = NULL;
@@ -93,9 +94,35 @@
 		pool_free2(var_pool, var);
 		size += sizeof(struct var);
 	}
-	var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -size);
+	var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -size);
 }
 
+/* This function frees all the memory used by all the session variables in the
+ * list starting at <vars>.
+ */
+void vars_prune_per_sess(struct vars *vars)
+{
+	struct var *var, *tmp;
+	unsigned int size = 0;
+
+	list_for_each_entry_safe(var, tmp, &vars->head, l) {
+		if (var->data.type == SMP_T_STR ||
+		    var->data.type == SMP_T_BIN) {
+			free(var->data.data.str.str);
+			size += var->data.data.str.len;
+		}
+		else if (var->data.type == SMP_T_METH) {
+			free(var->data.data.meth.str.str);
+			size += var->data.data.meth.str.len;
+		}
+		LIST_DEL(&var->l);
+		pool_free2(var_pool, var);
+		size += sizeof(struct var);
+	}
+	vars->size      -= size;
+	var_global_size -= size;
+}
+
 /* This function init a list of variabes. */
 void vars_init(struct vars *vars, enum vars_scope scope)
 {
@@ -207,7 +234,7 @@
 
 	/* Check the availibity of the variable. */
 	switch (var_desc->scope) {
-	case SCOPE_SESS: vars = &smp->strm->vars_sess;   break;
+	case SCOPE_SESS: vars = &smp->strm->sess->vars;  break;
 	case SCOPE_TXN:  vars = &smp->strm->vars_txn;    break;
 	case SCOPE_REQ:
 	case SCOPE_RES:
@@ -245,16 +272,16 @@
 		if (var->data.type == SMP_T_STR ||
 		    var->data.type == SMP_T_BIN) {
 			free(var->data.data.str.str);
-			var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -var->data.data.str.len);
+			var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -var->data.data.str.len);
 		}
 		else if (var->data.type == SMP_T_METH) {
 			free(var->data.data.meth.str.str);
-			var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -var->data.data.meth.str.len);
+			var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -var->data.data.meth.str.len);
 		}
 	} else {
 
 		/* Check memory avalaible. */
-		if (!var_accounting_add(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, sizeof(struct var)))
+		if (!var_accounting_add(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, sizeof(struct var)))
 			return 0;
 
 		/* Create new entry. */
@@ -283,13 +310,13 @@
 		break;
 	case SMP_T_STR:
 	case SMP_T_BIN:
-		if (!var_accounting_add(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, smp->data.str.len)) {
+		if (!var_accounting_add(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, smp->data.str.len)) {
 			var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
 			return 0;
 		}
 		var->data.data.str.str = malloc(smp->data.str.len);
 		if (!var->data.data.str.str) {
-			var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -smp->data.str.len);
+			var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -smp->data.str.len);
 			var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
 			return 0;
 		}
@@ -297,13 +324,13 @@
 		memcpy(var->data.data.str.str, smp->data.str.str, var->data.data.str.len);
 		break;
 	case SMP_T_METH:
-		if (!var_accounting_add(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, smp->data.meth.str.len)) {
+		if (!var_accounting_add(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, smp->data.meth.str.len)) {
 			var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
 			return 0;
 		}
 		var->data.data.meth.str.str = malloc(smp->data.meth.str.len);
 		if (!var->data.data.meth.str.str) {
-			var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -smp->data.meth.str.len);
+			var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -smp->data.meth.str.len);
 			var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
 			return 0;
 		}
@@ -323,7 +350,7 @@
 	struct vars *vars;
 
 	switch (scope) {
-	case SCOPE_SESS: vars = &strm->vars_sess;   break;
+	case SCOPE_SESS: vars = &strm->sess->vars;  break;
 	case SCOPE_TXN:  vars = &strm->vars_txn;    break;
 	case SCOPE_REQ:
 	case SCOPE_RES:
@@ -399,7 +426,7 @@
 
 	/* Select "vars" pool according with the scope. */
 	switch (scope) {
-	case SCOPE_SESS: vars = &strm->vars_sess;   break;
+	case SCOPE_SESS: vars = &strm->sess->vars;  break;
 	case SCOPE_TXN:  vars = &strm->vars_txn;    break;
 	case SCOPE_REQ:
 	case SCOPE_RES: