struct buffer *qcc_get_stream_rxbuf(struct qcs *qcs);
struct buffer *qcc_get_stream_txbuf(struct qcs *qcs);
void qcc_reset_stream(struct qcs *qcs, int err);
-void qcc_send_stream(struct qcs *qcs, int urg);
+void qcc_send_stream(struct qcs *qcs, int urg, int count);
void qcc_abort_stream_read(struct qcs *qcs);
int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
char fin, char *data);
ret = b_force_xfer(res, &pos, b_data(&pos));
if (ret > 0) {
/* Register qcs for sending before other streams. */
- qcc_send_stream(qcs, 1);
+ qcc_send_stream(qcs, 1, ret);
h3c->flags |= H3_CF_SETTINGS_SENT;
}
struct buffer pos, *res;
unsigned char data[3 * QUIC_VARINT_MAX_SIZE];
size_t frm_len = quic_int_getsize(h3c->id_goaway);
+ size_t xfer;
TRACE_ENTER(H3_EV_H3C_END, h3c->qcc->conn);
goto err;
}
- b_force_xfer(res, &pos, b_data(&pos));
- qcc_send_stream(qcs, 1);
+ xfer = b_force_xfer(res, &pos, b_data(&pos));
+ qcc_send_stream(qcs, 1, xfer);
h3c->flags |= H3_CF_GOAWAY_SENT;
TRACE_LEAVE(H3_EV_H3C_END, h3c->qcc->conn);
qcs_alert(qcs);
}
- qcc_send_stream(qcs, 1);
+ qcc_send_stream(qcs, 1, 0);
tasklet_wakeup(qcc->wait_event.tasklet);
}
/* Register <qcs> stream for emission of STREAM, STOP_SENDING or RESET_STREAM.
* Set <urg> to 1 if stream content should be treated in priority compared to
- * other streams.
+ * other streams. For STREAM emission, <count> must contains the size of the
+ * frame payload.
*/
-void qcc_send_stream(struct qcs *qcs, int urg)
+void qcc_send_stream(struct qcs *qcs, int urg, int count)
{
struct qcc *qcc = qcs->qcc;
TRACE_STATE("abort stream read", QMUX_EV_QCS_END, qcc->conn, qcs);
qcs->flags |= (QC_SF_TO_STOP_SENDING|QC_SF_READ_ABORTED);
- qcc_send_stream(qcs, 1);
+ qcc_send_stream(qcs, 1, 0);
tasklet_wakeup(qcc->wait_event.tasklet);
end:
size_t count, int flags)
{
struct qcs *qcs = __sc_mux_strm(sc);
+ const size_t old_data = b_data(&qcs->tx.buf);
size_t ret = 0;
char fin;
}
if (ret || fin) {
- qcc_send_stream(qcs, 0);
+ qcc_send_stream(qcs, 0, b_data(&qcs->tx.buf) - old_data);
if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
tasklet_wakeup(qcs->qcc->wait_event.tasklet);
}
struct qcs *qcs = __sc_mux_strm(sc);
struct qcc *qcc = qcs->qcc;
struct sedesc *sd = qcs->sd;
- size_t total = 0;
+ size_t total = 0, data = sd->iobuf.data;
TRACE_ENTER(QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
if (!(qcs->flags & QC_SF_FIN_STREAM) && !sd->iobuf.data)
goto end;
+ data += sd->iobuf.offset;
total = qcs->qcc->app_ops->done_ff(qcs);
- qcc_send_stream(qcs, 0);
+ qcc_send_stream(qcs, 0, data);
if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
tasklet_wakeup(qcc->wait_event.tasklet);
TRACE_STATE("set FIN STREAM",
QMUX_EV_STRM_SHUT, qcc->conn, qcs);
qcs->flags |= QC_SF_FIN_STREAM;
- qcc_send_stream(qcs, 0);
+ qcc_send_stream(qcs, 0, 0);
}
}
else {