static void qmux_ctrl_send(struct qc_stream_desc *, uint64_t data, uint64_t offset);
static void qmux_ctrl_room(struct qc_stream_desc *, uint64_t room);
+/* Free <qcc> STREAM frames in Tx list. */
+static void qcc_tx_frms_free(struct qcc *qcc)
+{
+ while (!LIST_ISEMPTY(&qcc->tx.frms)) {
+ struct quic_frame *frm = LIST_ELEM(qcc->tx.frms.n, struct quic_frame *, list);
+ qc_frm_free(qcc->conn->handle.qc, &frm);
+ }
+}
+
static void qcs_free_ncbuf(struct qcs *qcs, struct ncbuf *ncbuf)
{
struct buffer buf;
*/
static int qcc_io_send(struct qcc *qcc)
{
- struct list frms = LIST_HEAD_INIT(frms);
+ struct list *frms = &qcc->tx.frms;
/* Temporary list for QCS on error. */
struct list qcs_failed = LIST_HEAD_INIT(qcs_failed);
struct qcs *qcs, *qcs_tmp, *first_qcs = NULL;
if (!qfctl_rblocked(&qcc->tx.fc) &&
!qfctl_rblocked(&qcs->tx.fc) && window_conn > total) {
- if ((ret = qcs_send(qcs, &frms, window_conn - total)) < 0) {
+ if ((ret = qcs_send(qcs, frms, window_conn - total)) < 0) {
/* Temporarily remove QCS from send-list. */
LIST_DEL_INIT(&qcs->el_send);
LIST_APPEND(&qcs_failed, &qcs->el_send);
/* Retry sending until no frame to send, data rejected or connection
* flow-control limit reached.
*/
- while (qcc_send_frames(qcc, &frms) == 0 && !qfctl_rblocked(&qcc->tx.fc)) {
+ while (qcc_send_frames(qcc, frms) == 0 && !qfctl_rblocked(&qcc->tx.fc)) {
window_conn = qfctl_rcap(&qcc->tx.fc);
resent = 0;
BUG_ON(resent > window_conn);
if (!qfctl_rblocked(&qcs->tx.fc) && window_conn > resent) {
- if ((ret = qcs_send(qcs, &frms, window_conn - resent)) < 0) {
+ if ((ret = qcs_send(qcs, frms, window_conn - resent)) < 0) {
LIST_DEL_INIT(&qcs->el_send);
LIST_APPEND(&qcs_failed, &qcs->el_send);
continue;
sent_done:
/* Deallocate frames that the transport layer has rejected. */
- if (!LIST_ISEMPTY(&frms)) {
- struct quic_frame *frm, *frm2;
-
- list_for_each_entry_safe(frm, frm2, &frms, list)
- qc_frm_free(qcc->conn->handle.qc, &frm);
- }
+ qcc_tx_frms_free(qcc);
/* Re-insert on-error QCS at the end of the send-list. */
if (!LIST_ISEMPTY(&qcs_failed)) {
qc_frm_free(qcc->conn->handle.qc, &frm);
}
+ qcc_tx_frms_free(qcc);
+
if (qcc->app_ops && qcc->app_ops->release)
qcc->app_ops->release(qcc->ctx);
TRACE_PROTO("application layer released", QMUX_EV_QCC_END, conn);
qcc->app_ops = NULL;
qcc->streams_by_id = EB_ROOT_UNIQUE;
LIST_INIT(&qcc->lfctl.frms);
+ LIST_INIT(&qcc->tx.frms);
}
static int qmux_init(struct connection *conn, struct proxy *prx,