#include <haproxy/buf-t.h>
#include <haproxy/connection-t.h>
+#include <haproxy/htx-t.h>
#include <haproxy/list-t.h>
#include <haproxy/ncbuf-t.h>
#include <haproxy/quic_stream-t.h>
int (*init)(struct qcc *qcc);
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, int flags);
+ size_t (*snd_buf)(struct qcs *qcs, struct htx *htx, size_t count);
void (*detach)(struct qcs *qcs);
int (*finalize)(void *ctx);
void (*shutdown)(void *ctx); /* Close a connection. */
size_t qcs_http_rcv_buf(struct qcs *qcs, struct buffer *buf, size_t count,
char *fin);
+size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
+ char *fin);
#endif /* USE_QUIC */
}
/* Returns the total of bytes sent. */
-static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count)
+static int h3_resp_data_send(struct qcs *qcs, struct htx *htx, size_t count)
{
struct buffer outbuf;
struct buffer *res;
size_t total = 0;
- struct htx *htx;
int bsize, fsize, hsize;
struct htx_blk *blk;
enum htx_blk_type type;
TRACE_ENTER(H3_EV_TX_DATA, qcs->qcc->conn, qcs);
- htx = htx_from_buf(buf);
-
new_frame:
if (!count || htx_is_empty(htx))
goto end;
return total;
}
-static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count, int flags)
+static size_t h3_snd_buf(struct qcs *qcs, struct htx *htx, size_t count)
{
size_t total = 0;
- struct htx *htx;
enum htx_blk_type btype;
struct htx_blk *blk;
uint32_t bsize;
h3_debug_printf(stderr, "%s\n", __func__);
- htx = htx_from_buf(buf);
-
while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
idx = htx_get_head(htx);
blk = htx_get_blk(htx, idx);
break;
case HTX_BLK_DATA:
- ret = h3_resp_data_send(qcs, buf, count);
+ ret = h3_resp_data_send(qcs, htx, count);
if (ret > 0) {
- htx = htx_from_buf(buf);
total += ret;
count -= ret;
if (ret < bsize)
}
}
- if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx))
- qcs->flags |= QC_SF_FIN_STREAM;
-
out:
- if (total) {
- if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
- tasklet_wakeup(qcs->qcc->wait_event.tasklet);
- }
-
return total;
}
return &qcs->tx.buf;
}
-static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
- size_t count, int flags)
+static size_t hq_interop_snd_buf(struct qcs *qcs, struct htx *htx,
+ size_t count)
{
- struct htx *htx;
enum htx_blk_type btype;
struct htx_blk *blk;
int32_t idx;
struct buffer *res, outbuf;
size_t total = 0;
- htx = htx_from_buf(buf);
res = mux_get_buf(qcs);
outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
}
end:
- if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx))
- qcs->flags |= QC_SF_FIN_STREAM;
-
b_add(res, b_data(&outbuf));
- if (total) {
- if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
- tasklet_wakeup(qcs->qcc->wait_event.tasklet);
- }
-
return total;
}
{
struct qcs *qcs = __sc_mux_strm(sc);
size_t ret;
+ char fin;
TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
goto end;
}
- ret = qcs->qcc->app_ops->snd_buf(qcs, buf, count, flags);
+ ret = qcs_http_snd_buf(qcs, buf, count, &fin);
+ if (fin)
+ qcs->flags |= QC_SF_FIN_STREAM;
+
+ if (ret) {
+ if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
+ tasklet_wakeup(qcs->qcc->wait_event.tasklet);
+ }
end:
TRACE_LEAVE(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
return ret;
}
+
+/* QUIC MUX snd_buf operation using HTX data. HTX data will be transferred from
+ * <buf> to <qcs> stream buffer. Input buffer is expected to be of length
+ * <count>. <fin> will be set to signal the last data to send for this stream.
+ *
+ * Return the size in bytes of transferred data.
+ */
+size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
+ char *fin)
+{
+ struct htx *htx;
+ size_t ret;
+
+ TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
+
+ htx = htx_from_buf(buf);
+
+ ret = qcs->qcc->app_ops->snd_buf(qcs, htx, count);
+ *fin = (htx->flags & HTX_FL_EOM) && htx_is_empty(htx);
+
+ htx_to_buf(htx, buf);
+
+ TRACE_LEAVE(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
+
+ return ret;
+}