Path: blob/main/crypto/openssl/ssl/quic/quic_stream_map.c
101184 views
/*1* Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include "internal/quic_stream_map.h"10#include "internal/nelem.h"1112/*13* QUIC Stream Map14* ===============15*/16DEFINE_LHASH_OF_EX(QUIC_STREAM);1718static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs);1920/* Circular list management. */21static void list_insert_tail(QUIC_STREAM_LIST_NODE *l,22QUIC_STREAM_LIST_NODE *n)23{24/* Must not be in list. */25assert(n->prev == NULL && n->next == NULL26&& l->prev != NULL && l->next != NULL);2728n->prev = l->prev;29n->prev->next = n;30l->prev = n;31n->next = l;32}3334static void list_remove(QUIC_STREAM_LIST_NODE *l,35QUIC_STREAM_LIST_NODE *n)36{37assert(n->prev != NULL && n->next != NULL38&& n->prev != n && n->next != n);3940n->prev->next = n->next;41n->next->prev = n->prev;42n->next = n->prev = NULL;43}4445static QUIC_STREAM *list_next(QUIC_STREAM_LIST_NODE *l, QUIC_STREAM_LIST_NODE *n,46size_t off)47{48assert(n->prev != NULL && n->next != NULL49&& (n == l || (n->prev != n && n->next != n))50&& l->prev != NULL && l->next != NULL);5152n = n->next;5354if (n == l)55n = n->next;56if (n == l)57return NULL;5859assert(n != NULL);6061return (QUIC_STREAM *)(((char *)n) - off);62}6364#define active_next(l, s) list_next((l), &(s)->active_node, \65offsetof(QUIC_STREAM, active_node))66#define accept_next(l, s) list_next((l), &(s)->accept_node, \67offsetof(QUIC_STREAM, accept_node))68#define accept_head(l) list_next((l), (l), \69offsetof(QUIC_STREAM, accept_node))70#define ready_for_gc_head(l) list_next((l), (l), \71offsetof(QUIC_STREAM, ready_for_gc_node))7273static unsigned long hash_stream(const QUIC_STREAM *s)74{75return (unsigned long)s->id;76}7778static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)79{80if (a->id < b->id)81return -1;82if (a->id > b->id)83return 1;84return 0;85}8687int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,88uint64_t (*get_stream_limit_cb)(int uni, void *arg),89void *get_stream_limit_cb_arg,90QUIC_RXFC *max_streams_bidi_rxfc,91QUIC_RXFC *max_streams_uni_rxfc,92int is_server)93{94qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);95qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;96qsm->accept_list.prev = qsm->accept_list.next = &qsm->accept_list;97qsm->ready_for_gc_list.prev = qsm->ready_for_gc_list.next98= &qsm->ready_for_gc_list;99qsm->rr_stepping = 1;100qsm->rr_counter = 0;101qsm->rr_cur = NULL;102103qsm->num_accept_bidi = 0;104qsm->num_accept_uni = 0;105qsm->num_shutdown_flush = 0;106107qsm->get_stream_limit_cb = get_stream_limit_cb;108qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;109qsm->max_streams_bidi_rxfc = max_streams_bidi_rxfc;110qsm->max_streams_uni_rxfc = max_streams_uni_rxfc;111qsm->is_server = is_server;112return 1;113}114115static void release_each(QUIC_STREAM *stream, void *arg)116{117QUIC_STREAM_MAP *qsm = arg;118119ossl_quic_stream_map_release(qsm, stream);120}121122void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm)123{124ossl_quic_stream_map_visit(qsm, release_each, qsm);125126lh_QUIC_STREAM_free(qsm->map);127qsm->map = NULL;128}129130void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,131void (*visit_cb)(QUIC_STREAM *stream, void *arg),132void *visit_cb_arg)133{134lh_QUIC_STREAM_doall_arg(qsm->map, visit_cb, visit_cb_arg);135}136137QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,138uint64_t stream_id,139int type)140{141QUIC_STREAM *s;142QUIC_STREAM key;143144key.id = stream_id;145146s = lh_QUIC_STREAM_retrieve(qsm->map, &key);147if (s != NULL)148return NULL;149150s = OPENSSL_zalloc(sizeof(*s));151if (s == NULL)152return NULL;153154s->id = stream_id;155s->type = type;156s->as_server = qsm->is_server;157s->send_state = (ossl_quic_stream_is_local_init(s)158|| ossl_quic_stream_is_bidi(s))159? QUIC_SSTREAM_STATE_READY160: QUIC_SSTREAM_STATE_NONE;161s->recv_state = (!ossl_quic_stream_is_local_init(s)162|| ossl_quic_stream_is_bidi(s))163? QUIC_RSTREAM_STATE_RECV164: QUIC_RSTREAM_STATE_NONE;165166s->send_final_size = UINT64_MAX;167168lh_QUIC_STREAM_insert(qsm->map, s);169return s;170}171172void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream)173{174if (stream == NULL)175return;176177if (stream->active_node.next != NULL)178list_remove(&qsm->active_list, &stream->active_node);179if (stream->accept_node.next != NULL)180list_remove(&qsm->accept_list, &stream->accept_node);181if (stream->ready_for_gc_node.next != NULL)182list_remove(&qsm->ready_for_gc_list, &stream->ready_for_gc_node);183184ossl_quic_sstream_free(stream->sstream);185stream->sstream = NULL;186187ossl_quic_rstream_free(stream->rstream);188stream->rstream = NULL;189190lh_QUIC_STREAM_delete(qsm->map, stream);191OPENSSL_free(stream);192}193194QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,195uint64_t stream_id)196{197QUIC_STREAM key;198199key.id = stream_id;200201return lh_QUIC_STREAM_retrieve(qsm->map, &key);202}203204static void stream_map_mark_active(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)205{206if (s->active)207return;208209list_insert_tail(&qsm->active_list, &s->active_node);210211if (qsm->rr_cur == NULL)212qsm->rr_cur = s;213214s->active = 1;215}216217static void stream_map_mark_inactive(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)218{219if (!s->active)220return;221222if (qsm->rr_cur == s)223qsm->rr_cur = active_next(&qsm->active_list, s);224if (qsm->rr_cur == s)225qsm->rr_cur = NULL;226227list_remove(&qsm->active_list, &s->active_node);228229s->active = 0;230}231232void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping)233{234qsm->rr_stepping = stepping;235qsm->rr_counter = 0;236}237238static int stream_has_data_to_send(QUIC_STREAM *s)239{240OSSL_QUIC_FRAME_STREAM shdr;241OSSL_QTX_IOVEC iov[2];242size_t num_iov;243uint64_t fc_credit, fc_swm, fc_limit;244245switch (s->send_state) {246case QUIC_SSTREAM_STATE_READY:247case QUIC_SSTREAM_STATE_SEND:248case QUIC_SSTREAM_STATE_DATA_SENT:249/*250* We can still have data to send in DATA_SENT due to retransmissions,251* etc.252*/253break;254default:255return 0; /* Nothing to send. */256}257258/*259* We cannot determine if we have data to send simply by checking if260* ossl_quic_txfc_get_credit() is zero, because we may also have older261* stream data we need to retransmit. The SSTREAM returns older data first,262* so we do a simple comparison of the next chunk the SSTREAM wants to send263* against the TXFC CWM.264*/265num_iov = OSSL_NELEM(iov);266if (!ossl_quic_sstream_get_stream_frame(s->sstream, 0, &shdr, iov,267&num_iov))268return 0;269270fc_credit = ossl_quic_txfc_get_credit(&s->txfc, 0);271fc_swm = ossl_quic_txfc_get_swm(&s->txfc);272fc_limit = fc_swm + fc_credit;273274return (shdr.is_fin && shdr.len == 0) || shdr.offset < fc_limit;275}276277static ossl_unused int qsm_send_part_permits_gc(const QUIC_STREAM *qs)278{279switch (qs->send_state) {280case QUIC_SSTREAM_STATE_NONE:281case QUIC_SSTREAM_STATE_DATA_RECVD:282case QUIC_SSTREAM_STATE_RESET_RECVD:283return 1;284default:285return 0;286}287}288289static int qsm_ready_for_gc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)290{291int recv_stream_fully_drained = 0; /* TODO(QUIC FUTURE): Optimisation */292293/*294* If sstream has no FIN, we auto-reset it at marked-for-deletion time, so295* we don't need to worry about that here.296*/297assert(!qs->deleted298|| !ossl_quic_stream_has_send(qs)299|| ossl_quic_stream_send_is_reset(qs)300|| ossl_quic_stream_send_get_final_size(qs, NULL));301302return qs->deleted303&& (!ossl_quic_stream_has_recv(qs)304|| recv_stream_fully_drained305|| qs->acked_stop_sending)306&& (!ossl_quic_stream_has_send(qs)307|| qs->send_state == QUIC_SSTREAM_STATE_DATA_RECVD308|| qs->send_state == QUIC_SSTREAM_STATE_RESET_RECVD);309}310311int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm,312uint64_t stream_ordinal,313int is_uni)314{315uint64_t stream_limit;316317if (qsm->get_stream_limit_cb == NULL)318return 1;319320stream_limit = qsm->get_stream_limit_cb(is_uni, qsm->get_stream_limit_cb_arg);321return stream_ordinal < stream_limit;322}323324void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)325{326int should_be_active, allowed_by_stream_limit = 1;327328if (ossl_quic_stream_is_server_init(s) == qsm->is_server) {329int is_uni = !ossl_quic_stream_is_bidi(s);330uint64_t stream_ordinal = s->id >> 2;331332allowed_by_stream_limit333= ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm,334stream_ordinal,335is_uni);336}337338if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT339&& ossl_quic_sstream_is_totally_acked(s->sstream))340ossl_quic_stream_map_notify_totally_acked(qsm, s);341else if (s->shutdown_flush342&& s->send_state == QUIC_SSTREAM_STATE_SEND343&& ossl_quic_sstream_is_totally_acked(s->sstream))344shutdown_flush_done(qsm, s);345346if (!s->ready_for_gc) {347s->ready_for_gc = qsm_ready_for_gc(qsm, s);348if (s->ready_for_gc)349list_insert_tail(&qsm->ready_for_gc_list, &s->ready_for_gc_node);350}351352should_be_active353= allowed_by_stream_limit354&& !s->ready_for_gc355&& ((ossl_quic_stream_has_recv(s)356&& !ossl_quic_stream_recv_is_reset(s)357&& (s->recv_state == QUIC_RSTREAM_STATE_RECV358&& (s->want_max_stream_data359|| ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))))360|| s->want_stop_sending361|| s->want_reset_stream362|| (!s->peer_stop_sending && stream_has_data_to_send(s)));363364if (should_be_active)365stream_map_mark_active(qsm, s);366else367stream_map_mark_inactive(qsm, s);368}369370/*371* Stream Send Part State Management372* =================================373*/374375int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm,376QUIC_STREAM *qs)377{378switch (qs->send_state) {379case QUIC_SSTREAM_STATE_NONE:380/* Stream without send part - caller error. */381return 0;382383case QUIC_SSTREAM_STATE_READY:384/*385* We always allocate a stream ID upfront, so we don't need to do it386* here.387*/388qs->send_state = QUIC_SSTREAM_STATE_SEND;389return 1;390391default:392/* Nothing to do. */393return 1;394}395}396397int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,398QUIC_STREAM *qs)399{400switch (qs->send_state) {401default:402/* Wrong state - caller error. */403case QUIC_SSTREAM_STATE_NONE:404/* Stream without send part - caller error. */405return 0;406407case QUIC_SSTREAM_STATE_SEND:408if (!ossl_quic_sstream_get_final_size(qs->sstream, &qs->send_final_size))409return 0;410411qs->send_state = QUIC_SSTREAM_STATE_DATA_SENT;412return 1;413}414}415416static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)417{418if (!qs->shutdown_flush)419return;420421assert(qsm->num_shutdown_flush > 0);422qs->shutdown_flush = 0;423--qsm->num_shutdown_flush;424}425426int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,427QUIC_STREAM *qs)428{429switch (qs->send_state) {430default:431/* Wrong state - caller error. */432case QUIC_SSTREAM_STATE_NONE:433/* Stream without send part - caller error. */434return 0;435436case QUIC_SSTREAM_STATE_DATA_SENT:437qs->send_state = QUIC_SSTREAM_STATE_DATA_RECVD;438/* We no longer need a QUIC_SSTREAM in this state. */439ossl_quic_sstream_free(qs->sstream);440qs->sstream = NULL;441442shutdown_flush_done(qsm, qs);443return 1;444}445}446447int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,448QUIC_STREAM *qs,449uint64_t aec)450{451switch (qs->send_state) {452default:453case QUIC_SSTREAM_STATE_NONE:454/*455* RESET_STREAM pertains to sending part only, so we cannot reset a456* receive-only stream.457*/458case QUIC_SSTREAM_STATE_DATA_RECVD:459/*460* RFC 9000 s. 3.3: A sender MUST NOT [...] send RESET_STREAM from a461* terminal state. If the stream has already finished normally and the462* peer has acknowledged this, we cannot reset it.463*/464return 0;465466case QUIC_SSTREAM_STATE_READY:467if (!ossl_quic_stream_map_ensure_send_part_id(qsm, qs))468return 0;469470/* FALLTHROUGH */471case QUIC_SSTREAM_STATE_SEND:472/*473* If we already have a final size (e.g. because we are coming from474* DATA_SENT), we have to be consistent with that, so don't change it.475* If we don't already have a final size, determine a final size value.476* This is the value which we will end up using for a RESET_STREAM frame477* for flow control purposes. We could send the stream size (total478* number of bytes appended to QUIC_SSTREAM by the application), but it479* is in our interest to exclude any bytes we have not actually480* transmitted yet, to avoid unnecessarily consuming flow control481* credit. We can get this from the TXFC.482*/483qs->send_final_size = ossl_quic_txfc_get_swm(&qs->txfc);484485/* FALLTHROUGH */486case QUIC_SSTREAM_STATE_DATA_SENT:487qs->reset_stream_aec = aec;488qs->want_reset_stream = 1;489qs->send_state = QUIC_SSTREAM_STATE_RESET_SENT;490491ossl_quic_sstream_free(qs->sstream);492qs->sstream = NULL;493494shutdown_flush_done(qsm, qs);495ossl_quic_stream_map_update_state(qsm, qs);496return 1;497498case QUIC_SSTREAM_STATE_RESET_SENT:499case QUIC_SSTREAM_STATE_RESET_RECVD:500/*501* Idempotent - no-op. In any case, do not send RESET_STREAM again - as502* mentioned, we must not send it from a terminal state.503*/504return 1;505}506}507508int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,509QUIC_STREAM *qs)510{511switch (qs->send_state) {512default:513/* Wrong state - caller error. */514case QUIC_SSTREAM_STATE_NONE:515/* Stream without send part - caller error. */516return 0;517518case QUIC_SSTREAM_STATE_RESET_SENT:519qs->send_state = QUIC_SSTREAM_STATE_RESET_RECVD;520return 1;521522case QUIC_SSTREAM_STATE_RESET_RECVD:523/* Already in the correct state. */524return 1;525}526}527528/*529* Stream Receive Part State Management530* ====================================531*/532533int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm,534QUIC_STREAM *qs,535uint64_t final_size)536{537switch (qs->recv_state) {538default:539/* Wrong state - caller error. */540case QUIC_RSTREAM_STATE_NONE:541/* Stream without receive part - caller error. */542return 0;543544case QUIC_RSTREAM_STATE_RECV:545qs->recv_state = QUIC_RSTREAM_STATE_SIZE_KNOWN;546return 1;547}548}549550int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,551QUIC_STREAM *qs)552{553switch (qs->recv_state) {554default:555/* Wrong state - caller error. */556case QUIC_RSTREAM_STATE_NONE:557/* Stream without receive part - caller error. */558return 0;559560case QUIC_RSTREAM_STATE_SIZE_KNOWN:561qs->recv_state = QUIC_RSTREAM_STATE_DATA_RECVD;562qs->want_stop_sending = 0;563return 1;564}565}566567int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,568QUIC_STREAM *qs)569{570switch (qs->recv_state) {571default:572/* Wrong state - caller error. */573case QUIC_RSTREAM_STATE_NONE:574/* Stream without receive part - caller error. */575return 0;576577case QUIC_RSTREAM_STATE_DATA_RECVD:578qs->recv_state = QUIC_RSTREAM_STATE_DATA_READ;579580/* QUIC_RSTREAM is no longer needed */581ossl_quic_rstream_free(qs->rstream);582qs->rstream = NULL;583return 1;584}585}586587int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,588QUIC_STREAM *qs,589uint64_t app_error_code,590uint64_t final_size)591{592uint64_t prev_final_size;593594switch (qs->recv_state) {595default:596case QUIC_RSTREAM_STATE_NONE:597/* Stream without receive part - caller error. */598return 0;599600case QUIC_RSTREAM_STATE_RECV:601case QUIC_RSTREAM_STATE_SIZE_KNOWN:602case QUIC_RSTREAM_STATE_DATA_RECVD:603if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size)604&& prev_final_size != final_size)605/* Cannot change previous final size. */606return 0;607608qs->recv_state = QUIC_RSTREAM_STATE_RESET_RECVD;609qs->peer_reset_stream_aec = app_error_code;610611/* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */612qs->want_stop_sending = 0;613614/* QUIC_RSTREAM is no longer needed */615ossl_quic_rstream_free(qs->rstream);616qs->rstream = NULL;617618ossl_quic_stream_map_update_state(qsm, qs);619return 1;620621case QUIC_RSTREAM_STATE_DATA_READ:622/*623* If we already retired the FIN to the application this is moot624* - just ignore.625*/626case QUIC_RSTREAM_STATE_RESET_RECVD:627case QUIC_RSTREAM_STATE_RESET_READ:628/* Could be a reordered/retransmitted frame - just ignore. */629return 1;630}631}632633int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,634QUIC_STREAM *qs)635{636switch (qs->recv_state) {637default:638/* Wrong state - caller error. */639case QUIC_RSTREAM_STATE_NONE:640/* Stream without receive part - caller error. */641return 0;642643case QUIC_RSTREAM_STATE_RESET_RECVD:644qs->recv_state = QUIC_RSTREAM_STATE_RESET_READ;645return 1;646}647}648649int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,650QUIC_STREAM *qs,651uint64_t aec)652{653if (qs->stop_sending)654return 0;655656switch (qs->recv_state) {657default:658case QUIC_RSTREAM_STATE_NONE:659/* Send-only stream, so this makes no sense. */660case QUIC_RSTREAM_STATE_DATA_RECVD:661case QUIC_RSTREAM_STATE_DATA_READ:662/*663* Not really any point in STOP_SENDING if we already received all data.664*/665case QUIC_RSTREAM_STATE_RESET_RECVD:666case QUIC_RSTREAM_STATE_RESET_READ:667/*668* RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that669* has not been reset by the peer."670*671* No point in STOP_SENDING if the peer already reset their send part.672*/673return 0;674675case QUIC_RSTREAM_STATE_RECV:676case QUIC_RSTREAM_STATE_SIZE_KNOWN:677/*678* RFC 9000 s. 3.5: "If the stream is in the Recv or Size Known state,679* the transport SHOULD signal this by sending a STOP_SENDING frame to680* prompt closure of the stream in the opposite direction."681*682* Note that it does make sense to send STOP_SENDING for a receive part683* of a stream which has a known size (because we have received a FIN)684* but which still has other (previous) stream data yet to be received.685*/686break;687}688689qs->stop_sending = 1;690qs->stop_sending_aec = aec;691return ossl_quic_stream_map_schedule_stop_sending(qsm, qs);692}693694/* Called to mark STOP_SENDING for generation, or regeneration after loss. */695int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)696{697if (!qs->stop_sending)698return 0;699700/*701* Ignore the call as a no-op if already scheduled, or in a state702* where it makes no sense to send STOP_SENDING.703*/704if (qs->want_stop_sending)705return 1;706707switch (qs->recv_state) {708default:709return 1; /* ignore */710case QUIC_RSTREAM_STATE_RECV:711case QUIC_RSTREAM_STATE_SIZE_KNOWN:712/*713* RFC 9000 s. 3.5: "An endpoint is expected to send another714* STOP_SENDING frame if a packet containing a previous STOP_SENDING is715* lost. However, once either all stream data or a RESET_STREAM frame716* has been received for the stream -- that is, the stream is in any717* state other than "Recv" or "Size Known" -- sending a STOP_SENDING718* frame is unnecessary."719*/720break;721}722723qs->want_stop_sending = 1;724ossl_quic_stream_map_update_state(qsm, qs);725return 1;726}727728QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)729{730return accept_head(&qsm->accept_list);731}732733void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,734QUIC_STREAM *s)735{736list_insert_tail(&qsm->accept_list, &s->accept_node);737if (ossl_quic_stream_is_bidi(s))738++qsm->num_accept_bidi;739else740++qsm->num_accept_uni;741}742743static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)744{745return ossl_quic_stream_is_bidi(s)746? qsm->max_streams_bidi_rxfc747: qsm->max_streams_uni_rxfc;748}749750void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,751QUIC_STREAM *s,752OSSL_TIME rtt)753{754QUIC_RXFC *max_streams_rxfc;755756list_remove(&qsm->accept_list, &s->accept_node);757if (ossl_quic_stream_is_bidi(s))758--qsm->num_accept_bidi;759else760--qsm->num_accept_uni;761762if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL)763(void)ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt);764}765766size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni)767{768return is_uni ? qsm->num_accept_uni : qsm->num_accept_bidi;769}770771size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm)772{773return ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/0)774+ ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/1);775}776777void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm)778{779QUIC_STREAM *qs;780781while ((qs = ready_for_gc_head(&qsm->ready_for_gc_list)) != NULL) {782ossl_quic_stream_map_release(qsm, qs);783}784}785786static int eligible_for_shutdown_flush(QUIC_STREAM *qs)787{788/*789* We only care about servicing the send part of a stream (if any) during790* shutdown flush. We make sure we flush a stream if it is either791* non-terminated or was terminated normally such as via792* SSL_stream_conclude. A stream which was terminated via a reset is not793* flushed, and we will have thrown away the send buffer in that case794* anyway.795*/796switch (qs->send_state) {797case QUIC_SSTREAM_STATE_SEND:798case QUIC_SSTREAM_STATE_DATA_SENT:799return !ossl_quic_sstream_is_totally_acked(qs->sstream);800default:801return 0;802}803}804805static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg)806{807QUIC_STREAM_MAP *qsm = arg;808809if (!eligible_for_shutdown_flush(qs) || qs->shutdown_flush)810return;811812qs->shutdown_flush = 1;813++qsm->num_shutdown_flush;814}815816void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm)817{818qsm->num_shutdown_flush = 0;819820ossl_quic_stream_map_visit(qsm, begin_shutdown_flush_each, qsm);821}822823int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm)824{825return qsm->num_shutdown_flush == 0;826}827828/*829* QUIC Stream Iterator830* ====================831*/832void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,833int advance_rr)834{835it->qsm = qsm;836it->stream = it->first_stream = qsm->rr_cur;837if (advance_rr && it->stream != NULL838&& ++qsm->rr_counter >= qsm->rr_stepping) {839qsm->rr_counter = 0;840qsm->rr_cur = active_next(&qsm->active_list, qsm->rr_cur);841}842}843844void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it)845{846if (it->stream == NULL)847return;848849it->stream = active_next(&it->qsm->active_list, it->stream);850if (it->stream == it->first_stream)851it->stream = NULL;852}853854855