#define QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT (1U << 2)
#define QUIC_FL_CONN_LISTENER (1U << 3)
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
-/* gap here */
+#define QUIC_FL_CONN_RETRANS_LOST_DATA (1U << 5) /* retransmission in progress for lost data */
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
#define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7)
-#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8)
+#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */
#define QUIC_FL_CONN_TLS_ALERT (1U << 9)
/* gap here */
#define QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED (1U << 11) /* The half-open connection counter was decremented */
/* Try to send application frames from list <frms> on connection <qc>.
*
- * Use qc_send_app_probing wrapper when probing with old data.
+ * For retransmission you must use wrapper depending on the sending condition :
+ * - use qc_send_app_retransmit to send data detected as lost
+ * - use qc_send_app_probing when probing with already sent data
*
* Returns 1 on success. Some data might not have been sent due to congestion,
* in this case they are left in <frms> input list. The caller may subscribe on
goto leave;
}
+/* Try to send application frames from list <frms> on connection <qc>. Use this
+ * function when retransmitting lost frames.
+ *
+ * Returns the result from qc_send_app_pkts function.
+ */
+static forceinline int qc_send_app_retransmit(struct quic_conn *qc,
+ struct list *frms)
+{
+ int ret;
+
+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
+
+ TRACE_STATE("preparing lost data (retransmission)", QUIC_EV_CONN_TXPKT, qc);
+ qc->flags |= QUIC_FL_CONN_RETRANS_LOST_DATA;
+ ret = qc_send_app_pkts(qc, frms);
+ qc->flags &= ~QUIC_FL_CONN_RETRANS_LOST_DATA;
+
+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
+ return ret;
+}
+
/* Try to send application frames from list <frms> on connection <qc>. Use this
* function when probing is required.
*
}
/* XXX TODO: how to limit the list frames to send */
- if (!qc_send_app_pkts(qc, &qel->pktns->tx.frms)) {
- TRACE_DEVEL("qc_send_app_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
+ if (!qc_send_app_retransmit(qc, &qel->pktns->tx.frms)) {
+ TRACE_DEVEL("qc_send_app_retransmit() failed", QUIC_EV_CONN_IO_CB, qc);
goto out;
}
LIST_DELETE(&cf->list);
LIST_APPEND(outlist, &cf->list);
- /* The MUX stream might be released at this
- * stage. This can most notably happen on
- * retransmission.
- */
- if (qc->mux_state == QC_MUX_READY &&
- !cf->stream.stream->release) {
+ /* Do not notify MUX on retransmission. */
+ if (!(qc->flags & (QUIC_FL_CONN_RETRANS_LOST_DATA|QUIC_FL_CONN_RETRANS_OLD_DATA))) {
+ BUG_ON(qc->mux_state != QC_MUX_READY); /* MUX must be the caller if not on retransmission. */
qcc_streams_sent_done(cf->stream.stream->ctx,
cf->stream.len,
cf->stream.offset.key);
cf->stream.offset.key += dlen;
cf->stream.data = (unsigned char *)b_peek(&cf_buf, dlen);
- /* The MUX stream might be released at this
- * stage. This can most notably happen on
- * retransmission.
- */
- if (qc->mux_state == QC_MUX_READY &&
- !cf->stream.stream->release) {
+ /* Do not notify MUX on retransmission. */
+ if (!(qc->flags & (QUIC_FL_CONN_RETRANS_LOST_DATA|QUIC_FL_CONN_RETRANS_OLD_DATA))) {
+ BUG_ON(qc->mux_state != QC_MUX_READY); /* MUX must be the caller if not on retransmission. */
qcc_streams_sent_done(new_cf->stream.stream->ctx,
new_cf->stream.len,
new_cf->stream.offset.key);