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 htx *htx, size_t count);
+ size_t (*snd_buf)(struct qcs *qcs, struct buffer *buf, size_t count);
size_t (*nego_ff)(struct qcs *qcs, size_t count);
size_t (*done_ff)(struct qcs *qcs);
int (*close)(struct qcs *qcs, enum qcc_app_ops_close_side side);
}
/* Returns the total of bytes sent. */
-static int h3_resp_data_send(struct qcs *qcs, struct htx *htx, size_t count)
+static int h3_resp_data_send(struct qcs *qcs, struct buffer *buf, size_t count)
{
+ struct htx *htx;
struct buffer outbuf;
struct buffer *res;
size_t total = 0;
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;
type = htx_get_blk_type(blk);
fsize = bsize = htx_get_blksz(blk);
+ /* h3 DATA headers : 1-byte frame type + varint frame length */
+ hsize = 1 + QUIC_VARINT_MAX_SIZE;
+
if (type != HTX_BLK_DATA)
goto end;
res = mux_get_buf(qcs);
+ if (unlikely(fsize == count &&
+ !b_data(res) &&
+ htx_nbblks(htx) == 1 && type == HTX_BLK_DATA)) {
+ void *old_area = res->area;
+
+ /* map an H2 frame to the HTX block so that we can put the
+ * frame header there.
+ */
+ *res = b_make(buf->area, buf->size, sizeof(struct htx) + blk->addr - hsize, fsize + hsize);
+ outbuf = b_make(b_head(res), hsize, 0, 0);
+ b_putchr(&outbuf, 0x00); /* h3 frame type = DATA */
+ b_quic_enc_int(&outbuf, fsize, QUIC_VARINT_MAX_SIZE); /* h3 frame length */
+
+ /* and exchange with our old area */
+ buf->area = old_area;
+ buf->data = buf->head = 0;
+ total += fsize;
+ fsize = 0;
+ goto end;
+ }
+
if (fsize > count)
fsize = count;
- /* h3 DATA headers : 1-byte frame type + varint frame length */
- hsize = 1 + QUIC_VARINT_MAX_SIZE;
-
while (1) {
b_reset(&outbuf);
outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
return total;
}
-static size_t h3_snd_buf(struct qcs *qcs, struct htx *htx, size_t count)
+static size_t h3_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count)
{
size_t total = 0;
enum htx_blk_type btype;
+ struct htx *htx;
struct htx_blk *blk;
uint32_t bsize;
int32_t idx;
h3_debug_printf(stderr, "%s\n", __func__);
+ htx = htx_from_buf(buf);
+
+ if (htx->extra && htx->extra == HTX_UNKOWN_PAYLOAD_LENGTH)
+ qcs->flags |= QC_SF_UNKNOWN_PL_LENGTH;
+
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, htx, count);
+ ret = h3_resp_data_send(qcs, buf, count);
if (ret > 0) {
+ htx = htx_from_buf(buf);
total += ret;
count -= ret;
if (ret < bsize)
}
out:
+ htx_to_buf(htx, buf);
+
return total;
}
return &qcs->tx.buf;
}
-static size_t hq_interop_snd_buf(struct qcs *qcs, struct htx *htx,
+static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
size_t count)
{
enum htx_blk_type btype;
+ struct htx *htx;
struct htx_blk *blk;
int32_t idx;
uint32_t bsize, fsize;
res = mux_get_buf(qcs);
outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
+ htx = htx_from_buf(buf);
+
+ if (htx->extra && htx->extra == HTX_UNKOWN_PAYLOAD_LENGTH)
+ qcs->flags |= QC_SF_UNKNOWN_PL_LENGTH;
+
while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
/* Not implemented : QUIC on backend side */
idx = htx_get_head(htx);
end:
b_add(res, b_data(&outbuf));
+ htx_to_buf(htx, buf);
return total;
}
{
struct htx *htx;
size_t ret;
+ int eom = 0;
TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
- htx = htx_from_buf(buf);
-
- if (htx->extra && htx->extra == HTX_UNKOWN_PAYLOAD_LENGTH)
- qcs->flags |= QC_SF_UNKNOWN_PL_LENGTH;
-
- 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);
+ htx = htxbuf(buf);
+ eom = (htx->flags & HTX_FL_EOM);
+ ret = qcs->qcc->app_ops->snd_buf(qcs, buf, count);
+ *fin = (eom && !b_data(buf));
TRACE_LEAVE(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);