xref: /freebsd/crypto/openssl/ssl/quic/quic_stream_map.c (revision 78e936b2d0b5e6554425009199be31e76bc67c10)
1 /*
2  * Copyright 2022-2026 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include "internal/quic_stream_map.h"
11 #include "internal/nelem.h"
12 
13 /*
14  * QUIC Stream Map
15  * ===============
16  */
17 DEFINE_LHASH_OF_EX(QUIC_STREAM);
18 
19 static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs);
20 
21 /* Circular list management. */
list_insert_tail(QUIC_STREAM_LIST_NODE * l,QUIC_STREAM_LIST_NODE * n)22 static void list_insert_tail(QUIC_STREAM_LIST_NODE *l,
23     QUIC_STREAM_LIST_NODE *n)
24 {
25     /* Must not be in list. */
26     assert(n->prev == NULL && n->next == NULL
27         && l->prev != NULL && l->next != NULL);
28 
29     n->prev = l->prev;
30     n->prev->next = n;
31     l->prev = n;
32     n->next = l;
33 }
34 
list_remove(QUIC_STREAM_LIST_NODE * l,QUIC_STREAM_LIST_NODE * n)35 static void list_remove(QUIC_STREAM_LIST_NODE *l,
36     QUIC_STREAM_LIST_NODE *n)
37 {
38     assert(n->prev != NULL && n->next != NULL
39         && n->prev != n && n->next != n);
40 
41     n->prev->next = n->next;
42     n->next->prev = n->prev;
43     n->next = n->prev = NULL;
44 }
45 
list_next(QUIC_STREAM_LIST_NODE * l,QUIC_STREAM_LIST_NODE * n,size_t off)46 static QUIC_STREAM *list_next(QUIC_STREAM_LIST_NODE *l, QUIC_STREAM_LIST_NODE *n,
47     size_t off)
48 {
49     assert(n->prev != NULL && n->next != NULL
50         && (n == l || (n->prev != n && n->next != n))
51         && l->prev != NULL && l->next != NULL);
52 
53     n = n->next;
54 
55     if (n == l)
56         n = n->next;
57     if (n == l)
58         return NULL;
59 
60     assert(n != NULL);
61 
62     return (QUIC_STREAM *)(((char *)n) - off);
63 }
64 
65 #define active_next(l, s) list_next((l), &(s)->active_node, \
66     offsetof(QUIC_STREAM, active_node))
67 #define accept_next(l, s) list_next((l), &(s)->accept_node, \
68     offsetof(QUIC_STREAM, accept_node))
69 #define accept_head(l) list_next((l), (l), \
70     offsetof(QUIC_STREAM, accept_node))
71 #define ready_for_gc_head(l) list_next((l), (l), \
72     offsetof(QUIC_STREAM, ready_for_gc_node))
73 
hash_stream(const QUIC_STREAM * s)74 static unsigned long hash_stream(const QUIC_STREAM *s)
75 {
76     return (unsigned long)s->id;
77 }
78 
cmp_stream(const QUIC_STREAM * a,const QUIC_STREAM * b)79 static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)
80 {
81     if (a->id < b->id)
82         return -1;
83     if (a->id > b->id)
84         return 1;
85     return 0;
86 }
87 
ossl_quic_stream_map_init(QUIC_STREAM_MAP * qsm,uint64_t (* get_stream_limit_cb)(int uni,void * arg),void * get_stream_limit_cb_arg,QUIC_RXFC * max_streams_bidi_rxfc,QUIC_RXFC * max_streams_uni_rxfc,int is_server)88 int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
89     uint64_t (*get_stream_limit_cb)(int uni, void *arg),
90     void *get_stream_limit_cb_arg,
91     QUIC_RXFC *max_streams_bidi_rxfc,
92     QUIC_RXFC *max_streams_uni_rxfc,
93     int is_server)
94 {
95     qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);
96     qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;
97     qsm->accept_list.prev = qsm->accept_list.next = &qsm->accept_list;
98     qsm->ready_for_gc_list.prev = qsm->ready_for_gc_list.next
99         = &qsm->ready_for_gc_list;
100     qsm->rr_stepping = 1;
101     qsm->rr_counter = 0;
102     qsm->rr_cur = NULL;
103 
104     qsm->num_accept_bidi = 0;
105     qsm->num_accept_uni = 0;
106     qsm->num_shutdown_flush = 0;
107 
108     qsm->get_stream_limit_cb = get_stream_limit_cb;
109     qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;
110     qsm->max_streams_bidi_rxfc = max_streams_bidi_rxfc;
111     qsm->max_streams_uni_rxfc = max_streams_uni_rxfc;
112     qsm->is_server = is_server;
113     return 1;
114 }
115 
release_each(QUIC_STREAM * stream,void * arg)116 static void release_each(QUIC_STREAM *stream, void *arg)
117 {
118     QUIC_STREAM_MAP *qsm = arg;
119 
120     ossl_quic_stream_map_release(qsm, stream);
121 }
122 
ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP * qsm)123 void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm)
124 {
125     lh_QUIC_STREAM_set_down_load(qsm->map, 0);
126     ossl_quic_stream_map_visit(qsm, release_each, qsm);
127 
128     lh_QUIC_STREAM_free(qsm->map);
129     qsm->map = NULL;
130 }
131 
ossl_quic_stream_map_visit(QUIC_STREAM_MAP * qsm,void (* visit_cb)(QUIC_STREAM * stream,void * arg),void * visit_cb_arg)132 void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
133     void (*visit_cb)(QUIC_STREAM *stream, void *arg),
134     void *visit_cb_arg)
135 {
136     lh_QUIC_STREAM_doall_arg(qsm->map, visit_cb, visit_cb_arg);
137 }
138 
ossl_quic_stream_map_alloc(QUIC_STREAM_MAP * qsm,uint64_t stream_id,int type)139 QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
140     uint64_t stream_id,
141     int type)
142 {
143     QUIC_STREAM *s;
144     QUIC_STREAM key;
145 
146     key.id = stream_id;
147 
148     s = lh_QUIC_STREAM_retrieve(qsm->map, &key);
149     if (s != NULL)
150         return NULL;
151 
152     s = OPENSSL_zalloc(sizeof(*s));
153     if (s == NULL)
154         return NULL;
155 
156     s->id = stream_id;
157     s->type = type;
158     s->as_server = qsm->is_server;
159     s->send_state = (ossl_quic_stream_is_local_init(s)
160                         || ossl_quic_stream_is_bidi(s))
161         ? QUIC_SSTREAM_STATE_READY
162         : QUIC_SSTREAM_STATE_NONE;
163     s->recv_state = (!ossl_quic_stream_is_local_init(s)
164                         || ossl_quic_stream_is_bidi(s))
165         ? QUIC_RSTREAM_STATE_RECV
166         : QUIC_RSTREAM_STATE_NONE;
167 
168     s->send_final_size = UINT64_MAX;
169 
170     lh_QUIC_STREAM_insert(qsm->map, s);
171     if (lh_QUIC_STREAM_error(qsm->map)) {
172         OPENSSL_free(s);
173         return NULL;
174     }
175     return s;
176 }
177 
ossl_quic_stream_map_release(QUIC_STREAM_MAP * qsm,QUIC_STREAM * stream)178 void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream)
179 {
180     if (stream == NULL)
181         return;
182 
183     if (stream->active_node.next != NULL)
184         list_remove(&qsm->active_list, &stream->active_node);
185     if (stream->accept_node.next != NULL)
186         list_remove(&qsm->accept_list, &stream->accept_node);
187     if (stream->ready_for_gc_node.next != NULL)
188         list_remove(&qsm->ready_for_gc_list, &stream->ready_for_gc_node);
189 
190     ossl_quic_sstream_free(stream->sstream);
191     stream->sstream = NULL;
192 
193     ossl_quic_rstream_free(stream->rstream);
194     stream->rstream = NULL;
195 
196     lh_QUIC_STREAM_delete(qsm->map, stream);
197     OPENSSL_free(stream);
198 }
199 
ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP * qsm,uint64_t stream_id)200 QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
201     uint64_t stream_id)
202 {
203     QUIC_STREAM key;
204 
205     key.id = stream_id;
206 
207     return lh_QUIC_STREAM_retrieve(qsm->map, &key);
208 }
209 
stream_map_mark_active(QUIC_STREAM_MAP * qsm,QUIC_STREAM * s)210 static void stream_map_mark_active(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
211 {
212     if (s->active)
213         return;
214 
215     list_insert_tail(&qsm->active_list, &s->active_node);
216 
217     if (qsm->rr_cur == NULL)
218         qsm->rr_cur = s;
219 
220     s->active = 1;
221 }
222 
stream_map_mark_inactive(QUIC_STREAM_MAP * qsm,QUIC_STREAM * s)223 static void stream_map_mark_inactive(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
224 {
225     if (!s->active)
226         return;
227 
228     if (qsm->rr_cur == s)
229         qsm->rr_cur = active_next(&qsm->active_list, s);
230     if (qsm->rr_cur == s)
231         qsm->rr_cur = NULL;
232 
233     list_remove(&qsm->active_list, &s->active_node);
234 
235     s->active = 0;
236 }
237 
ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP * qsm,size_t stepping)238 void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping)
239 {
240     qsm->rr_stepping = stepping;
241     qsm->rr_counter = 0;
242 }
243 
stream_has_data_to_send(QUIC_STREAM * s)244 static int stream_has_data_to_send(QUIC_STREAM *s)
245 {
246     OSSL_QUIC_FRAME_STREAM shdr;
247     OSSL_QTX_IOVEC iov[2];
248     size_t num_iov;
249     uint64_t fc_credit, fc_swm, fc_limit;
250 
251     switch (s->send_state) {
252     case QUIC_SSTREAM_STATE_READY:
253     case QUIC_SSTREAM_STATE_SEND:
254     case QUIC_SSTREAM_STATE_DATA_SENT:
255         /*
256          * We can still have data to send in DATA_SENT due to retransmissions,
257          * etc.
258          */
259         break;
260     default:
261         return 0; /* Nothing to send. */
262     }
263 
264     /*
265      * We cannot determine if we have data to send simply by checking if
266      * ossl_quic_txfc_get_credit() is zero, because we may also have older
267      * stream data we need to retransmit. The SSTREAM returns older data first,
268      * so we do a simple comparison of the next chunk the SSTREAM wants to send
269      * against the TXFC CWM.
270      */
271     num_iov = OSSL_NELEM(iov);
272     if (!ossl_quic_sstream_get_stream_frame(s->sstream, 0, &shdr, iov,
273             &num_iov))
274         return 0;
275 
276     fc_credit = ossl_quic_txfc_get_credit(&s->txfc, 0);
277     fc_swm = ossl_quic_txfc_get_swm(&s->txfc);
278     fc_limit = fc_swm + fc_credit;
279 
280     return (shdr.is_fin && shdr.len == 0) || shdr.offset < fc_limit;
281 }
282 
qsm_send_part_permits_gc(const QUIC_STREAM * qs)283 static ossl_unused int qsm_send_part_permits_gc(const QUIC_STREAM *qs)
284 {
285     switch (qs->send_state) {
286     case QUIC_SSTREAM_STATE_NONE:
287     case QUIC_SSTREAM_STATE_DATA_RECVD:
288     case QUIC_SSTREAM_STATE_RESET_RECVD:
289         return 1;
290     default:
291         return 0;
292     }
293 }
294 
qsm_ready_for_gc(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)295 static int qsm_ready_for_gc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
296 {
297     int recv_stream_fully_drained = 0; /* TODO(QUIC FUTURE): Optimisation */
298 
299     /*
300      * If sstream has no FIN, we auto-reset it at marked-for-deletion time, so
301      * we don't need to worry about that here.
302      */
303     assert(!qs->deleted
304         || !ossl_quic_stream_has_send(qs)
305         || ossl_quic_stream_send_is_reset(qs)
306         || ossl_quic_stream_send_get_final_size(qs, NULL));
307 
308     return qs->deleted
309         && (!ossl_quic_stream_has_recv(qs)
310             || recv_stream_fully_drained
311             || qs->acked_stop_sending)
312         && (!ossl_quic_stream_has_send(qs)
313             || qs->send_state == QUIC_SSTREAM_STATE_DATA_RECVD
314             || qs->send_state == QUIC_SSTREAM_STATE_RESET_RECVD);
315 }
316 
ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP * qsm,uint64_t stream_ordinal,int is_uni)317 int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm,
318     uint64_t stream_ordinal,
319     int is_uni)
320 {
321     uint64_t stream_limit;
322 
323     if (qsm->get_stream_limit_cb == NULL)
324         return 1;
325 
326     stream_limit = qsm->get_stream_limit_cb(is_uni, qsm->get_stream_limit_cb_arg);
327     return stream_ordinal < stream_limit;
328 }
329 
ossl_quic_stream_map_update_state(QUIC_STREAM_MAP * qsm,QUIC_STREAM * s)330 void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
331 {
332     int should_be_active, allowed_by_stream_limit = 1;
333 
334     if (ossl_quic_stream_is_server_init(s) == qsm->is_server) {
335         int is_uni = !ossl_quic_stream_is_bidi(s);
336         uint64_t stream_ordinal = s->id >> 2;
337 
338         allowed_by_stream_limit
339             = ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm,
340                 stream_ordinal,
341                 is_uni);
342     }
343 
344     if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT
345         && ossl_quic_sstream_is_totally_acked(s->sstream))
346         ossl_quic_stream_map_notify_totally_acked(qsm, s);
347     else if (s->shutdown_flush
348         && s->send_state == QUIC_SSTREAM_STATE_SEND
349         && ossl_quic_sstream_is_totally_acked(s->sstream))
350         shutdown_flush_done(qsm, s);
351 
352     if (!s->ready_for_gc) {
353         s->ready_for_gc = qsm_ready_for_gc(qsm, s);
354         if (s->ready_for_gc)
355             list_insert_tail(&qsm->ready_for_gc_list, &s->ready_for_gc_node);
356     }
357 
358     should_be_active
359         = allowed_by_stream_limit
360         && !s->ready_for_gc
361         && ((ossl_quic_stream_has_recv(s)
362                 && !ossl_quic_stream_recv_is_reset(s)
363                 && (s->recv_state == QUIC_RSTREAM_STATE_RECV
364                     && (s->want_max_stream_data
365                         || ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))))
366             || s->want_stop_sending
367             || s->want_reset_stream
368             || (!s->peer_stop_sending && stream_has_data_to_send(s)));
369 
370     if (should_be_active)
371         stream_map_mark_active(qsm, s);
372     else
373         stream_map_mark_inactive(qsm, s);
374 }
375 
376 /*
377  * Stream Send Part State Management
378  * =================================
379  */
380 
ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)381 int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm,
382     QUIC_STREAM *qs)
383 {
384     switch (qs->send_state) {
385     case QUIC_SSTREAM_STATE_NONE:
386         /* Stream without send part - caller error. */
387         return 0;
388 
389     case QUIC_SSTREAM_STATE_READY:
390         /*
391          * We always allocate a stream ID upfront, so we don't need to do it
392          * here.
393          */
394         qs->send_state = QUIC_SSTREAM_STATE_SEND;
395         return 1;
396 
397     default:
398         /* Nothing to do. */
399         return 1;
400     }
401 }
402 
ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)403 int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,
404     QUIC_STREAM *qs)
405 {
406     switch (qs->send_state) {
407     default:
408         /* Wrong state - caller error. */
409     case QUIC_SSTREAM_STATE_NONE:
410         /* Stream without send part - caller error. */
411         return 0;
412 
413     case QUIC_SSTREAM_STATE_SEND:
414         if (!ossl_quic_sstream_get_final_size(qs->sstream, &qs->send_final_size))
415             return 0;
416 
417         qs->send_state = QUIC_SSTREAM_STATE_DATA_SENT;
418         return 1;
419     }
420 }
421 
shutdown_flush_done(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)422 static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
423 {
424     if (!qs->shutdown_flush)
425         return;
426 
427     assert(qsm->num_shutdown_flush > 0);
428     qs->shutdown_flush = 0;
429     --qsm->num_shutdown_flush;
430 }
431 
ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)432 int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,
433     QUIC_STREAM *qs)
434 {
435     switch (qs->send_state) {
436     default:
437         /* Wrong state - caller error. */
438     case QUIC_SSTREAM_STATE_NONE:
439         /* Stream without send part - caller error. */
440         return 0;
441 
442     case QUIC_SSTREAM_STATE_DATA_SENT:
443         qs->send_state = QUIC_SSTREAM_STATE_DATA_RECVD;
444         /*
445          * Remember final size in case  SSL_get_stream_write_state()
446          * gets called.
447          */
448         qs->have_final_size = ossl_quic_sstream_get_final_size(qs->sstream,
449             NULL);
450 
451         /* We no longer need a QUIC_SSTREAM in this state. */
452         ossl_quic_sstream_free(qs->sstream);
453         qs->sstream = NULL;
454 
455         shutdown_flush_done(qsm, qs);
456         return 1;
457     }
458 }
459 
ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs,uint64_t aec)460 int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
461     QUIC_STREAM *qs,
462     uint64_t aec)
463 {
464     switch (qs->send_state) {
465     default:
466     case QUIC_SSTREAM_STATE_NONE:
467         /*
468          * RESET_STREAM pertains to sending part only, so we cannot reset a
469          * receive-only stream.
470          */
471     case QUIC_SSTREAM_STATE_DATA_RECVD:
472         /*
473          * RFC 9000 s. 3.3: A sender MUST NOT [...] send RESET_STREAM from a
474          * terminal state. If the stream has already finished normally and the
475          * peer has acknowledged this, we cannot reset it.
476          */
477         return 0;
478 
479     case QUIC_SSTREAM_STATE_READY:
480         if (!ossl_quic_stream_map_ensure_send_part_id(qsm, qs))
481             return 0;
482 
483         /* FALLTHROUGH */
484     case QUIC_SSTREAM_STATE_SEND:
485         /*
486          * If we already have a final size (e.g. because we are coming from
487          * DATA_SENT), we have to be consistent with that, so don't change it.
488          * If we don't already have a final size, determine a final size value.
489          * This is the value which we will end up using for a RESET_STREAM frame
490          * for flow control purposes. We could send the stream size (total
491          * number of bytes appended to QUIC_SSTREAM by the application), but it
492          * is in our interest to exclude any bytes we have not actually
493          * transmitted yet, to avoid unnecessarily consuming flow control
494          * credit. We can get this from the TXFC.
495          */
496         qs->send_final_size = ossl_quic_txfc_get_swm(&qs->txfc);
497 
498         /* FALLTHROUGH */
499     case QUIC_SSTREAM_STATE_DATA_SENT:
500         qs->reset_stream_aec = aec;
501         qs->want_reset_stream = 1;
502         qs->send_state = QUIC_SSTREAM_STATE_RESET_SENT;
503 
504         ossl_quic_sstream_free(qs->sstream);
505         qs->sstream = NULL;
506 
507         shutdown_flush_done(qsm, qs);
508         ossl_quic_stream_map_update_state(qsm, qs);
509         return 1;
510 
511     case QUIC_SSTREAM_STATE_RESET_SENT:
512     case QUIC_SSTREAM_STATE_RESET_RECVD:
513         /*
514          * Idempotent - no-op. In any case, do not send RESET_STREAM again - as
515          * mentioned, we must not send it from a terminal state.
516          */
517         return 1;
518     }
519 }
520 
ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)521 int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,
522     QUIC_STREAM *qs)
523 {
524     switch (qs->send_state) {
525     default:
526         /* Wrong state - caller error. */
527     case QUIC_SSTREAM_STATE_NONE:
528         /* Stream without send part - caller error. */
529         return 0;
530 
531     case QUIC_SSTREAM_STATE_RESET_SENT:
532         qs->send_state = QUIC_SSTREAM_STATE_RESET_RECVD;
533         return 1;
534 
535     case QUIC_SSTREAM_STATE_RESET_RECVD:
536         /* Already in the correct state. */
537         return 1;
538     }
539 }
540 
541 /*
542  * Stream Receive Part State Management
543  * ====================================
544  */
545 
ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs,uint64_t final_size)546 int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm,
547     QUIC_STREAM *qs,
548     uint64_t final_size)
549 {
550     switch (qs->recv_state) {
551     default:
552         /* Wrong state - caller error. */
553     case QUIC_RSTREAM_STATE_NONE:
554         /* Stream without receive part - caller error. */
555         return 0;
556 
557     case QUIC_RSTREAM_STATE_RECV:
558         qs->recv_state = QUIC_RSTREAM_STATE_SIZE_KNOWN;
559         return 1;
560     }
561 }
562 
ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)563 int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,
564     QUIC_STREAM *qs)
565 {
566     switch (qs->recv_state) {
567     default:
568         /* Wrong state - caller error. */
569     case QUIC_RSTREAM_STATE_NONE:
570         /* Stream without receive part - caller error. */
571         return 0;
572 
573     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
574         qs->recv_state = QUIC_RSTREAM_STATE_DATA_RECVD;
575         qs->want_stop_sending = 0;
576         return 1;
577     }
578 }
579 
ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)580 int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
581     QUIC_STREAM *qs)
582 {
583     switch (qs->recv_state) {
584     default:
585         /* Wrong state - caller error. */
586     case QUIC_RSTREAM_STATE_NONE:
587         /* Stream without receive part - caller error. */
588         return 0;
589 
590     case QUIC_RSTREAM_STATE_DATA_RECVD:
591         qs->recv_state = QUIC_RSTREAM_STATE_DATA_READ;
592 
593         /* QUIC_RSTREAM is no longer needed */
594         ossl_quic_rstream_free(qs->rstream);
595         qs->rstream = NULL;
596         return 1;
597     }
598 }
599 
ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs,uint64_t app_error_code,uint64_t final_size)600 int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
601     QUIC_STREAM *qs,
602     uint64_t app_error_code,
603     uint64_t final_size)
604 {
605     uint64_t prev_final_size;
606 
607     switch (qs->recv_state) {
608     default:
609     case QUIC_RSTREAM_STATE_NONE:
610         /* Stream without receive part - caller error. */
611         return 0;
612 
613     case QUIC_RSTREAM_STATE_RECV:
614     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
615     case QUIC_RSTREAM_STATE_DATA_RECVD:
616         if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size)
617             && prev_final_size != final_size)
618             /* Cannot change previous final size. */
619             return 0;
620 
621         qs->recv_state = QUIC_RSTREAM_STATE_RESET_RECVD;
622         qs->peer_reset_stream_aec = app_error_code;
623 
624         /* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */
625         qs->want_stop_sending = 0;
626 
627         /* QUIC_RSTREAM is no longer needed */
628         ossl_quic_rstream_free(qs->rstream);
629         qs->rstream = NULL;
630 
631         ossl_quic_stream_map_update_state(qsm, qs);
632         return 1;
633 
634     case QUIC_RSTREAM_STATE_DATA_READ:
635         /*
636          * If we already retired the FIN to the application this is moot
637          * - just ignore.
638          */
639     case QUIC_RSTREAM_STATE_RESET_RECVD:
640     case QUIC_RSTREAM_STATE_RESET_READ:
641         /* Could be a reordered/retransmitted frame - just ignore. */
642         return 1;
643     }
644 }
645 
ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)646 int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,
647     QUIC_STREAM *qs)
648 {
649     switch (qs->recv_state) {
650     default:
651         /* Wrong state - caller error. */
652     case QUIC_RSTREAM_STATE_NONE:
653         /* Stream without receive part - caller error. */
654         return 0;
655 
656     case QUIC_RSTREAM_STATE_RESET_RECVD:
657         qs->recv_state = QUIC_RSTREAM_STATE_RESET_READ;
658         return 1;
659     }
660 }
661 
ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs,uint64_t aec)662 int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,
663     QUIC_STREAM *qs,
664     uint64_t aec)
665 {
666     if (qs->stop_sending)
667         return 0;
668 
669     switch (qs->recv_state) {
670     default:
671     case QUIC_RSTREAM_STATE_NONE:
672         /* Send-only stream, so this makes no sense. */
673     case QUIC_RSTREAM_STATE_DATA_RECVD:
674     case QUIC_RSTREAM_STATE_DATA_READ:
675         /*
676          * Not really any point in STOP_SENDING if we already received all data.
677          */
678     case QUIC_RSTREAM_STATE_RESET_RECVD:
679     case QUIC_RSTREAM_STATE_RESET_READ:
680         /*
681          * RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that
682          * has not been reset by the peer."
683          *
684          * No point in STOP_SENDING if the peer already reset their send part.
685          */
686         return 0;
687 
688     case QUIC_RSTREAM_STATE_RECV:
689     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
690         /*
691          * RFC 9000 s. 3.5: "If the stream is in the Recv or Size Known state,
692          * the transport SHOULD signal this by sending a STOP_SENDING frame to
693          * prompt closure of the stream in the opposite direction."
694          *
695          * Note that it does make sense to send STOP_SENDING for a receive part
696          * of a stream which has a known size (because we have received a FIN)
697          * but which still has other (previous) stream data yet to be received.
698          */
699         break;
700     }
701 
702     qs->stop_sending = 1;
703     qs->stop_sending_aec = aec;
704     return ossl_quic_stream_map_schedule_stop_sending(qsm, qs);
705 }
706 
707 /* Called to mark STOP_SENDING for generation, or regeneration after loss. */
ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP * qsm,QUIC_STREAM * qs)708 int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
709 {
710     if (!qs->stop_sending)
711         return 0;
712 
713     /*
714      * Ignore the call as a no-op if already scheduled, or in a state
715      * where it makes no sense to send STOP_SENDING.
716      */
717     if (qs->want_stop_sending)
718         return 1;
719 
720     switch (qs->recv_state) {
721     default:
722         return 1; /* ignore */
723     case QUIC_RSTREAM_STATE_RECV:
724     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
725         /*
726          * RFC 9000 s. 3.5: "An endpoint is expected to send another
727          * STOP_SENDING frame if a packet containing a previous STOP_SENDING is
728          * lost. However, once either all stream data or a RESET_STREAM frame
729          * has been received for the stream -- that is, the stream is in any
730          * state other than "Recv" or "Size Known" -- sending a STOP_SENDING
731          * frame is unnecessary."
732          */
733         break;
734     }
735 
736     qs->want_stop_sending = 1;
737     ossl_quic_stream_map_update_state(qsm, qs);
738     return 1;
739 }
740 
ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP * qsm)741 QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)
742 {
743     return accept_head(&qsm->accept_list);
744 }
745 
ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP * qsm,QUIC_STREAM * s)746 void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
747     QUIC_STREAM *s)
748 {
749     list_insert_tail(&qsm->accept_list, &s->accept_node);
750     if (ossl_quic_stream_is_bidi(s))
751         ++qsm->num_accept_bidi;
752     else
753         ++qsm->num_accept_uni;
754 }
755 
qsm_get_max_streams_rxfc(QUIC_STREAM_MAP * qsm,QUIC_STREAM * s)756 static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
757 {
758     return ossl_quic_stream_is_bidi(s)
759         ? qsm->max_streams_bidi_rxfc
760         : qsm->max_streams_uni_rxfc;
761 }
762 
ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP * qsm,QUIC_STREAM * s,OSSL_TIME rtt)763 void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
764     QUIC_STREAM *s,
765     OSSL_TIME rtt)
766 {
767     QUIC_RXFC *max_streams_rxfc;
768 
769     list_remove(&qsm->accept_list, &s->accept_node);
770     if (ossl_quic_stream_is_bidi(s))
771         --qsm->num_accept_bidi;
772     else
773         --qsm->num_accept_uni;
774 
775     if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL)
776         (void)ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt);
777 }
778 
ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP * qsm,int is_uni)779 size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni)
780 {
781     return is_uni ? qsm->num_accept_uni : qsm->num_accept_bidi;
782 }
783 
ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP * qsm)784 size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm)
785 {
786     return ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/0)
787         + ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/1);
788 }
789 
ossl_quic_stream_map_gc(QUIC_STREAM_MAP * qsm)790 void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm)
791 {
792     QUIC_STREAM *qs;
793 
794     while ((qs = ready_for_gc_head(&qsm->ready_for_gc_list)) != NULL) {
795         ossl_quic_stream_map_release(qsm, qs);
796     }
797 }
798 
eligible_for_shutdown_flush(QUIC_STREAM * qs)799 static int eligible_for_shutdown_flush(QUIC_STREAM *qs)
800 {
801     /*
802      * We only care about servicing the send part of a stream (if any) during
803      * shutdown flush. We make sure we flush a stream if it is either
804      * non-terminated or was terminated normally such as via
805      * SSL_stream_conclude. A stream which was terminated via a reset is not
806      * flushed, and we will have thrown away the send buffer in that case
807      * anyway.
808      */
809     switch (qs->send_state) {
810     case QUIC_SSTREAM_STATE_SEND:
811     case QUIC_SSTREAM_STATE_DATA_SENT:
812         return !ossl_quic_sstream_is_totally_acked(qs->sstream);
813     default:
814         return 0;
815     }
816 }
817 
begin_shutdown_flush_each(QUIC_STREAM * qs,void * arg)818 static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg)
819 {
820     QUIC_STREAM_MAP *qsm = arg;
821 
822     if (!eligible_for_shutdown_flush(qs) || qs->shutdown_flush)
823         return;
824 
825     qs->shutdown_flush = 1;
826     ++qsm->num_shutdown_flush;
827 }
828 
ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP * qsm)829 void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm)
830 {
831     qsm->num_shutdown_flush = 0;
832 
833     ossl_quic_stream_map_visit(qsm, begin_shutdown_flush_each, qsm);
834 }
835 
ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP * qsm)836 int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm)
837 {
838     return qsm->num_shutdown_flush == 0;
839 }
840 
841 /*
842  * QUIC Stream Iterator
843  * ====================
844  */
ossl_quic_stream_iter_init(QUIC_STREAM_ITER * it,QUIC_STREAM_MAP * qsm,int advance_rr)845 void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
846     int advance_rr)
847 {
848     it->qsm = qsm;
849     it->stream = it->first_stream = qsm->rr_cur;
850     if (advance_rr && it->stream != NULL
851         && ++qsm->rr_counter >= qsm->rr_stepping) {
852         qsm->rr_counter = 0;
853         qsm->rr_cur = active_next(&qsm->active_list, qsm->rr_cur);
854     }
855 }
856 
ossl_quic_stream_iter_next(QUIC_STREAM_ITER * it)857 void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it)
858 {
859     if (it->stream == NULL)
860         return;
861 
862     it->stream = active_next(&it->qsm->active_list, it->stream);
863     if (it->stream == it->first_stream)
864         it->stream = NULL;
865 }
866