diff --git a/src/quic_conn.c b/src/quic_conn.c index 8c7676ac9..d97e82eee 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -4183,6 +4183,34 @@ static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel) return ret; } +/* Flush txbuf for connection. This must be called prior to a packet + * preparation when txbuf contains older data. A send will be conducted for + * these data. + * + * Returns 1 on success : buffer is empty and can be use for packet + * preparation. On error 0 is returned. + */ +static int qc_purge_txbuf(struct quic_conn *qc, struct buffer *buf) +{ + TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc); + + /* This operation can only be conducted if txbuf is not empty. This + * case only happens for connection with their owned socket due to an + * older transient sendto() error. + */ + BUG_ON(!qc_test_fd(qc)); + + if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) { + if (qc->flags & QUIC_FL_CONN_TO_KILL) + qc_txb_release(qc); + TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc); + return 0; + } + + TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc); + return 1; +} + /* Try to send application frames from list on connection . * * Use qc_send_app_probing wrapper when probing with old data. @@ -4208,6 +4236,9 @@ static int qc_send_app_pkts(struct quic_conn *qc, struct list *frms) goto err; } + if (b_data(buf) && !qc_purge_txbuf(qc, buf)) + goto err; + /* Prepare and send packets until we could not further prepare packets. */ while (1) { int ret; @@ -4306,6 +4337,9 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data, goto leave; } + if (b_data(buf) && !qc_purge_txbuf(qc, buf)) + goto out; + /* Currently buf cannot be non-empty at this stage. Even if a previous * sendto() has failed it is emptied to simulate packet emission and * rely on QUIC lost detection to try to emit it. @@ -4613,6 +4647,9 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) if (!buf) goto out; + if (b_data(buf) && !qc_purge_txbuf(qc, buf)) + goto skip_send; + /* Currently buf cannot be non-empty at this stage. Even if a previous * sendto() has failed it is emptied to simulate packet emission and * rely on QUIC lost detection to try to emit it.