From 5d27e7e9ae7135f8ba92498e3c4e7f9b77f2f8e3 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 18 Apr 2023 19:30:55 +0100 Subject: QUIC FIFD: Ensure QUIC_STREAM is updated after QUIC_SSTREAM loss Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/20765) --- include/internal/quic_fifd.h | 8 +++++++- ssl/quic/quic_fifd.c | 22 +++++++++++++++++++--- ssl/quic/quic_txp.c | 16 +++++++++++++++- test/quic_fifd_test.c | 6 +++++- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/include/internal/quic_fifd.h b/include/internal/quic_fifd.h index 4a42449bbe..ae9e32882a 100644 --- a/include/internal/quic_fifd.h +++ b/include/internal/quic_fifd.h @@ -37,6 +37,9 @@ struct quic_fifd_st { QUIC_TXPIM_PKT *pkt, void *arg); void *regen_frame_arg; + void (*sstream_updated)(uint64_t stream_id, + void *arg); + void *sstream_updated_arg; }; int ossl_quic_fifd_init(QUIC_FIFD *fifd, @@ -53,7 +56,10 @@ int ossl_quic_fifd_init(QUIC_FIFD *fifd, uint64_t stream_id, QUIC_TXPIM_PKT *pkt, void *arg), - void *regen_frame_arg); + void *regen_frame_arg, + void (*sstream_updated)(uint64_t stream_id, + void *arg), + void *sstream_updated_arg); void ossl_quic_fifd_cleanup(QUIC_FIFD *fifd); /* (no-op) */ diff --git a/ssl/quic/quic_fifd.c b/ssl/quic/quic_fifd.c index e7241f60a8..ced7e31813 100644 --- a/ssl/quic/quic_fifd.c +++ b/ssl/quic/quic_fifd.c @@ -26,7 +26,10 @@ int ossl_quic_fifd_init(QUIC_FIFD *fifd, uint64_t stream_id, QUIC_TXPIM_PKT *pkt, void *arg), - void *regen_frame_arg) + void *regen_frame_arg, + void (*sstream_updated)(uint64_t stream_id, + void *arg), + void *sstream_updated_arg) { if (cfq == NULL || ackm == NULL || txpim == NULL || get_sstream_by_id == NULL || regen_frame == NULL) @@ -39,6 +42,8 @@ int ossl_quic_fifd_init(QUIC_FIFD *fifd, fifd->get_sstream_by_id_arg = get_sstream_by_id_arg; fifd->regen_frame = regen_frame; fifd->regen_frame_arg = regen_frame_arg; + fifd->sstream_updated = sstream_updated; + fifd->sstream_updated_arg = sstream_updated_arg; return 1; } @@ -89,6 +94,7 @@ static void on_lost(void *arg) size_t i, num_chunks = ossl_quic_txpim_pkt_get_num_chunks(pkt); QUIC_SSTREAM *sstream; QUIC_CFQ_ITEM *cfq_item, *cfq_item_next; + int sstream_updated; /* STREAM and CRYPTO stream chunks, FIN and stream FC frames */ for (i = 0; i < num_chunks; ++i) { @@ -98,12 +104,18 @@ static void on_lost(void *arg) if (sstream == NULL) continue; - if (chunks[i].end >= chunks[i].start) + sstream_updated = 0; + + if (chunks[i].end >= chunks[i].start) { ossl_quic_sstream_mark_lost(sstream, chunks[i].start, chunks[i].end); + sstream_updated = 1; + } - if (chunks[i].has_fin && chunks[i].stream_id != UINT64_MAX) + if (chunks[i].has_fin && chunks[i].stream_id != UINT64_MAX) { ossl_quic_sstream_mark_lost_fin(sstream); + sstream_updated = 1; + } if (chunks[i].has_stop_sending && chunks[i].stream_id != UINT64_MAX) fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_STOP_SENDING, @@ -129,6 +141,10 @@ static void on_lost(void *arg) chunks[i].stream_id, pkt, fifd->regen_frame_arg); + + if (sstream_updated && chunks[i].stream_id != UINT64_MAX) + fifd->sstream_updated(chunks[i].stream_id, + fifd->sstream_updated_arg); } /* GCR */ diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c index 786d25ecf6..97a88c3ff1 100644 --- a/ssl/quic/quic_txp.c +++ b/ssl/quic/quic_txp.c @@ -310,6 +310,7 @@ static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space, void *arg); static void on_regen_notify(uint64_t frame_type, uint64_t stream_id, QUIC_TXPIM_PKT *pkt, void *arg); +static void on_sstream_updated(uint64_t stream_id, void *arg); static int sstream_is_pending(QUIC_SSTREAM *sstream); static int txp_el_pending(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level, uint32_t archetype, @@ -365,7 +366,8 @@ OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETIS if (!ossl_quic_fifd_init(&txp->fifd, txp->args.cfq, txp->args.ackm, txp->args.txpim, get_sstream_by_id, txp, - on_regen_notify, txp)) { + on_regen_notify, txp, + on_sstream_updated, txp)) { OPENSSL_free(txp); return NULL; } @@ -1120,6 +1122,18 @@ static void on_regen_notify(uint64_t frame_type, uint64_t stream_id, } } +static void on_sstream_updated(uint64_t stream_id, void *arg) +{ + OSSL_QUIC_TX_PACKETISER *txp = arg; + QUIC_STREAM *s; + + s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); + if (s == NULL) + return; + + ossl_quic_stream_map_update_state(txp->args.qsm, s); +} + static int txp_generate_pre_token(OSSL_QUIC_TX_PACKETISER *txp, struct tx_helper *h, QUIC_TXPIM_PKT *tpkt, diff --git a/test/quic_fifd_test.c b/test/quic_fifd_test.c index d3d13bf53f..ccf01fb89b 100644 --- a/test/quic_fifd_test.c +++ b/test/quic_fifd_test.c @@ -40,6 +40,9 @@ static void regen_frame(uint64_t frame_type, uint64_t stream_id, regen_frame_p(frame_type, stream_id, pkt, arg); } +static void sstream_updated(uint64_t stream_id, void *arg) +{} + typedef struct info_st { QUIC_FIFD fifd; OSSL_ACKM *ackm; @@ -329,7 +332,8 @@ static int test_fifd(int idx) || !TEST_true(ossl_quic_fifd_init(&info.fifd, info.cfq, info.ackm, info.txpim, get_sstream_by_id, NULL, - regen_frame, NULL))) + regen_frame, NULL, + sstream_updated, NULL))) goto err; for (i = 0; i < OSSL_NELEM(info.sstream); ++i) -- cgit v1.2.1