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.
This commit is contained in:
parent
da6ad2092a
commit
0cc02a345b
3
Makefile
3
Makefile
@ -636,7 +636,8 @@ ifneq ($(USE_QUIC),)
|
||||
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),)
|
||||
|
@ -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>
|
||||
|
||||
|
32
include/haproxy/quic_stream-t.h
Normal file
32
include/haproxy/quic_stream-t.h
Normal file
@ -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_ */
|
16
include/haproxy/quic_stream.h
Normal file
16
include/haproxy/quic_stream.h
Normal file
@ -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_ */
|
@ -767,26 +767,5 @@ struct quic_conn {
|
||||
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 */
|
||||
|
@ -1248,9 +1248,6 @@ int quic_lstnr_dgram_dispatch(unsigned char *buf, size_t len, void *owner,
|
||||
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 */
|
||||
|
@ -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>
|
||||
|
99
src/quic_stream.c
Normal file
99
src/quic_stream.c
Normal file
@ -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;
|
||||
}
|
@ -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_POOL(pool_head_quic_rx_strm_frm, "quic_rx_strm_frm", sizeof(struct quic_
|
||||
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 @@ static int qc_pkt_decrypt(struct quic_rx_packet *pkt, struct quic_enc_level *qel
|
||||
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 @@ int quic_lstnr_dgram_dispatch(unsigned char *buf, size_t len, void *owner,
|
||||
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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user