/* QUIC application layer operations */
struct qcc_app_ops {
+ /* Initialize <qcc> connection app context. */
int (*init)(struct qcc *qcc);
+ /* Finish connection initialization if prelude required. */
+ int (*finalize)(void *ctx);
+
+ /* Initialize <qcs> stream app context or leave it to NULL if rejected. */
int (*attach)(struct qcs *qcs, void *conn_ctx);
- ssize_t (*decode_qcs)(struct qcs *qcs, struct buffer *b, int fin);
- size_t (*snd_buf)(struct qcs *qcs, struct buffer *buf, size_t count);
+
+ /* Convert received HTTP payload to HTX. */
+ ssize_t (*rcv_buf)(struct qcs *qcs, struct buffer *b, int fin);
+
+ /* Convert HTX to HTTP payload for sending. */
+ size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count);
+
+ /* Negotiate and commit fast-forward data from opposite MUX. */
size_t (*nego_ff)(struct qcs *qcs, size_t count);
size_t (*done_ff)(struct qcs *qcs);
+
+ /* Notify about <qcs> stream closure. */
int (*close)(struct qcs *qcs, enum qcc_app_ops_close_side side);
+ /* Free <qcs> stream app context. */
void (*detach)(struct qcs *qcs);
- int (*finalize)(void *ctx);
- void (*shutdown)(void *ctx); /* Close a connection. */
+
+ /* Perform graceful shutdown. */
+ void (*shutdown)(void *ctx);
+ /* Free connection app context. */
void (*release)(void *ctx);
+
+ /* Increment app counters on CONNECTION_CLOSE_APP reception. */
void (*inc_err_cnt)(void *ctx, int err_code);
};
return ret;
}
-/* Decode <qcs> remotely initiated bidi-stream. <fin> must be set to indicate
- * that we received the last data of the stream.
+/* Transcode HTTP/3 payload received in buffer <b> to HTX data for stream
+ * <qcs>. If <fin> is set, it indicates that no more data will arrive after.
*
* Returns 0 on success else non-zero.
*/
-static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
+static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
{
struct h3s *h3s = qcs->ctx;
struct h3c *h3c = h3s->h3c;
TRACE_LEAVE(H3_EV_H3S_END, qcs->qcc->conn, qcs);
}
-/* Initialize H3 control stream and prepare SETTINGS emission.
- *
- * Returns 0 on success else non-zero.
- */
-static int h3_finalize(void *ctx)
-{
- struct h3c *h3c = ctx;
- struct qcs *qcs;
-
- qcs = qcc_init_stream_local(h3c->qcc, 0);
- if (!qcs)
- return 1;
-
- h3_control_send(qcs, h3c);
- h3c->ctrl_strm = qcs;
-
- return 0;
-}
-
/* Generate a GOAWAY frame for <h3c> connection on the control stream.
*
* Returns 0 on success else non-zero.
return 0;
}
+/* Initialize H3 control stream and prepare SETTINGS emission.
+ *
+ * Returns 0 on success else non-zero.
+ */
+static int h3_finalize(void *ctx)
+{
+ struct h3c *h3c = ctx;
+ struct qcs *qcs;
+
+ qcs = qcc_init_stream_local(h3c->qcc, 0);
+ if (!qcs)
+ return 1;
+
+ h3_control_send(qcs, h3c);
+ h3c->ctrl_strm = qcs;
+
+ return 0;
+}
+
/* Send a HTTP/3 GOAWAY followed by a CONNECTION_CLOSE_APP. */
static void h3_shutdown(void *ctx)
{
/* HTTP/3 application layer operations */
const struct qcc_app_ops h3_ops = {
.init = h3_init,
+ .finalize = h3_finalize,
.attach = h3_attach,
- .decode_qcs = h3_decode_qcs,
+ .rcv_buf = h3_rcv_buf,
.snd_buf = h3_snd_buf,
.nego_ff = h3_nego_ff,
.done_ff = h3_done_ff,
.close = h3_close,
.detach = h3_detach,
- .finalize = h3_finalize,
.shutdown = h3_shutdown,
.inc_err_cnt = h3_stats_inc_err_cnt,
.release = h3_release,
#include <haproxy/mux_quic.h>
#include <haproxy/qmux_http.h>
-static ssize_t hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
+static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
{
struct htx *htx;
struct htx_sl *sl;
}
const struct qcc_app_ops hq_interop_ops = {
- .decode_qcs = hq_interop_decode_qcs,
+ .rcv_buf = hq_interop_rcv_buf,
.snd_buf = hq_interop_snd_buf,
.nego_ff = hq_interop_nego_ff,
.done_ff = hq_interop_done_ff,
fin = 1;
if (!(qcs->flags & QC_SF_READ_ABORTED)) {
- ret = qcc->app_ops->decode_qcs(qcs, &b, fin);
+ ret = qcc->app_ops->rcv_buf(qcs, &b, fin);
if (ret < 0) {
TRACE_ERROR("decoding error", QMUX_EV_QCS_RECV, qcc->conn, qcs);
goto err;