BUG/MEDIUM: http: adjust close mode when switching to backend

Commit 179085c ("MEDIUM: http: move Connection header processing earlier")
introduced a regression : the backend's HTTP mode is not considered anymore
when setting the session's HTTP mode, because wait_for_request() is only
called once, when the frontend receives the request (or when the frontend
is in TCP mode, when the backend receives the request).

The net effect is that in some situations when the frontend and the backend
do not work in the same mode (eg: keep-alive vs close), the backend's mode
is ignored.

This patch moves all that processing to a dedicated function, which is
called from the original place, as well as from session_set_backend()
when switching from an HTTP frontend to an HTTP backend in different
modes.

This fix must be backported to 1.5.
(cherry picked from commit 4e21ff9244aefa56bcf0793a9e07edba2c3c1960)
diff --git a/src/proto_http.c b/src/proto_http.c
index 7e35c8b..20e7088 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2393,6 +2393,59 @@
 	return 0;
 }
 
+void http_adjust_conn_mode(struct session *s, struct http_txn *txn, struct http_msg *msg)
+{
+	int tmp = TX_CON_WANT_KAL;
+
+	if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
+		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
+		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
+			tmp = TX_CON_WANT_TUN;
+
+		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
+		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
+			tmp = TX_CON_WANT_TUN;
+	}
+
+	if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
+	    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
+		/* option httpclose + server_close => forceclose */
+		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
+		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
+			tmp = TX_CON_WANT_CLO;
+		else
+			tmp = TX_CON_WANT_SCL;
+	}
+
+	if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
+	    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
+		tmp = TX_CON_WANT_CLO;
+
+	if ((txn->flags & TX_CON_WANT_MSK) < tmp)
+		txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
+
+	if (!(txn->flags & TX_HDR_CONN_PRS) &&
+	    (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
+		/* parse the Connection header and possibly clean it */
+		int to_del = 0;
+		if ((msg->flags & HTTP_MSGF_VER_11) ||
+		    ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
+		     !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
+			to_del |= 2; /* remove "keep-alive" */
+		if (!(msg->flags & HTTP_MSGF_VER_11))
+			to_del |= 1; /* remove "close" */
+		http_parse_connection_header(txn, msg, to_del);
+	}
+
+	/* check if client or config asks for explicit close in KAL/SCL */
+	if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
+	     (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
+	    ((txn->flags & TX_HDR_CONN_CLO) ||                         /* "connection: close" */
+	     (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
+	     !(msg->flags & HTTP_MSGF_XFER_LEN) ||                     /* no length known => close */
+	     s->fe->state == PR_STSTOPPED))                            /* frontend is stopping */
+		txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
+}
 
 /* This stream analyser waits for a complete HTTP request. It returns 1 if the
  * processing can continue on next analysers, or zero if it either needs more
@@ -2929,58 +2982,8 @@
 	 * time.
 	 */
 	if (!(txn->flags & TX_HDR_CONN_PRS) ||
-	    ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE))) {
-		int tmp = TX_CON_WANT_KAL;
-
-		if (!((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)) {
-			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN ||
-			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
-				tmp = TX_CON_WANT_TUN;
-
-			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
-			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
-				tmp = TX_CON_WANT_TUN;
-		}
-
-		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
-		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL) {
-			/* option httpclose + server_close => forceclose */
-			if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL ||
-			    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
-				tmp = TX_CON_WANT_CLO;
-			else
-				tmp = TX_CON_WANT_SCL;
-		}
-
-		if ((s->fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL ||
-		    (s->be->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
-			tmp = TX_CON_WANT_CLO;
-
-		if ((txn->flags & TX_CON_WANT_MSK) < tmp)
-			txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | tmp;
-
-		if (!(txn->flags & TX_HDR_CONN_PRS) &&
-		    (txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN) {
-			/* parse the Connection header and possibly clean it */
-			int to_del = 0;
-			if ((msg->flags & HTTP_MSGF_VER_11) ||
-			    ((txn->flags & TX_CON_WANT_MSK) >= TX_CON_WANT_SCL &&
-			     !((s->fe->options2|s->be->options2) & PR_O2_FAKE_KA)))
-				to_del |= 2; /* remove "keep-alive" */
-			if (!(msg->flags & HTTP_MSGF_VER_11))
-				to_del |= 1; /* remove "close" */
-			http_parse_connection_header(txn, msg, to_del);
-		}
-
-		/* check if client or config asks for explicit close in KAL/SCL */
-		if (((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
-		     (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL) &&
-		    ((txn->flags & TX_HDR_CONN_CLO) ||                         /* "connection: close" */
-		     (!(msg->flags & HTTP_MSGF_VER_11) && !(txn->flags & TX_HDR_CONN_KAL)) || /* no "connection: k-a" in 1.0 */
-		     !(msg->flags & HTTP_MSGF_XFER_LEN) ||                     /* no length known => close */
-		     s->fe->state == PR_STSTOPPED))                            /* frontend is stopping */
-		    txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_CLO;
-	}
+	    ((s->fe->options & PR_O_HTTP_MODE) != (s->be->options & PR_O_HTTP_MODE)))
+		http_adjust_conn_mode(s, txn, msg);
 
 	/* end of job, return OK */
 	req->analysers &= ~an_bit;