]> git.ipfire.org Git - thirdparty/openssl.git/blob - ssl/quic/quic_stream_map.c
Copyright year updates
[thirdparty/openssl.git] / ssl / quic / quic_stream_map.c
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. */
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
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
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
76 static unsigned long hash_stream(const QUIC_STREAM *s)
77 {
78 return (unsigned long)s->id;
79 }
80
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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. */
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
732 QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)
733 {
734 return accept_head(&qsm->accept_list);
735 }
736
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
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
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
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
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
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
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
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
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
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 */
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
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 }