REORG: quic: use a dedicated module for qc_stream_desc
Regroup all type definitions and functions related to qc_stream_desc in
the source file src/quic_stream.c.
qc_stream_desc complexity will be increased with the development of Tx
multi-buffers. Having a dedicated module is useful to mix it with
pure transport/quic-conn code.
diff --git a/Makefile b/Makefile
index fd1caa2..7c7d26a 100644
--- a/Makefile
+++ b/Makefile
@@ -636,7 +636,8 @@
OPTIONS_OBJS += src/quic_sock.o src/proto_quic.o src/xprt_quic.o src/quic_tls.o \
src/quic_frame.o src/quic_cc.o src/quic_cc_newreno.o src/mux_quic.o \
src/cbuf.o src/qpack-dec.o src/qpack-tbl.o src/h3.o src/qpack-enc.o \
- src/hq_interop.o src/cfgparse-quic.o src/quic_loss.o
+ src/hq_interop.o src/cfgparse-quic.o src/quic_loss.o \
+ src/quic_stream.o
endif
ifneq ($(USE_LUA),)
diff --git a/include/haproxy/mux_quic-t.h b/include/haproxy/mux_quic-t.h
index 6fa9522..f9b8b2f 100644
--- a/include/haproxy/mux_quic-t.h
+++ b/include/haproxy/mux_quic-t.h
@@ -10,6 +10,7 @@
#include <haproxy/buf-t.h>
#include <haproxy/connection-t.h>
+#include <haproxy/quic_stream-t.h>
#include <haproxy/xprt_quic-t.h>
#include <haproxy/conn_stream-t.h>
diff --git a/include/haproxy/quic_stream-t.h b/include/haproxy/quic_stream-t.h
new file mode 100644
index 0000000..6a451ac
--- /dev/null
+++ b/include/haproxy/quic_stream-t.h
@@ -0,0 +1,32 @@
+#ifndef _HAPROXY_QUIC_STREAM_T_H_
+#define _HAPROXY_QUIC_STREAM_T_H_
+
+#ifdef USE_QUIC
+
+#include <import/ebtree-t.h>
+
+#include <haproxy/buf-t.h>
+
+/* QUIC STREAM descriptor.
+ *
+ * This structure is the low-level counterpart of the QUIC STREAM at the MUX
+ * layer. It provides a node for tree-storage and buffering for Tx.
+ *
+ * Once the MUX has finished to transfer data on a STREAM, it must release its
+ * QUIC STREAM descriptor. The descriptor will be kept by the quic_conn until
+ * all acknowledgement has been received.
+ */
+struct qc_stream_desc {
+ struct eb64_node by_id; /* id of the stream used for <streams_by_id> tree */
+
+ struct buffer buf; /* buffer for STREAM data on Tx, emptied on acknowledge */
+ uint64_t ack_offset; /* last acknowledged offset */
+ struct eb_root acked_frms; /* ACK frames tree for non-contiguous ACK ranges */
+
+ int release; /* set to 1 when the MUX has finished to use this stream */
+
+ void *ctx; /* MUX specific context */
+};
+
+#endif /* USE_QUIC */
+#endif /* _HAPROXY_QUIC_STREAM_T_H_ */
diff --git a/include/haproxy/quic_stream.h b/include/haproxy/quic_stream.h
new file mode 100644
index 0000000..c524d10
--- /dev/null
+++ b/include/haproxy/quic_stream.h
@@ -0,0 +1,16 @@
+#ifndef _HAPROXY_QUIC_STREAM_H_
+#define _HAPROXY_QUIC_STREAM_H_
+
+#ifdef USE_QUIC
+
+#include <haproxy/quic_stream-t.h>
+
+struct quic_conn;
+
+struct qc_stream_desc *qc_stream_desc_new(uint64_t id, void *ctx);
+void qc_stream_desc_release(struct qc_stream_desc *stream,
+ struct quic_conn *qc);
+int qc_stream_desc_free(struct qc_stream_desc *stream);
+
+#endif /* USE_QUIC */
+#endif /* _HAPROXY_QUIC_STREAM_H_ */
diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h
index e2999a5..2478332 100644
--- a/include/haproxy/xprt_quic-t.h
+++ b/include/haproxy/xprt_quic-t.h
@@ -767,26 +767,5 @@
const struct qcc_app_ops *app_ops;
};
-/* QUIC STREAM descriptor.
- *
- * This structure is the low-level counterpart of the QUIC STREAM at the MUX
- * layer. It provides a node for tree-storage and buffering for Tx.
- *
- * Once the MUX has finished to transfer data on a STREAM, it must release its
- * QUIC STREAM descriptor. The descriptor will be kept by the quic_conn until
- * all acknowledgement has been received.
- */
-struct qc_stream_desc {
- struct eb64_node by_id; /* id of the stream used for <streams_by_id> tree */
-
- struct buffer buf; /* buffer for STREAM data on Tx, emptied on acknowledge */
- uint64_t ack_offset; /* last acknowledged offset */
- struct eb_root acked_frms; /* ACK frames tree for non-contiguous ACK ranges */
-
- int release; /* set to 1 when the MUX has finished to use this stream */
-
- void *ctx; /* MUX specific context */
-};
-
#endif /* USE_QUIC */
#endif /* _HAPROXY_XPRT_QUIC_T_H */
diff --git a/include/haproxy/xprt_quic.h b/include/haproxy/xprt_quic.h
index 94488b0..1a2a3ce 100644
--- a/include/haproxy/xprt_quic.h
+++ b/include/haproxy/xprt_quic.h
@@ -1248,9 +1248,6 @@
struct quic_dgram *new_dgram, struct list *dgrams);
int qc_send_app_pkts(struct quic_conn *qc, struct list *frms);
-struct qc_stream_desc *qc_stream_desc_new(uint64_t id, void *ctx);
-void qc_stream_desc_release(struct qc_stream_desc *stream, struct quic_conn *qc);
-
void qc_notify_close(struct quic_conn *qc);
#endif /* USE_QUIC */
diff --git a/src/mux_quic.c b/src/mux_quic.c
index d51bed1..642da72 100644
--- a/src/mux_quic.c
+++ b/src/mux_quic.c
@@ -8,6 +8,7 @@
#include <haproxy/dynbuf.h>
#include <haproxy/htx.h>
#include <haproxy/pool.h>
+#include <haproxy/quic_stream.h>
#include <haproxy/sink.h>
#include <haproxy/ssl_sock-t.h>
#include <haproxy/trace.h>
diff --git a/src/quic_stream.c b/src/quic_stream.c
new file mode 100644
index 0000000..4213e50
--- /dev/null
+++ b/src/quic_stream.c
@@ -0,0 +1,99 @@
+#include <haproxy/quic_stream.h>
+
+#include <import/eb64tree.h>
+
+#include <haproxy/api.h>
+#include <haproxy/buf.h>
+#include <haproxy/list.h>
+#include <haproxy/dynbuf.h>
+#include <haproxy/pool.h>
+#include <haproxy/xprt_quic.h>
+
+DECLARE_STATIC_POOL(pool_head_quic_conn_stream, "qc_stream_desc",
+ sizeof(struct qc_stream_desc));
+
+/* Allocate a new stream descriptor with id <id>. The caller is responsible to
+ * store the stream in the appropriate tree.
+ *
+ * Returns the newly allocated instance on success or else NULL.
+ */
+struct qc_stream_desc *qc_stream_desc_new(uint64_t id, void *ctx)
+{
+ struct qc_stream_desc *stream;
+
+ stream = pool_alloc(pool_head_quic_conn_stream);
+ if (!stream)
+ return NULL;
+
+ stream->by_id.key = id;
+ stream->by_id.node.leaf_p = NULL;
+
+ stream->buf = BUF_NULL;
+ stream->acked_frms = EB_ROOT;
+ stream->ack_offset = 0;
+ stream->release = 0;
+ stream->ctx = ctx;
+
+ return stream;
+}
+
+/* Mark the stream descriptor <stream> as released by the upper layer. It will
+ * be freed as soon as all its buffered data are acknowledged. In the meantime,
+ * the stream is stored in the <qc> tree : thus it must have been removed from
+ * any other tree before calling this function.
+ */
+void qc_stream_desc_release(struct qc_stream_desc *stream,
+ struct quic_conn *qc)
+{
+ BUG_ON(stream->by_id.node.leaf_p);
+
+ stream->release = 1;
+ stream->ctx = NULL;
+
+ if (!b_data(&stream->buf))
+ qc_stream_desc_free(stream);
+ else
+ eb64_insert(&qc->streams_by_id, &stream->by_id);
+}
+
+/* Free the stream descriptor <stream> buffer. This function should be used
+ * when all its data have been acknowledged. If the stream was released by the
+ * upper layer, the stream descriptor will be freed.
+ *
+ * Returns 0 if the stream was not freed else non-zero.
+ */
+int qc_stream_desc_free(struct qc_stream_desc *stream)
+{
+ b_free(&stream->buf);
+ offer_buffers(NULL, 1);
+
+ if (stream->release) {
+ /* Free frames still waiting for an ACK. Even if the stream buf
+ * is NULL, some frames could still be not acknowledged. This
+ * is notably the case for retransmission where multiple frames
+ * points to the same buffer content.
+ */
+ struct eb64_node *frm_node = eb64_first(&stream->acked_frms);
+ while (frm_node) {
+ struct quic_stream *strm;
+ struct quic_frame *frm;
+
+ strm = eb64_entry(&frm_node->node, struct quic_stream, offset);
+
+ frm_node = eb64_next(frm_node);
+ eb64_delete(&strm->offset);
+
+ frm = container_of(strm, struct quic_frame, stream);
+ LIST_DELETE(&frm->list);
+ quic_tx_packet_refdec(frm->pkt);
+ pool_free(pool_head_quic_frame, frm);
+ }
+
+ eb64_delete(&stream->by_id);
+ pool_free(pool_head_quic_conn_stream, stream);
+
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index 36b21e2..fde571d 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -45,6 +45,7 @@
#include <haproxy/quic_frame.h>
#include <haproxy/quic_loss.h>
#include <haproxy/quic_sock.h>
+#include <haproxy/quic_stream.h>
#include <haproxy/cbuf.h>
#include <haproxy/proto_quic.h>
#include <haproxy/quic_tls.h>
@@ -169,7 +170,6 @@
DECLARE_STATIC_POOL(pool_head_quic_crypto_buf, "quic_crypto_buf_pool", sizeof(struct quic_crypto_buf));
DECLARE_POOL(pool_head_quic_frame, "quic_frame_pool", sizeof(struct quic_frame));
DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng_pool", sizeof(struct quic_arng_node));
-DECLARE_STATIC_POOL(pool_head_quic_conn_stream, "qc_stream_desc", sizeof(struct qc_stream_desc));
static struct quic_tx_packet *qc_build_pkt(unsigned char **pos, const unsigned char *buf_end,
struct quic_enc_level *qel, struct list *frms,
@@ -1429,48 +1429,6 @@
return 1;
}
-/* Free the stream descriptor <stream> buffer. This function should be used
- * when all its data have been acknowledged. If the stream was released by the
- * upper layer, the stream descriptor will be freed.
- *
- * Returns 0 if the stream was not freed else non-zero.
- */
-static int qc_stream_desc_free(struct qc_stream_desc *stream)
-{
- b_free(&stream->buf);
- offer_buffers(NULL, 1);
-
- if (stream->release) {
- /* Free frames still waiting for an ACK. Even if the stream buf
- * is NULL, some frames could still be not acknowledged. This
- * is notably the case for retransmission where multiple frames
- * points to the same buffer content.
- */
- struct eb64_node *frm_node = eb64_first(&stream->acked_frms);
- while (frm_node) {
- struct quic_stream *strm;
- struct quic_frame *frm;
-
- strm = eb64_entry(&frm_node->node, struct quic_stream, offset);
-
- frm_node = eb64_next(frm_node);
- eb64_delete(&strm->offset);
-
- frm = container_of(strm, struct quic_frame, stream);
- LIST_DELETE(&frm->list);
- quic_tx_packet_refdec(frm->pkt);
- pool_free(pool_head_quic_frame, frm);
- }
-
- eb64_delete(&stream->by_id);
- pool_free(pool_head_quic_conn_stream, stream);
-
- return 1;
- }
-
- return 0;
-}
-
/* Remove from <stream> the acknowledged frames.
*
* Returns 1 if at least one frame was removed else 0.
@@ -5956,50 +5914,6 @@
return 0;
}
-/* Allocate a new stream descriptor with id <id>. The caller is responsible to
- * store the stream in the appropriate tree.
- *
- * Returns the newly allocated instance on success or else NULL.
- */
-struct qc_stream_desc *qc_stream_desc_new(uint64_t id, void *ctx)
-{
- struct qc_stream_desc *stream;
-
- stream = pool_alloc(pool_head_quic_conn_stream);
- if (!stream)
- return NULL;
-
- stream->by_id.key = id;
- stream->by_id.node.leaf_p = NULL;
-
- stream->buf = BUF_NULL;
- stream->acked_frms = EB_ROOT;
- stream->ack_offset = 0;
- stream->release = 0;
- stream->ctx = ctx;
-
- return stream;
-}
-
-/* Mark the stream descriptor <stream> as released by the upper layer. It will
- * be freed as soon as all its buffered data are acknowledged. In the meantime,
- * the stream is stored in the <qc> tree : thus it must have been removed from
- * any other tree before calling this function.
- */
-void qc_stream_desc_release(struct qc_stream_desc *stream,
- struct quic_conn *qc)
-{
- BUG_ON(stream->by_id.node.leaf_p);
-
- stream->release = 1;
- stream->ctx = NULL;
-
- if (!b_data(&stream->buf))
- qc_stream_desc_free(stream);
- else
- eb64_insert(&qc->streams_by_id, &stream->by_id);
-}
-
/* Notify the MUX layer if alive about an imminent close of <qc>. */
void qc_notify_close(struct quic_conn *qc)
{