MEDIUM: mux-h2: make h2_process_demux() capable of processing responses as well

The function now calls h2c_bck_handle_headers() or h2c_frt_handle_headers()
depending on the connection's side. The former doesn't create a new stream
but feeds an existing one. At this point it's possible to forward an H2
request to a backend server and retrieve the response headers.
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 36707be..64dbc5a 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -1833,6 +1833,69 @@
 	return NULL;
 }
 
+/* processes a HEADERS frame. Returns h2s on success or NULL on missing data.
+ * It may return an error in h2c or h2s. Described in RFC7540#6.2. Most of the
+ * errors here are reported as connection errors since it's impossible to
+ * recover from such errors after the compression context has been altered.
+ */
+static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s)
+{
+	int error;
+
+	if (!h2c->dfl) {
+		error = H2_ERR_PROTOCOL_ERROR; // empty headers frame!
+		sess_log(h2c->conn->owner);
+		goto strm_err;
+	}
+
+	if (!b_size(&h2c->dbuf))
+		return NULL; // empty buffer
+
+	if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf))
+		return NULL; // incomplete frame
+
+	if (h2c->flags & H2_CF_DEM_TOOMANY)
+		return 0; // too many cs still present
+
+	if (h2c->dff & H2_F_HEADERS_END_STREAM) {
+		h2s->flags |= H2_SF_ES_RCVD;
+		h2s->cs->flags |= CS_FL_REOS;
+	}
+
+	if (!h2s_decode_headers(h2s))
+		return NULL;
+
+	if (h2c->st0 >= H2_CS_ERROR)
+		return NULL;
+
+	if (h2s->st >= H2_SS_ERROR) {
+		/* stream error : send RST_STREAM */
+		h2c->st0 = H2_CS_FRAME_E;
+	}
+
+	if (h2s->cs->flags & CS_FL_ERROR && h2s->st < H2_SS_ERROR)
+		h2s->st = H2_SS_ERROR;
+	else if (h2s->cs->flags & CS_FL_REOS && h2s->st == H2_SS_OPEN)
+		h2s->st = H2_SS_HREM;
+	else if (h2s->cs->flags & CS_FL_REOS && h2s->st == H2_SS_HLOC)
+		h2s_close(h2s);
+
+	return h2s;
+
+ conn_err:
+	h2c_error(h2c, error);
+	return NULL;
+
+ strm_err:
+	if (h2s) {
+		h2s_error(h2s, error);
+		h2c->st0 = H2_CS_FRAME_E;
+	}
+	else
+		h2c_error(h2c, error);
+	return NULL;
+}
+
 /* processes a DATA frame. Returns > 0 on success or zero on missing data.
  * It may return an error in h2c or h2s. Described in RFC7540#6.1.
  */
@@ -2173,7 +2236,10 @@
 
 		case H2_FT_HEADERS:
 			if (h2c->st0 == H2_CS_FRAME_P) {
-				tmp_h2s = h2c_frt_handle_headers(h2c, h2s);
+				if (h2c->flags & H2_CF_IS_BACK)
+					tmp_h2s = h2c_bck_handle_headers(h2c, h2s);
+				else
+					tmp_h2s = h2c_frt_handle_headers(h2c, h2s);
 				if (tmp_h2s) {
 					h2s = tmp_h2s;
 					ret = 1;