int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
QUIC_TXP_STATUS *status);
+/*
+ * Returns a deadline after which a call to ossl_quic_tx_packetiser_generate()
+ * might succeed even if it did not previously. This may return
+ * ossl_time_infinite() if there is no such deadline currently applicable. It
+ * returns ossl_time_zero() if there is (potentially) more data to be generated
+ * immediately. The value returned is liable to change after any call to
+ * ossl_quic_tx_packetiser_generate() (or after ACKM or CC state changes). Note
+ * that ossl_quic_tx_packetiser_generate() can also start to succeed for other
+ * non-chronological reasons, such as changes to send stream buffers, etc.
+ */
+OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp);
+
/*
* Set the token used in Initial packets. The callback is called when the buffer
* is no longer needed; for example, when the TXP is freed or when this function
* Best effort. In particular if TXP fails for some reason we should still
* flush any queued packets which we already generated.
*/
- switch (ossl_quic_tx_packetiser_generate(ch->txp,
- TX_PACKETISER_ARCHETYPE_NORMAL,
- &status)) {
+ switch (ossl_quic_tx_packetiser_generate(ch->txp, &status)) {
case TX_PACKETISER_RES_SENT_PKT:
ch->have_sent_any_pkt = 1; /* Packet was sent */
}
}
- /* When will CC let us send more? */
- if (ossl_quic_tx_packetiser_has_pending(ch->txp, TX_PACKETISER_ARCHETYPE_NORMAL,
- TX_PACKETISER_BYPASS_CC))
- deadline = ossl_time_min(deadline,
- ch->cc_method->get_wakeup_deadline(ch->cc_data));
+ /* Apply TXP wakeup deadline. */
+ deadline = ossl_time_min(deadline,
+ ossl_quic_tx_packetiser_get_deadline(ch->txp));
/* Is the terminating timer armed? */
if (ossl_quic_channel_is_terminating(ch))
OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes);
static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, struct txp_pkt *pkt,
uint32_t archetype);
-static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp);
+static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
+ uint64_t cc_limit);
OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args)
{
ossl_qtx_finish_dgram(txp->args.qtx);
/* 1. Archetype Selection */
- archetype = txp_determine_archetype(txp);
+ archetype = txp_determine_archetype(txp, cc_limit);
/* 2. Packet Staging */
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
return 1;
}
-static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp)
+static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
+ uint64_t cc_limit)
{
OSSL_ACKM_PROBE_INFO *probe_info
= ossl_ackm_get0_probe_request(txp->args.ackm);
- uint64_t cc_limit
- = txp->args.cc_method->get_tx_allowance(txp->args.cc_data);
uint32_t pn_space;
/*
return txp->next_pn[pn_space];
}
+
+OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp)
+{
+ /*
+ * TXP-specific deadline computations which rely on TXP innards. This is in
+ * turn relied on by the QUIC_CHANNEL code to determine the channel event
+ * handling deadline.
+ */
+ OSSL_TIME deadline = ossl_time_infinite();
+ uint32_t enc_level, pn_space;
+
+ /*
+ * ACK generation is not CC-gated - packets containing only ACKs are allowed
+ * to bypass CC. We want to generate ACK frames even if we are currently
+ * restricted by CC so the peer knows we have received data. The generate
+ * call will take care of selecting the correct packet archetype.
+ */
+ for (enc_level = QUIC_ENC_LEVEL_INITIAL;
+ enc_level < QUIC_ENC_LEVEL_NUM;
+ ++enc_level)
+ if (ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level)) {
+ pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
+ deadline = ossl_time_min(deadline,
+ ossl_ackm_get_ack_deadline(txp->args.ackm, pn_space));
+ }
+
+ /* When will CC let us send more? */
+ deadline = ossl_time_min(deadline,
+ txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data));
+
+ return deadline;
+}