2 * Copyright 2022-2024 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;
106 qsm
->num_accept_bidi
= 0;
107 qsm
->num_accept_uni
= 0;
108 qsm
->num_shutdown_flush
= 0;
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
;
118 static void release_each(QUIC_STREAM
*stream
, void *arg
)
120 QUIC_STREAM_MAP
*qsm
= arg
;
122 ossl_quic_stream_map_release(qsm
, stream
);
125 void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP
*qsm
)
127 ossl_quic_stream_map_visit(qsm
, release_each
, qsm
);
129 lh_QUIC_STREAM_free(qsm
->map
);
133 void ossl_quic_stream_map_visit(QUIC_STREAM_MAP
*qsm
,
134 void (*visit_cb
)(QUIC_STREAM
*stream
, void *arg
),
137 lh_QUIC_STREAM_doall_arg(qsm
->map
, visit_cb
, visit_cb_arg
);
140 QUIC_STREAM
*ossl_quic_stream_map_alloc(QUIC_STREAM_MAP
*qsm
,
149 s
= lh_QUIC_STREAM_retrieve(qsm
->map
, &key
);
153 s
= OPENSSL_zalloc(sizeof(*s
));
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
;
169 s
->send_final_size
= UINT64_MAX
;
171 lh_QUIC_STREAM_insert(qsm
->map
, s
);
175 void ossl_quic_stream_map_release(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*stream
)
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
);
187 ossl_quic_sstream_free(stream
->sstream
);
188 stream
->sstream
= NULL
;
190 ossl_quic_rstream_free(stream
->rstream
);
191 stream
->rstream
= NULL
;
193 lh_QUIC_STREAM_delete(qsm
->map
, stream
);
194 OPENSSL_free(stream
);
197 QUIC_STREAM
*ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP
*qsm
,
204 return lh_QUIC_STREAM_retrieve(qsm
->map
, &key
);
207 static void stream_map_mark_active(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
212 list_insert_tail(&qsm
->active_list
, &s
->active_node
);
214 if (qsm
->rr_cur
== NULL
)
220 static void stream_map_mark_inactive(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
225 if (qsm
->rr_cur
== s
)
226 qsm
->rr_cur
= active_next(&qsm
->active_list
, s
);
227 if (qsm
->rr_cur
== s
)
230 list_remove(&qsm
->active_list
, &s
->active_node
);
235 void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP
*qsm
, size_t stepping
)
237 qsm
->rr_stepping
= stepping
;
241 static int stream_has_data_to_send(QUIC_STREAM
*s
)
243 OSSL_QUIC_FRAME_STREAM shdr
;
244 OSSL_QTX_IOVEC iov
[2];
246 uint64_t fc_credit
, fc_swm
, fc_limit
;
248 switch (s
->send_state
) {
249 case QUIC_SSTREAM_STATE_READY
:
250 case QUIC_SSTREAM_STATE_SEND
:
251 case QUIC_SSTREAM_STATE_DATA_SENT
:
253 * We can still have data to send in DATA_SENT due to retransmissions,
258 return 0; /* Nothing to send. */
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.
268 num_iov
= OSSL_NELEM(iov
);
269 if (!ossl_quic_sstream_get_stream_frame(s
->sstream
, 0, &shdr
, iov
,
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
;
277 return (shdr
.is_fin
&& shdr
.len
== 0) || shdr
.offset
< fc_limit
;
280 static ossl_unused
int qsm_send_part_permits_gc(const QUIC_STREAM
*qs
)
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
:
292 static int qsm_ready_for_gc(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*qs
)
294 int recv_stream_fully_drained
= 0; /* TODO(QUIC FUTURE): Optimisation */
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.
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
));
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
);
315 int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP
*qsm
,
316 uint64_t stream_ordinal
,
319 uint64_t stream_limit
;
321 if (qsm
->get_stream_limit_cb
== NULL
)
324 stream_limit
= qsm
->get_stream_limit_cb(is_uni
, qsm
->get_stream_limit_cb_arg
);
325 return stream_ordinal
< stream_limit
;
328 void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
330 int should_be_active
, allowed_by_stream_limit
= 1;
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;
336 allowed_by_stream_limit
337 = ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm
,
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
);
350 if (!s
->ready_for_gc
) {
351 s
->ready_for_gc
= qsm_ready_for_gc(qsm
, s
);
353 list_insert_tail(&qsm
->ready_for_gc_list
, &s
->ready_for_gc_node
);
357 = allowed_by_stream_limit
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
)));
368 if (should_be_active
)
369 stream_map_mark_active(qsm
, s
);
371 stream_map_mark_inactive(qsm
, s
);
375 * Stream Send Part State Management
376 * =================================
379 int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP
*qsm
,
382 switch (qs
->send_state
) {
383 case QUIC_SSTREAM_STATE_NONE
:
384 /* Stream without send part - caller error. */
387 case QUIC_SSTREAM_STATE_READY
:
389 * We always allocate a stream ID upfront, so we don't need to do it
392 qs
->send_state
= QUIC_SSTREAM_STATE_SEND
;
401 int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP
*qsm
,
404 switch (qs
->send_state
) {
406 /* Wrong state - caller error. */
407 case QUIC_SSTREAM_STATE_NONE
:
408 /* Stream without send part - caller error. */
411 case QUIC_SSTREAM_STATE_SEND
:
412 if (!ossl_quic_sstream_get_final_size(qs
->sstream
, &qs
->send_final_size
))
415 qs
->send_state
= QUIC_SSTREAM_STATE_DATA_SENT
;
420 static void shutdown_flush_done(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*qs
)
422 if (!qs
->shutdown_flush
)
425 assert(qsm
->num_shutdown_flush
> 0);
426 qs
->shutdown_flush
= 0;
427 --qsm
->num_shutdown_flush
;
430 int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP
*qsm
,
433 switch (qs
->send_state
) {
435 /* Wrong state - caller error. */
436 case QUIC_SSTREAM_STATE_NONE
:
437 /* Stream without send part - caller error. */
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
);
446 shutdown_flush_done(qsm
, qs
);
451 int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP
*qsm
,
455 switch (qs
->send_state
) {
457 case QUIC_SSTREAM_STATE_NONE
:
459 * RESET_STREAM pertains to sending part only, so we cannot reset a
460 * receive-only stream.
462 case QUIC_SSTREAM_STATE_DATA_RECVD
:
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.
470 case QUIC_SSTREAM_STATE_READY
:
471 if (!ossl_quic_stream_map_ensure_send_part_id(qsm
, qs
))
475 case QUIC_SSTREAM_STATE_SEND
:
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.
487 qs
->send_final_size
= ossl_quic_txfc_get_swm(&qs
->txfc
);
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
;
495 ossl_quic_sstream_free(qs
->sstream
);
498 shutdown_flush_done(qsm
, qs
);
499 ossl_quic_stream_map_update_state(qsm
, qs
);
502 case QUIC_SSTREAM_STATE_RESET_SENT
:
503 case QUIC_SSTREAM_STATE_RESET_RECVD
:
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.
512 int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP
*qsm
,
515 switch (qs
->send_state
) {
517 /* Wrong state - caller error. */
518 case QUIC_SSTREAM_STATE_NONE
:
519 /* Stream without send part - caller error. */
522 case QUIC_SSTREAM_STATE_RESET_SENT
:
523 qs
->send_state
= QUIC_SSTREAM_STATE_RESET_RECVD
;
526 case QUIC_SSTREAM_STATE_RESET_RECVD
:
527 /* Already in the correct state. */
533 * Stream Receive Part State Management
534 * ====================================
537 int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP
*qsm
,
541 switch (qs
->recv_state
) {
543 /* Wrong state - caller error. */
544 case QUIC_RSTREAM_STATE_NONE
:
545 /* Stream without receive part - caller error. */
548 case QUIC_RSTREAM_STATE_RECV
:
549 qs
->recv_state
= QUIC_RSTREAM_STATE_SIZE_KNOWN
;
554 int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP
*qsm
,
557 switch (qs
->recv_state
) {
559 /* Wrong state - caller error. */
560 case QUIC_RSTREAM_STATE_NONE
:
561 /* Stream without receive part - caller error. */
564 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
565 qs
->recv_state
= QUIC_RSTREAM_STATE_DATA_RECVD
;
566 qs
->want_stop_sending
= 0;
571 int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP
*qsm
,
574 switch (qs
->recv_state
) {
576 /* Wrong state - caller error. */
577 case QUIC_RSTREAM_STATE_NONE
:
578 /* Stream without receive part - caller error. */
581 case QUIC_RSTREAM_STATE_DATA_RECVD
:
582 qs
->recv_state
= QUIC_RSTREAM_STATE_DATA_READ
;
584 /* QUIC_RSTREAM is no longer needed */
585 ossl_quic_rstream_free(qs
->rstream
);
591 int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP
*qsm
,
593 uint64_t app_error_code
,
596 uint64_t prev_final_size
;
598 switch (qs
->recv_state
) {
600 case QUIC_RSTREAM_STATE_NONE
:
601 /* Stream without receive part - caller error. */
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. */
612 qs
->recv_state
= QUIC_RSTREAM_STATE_RESET_RECVD
;
613 qs
->peer_reset_stream_aec
= app_error_code
;
615 /* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */
616 qs
->want_stop_sending
= 0;
618 /* QUIC_RSTREAM is no longer needed */
619 ossl_quic_rstream_free(qs
->rstream
);
622 ossl_quic_stream_map_update_state(qsm
, qs
);
625 case QUIC_RSTREAM_STATE_DATA_READ
:
627 * If we already retired the FIN to the application this is moot
630 case QUIC_RSTREAM_STATE_RESET_RECVD
:
631 case QUIC_RSTREAM_STATE_RESET_READ
:
632 /* Could be a reordered/retransmitted frame - just ignore. */
637 int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP
*qsm
,
640 switch (qs
->recv_state
) {
642 /* Wrong state - caller error. */
643 case QUIC_RSTREAM_STATE_NONE
:
644 /* Stream without receive part - caller error. */
647 case QUIC_RSTREAM_STATE_RESET_RECVD
:
648 qs
->recv_state
= QUIC_RSTREAM_STATE_RESET_READ
;
653 int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP
*qsm
,
657 if (qs
->stop_sending
)
660 switch (qs
->recv_state
) {
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
:
667 * Not really any point in STOP_SENDING if we already received all data.
669 case QUIC_RSTREAM_STATE_RESET_RECVD
:
670 case QUIC_RSTREAM_STATE_RESET_READ
:
672 * RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that
673 * has not been reset by the peer."
675 * No point in STOP_SENDING if the peer already reset their send part.
679 case QUIC_RSTREAM_STATE_RECV
:
680 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
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."
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.
693 qs
->stop_sending
= 1;
694 qs
->stop_sending_aec
= aec
;
695 return ossl_quic_stream_map_schedule_stop_sending(qsm
, qs
);
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
)
701 if (!qs
->stop_sending
)
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.
708 if (qs
->want_stop_sending
)
711 switch (qs
->recv_state
) {
713 return 1; /* ignore */
714 case QUIC_RSTREAM_STATE_RECV
:
715 case QUIC_RSTREAM_STATE_SIZE_KNOWN
:
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."
727 qs
->want_stop_sending
= 1;
728 ossl_quic_stream_map_update_state(qsm
, qs
);
732 QUIC_STREAM
*ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP
*qsm
)
734 return accept_head(&qsm
->accept_list
);
737 void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP
*qsm
,
740 list_insert_tail(&qsm
->accept_list
, &s
->accept_node
);
741 if (ossl_quic_stream_is_bidi(s
))
742 ++qsm
->num_accept_bidi
;
744 ++qsm
->num_accept_uni
;
747 static QUIC_RXFC
*qsm_get_max_streams_rxfc(QUIC_STREAM_MAP
*qsm
, QUIC_STREAM
*s
)
749 return ossl_quic_stream_is_bidi(s
)
750 ? qsm
->max_streams_bidi_rxfc
751 : qsm
->max_streams_uni_rxfc
;
754 void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP
*qsm
,
758 QUIC_RXFC
*max_streams_rxfc
;
760 list_remove(&qsm
->accept_list
, &s
->accept_node
);
761 if (ossl_quic_stream_is_bidi(s
))
762 --qsm
->num_accept_bidi
;
764 --qsm
->num_accept_uni
;
766 if ((max_streams_rxfc
= qsm_get_max_streams_rxfc(qsm
, s
)) != NULL
)
767 ossl_quic_rxfc_on_retire(max_streams_rxfc
, 1, rtt
);
770 size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP
*qsm
, int is_uni
)
772 return is_uni
? qsm
->num_accept_uni
: qsm
->num_accept_bidi
;
775 size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP
*qsm
)
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);
781 void ossl_quic_stream_map_gc(QUIC_STREAM_MAP
*qsm
)
783 QUIC_STREAM
*qs
, *qs_head
, *qsn
= NULL
;
785 for (qs
= qs_head
= ready_for_gc_head(&qsm
->ready_for_gc_list
);
786 qs
!= NULL
&& qs
!= qs_head
;
789 qsn
= ready_for_gc_next(&qsm
->ready_for_gc_list
, qs
);
791 ossl_quic_stream_map_release(qsm
, qs
);
795 static int eligible_for_shutdown_flush(QUIC_STREAM
*qs
)
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
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
);
814 static void begin_shutdown_flush_each(QUIC_STREAM
*qs
, void *arg
)
816 QUIC_STREAM_MAP
*qsm
= arg
;
818 if (!eligible_for_shutdown_flush(qs
) || qs
->shutdown_flush
)
821 qs
->shutdown_flush
= 1;
822 ++qsm
->num_shutdown_flush
;
825 void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP
*qsm
)
827 qsm
->num_shutdown_flush
= 0;
829 ossl_quic_stream_map_visit(qsm
, begin_shutdown_flush_each
, qsm
);
832 int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP
*qsm
)
834 return qsm
->num_shutdown_flush
== 0;
838 * QUIC Stream Iterator
839 * ====================
841 void ossl_quic_stream_iter_init(QUIC_STREAM_ITER
*it
, QUIC_STREAM_MAP
*qsm
,
845 it
->stream
= it
->first_stream
= qsm
->rr_cur
;
846 if (advance_rr
&& it
->stream
!= NULL
847 && ++qsm
->rr_counter
>= qsm
->rr_stepping
) {
849 qsm
->rr_cur
= active_next(&qsm
->active_list
, qsm
->rr_cur
);
853 void ossl_quic_stream_iter_next(QUIC_STREAM_ITER
*it
)
855 if (it
->stream
== NULL
)
858 it
->stream
= active_next(&it
->qsm
->active_list
, it
->stream
);
859 if (it
->stream
== it
->first_stream
)