xref: /freebsd/crypto/openssl/ssl/quic/quic_cfq.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery 
10*e7be843bSPierre Pronchery #include "internal/quic_cfq.h"
11*e7be843bSPierre Pronchery #include "internal/numbers.h"
12*e7be843bSPierre Pronchery 
13*e7be843bSPierre Pronchery typedef struct quic_cfq_item_ex_st QUIC_CFQ_ITEM_EX;
14*e7be843bSPierre Pronchery 
15*e7be843bSPierre Pronchery struct quic_cfq_item_ex_st {
16*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM           public;
17*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX       *prev, *next;
18*e7be843bSPierre Pronchery     unsigned char          *encoded;
19*e7be843bSPierre Pronchery     cfq_free_cb            *free_cb;
20*e7be843bSPierre Pronchery     void                   *free_cb_arg;
21*e7be843bSPierre Pronchery     uint64_t                frame_type;
22*e7be843bSPierre Pronchery     size_t                  encoded_len;
23*e7be843bSPierre Pronchery     uint32_t                priority, pn_space, flags;
24*e7be843bSPierre Pronchery     int                     state;
25*e7be843bSPierre Pronchery };
26*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_get_frame_type(const QUIC_CFQ_ITEM * item)27*e7be843bSPierre Pronchery uint64_t ossl_quic_cfq_item_get_frame_type(const QUIC_CFQ_ITEM *item)
28*e7be843bSPierre Pronchery {
29*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
30*e7be843bSPierre Pronchery 
31*e7be843bSPierre Pronchery     return ex->frame_type;
32*e7be843bSPierre Pronchery }
33*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_get_encoded(const QUIC_CFQ_ITEM * item)34*e7be843bSPierre Pronchery const unsigned char *ossl_quic_cfq_item_get_encoded(const QUIC_CFQ_ITEM *item)
35*e7be843bSPierre Pronchery {
36*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
37*e7be843bSPierre Pronchery 
38*e7be843bSPierre Pronchery     return ex->encoded;
39*e7be843bSPierre Pronchery }
40*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_get_encoded_len(const QUIC_CFQ_ITEM * item)41*e7be843bSPierre Pronchery size_t ossl_quic_cfq_item_get_encoded_len(const QUIC_CFQ_ITEM *item)
42*e7be843bSPierre Pronchery {
43*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
44*e7be843bSPierre Pronchery 
45*e7be843bSPierre Pronchery     return ex->encoded_len;
46*e7be843bSPierre Pronchery }
47*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_get_state(const QUIC_CFQ_ITEM * item)48*e7be843bSPierre Pronchery int ossl_quic_cfq_item_get_state(const QUIC_CFQ_ITEM *item)
49*e7be843bSPierre Pronchery {
50*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
51*e7be843bSPierre Pronchery 
52*e7be843bSPierre Pronchery     return ex->state;
53*e7be843bSPierre Pronchery }
54*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_get_pn_space(const QUIC_CFQ_ITEM * item)55*e7be843bSPierre Pronchery uint32_t ossl_quic_cfq_item_get_pn_space(const QUIC_CFQ_ITEM *item)
56*e7be843bSPierre Pronchery {
57*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
58*e7be843bSPierre Pronchery 
59*e7be843bSPierre Pronchery     return ex->pn_space;
60*e7be843bSPierre Pronchery }
61*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM * item)62*e7be843bSPierre Pronchery int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item)
63*e7be843bSPierre Pronchery {
64*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
65*e7be843bSPierre Pronchery 
66*e7be843bSPierre Pronchery     return (ex->flags & QUIC_CFQ_ITEM_FLAG_UNRELIABLE) != 0;
67*e7be843bSPierre Pronchery }
68*e7be843bSPierre Pronchery 
69*e7be843bSPierre Pronchery typedef struct quic_cfq_item_list_st {
70*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *head, *tail;
71*e7be843bSPierre Pronchery } QUIC_CFQ_ITEM_LIST;
72*e7be843bSPierre Pronchery 
73*e7be843bSPierre Pronchery struct quic_cfq_st {
74*e7be843bSPierre Pronchery     /*
75*e7be843bSPierre Pronchery      * Invariant: A CFQ item is always in exactly one of these lists, never more
76*e7be843bSPierre Pronchery      * or less than one.
77*e7be843bSPierre Pronchery      *
78*e7be843bSPierre Pronchery      * Invariant: The list the CFQ item is determined exactly by the state field
79*e7be843bSPierre Pronchery      * of the item.
80*e7be843bSPierre Pronchery      */
81*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_LIST                      new_list, tx_list, free_list;
82*e7be843bSPierre Pronchery };
83*e7be843bSPierre Pronchery 
compare(const QUIC_CFQ_ITEM_EX * a,const QUIC_CFQ_ITEM_EX * b)84*e7be843bSPierre Pronchery static int compare(const QUIC_CFQ_ITEM_EX *a, const QUIC_CFQ_ITEM_EX *b)
85*e7be843bSPierre Pronchery {
86*e7be843bSPierre Pronchery     if (a->pn_space < b->pn_space)
87*e7be843bSPierre Pronchery         return -1;
88*e7be843bSPierre Pronchery     else if (a->pn_space > b->pn_space)
89*e7be843bSPierre Pronchery         return 1;
90*e7be843bSPierre Pronchery 
91*e7be843bSPierre Pronchery     if (a->priority > b->priority)
92*e7be843bSPierre Pronchery         return -1;
93*e7be843bSPierre Pronchery     else if (a->priority < b->priority)
94*e7be843bSPierre Pronchery         return 1;
95*e7be843bSPierre Pronchery 
96*e7be843bSPierre Pronchery     return 0;
97*e7be843bSPierre Pronchery }
98*e7be843bSPierre Pronchery 
list_remove(QUIC_CFQ_ITEM_LIST * l,QUIC_CFQ_ITEM_EX * n)99*e7be843bSPierre Pronchery static void list_remove(QUIC_CFQ_ITEM_LIST *l, QUIC_CFQ_ITEM_EX *n)
100*e7be843bSPierre Pronchery {
101*e7be843bSPierre Pronchery     if (l->head == n)
102*e7be843bSPierre Pronchery         l->head = n->next;
103*e7be843bSPierre Pronchery     if (l->tail == n)
104*e7be843bSPierre Pronchery         l->tail = n->prev;
105*e7be843bSPierre Pronchery     if (n->prev != NULL)
106*e7be843bSPierre Pronchery         n->prev->next = n->next;
107*e7be843bSPierre Pronchery     if (n->next != NULL)
108*e7be843bSPierre Pronchery         n->next->prev = n->prev;
109*e7be843bSPierre Pronchery     n->prev = n->next = NULL;
110*e7be843bSPierre Pronchery }
111*e7be843bSPierre Pronchery 
list_insert_head(QUIC_CFQ_ITEM_LIST * l,QUIC_CFQ_ITEM_EX * n)112*e7be843bSPierre Pronchery static void list_insert_head(QUIC_CFQ_ITEM_LIST *l, QUIC_CFQ_ITEM_EX *n)
113*e7be843bSPierre Pronchery {
114*e7be843bSPierre Pronchery     n->next = l->head;
115*e7be843bSPierre Pronchery     n->prev = NULL;
116*e7be843bSPierre Pronchery     l->head = n;
117*e7be843bSPierre Pronchery     if (n->next != NULL)
118*e7be843bSPierre Pronchery         n->next->prev = n;
119*e7be843bSPierre Pronchery     if (l->tail == NULL)
120*e7be843bSPierre Pronchery         l->tail = n;
121*e7be843bSPierre Pronchery }
122*e7be843bSPierre Pronchery 
list_insert_tail(QUIC_CFQ_ITEM_LIST * l,QUIC_CFQ_ITEM_EX * n)123*e7be843bSPierre Pronchery static void list_insert_tail(QUIC_CFQ_ITEM_LIST *l, QUIC_CFQ_ITEM_EX *n)
124*e7be843bSPierre Pronchery {
125*e7be843bSPierre Pronchery     n->prev = l->tail;
126*e7be843bSPierre Pronchery     n->next = NULL;
127*e7be843bSPierre Pronchery     l->tail = n;
128*e7be843bSPierre Pronchery     if (n->prev != NULL)
129*e7be843bSPierre Pronchery         n->prev->next = n;
130*e7be843bSPierre Pronchery     if (l->head == NULL)
131*e7be843bSPierre Pronchery         l->head = n;
132*e7be843bSPierre Pronchery }
133*e7be843bSPierre Pronchery 
list_insert_after(QUIC_CFQ_ITEM_LIST * l,QUIC_CFQ_ITEM_EX * ref,QUIC_CFQ_ITEM_EX * n)134*e7be843bSPierre Pronchery static void list_insert_after(QUIC_CFQ_ITEM_LIST *l,
135*e7be843bSPierre Pronchery                               QUIC_CFQ_ITEM_EX *ref,
136*e7be843bSPierre Pronchery                               QUIC_CFQ_ITEM_EX *n)
137*e7be843bSPierre Pronchery {
138*e7be843bSPierre Pronchery     n->prev = ref;
139*e7be843bSPierre Pronchery     n->next = ref->next;
140*e7be843bSPierre Pronchery     if (ref->next != NULL)
141*e7be843bSPierre Pronchery         ref->next->prev = n;
142*e7be843bSPierre Pronchery     ref->next = n;
143*e7be843bSPierre Pronchery     if (l->tail == ref)
144*e7be843bSPierre Pronchery         l->tail = n;
145*e7be843bSPierre Pronchery }
146*e7be843bSPierre Pronchery 
list_insert_sorted(QUIC_CFQ_ITEM_LIST * l,QUIC_CFQ_ITEM_EX * n,int (* cmp)(const QUIC_CFQ_ITEM_EX * a,const QUIC_CFQ_ITEM_EX * b))147*e7be843bSPierre Pronchery static void list_insert_sorted(QUIC_CFQ_ITEM_LIST *l, QUIC_CFQ_ITEM_EX *n,
148*e7be843bSPierre Pronchery                                int (*cmp)(const QUIC_CFQ_ITEM_EX *a,
149*e7be843bSPierre Pronchery                                           const QUIC_CFQ_ITEM_EX *b))
150*e7be843bSPierre Pronchery {
151*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *p = l->head, *pprev = NULL;
152*e7be843bSPierre Pronchery 
153*e7be843bSPierre Pronchery     if (p == NULL) {
154*e7be843bSPierre Pronchery         l->head = l->tail = n;
155*e7be843bSPierre Pronchery         n->prev = n->next = NULL;
156*e7be843bSPierre Pronchery         return;
157*e7be843bSPierre Pronchery     }
158*e7be843bSPierre Pronchery 
159*e7be843bSPierre Pronchery     for (; p != NULL && cmp(p, n) < 0; pprev = p, p = p->next);
160*e7be843bSPierre Pronchery 
161*e7be843bSPierre Pronchery     if (p == NULL)
162*e7be843bSPierre Pronchery         list_insert_tail(l, n);
163*e7be843bSPierre Pronchery     else if (pprev == NULL)
164*e7be843bSPierre Pronchery         list_insert_head(l, n);
165*e7be843bSPierre Pronchery     else
166*e7be843bSPierre Pronchery         list_insert_after(l, pprev, n);
167*e7be843bSPierre Pronchery }
168*e7be843bSPierre Pronchery 
ossl_quic_cfq_new(void)169*e7be843bSPierre Pronchery QUIC_CFQ *ossl_quic_cfq_new(void)
170*e7be843bSPierre Pronchery {
171*e7be843bSPierre Pronchery     QUIC_CFQ *cfq = OPENSSL_zalloc(sizeof(*cfq));
172*e7be843bSPierre Pronchery 
173*e7be843bSPierre Pronchery     if (cfq == NULL)
174*e7be843bSPierre Pronchery         return NULL;
175*e7be843bSPierre Pronchery 
176*e7be843bSPierre Pronchery     return cfq;
177*e7be843bSPierre Pronchery }
178*e7be843bSPierre Pronchery 
clear_item(QUIC_CFQ_ITEM_EX * item)179*e7be843bSPierre Pronchery static void clear_item(QUIC_CFQ_ITEM_EX *item)
180*e7be843bSPierre Pronchery {
181*e7be843bSPierre Pronchery     if (item->free_cb != NULL) {
182*e7be843bSPierre Pronchery         item->free_cb(item->encoded, item->encoded_len, item->free_cb_arg);
183*e7be843bSPierre Pronchery 
184*e7be843bSPierre Pronchery         item->free_cb       = NULL;
185*e7be843bSPierre Pronchery         item->encoded       = NULL;
186*e7be843bSPierre Pronchery         item->encoded_len   = 0;
187*e7be843bSPierre Pronchery     }
188*e7be843bSPierre Pronchery 
189*e7be843bSPierre Pronchery     item->state = -1;
190*e7be843bSPierre Pronchery }
191*e7be843bSPierre Pronchery 
free_list_items(QUIC_CFQ_ITEM_LIST * l)192*e7be843bSPierre Pronchery static void free_list_items(QUIC_CFQ_ITEM_LIST *l)
193*e7be843bSPierre Pronchery {
194*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *p, *pnext;
195*e7be843bSPierre Pronchery 
196*e7be843bSPierre Pronchery     for (p = l->head; p != NULL; p = pnext) {
197*e7be843bSPierre Pronchery         pnext = p->next;
198*e7be843bSPierre Pronchery         clear_item(p);
199*e7be843bSPierre Pronchery         OPENSSL_free(p);
200*e7be843bSPierre Pronchery     }
201*e7be843bSPierre Pronchery }
202*e7be843bSPierre Pronchery 
ossl_quic_cfq_free(QUIC_CFQ * cfq)203*e7be843bSPierre Pronchery void ossl_quic_cfq_free(QUIC_CFQ *cfq)
204*e7be843bSPierre Pronchery {
205*e7be843bSPierre Pronchery     if (cfq == NULL)
206*e7be843bSPierre Pronchery         return;
207*e7be843bSPierre Pronchery 
208*e7be843bSPierre Pronchery     free_list_items(&cfq->new_list);
209*e7be843bSPierre Pronchery     free_list_items(&cfq->tx_list);
210*e7be843bSPierre Pronchery     free_list_items(&cfq->free_list);
211*e7be843bSPierre Pronchery     OPENSSL_free(cfq);
212*e7be843bSPierre Pronchery }
213*e7be843bSPierre Pronchery 
cfq_get_free(QUIC_CFQ * cfq)214*e7be843bSPierre Pronchery static QUIC_CFQ_ITEM_EX *cfq_get_free(QUIC_CFQ *cfq)
215*e7be843bSPierre Pronchery {
216*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *item = cfq->free_list.head;
217*e7be843bSPierre Pronchery 
218*e7be843bSPierre Pronchery     if (item != NULL)
219*e7be843bSPierre Pronchery         return item;
220*e7be843bSPierre Pronchery 
221*e7be843bSPierre Pronchery     item = OPENSSL_zalloc(sizeof(*item));
222*e7be843bSPierre Pronchery     if (item == NULL)
223*e7be843bSPierre Pronchery         return NULL;
224*e7be843bSPierre Pronchery 
225*e7be843bSPierre Pronchery     item->state = -1;
226*e7be843bSPierre Pronchery     list_insert_tail(&cfq->free_list, item);
227*e7be843bSPierre Pronchery     return item;
228*e7be843bSPierre Pronchery }
229*e7be843bSPierre Pronchery 
ossl_quic_cfq_add_frame(QUIC_CFQ * cfq,uint32_t priority,uint32_t pn_space,uint64_t frame_type,uint32_t flags,const unsigned char * encoded,size_t encoded_len,cfq_free_cb * free_cb,void * free_cb_arg)230*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *ossl_quic_cfq_add_frame(QUIC_CFQ            *cfq,
231*e7be843bSPierre Pronchery                                        uint32_t             priority,
232*e7be843bSPierre Pronchery                                        uint32_t             pn_space,
233*e7be843bSPierre Pronchery                                        uint64_t             frame_type,
234*e7be843bSPierre Pronchery                                        uint32_t             flags,
235*e7be843bSPierre Pronchery                                        const unsigned char *encoded,
236*e7be843bSPierre Pronchery                                        size_t               encoded_len,
237*e7be843bSPierre Pronchery                                        cfq_free_cb         *free_cb,
238*e7be843bSPierre Pronchery                                        void                *free_cb_arg)
239*e7be843bSPierre Pronchery {
240*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *item = cfq_get_free(cfq);
241*e7be843bSPierre Pronchery 
242*e7be843bSPierre Pronchery     if (item == NULL)
243*e7be843bSPierre Pronchery         return NULL;
244*e7be843bSPierre Pronchery 
245*e7be843bSPierre Pronchery     item->priority      = priority;
246*e7be843bSPierre Pronchery     item->frame_type    = frame_type;
247*e7be843bSPierre Pronchery     item->pn_space      = pn_space;
248*e7be843bSPierre Pronchery     item->encoded       = (unsigned char *)encoded;
249*e7be843bSPierre Pronchery     item->encoded_len   = encoded_len;
250*e7be843bSPierre Pronchery     item->free_cb       = free_cb;
251*e7be843bSPierre Pronchery     item->free_cb_arg   = free_cb_arg;
252*e7be843bSPierre Pronchery 
253*e7be843bSPierre Pronchery     item->state = QUIC_CFQ_STATE_NEW;
254*e7be843bSPierre Pronchery     item->flags = flags;
255*e7be843bSPierre Pronchery     list_remove(&cfq->free_list, item);
256*e7be843bSPierre Pronchery     list_insert_sorted(&cfq->new_list, item, compare);
257*e7be843bSPierre Pronchery     return &item->public;
258*e7be843bSPierre Pronchery }
259*e7be843bSPierre Pronchery 
ossl_quic_cfq_mark_tx(QUIC_CFQ * cfq,QUIC_CFQ_ITEM * item)260*e7be843bSPierre Pronchery void ossl_quic_cfq_mark_tx(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item)
261*e7be843bSPierre Pronchery {
262*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
263*e7be843bSPierre Pronchery 
264*e7be843bSPierre Pronchery     switch (ex->state) {
265*e7be843bSPierre Pronchery     case QUIC_CFQ_STATE_NEW:
266*e7be843bSPierre Pronchery         list_remove(&cfq->new_list, ex);
267*e7be843bSPierre Pronchery         list_insert_tail(&cfq->tx_list, ex);
268*e7be843bSPierre Pronchery         ex->state = QUIC_CFQ_STATE_TX;
269*e7be843bSPierre Pronchery         break;
270*e7be843bSPierre Pronchery     case QUIC_CFQ_STATE_TX:
271*e7be843bSPierre Pronchery         break; /* nothing to do */
272*e7be843bSPierre Pronchery     default:
273*e7be843bSPierre Pronchery         assert(0); /* invalid state (e.g. in free state) */
274*e7be843bSPierre Pronchery         break;
275*e7be843bSPierre Pronchery     }
276*e7be843bSPierre Pronchery }
277*e7be843bSPierre Pronchery 
ossl_quic_cfq_mark_lost(QUIC_CFQ * cfq,QUIC_CFQ_ITEM * item,uint32_t priority)278*e7be843bSPierre Pronchery void ossl_quic_cfq_mark_lost(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item,
279*e7be843bSPierre Pronchery                              uint32_t priority)
280*e7be843bSPierre Pronchery {
281*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
282*e7be843bSPierre Pronchery 
283*e7be843bSPierre Pronchery     if (ossl_quic_cfq_item_is_unreliable(item)) {
284*e7be843bSPierre Pronchery         ossl_quic_cfq_release(cfq, item);
285*e7be843bSPierre Pronchery         return;
286*e7be843bSPierre Pronchery     }
287*e7be843bSPierre Pronchery 
288*e7be843bSPierre Pronchery     switch (ex->state) {
289*e7be843bSPierre Pronchery     case QUIC_CFQ_STATE_NEW:
290*e7be843bSPierre Pronchery         if (priority != UINT32_MAX && priority != ex->priority) {
291*e7be843bSPierre Pronchery             list_remove(&cfq->new_list, ex);
292*e7be843bSPierre Pronchery             ex->priority = priority;
293*e7be843bSPierre Pronchery             list_insert_sorted(&cfq->new_list, ex, compare);
294*e7be843bSPierre Pronchery         }
295*e7be843bSPierre Pronchery         break; /* nothing to do */
296*e7be843bSPierre Pronchery     case QUIC_CFQ_STATE_TX:
297*e7be843bSPierre Pronchery         if (priority != UINT32_MAX)
298*e7be843bSPierre Pronchery             ex->priority = priority;
299*e7be843bSPierre Pronchery         list_remove(&cfq->tx_list, ex);
300*e7be843bSPierre Pronchery         list_insert_sorted(&cfq->new_list, ex, compare);
301*e7be843bSPierre Pronchery         ex->state = QUIC_CFQ_STATE_NEW;
302*e7be843bSPierre Pronchery         break;
303*e7be843bSPierre Pronchery     default:
304*e7be843bSPierre Pronchery         assert(0); /* invalid state (e.g. in free state) */
305*e7be843bSPierre Pronchery         break;
306*e7be843bSPierre Pronchery     }
307*e7be843bSPierre Pronchery }
308*e7be843bSPierre Pronchery 
309*e7be843bSPierre Pronchery /*
310*e7be843bSPierre Pronchery  * Releases a CFQ item. The item may be in either state (NEW or TX) prior to the
311*e7be843bSPierre Pronchery  * call. The QUIC_CFQ_ITEM pointer must not be used following this call.
312*e7be843bSPierre Pronchery  */
ossl_quic_cfq_release(QUIC_CFQ * cfq,QUIC_CFQ_ITEM * item)313*e7be843bSPierre Pronchery void ossl_quic_cfq_release(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item)
314*e7be843bSPierre Pronchery {
315*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
316*e7be843bSPierre Pronchery 
317*e7be843bSPierre Pronchery     switch (ex->state) {
318*e7be843bSPierre Pronchery     case QUIC_CFQ_STATE_NEW:
319*e7be843bSPierre Pronchery         list_remove(&cfq->new_list, ex);
320*e7be843bSPierre Pronchery         list_insert_tail(&cfq->free_list, ex);
321*e7be843bSPierre Pronchery         clear_item(ex);
322*e7be843bSPierre Pronchery         break;
323*e7be843bSPierre Pronchery     case QUIC_CFQ_STATE_TX:
324*e7be843bSPierre Pronchery         list_remove(&cfq->tx_list, ex);
325*e7be843bSPierre Pronchery         list_insert_tail(&cfq->free_list, ex);
326*e7be843bSPierre Pronchery         clear_item(ex);
327*e7be843bSPierre Pronchery         break;
328*e7be843bSPierre Pronchery     default:
329*e7be843bSPierre Pronchery         assert(0); /* invalid state (e.g. in free state) */
330*e7be843bSPierre Pronchery         break;
331*e7be843bSPierre Pronchery     }
332*e7be843bSPierre Pronchery }
333*e7be843bSPierre Pronchery 
ossl_quic_cfq_get_priority_head(const QUIC_CFQ * cfq,uint32_t pn_space)334*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *ossl_quic_cfq_get_priority_head(const QUIC_CFQ *cfq,
335*e7be843bSPierre Pronchery                                                uint32_t pn_space)
336*e7be843bSPierre Pronchery {
337*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *item = cfq->new_list.head;
338*e7be843bSPierre Pronchery 
339*e7be843bSPierre Pronchery     for (; item != NULL && item->pn_space != pn_space; item = item->next);
340*e7be843bSPierre Pronchery 
341*e7be843bSPierre Pronchery     if (item == NULL)
342*e7be843bSPierre Pronchery         return NULL;
343*e7be843bSPierre Pronchery 
344*e7be843bSPierre Pronchery     return &item->public;
345*e7be843bSPierre Pronchery }
346*e7be843bSPierre Pronchery 
ossl_quic_cfq_item_get_priority_next(const QUIC_CFQ_ITEM * item,uint32_t pn_space)347*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *ossl_quic_cfq_item_get_priority_next(const QUIC_CFQ_ITEM *item,
348*e7be843bSPierre Pronchery                                                     uint32_t pn_space)
349*e7be843bSPierre Pronchery {
350*e7be843bSPierre Pronchery     QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
351*e7be843bSPierre Pronchery 
352*e7be843bSPierre Pronchery     if (ex == NULL)
353*e7be843bSPierre Pronchery         return NULL;
354*e7be843bSPierre Pronchery 
355*e7be843bSPierre Pronchery      ex = ex->next;
356*e7be843bSPierre Pronchery 
357*e7be843bSPierre Pronchery      for (; ex != NULL && ex->pn_space != pn_space; ex = ex->next);
358*e7be843bSPierre Pronchery 
359*e7be843bSPierre Pronchery      if (ex == NULL)
360*e7be843bSPierre Pronchery          return NULL; /* ubsan */
361*e7be843bSPierre Pronchery 
362*e7be843bSPierre Pronchery      return &ex->public;
363*e7be843bSPierre Pronchery }
364