diff options
author | Matt Caswell <matt@openssl.org> | 2023-08-17 15:35:15 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2023-08-25 08:42:39 +0200 |
commit | aa433014bb36bfff0af17c0eb9d25b6fb2d7d068 (patch) | |
tree | 11635db7643e72037b309e6e2406659700e12096 /ssl/quic/quic_channel.c | |
parent | e2972982c64f3f1ac10b3ebe1086d99ec67631bd (diff) |
Keep sending datagrams while we have data to send
If we've got more data to send than will fit in a single datagram we should
keep generating those datagrams until we've sent it all.
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21798)
Diffstat (limited to 'ssl/quic/quic_channel.c')
-rw-r--r-- | ssl/quic/quic_channel.c | 95 |
1 files changed, 50 insertions, 45 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 9fca47bb31..5cee9f7532 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -2406,57 +2406,62 @@ static int ch_tx(QUIC_CHANNEL *ch) ch->rxku_pending_confirm_done = 0; - /* - * Send a packet, if we need to. Best effort. The TXP consults the CC and - * applies any limitations imposed by it, so we don't need to do it here. - * - * Best effort. In particular if TXP fails for some reason we should still - * flush any queued packets which we already generated. - */ - res = ossl_quic_tx_packetiser_generate(ch->txp, &status); - if (status.sent_pkt > 0) { - ch->have_sent_any_pkt = 1; /* Packet was sent */ - + /* Loop until we stop generating packets to send */ + do { /* - * RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when - * sending an ack-eliciting packet if no other ack-eliciting packets - * have been sent since last receiving and processing a packet.' - */ - if (status.sent_ack_eliciting && !ch->have_sent_ack_eliciting_since_rx) { - ch_update_idle(ch); - ch->have_sent_ack_eliciting_since_rx = 1; - } + * Send packet, if we need to. Best effort. The TXP consults the CC and + * applies any limitations imposed by it, so we don't need to do it here. + * + * Best effort. In particular if TXP fails for some reason we should + * still flush any queued packets which we already generated. + */ + res = ossl_quic_tx_packetiser_generate(ch->txp, &status); + if (status.sent_pkt > 0) { + ch->have_sent_any_pkt = 1; /* Packet(s) were sent */ - if (!ch->is_server && status.sent_handshake) /* - * RFC 9001 s. 4.9.1: A client MUST discard Initial keys when it - * first sends a Handshake packet. - */ - ch_discard_el(ch, QUIC_ENC_LEVEL_INITIAL); + * RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when + * sending an ack-eliciting packet if no other ack-eliciting packets + * have been sent since last receiving and processing a packet.' + */ + if (status.sent_ack_eliciting + && !ch->have_sent_ack_eliciting_since_rx) { + ch_update_idle(ch); + ch->have_sent_ack_eliciting_since_rx = 1; + } - if (ch->rxku_pending_confirm_done) - ch->rxku_pending_confirm = 0; + if (!ch->is_server && status.sent_handshake) + /* + * RFC 9001 s. 4.9.1: A client MUST discard Initial keys when it + * first sends a Handshake packet. + */ + ch_discard_el(ch, QUIC_ENC_LEVEL_INITIAL); - ch_update_ping_deadline(ch); - } + if (ch->rxku_pending_confirm_done) + ch->rxku_pending_confirm = 0; - if (!res) { - /* - * Internal failure (e.g. allocation, assertion). - * - * One case where TXP can fail is if we reach a TX PN of 2**62 - 1. As - * per RFC 9000 s. 12.3, if this happens we MUST close the connection - * without sending a CONNECTION_CLOSE frame. This is actually handled as - * an emergent consequence of our design, as the TX packetiser will - * never transmit another packet when the TX PN reaches the limit. - * - * Calling the below function terminates the connection; its attempt to - * schedule a CONNECTION_CLOSE frame will not actually cause a packet to - * be transmitted for this reason. - */ - ossl_quic_channel_raise_protocol_error(ch, QUIC_ERR_INTERNAL_ERROR, 0, - "internal error (txp generate)"); - } + ch_update_ping_deadline(ch); + } + + if (!res) { + /* + * One case where TXP can fail is if we reach a TX PN of 2**62 - 1. + * As per RFC 9000 s. 12.3, if this happens we MUST close the + * connection without sending a CONNECTION_CLOSE frame. This is + * actually handled as an emergent consequence of our design, as the + * TX packetiser will never transmit another packet when the TX PN + * reaches the limit. + * + * Calling the below function terminates the connection; its attempt + * to schedule a CONNECTION_CLOSE frame will not actually cause a + * packet to be transmitted for this reason. + */ + ossl_quic_channel_raise_protocol_error(ch, QUIC_ERR_INTERNAL_ERROR, + 0, + "internal error (txp generate)"); + break; + } + } while (status.sent_pkt > 0); /* Flush packets to network. */ switch (ossl_qtx_flush_net(ch->qtx)) { |