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