From 9cacba434b027bc6f3a3f3c4255c2453935e5357 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 18 Apr 2023 19:30:56 +0100 Subject: QUIC FIFD: Add support for callback on frame ACK We need to get acknowledgement notifications for our STOP_SENDING and STREAM_RESET frames as this information is needed to know when we can delete a QUIC_STREAM object. Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/20765) --- include/internal/quic_fifd.h | 10 ++++++++++ include/internal/quic_stream_map.h | 4 ++++ ssl/quic/quic_fifd.c | 17 +++++++++++++++++ ssl/quic/quic_txp.c | 39 ++++++++++++++++++++++++++++++++++++++ test/quic_fifd_test.c | 5 +++++ 5 files changed, 75 insertions(+) diff --git a/include/internal/quic_fifd.h b/include/internal/quic_fifd.h index ae9e32882a..b395865f2e 100644 --- a/include/internal/quic_fifd.h +++ b/include/internal/quic_fifd.h @@ -37,6 +37,11 @@ struct quic_fifd_st { QUIC_TXPIM_PKT *pkt, void *arg); void *regen_frame_arg; + void (*confirm_frame)(uint64_t frame_type, + uint64_t stream_id, + QUIC_TXPIM_PKT *pkt, + void *arg); + void *confirm_frame_arg; void (*sstream_updated)(uint64_t stream_id, void *arg); void *sstream_updated_arg; @@ -57,6 +62,11 @@ int ossl_quic_fifd_init(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *pkt, void *arg), void *regen_frame_arg, + void (*confirm_frame)(uint64_t frame_type, + uint64_t stream_id, + QUIC_TXPIM_PKT *pkt, + void *arg), + void *confirm_frame_arg, void (*sstream_updated)(uint64_t stream_id, void *arg), void *sstream_updated_arg); diff --git a/include/internal/quic_stream_map.h b/include/internal/quic_stream_map.h index 152a21108d..0f2732a6fc 100644 --- a/include/internal/quic_stream_map.h +++ b/include/internal/quic_stream_map.h @@ -112,6 +112,10 @@ struct quic_stream_st { unsigned int want_stop_sending : 1; /* used for gen or regen */ unsigned int want_reset_stream : 1; /* used for gen or regen */ + /* Flags set when frames *we* sent were acknowledged. */ + unsigned int acked_stop_sending : 1; + unsigned int acked_reset_stream : 1; + /* A FIN has been retired from the rstream buffer. */ unsigned int recv_fin_retired : 1; diff --git a/ssl/quic/quic_fifd.c b/ssl/quic/quic_fifd.c index ced7e31813..8eca7520df 100644 --- a/ssl/quic/quic_fifd.c +++ b/ssl/quic/quic_fifd.c @@ -27,6 +27,11 @@ int ossl_quic_fifd_init(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *pkt, void *arg), void *regen_frame_arg, + void (*confirm_frame)(uint64_t frame_type, + uint64_t stream_id, + QUIC_TXPIM_PKT *pkt, + void *arg), + void *confirm_frame_arg, void (*sstream_updated)(uint64_t stream_id, void *arg), void *sstream_updated_arg) @@ -42,6 +47,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->confirm_frame = confirm_frame; + fifd->confirm_frame_arg = confirm_frame_arg; fifd->sstream_updated = sstream_updated; fifd->sstream_updated_arg = sstream_updated_arg; return 1; @@ -75,6 +82,16 @@ static void on_acked(void *arg) if (chunks[i].has_fin && chunks[i].stream_id != UINT64_MAX) ossl_quic_sstream_mark_acked_fin(sstream); + + if (chunks[i].has_stop_sending && chunks[i].stream_id != UINT64_MAX) + fifd->confirm_frame(OSSL_QUIC_FRAME_TYPE_STOP_SENDING, + chunks[i].stream_id, pkt, + fifd->confirm_frame_arg); + + if (chunks[i].has_reset_stream && chunks[i].stream_id != UINT64_MAX) + fifd->confirm_frame(OSSL_QUIC_FRAME_TYPE_RESET_STREAM, + chunks[i].stream_id, pkt, + fifd->confirm_frame_arg); } /* GCR */ diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c index 10a1a5f18e..a1341d8b13 100644 --- a/ssl/quic/quic_txp.c +++ b/ssl/quic/quic_txp.c @@ -310,6 +310,8 @@ 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_confirm_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, @@ -369,6 +371,7 @@ OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETIS txp->args.cfq, txp->args.ackm, txp->args.txpim, get_sstream_by_id, txp, on_regen_notify, txp, + on_confirm_notify, txp, on_sstream_updated, txp)) { OPENSSL_free(txp); return NULL; @@ -1129,6 +1132,42 @@ static void on_regen_notify(uint64_t frame_type, uint64_t stream_id, } } +static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id, + QUIC_TXPIM_PKT *pkt, void *arg) +{ + OSSL_QUIC_TX_PACKETISER *txp = arg; + + switch (frame_type) { + case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: + { + QUIC_STREAM *s + = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); + + if (s == NULL) + return; + + s->acked_stop_sending = 1; + ossl_quic_stream_map_update_state(txp->args.qsm, s); + } + break; + case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: + { + QUIC_STREAM *s + = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id); + + if (s == NULL) + return; + + s->acked_reset_stream = 1; + ossl_quic_stream_map_update_state(txp->args.qsm, s); + } + break; + default: + assert(0); + break; + } +} + static void on_sstream_updated(uint64_t stream_id, void *arg) { OSSL_QUIC_TX_PACKETISER *txp = arg; diff --git a/test/quic_fifd_test.c b/test/quic_fifd_test.c index ccf01fb89b..bb0cd77105 100644 --- a/test/quic_fifd_test.c +++ b/test/quic_fifd_test.c @@ -40,6 +40,10 @@ static void regen_frame(uint64_t frame_type, uint64_t stream_id, regen_frame_p(frame_type, stream_id, pkt, arg); } +static void confirm_frame(uint64_t frame_type, uint64_t stream_id, + QUIC_TXPIM_PKT *pkt, void *arg) +{} + static void sstream_updated(uint64_t stream_id, void *arg) {} @@ -333,6 +337,7 @@ static int test_fifd(int idx) info.txpim, get_sstream_by_id, NULL, regen_frame, NULL, + confirm_frame, NULL, sstream_updated, NULL))) goto err; -- cgit v1.2.1