Path: blob/main/crypto/openssl/ssl/quic/quic_stream_map.c
48266 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 ready_for_gc_next(l, s) list_next((l), &(s)->ready_for_gc_node, \69offsetof(QUIC_STREAM, ready_for_gc_node))70#define accept_head(l) list_next((l), (l), \71offsetof(QUIC_STREAM, accept_node))72#define ready_for_gc_head(l) list_next((l), (l), \73offsetof(QUIC_STREAM, ready_for_gc_node))7475static unsigned long hash_stream(const QUIC_STREAM *s)76{77return (unsigned long)s->id;78}7980static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)81{82if (a->id < b->id)83return -1;84if (a->id > b->id)85return 1;86return 0;87}8889int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,90uint64_t (*get_stream_limit_cb)(int uni, void *arg),91void *get_stream_limit_cb_arg,92QUIC_RXFC *max_streams_bidi_rxfc,93QUIC_RXFC *max_streams_uni_rxfc,94int is_server)95{96qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);97qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;98qsm->accept_list.prev = qsm->accept_list.next = &qsm->accept_list;99qsm->ready_for_gc_list.prev = qsm->ready_for_gc_list.next100= &qsm->ready_for_gc_list;101qsm->rr_stepping = 1;102qsm->rr_counter = 0;103qsm->rr_cur = NULL;104105qsm->num_accept_bidi = 0;106qsm->num_accept_uni = 0;107qsm->num_shutdown_flush = 0;108109qsm->get_stream_limit_cb = get_stream_limit_cb;110qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;111qsm->max_streams_bidi_rxfc = max_streams_bidi_rxfc;112qsm->max_streams_uni_rxfc = max_streams_uni_rxfc;113qsm->is_server = is_server;114return 1;115}116117static void release_each(QUIC_STREAM *stream, void *arg)118{119QUIC_STREAM_MAP *qsm = arg;120121ossl_quic_stream_map_release(qsm, stream);122}123124void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm)125{126ossl_quic_stream_map_visit(qsm, release_each, qsm);127128lh_QUIC_STREAM_free(qsm->map);129qsm->map = NULL;130}131132void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,133void (*visit_cb)(QUIC_STREAM *stream, void *arg),134void *visit_cb_arg)135{136lh_QUIC_STREAM_doall_arg(qsm->map, visit_cb, visit_cb_arg);137}138139QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,140uint64_t stream_id,141int type)142{143QUIC_STREAM *s;144QUIC_STREAM key;145146key.id = stream_id;147148s = lh_QUIC_STREAM_retrieve(qsm->map, &key);149if (s != NULL)150return NULL;151152s = OPENSSL_zalloc(sizeof(*s));153if (s == NULL)154return NULL;155156s->id = stream_id;157s->type = type;158s->as_server = qsm->is_server;159s->send_state = (ossl_quic_stream_is_local_init(s)160|| ossl_quic_stream_is_bidi(s))161? QUIC_SSTREAM_STATE_READY162: QUIC_SSTREAM_STATE_NONE;163s->recv_state = (!ossl_quic_stream_is_local_init(s)164|| ossl_quic_stream_is_bidi(s))165? QUIC_RSTREAM_STATE_RECV166: QUIC_RSTREAM_STATE_NONE;167168s->send_final_size = UINT64_MAX;169170lh_QUIC_STREAM_insert(qsm->map, s);171return s;172}173174void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream)175{176if (stream == NULL)177return;178179if (stream->active_node.next != NULL)180list_remove(&qsm->active_list, &stream->active_node);181if (stream->accept_node.next != NULL)182list_remove(&qsm->accept_list, &stream->accept_node);183if (stream->ready_for_gc_node.next != NULL)184list_remove(&qsm->ready_for_gc_list, &stream->ready_for_gc_node);185186ossl_quic_sstream_free(stream->sstream);187stream->sstream = NULL;188189ossl_quic_rstream_free(stream->rstream);190stream->rstream = NULL;191192lh_QUIC_STREAM_delete(qsm->map, stream);193OPENSSL_free(stream);194}195196QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,197uint64_t stream_id)198{199QUIC_STREAM key;200201key.id = stream_id;202203return lh_QUIC_STREAM_retrieve(qsm->map, &key);204}205206static void stream_map_mark_active(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)207{208if (s->active)209return;210211list_insert_tail(&qsm->active_list, &s->active_node);212213if (qsm->rr_cur == NULL)214qsm->rr_cur = s;215216s->active = 1;217}218219static void stream_map_mark_inactive(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)220{221if (!s->active)222return;223224if (qsm->rr_cur == s)225qsm->rr_cur = active_next(&qsm->active_list, s);226if (qsm->rr_cur == s)227qsm->rr_cur = NULL;228229list_remove(&qsm->active_list, &s->active_node);230231s->active = 0;232}233234void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping)235{236qsm->rr_stepping = stepping;237qsm->rr_counter = 0;238}239240static int stream_has_data_to_send(QUIC_STREAM *s)241{242OSSL_QUIC_FRAME_STREAM shdr;243OSSL_QTX_IOVEC iov[2];244size_t num_iov;245uint64_t fc_credit, fc_swm, fc_limit;246247switch (s->send_state) {248case QUIC_SSTREAM_STATE_READY:249case QUIC_SSTREAM_STATE_SEND:250case QUIC_SSTREAM_STATE_DATA_SENT:251/*252* We can still have data to send in DATA_SENT due to retransmissions,253* etc.254*/255break;256default:257return 0; /* Nothing to send. */258}259260/*261* We cannot determine if we have data to send simply by checking if262* ossl_quic_txfc_get_credit() is zero, because we may also have older263* 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 send265* against the TXFC CWM.266*/267num_iov = OSSL_NELEM(iov);268if (!ossl_quic_sstream_get_stream_frame(s->sstream, 0, &shdr, iov,269&num_iov))270return 0;271272fc_credit = ossl_quic_txfc_get_credit(&s->txfc, 0);273fc_swm = ossl_quic_txfc_get_swm(&s->txfc);274fc_limit = fc_swm + fc_credit;275276return (shdr.is_fin && shdr.len == 0) || shdr.offset < fc_limit;277}278279static ossl_unused int qsm_send_part_permits_gc(const QUIC_STREAM *qs)280{281switch (qs->send_state) {282case QUIC_SSTREAM_STATE_NONE:283case QUIC_SSTREAM_STATE_DATA_RECVD:284case QUIC_SSTREAM_STATE_RESET_RECVD:285return 1;286default:287return 0;288}289}290291static int qsm_ready_for_gc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)292{293int recv_stream_fully_drained = 0; /* TODO(QUIC FUTURE): Optimisation */294295/*296* If sstream has no FIN, we auto-reset it at marked-for-deletion time, so297* we don't need to worry about that here.298*/299assert(!qs->deleted300|| !ossl_quic_stream_has_send(qs)301|| ossl_quic_stream_send_is_reset(qs)302|| ossl_quic_stream_send_get_final_size(qs, NULL));303304return305qs->deleted306&& (!ossl_quic_stream_has_recv(qs)307|| recv_stream_fully_drained308|| qs->acked_stop_sending)309&& (!ossl_quic_stream_has_send(qs)310|| qs->send_state == QUIC_SSTREAM_STATE_DATA_RECVD311|| qs->send_state == QUIC_SSTREAM_STATE_RESET_RECVD);312}313314int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm,315uint64_t stream_ordinal,316int is_uni)317{318uint64_t stream_limit;319320if (qsm->get_stream_limit_cb == NULL)321return 1;322323stream_limit = qsm->get_stream_limit_cb(is_uni, qsm->get_stream_limit_cb_arg);324return stream_ordinal < stream_limit;325}326327void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)328{329int should_be_active, allowed_by_stream_limit = 1;330331if (ossl_quic_stream_is_server_init(s) == qsm->is_server) {332int is_uni = !ossl_quic_stream_is_bidi(s);333uint64_t stream_ordinal = s->id >> 2;334335allowed_by_stream_limit336= ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm,337stream_ordinal,338is_uni);339}340341if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT342&& ossl_quic_sstream_is_totally_acked(s->sstream))343ossl_quic_stream_map_notify_totally_acked(qsm, s);344else if (s->shutdown_flush345&& s->send_state == QUIC_SSTREAM_STATE_SEND346&& ossl_quic_sstream_is_totally_acked(s->sstream))347shutdown_flush_done(qsm, s);348349if (!s->ready_for_gc) {350s->ready_for_gc = qsm_ready_for_gc(qsm, s);351if (s->ready_for_gc)352list_insert_tail(&qsm->ready_for_gc_list, &s->ready_for_gc_node);353}354355should_be_active356= allowed_by_stream_limit357&& !s->ready_for_gc358&& ((ossl_quic_stream_has_recv(s)359&& !ossl_quic_stream_recv_is_reset(s)360&& (s->recv_state == QUIC_RSTREAM_STATE_RECV361&& (s->want_max_stream_data362|| ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))))363|| s->want_stop_sending364|| s->want_reset_stream365|| (!s->peer_stop_sending && stream_has_data_to_send(s)));366367if (should_be_active)368stream_map_mark_active(qsm, s);369else370stream_map_mark_inactive(qsm, s);371}372373/*374* Stream Send Part State Management375* =================================376*/377378int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm,379QUIC_STREAM *qs)380{381switch (qs->send_state) {382case QUIC_SSTREAM_STATE_NONE:383/* Stream without send part - caller error. */384return 0;385386case QUIC_SSTREAM_STATE_READY:387/*388* We always allocate a stream ID upfront, so we don't need to do it389* here.390*/391qs->send_state = QUIC_SSTREAM_STATE_SEND;392return 1;393394default:395/* Nothing to do. */396return 1;397}398}399400int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,401QUIC_STREAM *qs)402{403switch (qs->send_state) {404default:405/* Wrong state - caller error. */406case QUIC_SSTREAM_STATE_NONE:407/* Stream without send part - caller error. */408return 0;409410case QUIC_SSTREAM_STATE_SEND:411if (!ossl_quic_sstream_get_final_size(qs->sstream, &qs->send_final_size))412return 0;413414qs->send_state = QUIC_SSTREAM_STATE_DATA_SENT;415return 1;416}417}418419static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)420{421if (!qs->shutdown_flush)422return;423424assert(qsm->num_shutdown_flush > 0);425qs->shutdown_flush = 0;426--qsm->num_shutdown_flush;427}428429int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,430QUIC_STREAM *qs)431{432switch (qs->send_state) {433default:434/* Wrong state - caller error. */435case QUIC_SSTREAM_STATE_NONE:436/* Stream without send part - caller error. */437return 0;438439case QUIC_SSTREAM_STATE_DATA_SENT:440qs->send_state = QUIC_SSTREAM_STATE_DATA_RECVD;441/* We no longer need a QUIC_SSTREAM in this state. */442ossl_quic_sstream_free(qs->sstream);443qs->sstream = NULL;444445shutdown_flush_done(qsm, qs);446return 1;447}448}449450int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,451QUIC_STREAM *qs,452uint64_t aec)453{454switch (qs->send_state) {455default:456case QUIC_SSTREAM_STATE_NONE:457/*458* RESET_STREAM pertains to sending part only, so we cannot reset a459* receive-only stream.460*/461case QUIC_SSTREAM_STATE_DATA_RECVD:462/*463* RFC 9000 s. 3.3: A sender MUST NOT [...] send RESET_STREAM from a464* terminal state. If the stream has already finished normally and the465* peer has acknowledged this, we cannot reset it.466*/467return 0;468469case QUIC_SSTREAM_STATE_READY:470if (!ossl_quic_stream_map_ensure_send_part_id(qsm, qs))471return 0;472473/* FALLTHROUGH */474case QUIC_SSTREAM_STATE_SEND:475/*476* If we already have a final size (e.g. because we are coming from477* 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 frame480* for flow control purposes. We could send the stream size (total481* number of bytes appended to QUIC_SSTREAM by the application), but it482* is in our interest to exclude any bytes we have not actually483* transmitted yet, to avoid unnecessarily consuming flow control484* credit. We can get this from the TXFC.485*/486qs->send_final_size = ossl_quic_txfc_get_swm(&qs->txfc);487488/* FALLTHROUGH */489case QUIC_SSTREAM_STATE_DATA_SENT:490qs->reset_stream_aec = aec;491qs->want_reset_stream = 1;492qs->send_state = QUIC_SSTREAM_STATE_RESET_SENT;493494ossl_quic_sstream_free(qs->sstream);495qs->sstream = NULL;496497shutdown_flush_done(qsm, qs);498ossl_quic_stream_map_update_state(qsm, qs);499return 1;500501case QUIC_SSTREAM_STATE_RESET_SENT:502case QUIC_SSTREAM_STATE_RESET_RECVD:503/*504* Idempotent - no-op. In any case, do not send RESET_STREAM again - as505* mentioned, we must not send it from a terminal state.506*/507return 1;508}509}510511int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,512QUIC_STREAM *qs)513{514switch (qs->send_state) {515default:516/* Wrong state - caller error. */517case QUIC_SSTREAM_STATE_NONE:518/* Stream without send part - caller error. */519return 0;520521case QUIC_SSTREAM_STATE_RESET_SENT:522qs->send_state = QUIC_SSTREAM_STATE_RESET_RECVD;523return 1;524525case QUIC_SSTREAM_STATE_RESET_RECVD:526/* Already in the correct state. */527return 1;528}529}530531/*532* Stream Receive Part State Management533* ====================================534*/535536int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm,537QUIC_STREAM *qs,538uint64_t final_size)539{540switch (qs->recv_state) {541default:542/* Wrong state - caller error. */543case QUIC_RSTREAM_STATE_NONE:544/* Stream without receive part - caller error. */545return 0;546547case QUIC_RSTREAM_STATE_RECV:548qs->recv_state = QUIC_RSTREAM_STATE_SIZE_KNOWN;549return 1;550}551}552553int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,554QUIC_STREAM *qs)555{556switch (qs->recv_state) {557default:558/* Wrong state - caller error. */559case QUIC_RSTREAM_STATE_NONE:560/* Stream without receive part - caller error. */561return 0;562563case QUIC_RSTREAM_STATE_SIZE_KNOWN:564qs->recv_state = QUIC_RSTREAM_STATE_DATA_RECVD;565qs->want_stop_sending = 0;566return 1;567}568}569570int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,571QUIC_STREAM *qs)572{573switch (qs->recv_state) {574default:575/* Wrong state - caller error. */576case QUIC_RSTREAM_STATE_NONE:577/* Stream without receive part - caller error. */578return 0;579580case QUIC_RSTREAM_STATE_DATA_RECVD:581qs->recv_state = QUIC_RSTREAM_STATE_DATA_READ;582583/* QUIC_RSTREAM is no longer needed */584ossl_quic_rstream_free(qs->rstream);585qs->rstream = NULL;586return 1;587}588}589590int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,591QUIC_STREAM *qs,592uint64_t app_error_code,593uint64_t final_size)594{595uint64_t prev_final_size;596597switch (qs->recv_state) {598default:599case QUIC_RSTREAM_STATE_NONE:600/* Stream without receive part - caller error. */601return 0;602603case QUIC_RSTREAM_STATE_RECV:604case QUIC_RSTREAM_STATE_SIZE_KNOWN:605case QUIC_RSTREAM_STATE_DATA_RECVD:606if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size)607&& prev_final_size != final_size)608/* Cannot change previous final size. */609return 0;610611qs->recv_state = QUIC_RSTREAM_STATE_RESET_RECVD;612qs->peer_reset_stream_aec = app_error_code;613614/* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */615qs->want_stop_sending = 0;616617/* QUIC_RSTREAM is no longer needed */618ossl_quic_rstream_free(qs->rstream);619qs->rstream = NULL;620621ossl_quic_stream_map_update_state(qsm, qs);622return 1;623624case QUIC_RSTREAM_STATE_DATA_READ:625/*626* If we already retired the FIN to the application this is moot627* - just ignore.628*/629case QUIC_RSTREAM_STATE_RESET_RECVD:630case QUIC_RSTREAM_STATE_RESET_READ:631/* Could be a reordered/retransmitted frame - just ignore. */632return 1;633}634}635636int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,637QUIC_STREAM *qs)638{639switch (qs->recv_state) {640default:641/* Wrong state - caller error. */642case QUIC_RSTREAM_STATE_NONE:643/* Stream without receive part - caller error. */644return 0;645646case QUIC_RSTREAM_STATE_RESET_RECVD:647qs->recv_state = QUIC_RSTREAM_STATE_RESET_READ;648return 1;649}650}651652int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,653QUIC_STREAM *qs,654uint64_t aec)655{656if (qs->stop_sending)657return 0;658659switch (qs->recv_state) {660default:661case QUIC_RSTREAM_STATE_NONE:662/* Send-only stream, so this makes no sense. */663case QUIC_RSTREAM_STATE_DATA_RECVD:664case QUIC_RSTREAM_STATE_DATA_READ:665/*666* Not really any point in STOP_SENDING if we already received all data.667*/668case QUIC_RSTREAM_STATE_RESET_RECVD:669case QUIC_RSTREAM_STATE_RESET_READ:670/*671* RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that672* has not been reset by the peer."673*674* No point in STOP_SENDING if the peer already reset their send part.675*/676return 0;677678case QUIC_RSTREAM_STATE_RECV:679case QUIC_RSTREAM_STATE_SIZE_KNOWN:680/*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 to683* prompt closure of the stream in the opposite direction."684*685* Note that it does make sense to send STOP_SENDING for a receive part686* 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.688*/689break;690}691692qs->stop_sending = 1;693qs->stop_sending_aec = aec;694return ossl_quic_stream_map_schedule_stop_sending(qsm, qs);695}696697/* Called to mark STOP_SENDING for generation, or regeneration after loss. */698int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)699{700if (!qs->stop_sending)701return 0;702703/*704* Ignore the call as a no-op if already scheduled, or in a state705* where it makes no sense to send STOP_SENDING.706*/707if (qs->want_stop_sending)708return 1;709710switch (qs->recv_state) {711default:712return 1; /* ignore */713case QUIC_RSTREAM_STATE_RECV:714case QUIC_RSTREAM_STATE_SIZE_KNOWN:715/*716* RFC 9000 s. 3.5: "An endpoint is expected to send another717* STOP_SENDING frame if a packet containing a previous STOP_SENDING is718* lost. However, once either all stream data or a RESET_STREAM frame719* has been received for the stream -- that is, the stream is in any720* state other than "Recv" or "Size Known" -- sending a STOP_SENDING721* frame is unnecessary."722*/723break;724}725726qs->want_stop_sending = 1;727ossl_quic_stream_map_update_state(qsm, qs);728return 1;729}730731QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)732{733return accept_head(&qsm->accept_list);734}735736void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,737QUIC_STREAM *s)738{739list_insert_tail(&qsm->accept_list, &s->accept_node);740if (ossl_quic_stream_is_bidi(s))741++qsm->num_accept_bidi;742else743++qsm->num_accept_uni;744}745746static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)747{748return ossl_quic_stream_is_bidi(s)749? qsm->max_streams_bidi_rxfc750: qsm->max_streams_uni_rxfc;751}752753void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,754QUIC_STREAM *s,755OSSL_TIME rtt)756{757QUIC_RXFC *max_streams_rxfc;758759list_remove(&qsm->accept_list, &s->accept_node);760if (ossl_quic_stream_is_bidi(s))761--qsm->num_accept_bidi;762else763--qsm->num_accept_uni;764765if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL)766(void)ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt);767}768769size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni)770{771return is_uni ? qsm->num_accept_uni : qsm->num_accept_bidi;772}773774size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm)775{776return ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/0)777+ ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/1);778}779780void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm)781{782QUIC_STREAM *qs, *qs_head, *qsn = NULL;783784for (qs = qs_head = ready_for_gc_head(&qsm->ready_for_gc_list);785qs != NULL && qs != qs_head;786qs = qsn)787{788qsn = ready_for_gc_next(&qsm->ready_for_gc_list, qs);789790ossl_quic_stream_map_release(qsm, qs);791}792}793794static int eligible_for_shutdown_flush(QUIC_STREAM *qs)795{796/*797* We only care about servicing the send part of a stream (if any) during798* shutdown flush. We make sure we flush a stream if it is either799* non-terminated or was terminated normally such as via800* SSL_stream_conclude. A stream which was terminated via a reset is not801* flushed, and we will have thrown away the send buffer in that case802* anyway.803*/804switch (qs->send_state) {805case QUIC_SSTREAM_STATE_SEND:806case QUIC_SSTREAM_STATE_DATA_SENT:807return !ossl_quic_sstream_is_totally_acked(qs->sstream);808default:809return 0;810}811}812813static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg)814{815QUIC_STREAM_MAP *qsm = arg;816817if (!eligible_for_shutdown_flush(qs) || qs->shutdown_flush)818return;819820qs->shutdown_flush = 1;821++qsm->num_shutdown_flush;822}823824void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm)825{826qsm->num_shutdown_flush = 0;827828ossl_quic_stream_map_visit(qsm, begin_shutdown_flush_each, qsm);829}830831int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm)832{833return qsm->num_shutdown_flush == 0;834}835836/*837* QUIC Stream Iterator838* ====================839*/840void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,841int advance_rr)842{843it->qsm = qsm;844it->stream = it->first_stream = qsm->rr_cur;845if (advance_rr && it->stream != NULL846&& ++qsm->rr_counter >= qsm->rr_stepping) {847qsm->rr_counter = 0;848qsm->rr_cur = active_next(&qsm->active_list, qsm->rr_cur);849}850}851852void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it)853{854if (it->stream == NULL)855return;856857it->stream = active_next(&it->qsm->active_list, it->stream);858if (it->stream == it->first_stream)859it->stream = NULL;860}861862863