void qel_register_send(struct list *send_list, struct quic_enc_level *qel,
struct list *frms);
+int qel_need_sending(struct quic_enc_level *qel, struct quic_conn *qc);
int qc_send(struct quic_conn *qc, int old_data, struct list *send_list);
int qc_dgrams_retransmit(struct quic_conn *qc);
goto out;
}
+ if (!qel_need_sending(qel, qc))
+ goto out;
+
/* XXX TODO: how to limit the list frames to send */
qel_register_send(&send_list, qel, &qel->pktns->tx.frms);
if (!qc_send(qc, 0, &send_list)) {
}
}
- /* Insert each QEL into sending list. */
- list_for_each_entry(qel, &qc->qel_list, list)
- qel_register_send(&send_list, qel, &qel->pktns->tx.frms);
+ /* Insert each QEL into sending list if needed. */
+ list_for_each_entry(qel, &qc->qel_list, list) {
+ if (qel_need_sending(qel, qc))
+ qel_register_send(&send_list, qel, &qel->pktns->tx.frms);
+ }
+
+ /* Skip sending if no QEL with frames to sent. */
+ if (LIST_ISEMPTY(&send_list))
+ goto out;
if (!qc_send(qc, 0, &send_list)) {
TRACE_DEVEL("qc_send() failed", QUIC_EV_CONN_IO_CB, qc);
qel->send_frms = frms;
}
+/* Returns true if <qel> should be registered for sending. This is the case if
+ * frames are prepared, probing is set, <qc> ACK timer has fired or a
+ * CONNECTION_CLOSE is required.
+ */
+int qel_need_sending(struct quic_enc_level *qel, struct quic_conn *qc)
+{
+ return !LIST_ISEMPTY(&qel->pktns->tx.frms) ||
+ qel->pktns->tx.pto_probe ||
+ (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) ||
+ (qc->flags & (QUIC_FL_CONN_ACK_TIMER_FIRED|QUIC_FL_CONN_IMMEDIATE_CLOSE));
+}
+
/* Retransmit up to two datagrams depending on packet number space.
* Return 0 when failed, 0 if not.
*/