MINOR: h2: new function h2_peek_frame_hdr() to retrieve a new frame header

This function extracts the next frame header but doesn't consume it.
This will allow to detect a stream-id change and to perform a yielding
window update without losing information. The result is stored into a
temporary frame descriptor. We could also store the next frame header
into the connection but parsing the header again is much cheaper than
wasting bytes in the connection for a rare use case.

A function (h2_skip_frame_hdr()) is also provided to skip the parsed
header (always 9 bytes) and another one (h2_get_frame_hdr()) to do both
at once.
diff --git a/src/mux_h2.c b/src/mux_h2.c
index 7cdf31c..422fca2 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -401,6 +401,57 @@
 	write_n16(out + 1, len);
 }
 
+/* Peeks an H2 frame header from buffer <b> into descriptor <h>. The algorithm
+ * is not obvious. It turns out that H2 headers are neither aligned nor do they
+ * use regular sizes. And to add to the trouble, the buffer may wrap so each
+ * byte read must be checked. The header is formed like this :
+ *
+ *       b0         b1       b2     b3   b4         b5..b8
+ *  +----------+---------+--------+----+----+----------------------+
+ *  |len[23:16]|len[15:8]|len[7:0]|type|flag|sid[31:0] (big endian)|
+ *  +----------+---------+--------+----+----+----------------------+
+ *
+ * Here we read a big-endian 64 bit word from h[1]. This way in a single read
+ * we get the sid properly aligned and ordered, and 16 bits of len properly
+ * ordered as well. The type and flags can be extracted using bit shifts from
+ * the word, and only one extra read is needed to fetch len[16:23].
+ * Returns zero if some bytes are missing, otherwise non-zero on success.
+ */
+static int h2_peek_frame_hdr(const struct buffer *b, struct h2_fh *h)
+{
+	uint64_t w;
+
+	if (b->i < 9)
+		return 0;
+
+	w = readv_n64(b_ptr(b,1), b_end(b) - b_ptr(b,1), b->data);
+	h->len = *b->p << 16;
+	h->sid = w & 0x7FFFFFFF; /* RFC7540#4.1: R bit must be ignored */
+	h->ff = w >> 32;
+	h->ft = w >> 40;
+	h->len += w >> 48;
+	return 1;
+}
+
+/* skip the next 9 bytes corresponding to the frame header possibly parsed by
+ * h2_peek_frame_hdr() above.
+ */
+static inline void h2_skip_frame_hdr(struct buffer *b)
+{
+	bi_del(b, 9);
+}
+
+/* same as above, automatically advances the buffer on success */
+static inline int h2_get_frame_hdr(struct buffer *b, struct h2_fh *h)
+{
+	int ret;
+
+	ret = h2_peek_frame_hdr(b, h);
+	if (ret > 0)
+		h2_skip_frame_hdr(b);
+	return ret;
+}
+
 
 /*********************************************************/
 /* functions below are I/O callbacks from the connection */