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