2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include "internal/quic_stream_map.h"
11 #include "internal/nelem.h"
17 DEFINE_LHASH_OF_EX(QUIC_STREAM
);
19 static void shutdown_flush_done(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*qs
);
21 /* Circular list management. */
22 static void list_insert_tail(QUIC_STREAM_LIST_NODE
*l
,
23 QUIC_STREAM_LIST_NODE
*n
)
25 /* Must not be in list. */
26 assert(n
->prev
== NULL
&& n
->next
== NULL
27 && l
->prev
!= NULL
&& l
->next
!= NULL
);
35 static void list_remove(QUIC_STREAM_LIST_NODE
*l
,
36 QUIC_STREAM_LIST_NODE
*n
)
38 assert(n
->prev
!= NULL
&& n
->next
!= NULL
39 && n
->prev
!= n
&& n
->next
!= n
);
41 n
->prev
->next
= n
->next
;
42 n
->next
->prev
= n
->prev
;
43 n
->next
= n
->prev
= NULL
;
46 static QUIC_STREAM
*list_next(QUIC_STREAM_LIST_NODE
*l
, QUIC_STREAM_LIST_NODE
*n
,
49 assert(n
->prev
!= NULL
&& n
->next
!= NULL
50 && (n
== l
|| (n
->prev
!= n
&& n
->next
!= n
))
51 && l
->prev
!= NULL
&& l
->next
!= NULL
);
62 return (QUIC_STREAM
*)(((char *)n
) - off
);
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))
76 static unsigned long hash_stream(const QUIC_STREAM
*s
)
78 return (unsigned long)s
->id
;
81 static int cmp_stream(const QUIC_STREAM
*a
, const QUIC_STREAM
*b
)
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
,
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;
107 qsm
->num_shutdown_flush
= 0;
109 qsm
->get_stream_limit_cb
= get_stream_limit_cb
;
110 qsm
->get_stream_limit_cb_arg
= get_stream_limit_cb_arg
;
111 qsm
->max_streams_bidi_rxfc
= max_streams_bidi_rxfc
;
112 qsm
->max_streams_uni_rxfc
= max_streams_uni_rxfc
;
113 qsm
->is_server
= is_server
;
117 static void release_each(QUIC_STREAM
*stream
, void *arg
)
119 QUIC_STREAM_MAP
*qsm
= arg
;
121 ossl_quic_stream_map_release(qsm
, stream
);
124 void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP
*qsm
)
126 ossl_quic_stream_map_visit(qsm
, release_each
, qsm
);
128 lh_QUIC_STREAM_free(qsm
->map
);
132 void ossl_quic_stream_map_visit(QUIC_STREAM_MAP
*qsm
,
133 void (*visit_cb
)(QUIC_STREAM
*stream
, void *arg
),
136 lh_QUIC_STREAM_doall_arg(qsm
->map
, visit_cb
, visit_cb_arg
);
139 QUIC_STREAM
*ossl_quic_stream_map_alloc(QUIC_STREAM_MAP
*qsm
,
148 s
= lh_QUIC_STREAM_retrieve(qsm
->map
, &key
);
152 s
= OPENSSL_zalloc(sizeof(*s
));
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
;
168 s
->send_final_size
= UINT64_MAX
;
170 lh_QUIC_STREAM_insert(qsm
->map
, s
);
174 void ossl_quic_stream_map_release(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*stream
)
179 if (stream
->active_node
.next
!= NULL
)
180 list_remove(&qsm
->active_list
, &stream
->active_node
);
181 if (stream
->accept_node
.next
!= NULL
)
182 list_remove(&qsm
->accept_list
, &stream
->accept_node
);
183 if (stream
->ready_for_gc_node
.next
!= NULL
)
184 list_remove(&qsm
->ready_for_gc_list
, &stream
->ready_for_gc_node
);
186 ossl_quic_sstream_free(stream
->sstream
);
187 stream
->sstream
= NULL
;
189 ossl_quic_rstream_free(stream
->rstream
);
190 stream
->rstream
= NULL
;
192 lh_QUIC_STREAM_delete(qsm
->map
, stream
);
193 OPENSSL_free(stream
);
196 QUIC_STREAM
*ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP
*qsm
,
203 return lh_QUIC_STREAM_retrieve(qsm
->map
, &key
);
206 static void stream_map_mark_active(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
211 list_insert_tail(&qsm
->active_list
, &s
->active_node
);
213 if (qsm
->rr_cur
== NULL
)
219 static void stream_map_mark_inactive(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
224 if (qsm
->rr_cur
== s
)
225 qsm
->rr_cur
= active_next(&qsm
->active_list
, s
);
226 if (qsm
->rr_cur
== s
)
229 list_remove(&qsm
->active_list
, &s
->active_node
);
234 void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP
*qsm
, size_t stepping
)
236 qsm
->rr_stepping
= stepping
;
240 static int stream_has_data_to_send(QUIC_STREAM
*s
)
242 OSSL_QUIC_FRAME_STREAM shdr
;
243 OSSL_QTX_IOVEC iov
[2];
245 uint64_t fc_credit
, fc_swm
, fc_limit
;
247 switch (s
->send_state
) {
248 case QUIC_SSTREAM_STATE_READY
:
249 case QUIC_SSTREAM_STATE_SEND
:
250 case QUIC_SSTREAM_STATE_DATA_SENT
:
252 * We can still have data to send in DATA_SENT due to retransmissions,
257 return 0; /* Nothing to send. */
261 * We cannot determine if we have data to send simply by checking if
262 * ossl_quic_txfc_get_credit() is zero, because we may also have older
263 * stream data we need to retransmit. The SSTREAM returns older data first,
264 * so we do a simple comparison of the next chunk the SSTREAM wants to send
265 * against the TXFC CWM.
267 num_iov
= OSSL_NELEM(iov
);
268 if (!ossl_quic_sstream_get_stream_frame(s
->sstream
, 0, &shdr
, iov
,
272 fc_credit
= ossl_quic_txfc_get_credit(&s
->txfc
);
273 fc_swm
= ossl_quic_txfc_get_swm(&s
->txfc
);
274 fc_limit
= fc_swm
+ fc_credit
;
276 return (shdr
.is_fin
&& shdr
.len
== 0) || shdr
.offset
< fc_limit
;
279 static ossl_unused
int qsm_send_part_permits_gc(const QUIC_STREAM
*qs
)
281 switch (qs
->send_state
) {
282 case QUIC_SSTREAM_STATE_NONE
:
283 case QUIC_SSTREAM_STATE_DATA_RECVD
:
284 case QUIC_SSTREAM_STATE_RESET_RECVD
:
291 static int qsm_ready_for_gc(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*qs
)
293 int recv_stream_fully_drained
= 0; /* TODO(QUIC FUTURE): Optimisation */
296 * If sstream has no FIN, we auto-reset it at marked-for-deletion time, so
297 * we don't need to worry about that here.
300 || !ossl_quic_stream_has_send(qs
)
301 || ossl_quic_stream_send_is_reset(qs
)
302 || ossl_quic_stream_send_get_final_size(qs
, NULL
));
306 && (!ossl_quic_stream_has_recv(qs
)
307 || recv_stream_fully_drained
308 || qs
->acked_stop_sending
)
309 && (!ossl_quic_stream_has_send(qs
)
310 || qs
->send_state
== QUIC_SSTREAM_STATE_DATA_RECVD
311 || qs
->send_state
== QUIC_SSTREAM_STATE_RESET_RECVD
);
314 int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP
*qsm
,
315 uint64_t stream_ordinal
,
318 uint64_t stream_limit
;
320 if (qsm
->get_stream_limit_cb
== NULL
)
323 stream_limit
= qsm
->get_stream_limit_cb(is_uni
, qsm
->get_stream_limit_cb_arg
);
324 return stream_ordinal
< stream_limit
;
327 void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
329 int should_be_active
, allowed_by_stream_limit
= 1;
331 if (ossl_quic_stream_is_server_init(s
) == qsm
->is_server
) {
332 int is_uni
= !ossl_quic_stream_is_bidi(s
);
333 uint64_t stream_ordinal
= s
->id
>> 2;
335 allowed_by_stream_limit
336 = ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm
,
341 if (s
->send_state
== QUIC_SSTREAM_STATE_DATA_SENT
342 && ossl_quic_sstream_is_totally_acked(s
->sstream
))
343 ossl_quic_stream_map_notify_totally_acked(qsm
, s
);
344 else if (s
->shutdown_flush
345 && s
->send_state
== QUIC_SSTREAM_STATE_SEND
346 && ossl_quic_sstream_is_totally_acked(s
->sstream
))
347 shutdown_flush_done(qsm
, s
);
349 if (!s
->ready_for_gc
) {
350 s
->ready_for_gc
= qsm_ready_for_gc(qsm
, s
);
352 list_insert_tail(&qsm
->ready_for_gc_list
, &s
->ready_for_gc_node
);
356 = allowed_by_stream_limit
358 && ((ossl_quic_stream_has_recv(s
)
359 && !ossl_quic_stream_recv_is_reset(s
)
360 && (s
->recv_state
== QUIC_RSTREAM_STATE_RECV
361 && (s
->want_max_stream_data
362 || ossl_quic_rxfc_has_cwm_changed(&s
->rxfc
, 0))))
363 || s
->want_stop_sending
364 || s
->want_reset_stream
365 || (!s
->peer_stop_sending
&& stream_has_data_to_send(s
)));
367 if (should_be_active
)
368 stream_map_mark_active(qsm
, s
);
370 stream_map_mark_inactive(qsm
, s
);
374 * Stream Send Part State Management
375 * =================================
378 int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP
*qsm
,
381 switch (qs
->send_state
) {
382 case QUIC_SSTREAM_STATE_NONE
:
383 /* Stream without send part - caller error. */
386 case QUIC_SSTREAM_STATE_READY
:
388 * We always allocate a stream ID upfront, so we don't need to do it
391 qs
->send_state
= QUIC_SSTREAM_STATE_SEND
;
400 int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP
*qsm
,
403 switch (qs
->send_state
) {
405 /* Wrong state - caller error. */
406 case QUIC_SSTREAM_STATE_NONE
:
407 /* Stream without send part - caller error. */
410 case QUIC_SSTREAM_STATE_SEND
:
411 if (!ossl_quic_sstream_get_final_size(qs
->sstream
, &qs
->send_final_size
))
414 qs
->send_state
= QUIC_SSTREAM_STATE_DATA_SENT
;
419 static void shutdown_flush_done(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*qs
)
421 if (!qs
->shutdown_flush
)
424 assert(qsm
->num_shutdown_flush
> 0);
425 qs
->shutdown_flush
= 0;
426 --qsm
->num_shutdown_flush
;
429 int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP
*qsm
,
432 switch (qs
->send_state
) {
434 /* Wrong state - caller error. */
435 case QUIC_SSTREAM_STATE_NONE
:
436 /* Stream without send part - caller error. */
439 case QUIC_SSTREAM_STATE_DATA_SENT
:
440 qs
->send_state
= QUIC_SSTREAM_STATE_DATA_RECVD
;
441 /* We no longer need a QUIC_SSTREAM in this state. */
442 ossl_quic_sstream_free(qs
->sstream
);
445 shutdown_flush_done(qsm
, qs
);
450 int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP
*qsm
,
454 switch (qs
->send_state
) {
456 case QUIC_SSTREAM_STATE_NONE
:
458 * RESET_STREAM pertains to sending part only, so we cannot reset a
459 * receive-only stream.
461 case QUIC_SSTREAM_STATE_DATA_RECVD
:
463 * RFC 9000 s. 3.3: A sender MUST NOT [...] send RESET_STREAM from a
464 * terminal state. If the stream has already finished normally and the
465 * peer has acknowledged this, we cannot reset it.
469 case QUIC_SSTREAM_STATE_READY
:
470 if (!ossl_quic_stream_map_ensure_send_part_id(qsm
, qs
))
474 case QUIC_SSTREAM_STATE_SEND
:
476 * If we already have a final size (e.g. because we are coming from
477 * DATA_SENT), we have to be consistent with that, so don't change it.
478 * If we don't already have a final size, determine a final size value.
479 * This is the value which we will end up using for a RESET_STREAM frame
480 * for flow control purposes. We could send the stream size (total
481 * number of bytes appended to QUIC_SSTREAM by the application), but it
482 * is in our interest to exclude any bytes we have not actually
483 * transmitted yet, to avoid unnecessarily consuming flow control
484 * credit. We can get this from the TXFC.
486 qs
->send_final_size
= ossl_quic_txfc_get_swm(&qs
->txfc
);
489 case QUIC_SSTREAM_STATE_DATA_SENT
:
490 qs
->reset_stream_aec
= aec
;
491 qs
->want_reset_stream
= 1;
492 qs
->send_state
= QUIC_SSTREAM_STATE_RESET_SENT
;
494 ossl_quic_sstream_free(qs
->sstream
);
497 shutdown_flush_done(qsm
, qs
);
498 ossl_quic_stream_map_update_state(qsm
, qs
);
501 case QUIC_SSTREAM_STATE_RESET_SENT
:
502 case QUIC_SSTREAM_STATE_RESET_RECVD
:
504 * Idempotent - no-op. In any case, do not send RESET_STREAM again - as
505 * mentioned, we must not send it from a terminal state.
511 int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP
*qsm
,
514 switch (qs
->send_state
) {
516 /* Wrong state - caller error. */
517 case QUIC_SSTREAM_STATE_NONE
:
518 /* Stream without send part - caller error. */
521 case QUIC_SSTREAM_STATE_RESET_SENT
:
522 qs
->send_state
= QUIC_SSTREAM_STATE_RESET_RECVD
;
525 case QUIC_SSTREAM_STATE_RESET_RECVD
:
526 /* Already in the correct state. */
532 * Stream Receive Part State Management
533 * ====================================
536 int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP
*qsm
,
540 switch (qs
->recv_state
) {
542 /* Wrong state - caller error. */
543 case QUIC_RSTREAM_STATE_NONE
:
544 /* Stream without receive part - caller error. */
547 case QUIC_RSTREAM_STATE_RECV
:
548 qs
->recv_state
= QUIC_RSTREAM_STATE_SIZE_KNOWN
;
553 int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP
*qsm
,
556 switch (qs
->recv_state
) {
558 /* Wrong state - caller error. */
559 case QUIC_RSTREAM_STATE_NONE
:
560 /* Stream without receive part - caller error. */
563 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
564 qs
->recv_state
= QUIC_RSTREAM_STATE_DATA_RECVD
;
565 qs
->want_stop_sending
= 0;
570 int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP
*qsm
,
573 switch (qs
->recv_state
) {
575 /* Wrong state - caller error. */
576 case QUIC_RSTREAM_STATE_NONE
:
577 /* Stream without receive part - caller error. */
580 case QUIC_RSTREAM_STATE_DATA_RECVD
:
581 qs
->recv_state
= QUIC_RSTREAM_STATE_DATA_READ
;
583 /* QUIC_RSTREAM is no longer needed */
584 ossl_quic_rstream_free(qs
->rstream
);
590 int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP
*qsm
,
592 uint64_t app_error_code
,
595 uint64_t prev_final_size
;
597 switch (qs
->recv_state
) {
599 case QUIC_RSTREAM_STATE_NONE
:
600 /* Stream without receive part - caller error. */
603 case QUIC_RSTREAM_STATE_RECV
:
604 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
605 case QUIC_RSTREAM_STATE_DATA_RECVD
:
606 if (ossl_quic_stream_recv_get_final_size(qs
, &prev_final_size
)
607 && prev_final_size
!= final_size
)
608 /* Cannot change previous final size. */
611 qs
->recv_state
= QUIC_RSTREAM_STATE_RESET_RECVD
;
612 qs
->peer_reset_stream_aec
= app_error_code
;
614 /* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */
615 qs
->want_stop_sending
= 0;
617 /* QUIC_RSTREAM is no longer needed */
618 ossl_quic_rstream_free(qs
->rstream
);
621 ossl_quic_stream_map_update_state(qsm
, qs
);
624 case QUIC_RSTREAM_STATE_DATA_READ
:
626 * If we already retired the FIN to the application this is moot
629 case QUIC_RSTREAM_STATE_RESET_RECVD
:
630 case QUIC_RSTREAM_STATE_RESET_READ
:
631 /* Could be a reordered/retransmitted frame - just ignore. */
636 int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP
*qsm
,
639 switch (qs
->recv_state
) {
641 /* Wrong state - caller error. */
642 case QUIC_RSTREAM_STATE_NONE
:
643 /* Stream without receive part - caller error. */
646 case QUIC_RSTREAM_STATE_RESET_RECVD
:
647 qs
->recv_state
= QUIC_RSTREAM_STATE_RESET_READ
;
652 int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP
*qsm
,
656 if (qs
->stop_sending
)
659 switch (qs
->recv_state
) {
661 case QUIC_RSTREAM_STATE_NONE
:
662 /* Send-only stream, so this makes no sense. */
663 case QUIC_RSTREAM_STATE_DATA_RECVD
:
664 case QUIC_RSTREAM_STATE_DATA_READ
:
666 * Not really any point in STOP_SENDING if we already received all data.
668 case QUIC_RSTREAM_STATE_RESET_RECVD
:
669 case QUIC_RSTREAM_STATE_RESET_READ
:
671 * RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that
672 * has not been reset by the peer."
674 * No point in STOP_SENDING if the peer already reset their send part.
678 case QUIC_RSTREAM_STATE_RECV
:
679 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
681 * RFC 9000 s. 3.5: "If the stream is in the Recv or Size Known state,
682 * the transport SHOULD signal this by sending a STOP_SENDING frame to
683 * prompt closure of the stream in the opposite direction."
685 * Note that it does make sense to send STOP_SENDING for a receive part
686 * of a stream which has a known size (because we have received a FIN)
687 * but which still has other (previous) stream data yet to be received.
692 qs
->stop_sending
= 1;
693 qs
->stop_sending_aec
= aec
;
694 return ossl_quic_stream_map_schedule_stop_sending(qsm
, qs
);
697 /* Called to mark STOP_SENDING for generation, or regeneration after loss. */
698 int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*qs
)
700 if (!qs
->stop_sending
)
704 * Ignore the call as a no-op if already scheduled, or in a state
705 * where it makes no sense to send STOP_SENDING.
707 if (qs
->want_stop_sending
)
710 switch (qs
->recv_state
) {
712 return 1; /* ignore */
713 case QUIC_RSTREAM_STATE_RECV
:
714 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
716 * RFC 9000 s. 3.5: "An endpoint is expected to send another
717 * STOP_SENDING frame if a packet containing a previous STOP_SENDING is
718 * lost. However, once either all stream data or a RESET_STREAM frame
719 * has been received for the stream -- that is, the stream is in any
720 * state other than "Recv" or "Size Known" -- sending a STOP_SENDING
721 * frame is unnecessary."
726 qs
->want_stop_sending
= 1;
727 ossl_quic_stream_map_update_state(qsm
, qs
);
731 QUIC_STREAM
*ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP
*qsm
)
733 return accept_head(&qsm
->accept_list
);
736 void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP
*qsm
,
739 list_insert_tail(&qsm
->accept_list
, &s
->accept_node
);
743 static QUIC_RXFC
*qsm_get_max_streams_rxfc(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
745 return ossl_quic_stream_is_bidi(s
)
746 ? qsm
->max_streams_bidi_rxfc
747 : qsm
->max_streams_uni_rxfc
;
750 void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP
*qsm
,
754 QUIC_RXFC
*max_streams_rxfc
;
756 list_remove(&qsm
->accept_list
, &s
->accept_node
);
759 if ((max_streams_rxfc
= qsm_get_max_streams_rxfc(qsm
, s
)) != NULL
)
760 ossl_quic_rxfc_on_retire(max_streams_rxfc
, 1, rtt
);
763 size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP
*qsm
)
765 return qsm
->num_accept
;
768 void ossl_quic_stream_map_gc(QUIC_STREAM_MAP
*qsm
)
770 QUIC_STREAM
*qs
, *qs_head
, *qsn
= NULL
;
772 for (qs
= qs_head
= ready_for_gc_head(&qsm
->ready_for_gc_list
);
773 qs
!= NULL
&& qs
!= qs_head
;
776 qsn
= ready_for_gc_next(&qsm
->ready_for_gc_list
, qs
);
778 ossl_quic_stream_map_release(qsm
, qs
);
782 static int eligible_for_shutdown_flush(QUIC_STREAM
*qs
)
785 * We only care about servicing the send part of a stream (if any) during
786 * shutdown flush. We make sure we flush a stream if it is either
787 * non-terminated or was terminated normally such as via
788 * SSL_stream_conclude. A stream which was terminated via a reset is not
789 * flushed, and we will have thrown away the send buffer in that case
792 switch (qs
->send_state
) {
793 case QUIC_SSTREAM_STATE_SEND
:
794 case QUIC_SSTREAM_STATE_DATA_SENT
:
795 return !ossl_quic_sstream_is_totally_acked(qs
->sstream
);
801 static void begin_shutdown_flush_each(QUIC_STREAM
*qs
, void *arg
)
803 QUIC_STREAM_MAP
*qsm
= arg
;
805 if (!eligible_for_shutdown_flush(qs
) || qs
->shutdown_flush
)
808 qs
->shutdown_flush
= 1;
809 ++qsm
->num_shutdown_flush
;
812 void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP
*qsm
)
814 qsm
->num_shutdown_flush
= 0;
816 ossl_quic_stream_map_visit(qsm
, begin_shutdown_flush_each
, qsm
);
819 int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP
*qsm
)
821 return qsm
->num_shutdown_flush
== 0;
825 * QUIC Stream Iterator
826 * ====================
828 void ossl_quic_stream_iter_init(QUIC_STREAM_ITER
*it
, QUIC_STREAM_MAP
*qsm
,
832 it
->stream
= it
->first_stream
= qsm
->rr_cur
;
833 if (advance_rr
&& it
->stream
!= NULL
834 && ++qsm
->rr_counter
>= qsm
->rr_stepping
) {
836 qsm
->rr_cur
= active_next(&qsm
->active_list
, qsm
->rr_cur
);
840 void ossl_quic_stream_iter_next(QUIC_STREAM_ITER
*it
)
842 if (it
->stream
== NULL
)
845 it
->stream
= active_next(&it
->qsm
->active_list
, it
->stream
);
846 if (it
->stream
== it
->first_stream
)