QUIC FIFD: Ensure QUIC_STREAM is updated after QUIC_SSTREAM loss
authorHugo Landau <hlandau@openssl.org>
Tue, 18 Apr 2023 18:30:55 +0000 (19:30 +0100)
committerHugo Landau <hlandau@openssl.org>
Fri, 12 May 2023 13:47:12 +0000 (14:47 +0100)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20765)

include/internal/quic_fifd.h
ssl/quic/quic_fifd.c
ssl/quic/quic_txp.c
test/quic_fifd_test.c

index 4a42449bbe554d3612a2aa3c8dc936a8d78a4056..ae9e32882aa2674e54d77dfbb52ab320e064418b 100644 (file)
@@ -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) */
 
index e7241f60a82746799b722422451d0240d1ac5ddd..ced7e318139aa1682cd8eb296c77194ad5722bb1 100644 (file)
@@ -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 */
index 786d25ecf639d56b19cf503f19e4d87d93f029d1..97a88c3ff1f5b8fea8918ccb3e0c41a12064e1ef 100644 (file)
@@ -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,
index d3d13bf53f92f9f65a6dd2b4a62ba48b5c1e8d8d..ccf01fb89b4f49d71b8444bac7b0c81f7a2213b8 100644 (file)
@@ -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)