MINOR: quic: Drop packets with STREAM frames with wrong direction.

A server initiates streams with odd-numbered stream IDs.
Also add useful traces when parsing STREAM frames.
diff --git a/include/haproxy/quic_frame-t.h b/include/haproxy/quic_frame-t.h
index 855a37e..6a3226e 100644
--- a/include/haproxy/quic_frame-t.h
+++ b/include/haproxy/quic_frame-t.h
@@ -88,9 +88,14 @@
 
 #define QUIC_FT_PKT_TYPE____1_BITMASK QUIC_FT_PKT_TYPE_1_BITMASK
 
-#define QUIC_STREAM_FRAME_FIN_BIT    0x01
-#define QUIC_STREAM_FRAME_LEN_BIT    0x02
-#define QUIC_STREAM_FRAME_OFF_BIT    0x04
+#define QUIC_STREAM_FRAME_TYPE_FIN_BIT     0x01
+#define QUIC_STREAM_FRAME_TYPE_LEN_BIT     0x02
+#define QUIC_STREAM_FRAME_TYPE_OFF_BIT     0x04
+
+/* Servers have the stream initiator bit set. */
+#define QUIC_STREAM_FRAME_ID_INITIATOR_BIT 0x01
+/* Unidirectional streams have the direction bit set. */
+#define QUIC_STREAM_FRAME_ID_DIR_BIT       0x02
 
 #define QUIC_PATH_CHALLENGE_LEN         8
 
diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h
index bb05c54..6cf9fae 100644
--- a/include/haproxy/xprt_quic-t.h
+++ b/include/haproxy/xprt_quic-t.h
@@ -201,6 +201,7 @@
 #define           QUIC_EV_CONN_ADDDATA   (1ULL << 25)
 #define           QUIC_EV_CONN_FFLIGHT   (1ULL << 26)
 #define           QUIC_EV_CONN_SSLALERT  (1ULL << 27)
+#define           QUIC_EV_CONN_PSTRM     (1ULL << 28)
 #define           QUIC_EV_CONN_RTTUPDT   (1ULL << 29)
 #define           QUIC_EV_CONN_CC        (1ULL << 30)
 #define           QUIC_EV_CONN_SPPKTS    (1ULL << 31)
diff --git a/src/quic_frame.c b/src/quic_frame.c
index d80eb5a..5947856 100644
--- a/src/quic_frame.c
+++ b/src/quic_frame.c
@@ -377,8 +377,8 @@
 	struct quic_stream *stream = &frm->stream;
 
 	if (!quic_enc_int(buf, end, stream->id) ||
-	    ((frm->type & QUIC_STREAM_FRAME_OFF_BIT) && !quic_enc_int(buf, end, stream->offset)) ||
-	    ((frm->type & QUIC_STREAM_FRAME_LEN_BIT) &&
+	    ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(buf, end, stream->offset)) ||
+	    ((frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) &&
 	     (!quic_enc_int(buf, end, stream->len) || end - *buf < stream->len)))
 		return 0;
 
@@ -400,14 +400,14 @@
 		return 0;
 
 	/* Offset parsing */
-	if (!(frm->type & QUIC_STREAM_FRAME_OFF_BIT)) {
+	if (!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT)) {
 		stream->offset = 0;
 	}
 	else if (!quic_dec_int(&stream->offset, buf, end))
 		return 0;
 
 	/* Length parsing */
-	if (!(frm->type & QUIC_STREAM_FRAME_LEN_BIT)) {
+	if (!(frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT)) {
 		stream->len = end - *buf;
 	}
 	else if (!quic_dec_int(&stream->len, buf, end) || end - *buf < stream->len)
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index 97160ab..c20d877 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -571,6 +571,18 @@
 			if (sz3)
 				chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz3);
 		}
+
+		if (mask & QUIC_EV_CONN_PSTRM) {
+			const struct quic_frame *frm = a2;
+			const struct quic_stream *s = &frm->stream;
+
+			chunk_appendf(&trace_buf, " uni=%d fin=%d id=%llu off=%llu len=%llu",
+			              !!(s->id & QUIC_STREAM_FRAME_ID_DIR_BIT),
+			              !!(frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT),
+			              (unsigned long long)s->id,
+			              (unsigned long long)s->offset,
+			              (unsigned long long)s->len);
+		}
 	}
 	if (mask & QUIC_EV_CONN_LPKT) {
 		const struct quic_rx_packet *pkt = a2;
@@ -1642,6 +1654,17 @@
 		case QUIC_FT_STREAM_D:
 		case QUIC_FT_STREAM_E:
 		case QUIC_FT_STREAM_F:
+		{
+			struct quic_stream *stream = &frm.stream;
+
+			TRACE_PROTO("STREAM frame", QUIC_EV_CONN_PSTRM, ctx->conn, &frm);
+			if (objt_listener(ctx->conn->target)) {
+				if (stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT)
+					goto err;
+			} else if (!(stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT))
+				goto err;
+			break;
+		}
 		case QUIC_FT_NEW_CONNECTION_ID:
 			break;
 		case QUIC_FT_CONNECTION_CLOSE: