| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 | 
							- /*
 
- * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
 
- *
 
- * Licensed under the Apache License 2.0 (the "License").  You may not use
 
- * this file except in compliance with the License.  You can obtain a copy
 
- * in the file LICENSE in the source distribution or at
 
- * https://www.openssl.org/source/license.html
 
- */
 
- #ifndef OSSL_INTERNAL_QUIC_STREAM_MAP_H
 
- # define OSSL_INTERNAL_QUIC_STREAM_MAP_H
 
- # pragma once
 
- # include "internal/e_os.h"
 
- # include "internal/time.h"
 
- # include "internal/common.h"
 
- # include "internal/quic_types.h"
 
- # include "internal/quic_predef.h"
 
- # include "internal/quic_stream.h"
 
- # include "internal/quic_fc.h"
 
- # include <openssl/lhash.h>
 
- # ifndef OPENSSL_NO_QUIC
 
- /*
 
-  * QUIC Stream
 
-  * ===========
 
-  *
 
-  * Logical QUIC stream composing all relevant send and receive components.
 
-  */
 
- typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE;
 
- struct quic_stream_list_node_st {
 
-     QUIC_STREAM_LIST_NODE *prev, *next;
 
- };
 
- /*
 
-  * QUIC Send Stream States
 
-  * -----------------------
 
-  *
 
-  * These correspond to the states defined in RFC 9000 s. 3.1, with the
 
-  * exception of the NONE state which represents the absence of a send stream
 
-  * part.
 
-  *
 
-  * Invariants in each state are noted in comments below. In particular, once all
 
-  * data has been acknowledged received, or we have reset the stream, we don't
 
-  * need to keep the QUIC_SSTREAM and data buffers around. Of course, we also
 
-  * don't have a QUIC_SSTREAM on a receive-only stream.
 
-  */
 
- #define QUIC_SSTREAM_STATE_NONE         0   /* --- sstream == NULL  */
 
- #define QUIC_SSTREAM_STATE_READY        1   /* \                    */
 
- #define QUIC_SSTREAM_STATE_SEND         2   /* |-- sstream != NULL  */
 
- #define QUIC_SSTREAM_STATE_DATA_SENT    3   /* /                    */
 
- #define QUIC_SSTREAM_STATE_DATA_RECVD   4   /* \                    */
 
- #define QUIC_SSTREAM_STATE_RESET_SENT   5   /* |-- sstream == NULL  */
 
- #define QUIC_SSTREAM_STATE_RESET_RECVD  6   /* /                    */
 
- /*
 
-  * QUIC Receive Stream States
 
-  * --------------------------
 
-  *
 
-  * These correspond to the states defined in RFC 9000 s. 3.2, with the exception
 
-  * of the NONE state which represents the absence of a receive stream part.
 
-  *
 
-  * Invariants in each state are noted in comments below. In particular, once all
 
-  * data has been read by the application, we don't need to keep the QUIC_RSTREAM
 
-  * and data buffers around. If the receive part is instead reset before it is
 
-  * finished, we also don't need to keep the QUIC_RSTREAM around. Finally, we
 
-  * don't need a QUIC_RSTREAM on a send-only stream.
 
-  */
 
- #define QUIC_RSTREAM_STATE_NONE         0   /* --- rstream == NULL  */
 
- #define QUIC_RSTREAM_STATE_RECV         1   /* \                    */
 
- #define QUIC_RSTREAM_STATE_SIZE_KNOWN   2   /* |-- rstream != NULL  */
 
- #define QUIC_RSTREAM_STATE_DATA_RECVD   3   /* /                    */
 
- #define QUIC_RSTREAM_STATE_DATA_READ    4   /* \                    */
 
- #define QUIC_RSTREAM_STATE_RESET_RECVD  5   /* |-- rstream == NULL  */
 
- #define QUIC_RSTREAM_STATE_RESET_READ   6   /* /                    */
 
- struct quic_stream_st {
 
-     QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */
 
-     QUIC_STREAM_LIST_NODE accept_node; /* accept queue of remotely-created streams */
 
-     QUIC_STREAM_LIST_NODE ready_for_gc_node; /* queue of streams now ready for GC */
 
-     /* Temporary link used by TXP. */
 
-     QUIC_STREAM    *txp_next;
 
-     /*
 
-      * QUIC Stream ID. Do not assume that this encodes a type as this is a
 
-      * version-specific property and may change between QUIC versions; instead,
 
-      * use the type field.
 
-      */
 
-     uint64_t        id;
 
-     /*
 
-      * Application Error Code (AEC) used for STOP_SENDING frame.
 
-      * This is only valid if stop_sending is 1.
 
-      */
 
-     uint64_t        stop_sending_aec;
 
-     /*
 
-      * Application Error Code (AEC) used for RESET_STREAM frame.
 
-      * This is only valid if reset_stream is 1.
 
-      */
 
-     uint64_t        reset_stream_aec;
 
-     /*
 
-      * Application Error Code (AEC) for incoming STOP_SENDING frame.
 
-      * This is only valid if peer_stop_sending is 1.
 
-      */
 
-     uint64_t        peer_stop_sending_aec;
 
-     /*
 
-      * Application Error Code (AEC) for incoming RESET_STREAM frame.
 
-      * This is only valid if peer_reset_stream is 1.
 
-      */
 
-     uint64_t        peer_reset_stream_aec;
 
-     /* Temporary value used by TXP. */
 
-     uint64_t        txp_txfc_new_credit_consumed;
 
-     /*
 
-      * The final size of the send stream. Although this information can be
 
-      * discerned from a QUIC_SSTREAM, it is stored separately as we need to keep
 
-      * track of this even if we have thrown away the QUIC_SSTREAM. Use
 
-      * ossl_quic_stream_send_get_final_size to determine if this contain a
 
-      * valid value or if there is no final size yet for a sending part.
 
-      *
 
-      * For the receive part, the final size is tracked by the stream-level RXFC;
 
-      * use ossl_quic_stream_recv_get_final_size or
 
-      * ossl_quic_rxfc_get_final_size.
 
-      */
 
-     uint64_t        send_final_size;
 
-     /*
 
-      * Send stream part and receive stream part buffer management objects.
 
-      *
 
-      * DO NOT test these pointers (sstream, rstream) for NULL. Determine the
 
-      * state of the send or receive stream part first using the appropriate
 
-      * function; then the invariant of that state guarantees that sstream or
 
-      * rstream either is or is not NULL respectively, therefore there is no
 
-      * valid use case for testing these pointers for NULL. In particular, a
 
-      * stream with a send part can still have sstream as NULL, and a stream with
 
-      * a receive part can still have rstream as NULL. QUIC_SSTREAM and
 
-      * QUIC_RSTREAM are stream buffer resource management objects which exist
 
-      * only when they need to for buffer management purposes. The existence or
 
-      * non-existence of a QUIC_SSTREAM or QUIC_RSTREAM object does not
 
-      * correspond with whether a stream's respective send or receive part
 
-      * logically exists or not.
 
-      */
 
-     QUIC_SSTREAM    *sstream;   /* NULL if RX-only */
 
-     QUIC_RSTREAM    *rstream;   /* NULL if TX only */
 
-     /* Stream-level flow control managers. */
 
-     QUIC_TXFC       txfc;       /* NULL if RX-only */
 
-     QUIC_RXFC       rxfc;       /* NULL if TX-only */
 
-     unsigned int    type : 8; /* QUIC_STREAM_INITIATOR_*, QUIC_STREAM_DIR_* */
 
-     unsigned int    send_state : 8; /* QUIC_SSTREAM_STATE_* */
 
-     unsigned int    recv_state : 8; /* QUIC_RSTREAM_STATE_* */
 
-     /* 1 iff this QUIC_STREAM is on the active queue (invariant). */
 
-     unsigned int    active : 1;
 
-     /*
 
-      * This is a copy of the QUIC connection as_server value, indicating
 
-      * whether we are locally operating as a server or not. Having this
 
-      * significantly simplifies stream type determination relative to our
 
-      * perspective. It never changes after a QUIC_STREAM is created and is the
 
-      * same for all QUIC_STREAMS under a QUIC_STREAM_MAP.
 
-      */
 
-     unsigned int    as_server : 1;
 
-     /*
 
-      * Has STOP_SENDING been requested (by us)? Note that this is not the same
 
-      * as want_stop_sending below, as a STOP_SENDING frame may already have been
 
-      * sent and fully acknowledged.
 
-      */
 
-     unsigned int    stop_sending            : 1;
 
-     /*
 
-      * Has RESET_STREAM been requested (by us)? Works identically to
 
-      * STOP_SENDING for transmission purposes.
 
-      */
 
-     /* Has our peer sent a STOP_SENDING frame? */
 
-     unsigned int    peer_stop_sending       : 1;
 
-     /* Temporary flags used by TXP. */
 
-     unsigned int    txp_sent_fc             : 1;
 
-     unsigned int    txp_sent_stop_sending   : 1;
 
-     unsigned int    txp_sent_reset_stream   : 1;
 
-     unsigned int    txp_drained             : 1;
 
-     unsigned int    txp_blocked             : 1;
 
-     /* Frame regeneration flags. */
 
-     unsigned int    want_max_stream_data    : 1; /* used for regen only */
 
-     unsigned int    want_stop_sending       : 1; /* used for gen or regen */
 
-     unsigned int    want_reset_stream       : 1; /* used for gen or regen */
 
-     /* Flags set when frames *we* sent were acknowledged. */
 
-     unsigned int    acked_stop_sending      : 1;
 
-     /*
 
-      * The stream's XSO has been deleted. Pending GC.
 
-      *
 
-      * Here is how stream deletion works:
 
-      *
 
-      *   - A QUIC_STREAM cannot be deleted until it is neither in the accept
 
-      *     queue nor has an associated XSO. This condition occurs when and only
 
-      *     when deleted is true.
 
-      *
 
-      *   - Once this is the case (i.e., no user-facing API object exposing the
 
-      *     stream), we can delete the stream once we determine that all of our
 
-      *     protocol obligations requiring us to keep the QUIC_STREAM around have
 
-      *     been met.
 
-      *
 
-      *     The following frames relate to the streams layer for a specific
 
-      *     stream:
 
-      *
 
-      *          STREAM
 
-      *
 
-      *              RX Obligations:
 
-      *                  Ignore for a deleted stream.
 
-      *
 
-      *                  (This is different from our obligation for a
 
-      *                  locally-initiated stream ID we have not created yet,
 
-      *                  which we must treat as a protocol error. This can be
 
-      *                  distinguished via a simple monotonic counter.)
 
-      *
 
-      *              TX Obligations:
 
-      *                  None, once we've decided to (someday) delete the stream.
 
-      *
 
-      *          STOP_SENDING
 
-      *
 
-      *              We cannot delete the stream until we have finished informing
 
-      *              the peer that we are not going to be listening to it
 
-      *              anymore.
 
-      *
 
-      *              RX Obligations:
 
-      *                  When we delete a stream we must have already had a FIN
 
-      *                  or RESET_STREAM we transmitted acknowledged by the peer.
 
-      *                  Thus we can ignore STOP_SENDING frames for deleted
 
-      *                  streams (if they occur, they are probably just
 
-      *                  retransmissions).
 
-      *
 
-      *              TX Obligations:
 
-      *                  _Acknowledged_ receipt of a STOP_SENDING frame by the
 
-      *                  peer (unless the peer's send part has already FIN'd).
 
-      *
 
-      *          RESET_STREAM
 
-      *
 
-      *              We cannot delete the stream until we have finished informing
 
-      *              the peer that we are not going to be transmitting on it
 
-      *              anymore.
 
-      *
 
-      *              RX Obligations:
 
-      *                  This indicates the peer is not going to send any more
 
-      *                  data on the stream. We don't need to care about this
 
-      *                  since once a stream is marked for deletion we don't care
 
-      *                  about any data it does send. We can ignore this for
 
-      *                  deleted streams. The important criterion is that the
 
-      *                  peer has been successfully delivered our STOP_SENDING
 
-      *                  frame.
 
-      *
 
-      *              TX Obligations:
 
-      *                  _Acknowledged_ receipt of a RESET_STREAM frame or FIN by
 
-      *                  the peer.
 
-      *
 
-      *          MAX_STREAM_DATA
 
-      *
 
-      *              RX Obligations:
 
-      *                 Ignore. Since we are not going to be sending any more
 
-      *                 data on a stream once it has been marked for deletion,
 
-      *                 we don't need to care about flow control information.
 
-      *
 
-      *              TX Obligations:
 
-      *                  None.
 
-      *
 
-      *     In other words, our protocol obligation is simply:
 
-      *
 
-      *       - either:
 
-      *         - the peer has acknowledged receipt of a STOP_SENDING frame sent
 
-      *            by us; -or-
 
-      *         - we have received a FIN and all preceding segments from the peer
 
-      *
 
-      *            [NOTE: The actual criterion required here is simply 'we have
 
-      *            received a FIN from the peer'. However, due to reordering and
 
-      *            retransmissions we might subsequently receive non-FIN segments
 
-      *            out of order. The FIN means we know the peer will stop
 
-      *            transmitting on the stream at *some* point, but by sending
 
-      *            STOP_SENDING we can avoid these needless retransmissions we
 
-      *            will just ignore anyway. In actuality we could just handle all
 
-      *            cases by sending a STOP_SENDING. The strategy we choose is to
 
-      *            only avoid sending a STOP_SENDING and rely on a received FIN
 
-      *            when we have received all preceding data, as this makes it
 
-      *            reasonably certain no benefit would be gained by sending
 
-      *            STOP_SENDING.]
 
-      *
 
-      *            TODO(QUIC FUTURE): Implement the latter case (currently we
 
-                                      just always do STOP_SENDING).
 
-      *
 
-      *         and;
 
-      *
 
-      *       - we have drained our send stream (for a finished send stream)
 
-      *         and got acknowledgement all parts of it including the FIN, or
 
-      *         sent a RESET_STREAM frame and got acknowledgement of that frame.
 
-      *
 
-      *      Once these conditions are met, we can GC the QUIC_STREAM.
 
-      *
 
-      */
 
-     unsigned int    deleted                 : 1;
 
-     /* Set to 1 once the above conditions are actually met. */
 
-     unsigned int    ready_for_gc            : 1;
 
-     /* Set to 1 if this is currently counted in the shutdown flush stream count. */
 
-     unsigned int    shutdown_flush          : 1;
 
- };
 
- #define QUIC_STREAM_INITIATOR_CLIENT        0
 
- #define QUIC_STREAM_INITIATOR_SERVER        1
 
- #define QUIC_STREAM_INITIATOR_MASK          1
 
- #define QUIC_STREAM_DIR_BIDI                0
 
- #define QUIC_STREAM_DIR_UNI                 2
 
- #define QUIC_STREAM_DIR_MASK                2
 
- void ossl_quic_stream_check(const QUIC_STREAM *s);
 
- /*
 
-  * Returns 1 if the QUIC_STREAM was initiated by the endpoint with the server
 
-  * role.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(const QUIC_STREAM *s)
 
- {
 
-     return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM is bidirectional and 0 if it is unidirectional.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(const QUIC_STREAM *s)
 
- {
 
-     return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
 
- }
 
- /* Returns 1 if the QUIC_STREAM was locally initiated. */
 
- static ossl_inline ossl_unused int ossl_quic_stream_is_local_init(const QUIC_STREAM *s)
 
- {
 
-     return ossl_quic_stream_is_server_init(s) == s->as_server;
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM has a sending part, based on its stream type.
 
-  *
 
-  * Do NOT use (s->sstream != NULL) to test this; use this function. Note that
 
-  * even if this function returns 1, s->sstream might be NULL if the QUIC_SSTREAM
 
-  * has been deemed no longer needed, for example due to a RESET_STREAM.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_has_send(const QUIC_STREAM *s)
 
- {
 
-     return s->send_state != QUIC_SSTREAM_STATE_NONE;
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM has a receiving part, based on its stream type.
 
-  *
 
-  * Do NOT use (s->rstream != NULL) to test this; use this function. Note that
 
-  * even if this function returns 1, s->rstream might be NULL if the QUIC_RSTREAM
 
-  * has been deemed no longer needed, for example if the receive stream is
 
-  * completely finished with.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_has_recv(const QUIC_STREAM *s)
 
- {
 
-     return s->recv_state != QUIC_RSTREAM_STATE_NONE;
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM has a QUIC_SSTREAM send buffer associated with
 
-  * it. If this returns 1, s->sstream is guaranteed to be non-NULL. The converse
 
-  * is not necessarily true; erasure of a send stream buffer which is no longer
 
-  * required is an optimisation which the QSM may, but is not obliged, to
 
-  * perform.
 
-  *
 
-  * This call should be used where it is desired to do something with the send
 
-  * stream buffer but there is no more specific send state restriction which is
 
-  * applicable.
 
-  *
 
-  * Note: This does NOT indicate whether it is suitable to allow an application
 
-  * to append to the buffer. DATA_SENT indicates all data (including FIN) has
 
-  * been *sent*; the absence of DATA_SENT does not mean a FIN has not been queued
 
-  * (meaning no more application data can be appended). This is enforced by
 
-  * QUIC_SSTREAM.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_has_send_buffer(const QUIC_STREAM *s)
 
- {
 
-     switch (s->send_state) {
 
-     case QUIC_SSTREAM_STATE_READY:
 
-     case QUIC_SSTREAM_STATE_SEND:
 
-     case QUIC_SSTREAM_STATE_DATA_SENT:
 
-         return 1;
 
-     default:
 
-         return 0;
 
-     }
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM has a sending part which is in one of the reset
 
-  * states.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_send_is_reset(const QUIC_STREAM *s)
 
- {
 
-     return s->send_state == QUIC_SSTREAM_STATE_RESET_SENT
 
-         || s->send_state == QUIC_SSTREAM_STATE_RESET_RECVD;
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM has a QUIC_RSTREAM receive buffer associated
 
-  * with it. If this returns 1, s->rstream is guaranteed to be non-NULL. The
 
-  * converse is not necessarily true; erasure of a receive stream buffer which is
 
-  * no longer required is an optimisation which the QSM may, but is not obliged,
 
-  * to perform.
 
-  *
 
-  * This call should be used where it is desired to do something with the receive
 
-  * stream buffer but there is no more specific receive state restriction which is
 
-  * applicable.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_has_recv_buffer(const QUIC_STREAM *s)
 
- {
 
-     switch (s->recv_state) {
 
-     case QUIC_RSTREAM_STATE_RECV:
 
-     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
 
-     case QUIC_RSTREAM_STATE_DATA_RECVD:
 
-         return 1;
 
-     default:
 
-         return 0;
 
-     }
 
- }
 
- /*
 
-  * Returns 1 if the QUIC_STREAM has a receiving part which is in one of the
 
-  * reset states.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_recv_is_reset(const QUIC_STREAM *s)
 
- {
 
-     return s->recv_state == QUIC_RSTREAM_STATE_RESET_RECVD
 
-         || s->recv_state == QUIC_RSTREAM_STATE_RESET_READ;
 
- }
 
- /*
 
-  * Returns 1 if the stream has a send part and that part has a final size.
 
-  *
 
-  * If final_size is non-NULL, *final_size is the final size (on success) or an
 
-  * undefined value otherwise.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_send_get_final_size(const QUIC_STREAM *s,
 
-                                                                         uint64_t *final_size)
 
- {
 
-     switch (s->send_state) {
 
-     default:
 
-     case QUIC_SSTREAM_STATE_NONE:
 
-         return 0;
 
-     case QUIC_SSTREAM_STATE_SEND:
 
-         /*
 
-          * SEND may or may not have had a FIN - even if we have a FIN we do not
 
-          * move to DATA_SENT until we have actually sent all the data. So
 
-          * ask the QUIC_SSTREAM.
 
-          */
 
-         return ossl_quic_sstream_get_final_size(s->sstream, final_size);
 
-     case QUIC_SSTREAM_STATE_DATA_SENT:
 
-     case QUIC_SSTREAM_STATE_DATA_RECVD:
 
-     case QUIC_SSTREAM_STATE_RESET_SENT:
 
-     case QUIC_SSTREAM_STATE_RESET_RECVD:
 
-         if (final_size != NULL)
 
-             *final_size = s->send_final_size;
 
-         return 1;
 
-     }
 
- }
 
- /*
 
-  * Returns 1 if the stream has a receive part and that part has a final size.
 
-  *
 
-  * If final_size is non-NULL, *final_size is the final size (on success) or an
 
-  * undefined value otherwise.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_recv_get_final_size(const QUIC_STREAM *s,
 
-                                                                         uint64_t *final_size)
 
- {
 
-     switch (s->recv_state) {
 
-     default:
 
-     case QUIC_RSTREAM_STATE_NONE:
 
-     case QUIC_RSTREAM_STATE_RECV:
 
-         return 0;
 
-     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
 
-     case QUIC_RSTREAM_STATE_DATA_RECVD:
 
-     case QUIC_RSTREAM_STATE_DATA_READ:
 
-     case QUIC_RSTREAM_STATE_RESET_RECVD:
 
-     case QUIC_RSTREAM_STATE_RESET_READ:
 
-         if (!ossl_assert(ossl_quic_rxfc_get_final_size(&s->rxfc, final_size)))
 
-             return 0;
 
-         return 1;
 
-     }
 
- }
 
- /*
 
-  * Determines the number of bytes available still to be read, and (if
 
-  * include_fin is 1) whether a FIN or reset has yet to be read.
 
-  */
 
- static ossl_inline ossl_unused int ossl_quic_stream_recv_pending(const QUIC_STREAM *s,
 
-                                                                  int include_fin)
 
- {
 
-     size_t avail;
 
-     int fin = 0;
 
-     switch (s->recv_state) {
 
-     default:
 
-     case QUIC_RSTREAM_STATE_NONE:
 
-         return 0;
 
-     case QUIC_RSTREAM_STATE_RECV:
 
-     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
 
-     case QUIC_RSTREAM_STATE_DATA_RECVD:
 
-         if (!ossl_quic_rstream_available(s->rstream, &avail, &fin))
 
-             avail = 0;
 
-         if (avail == 0 && include_fin && fin)
 
-             avail = 1;
 
-         return avail;
 
-     case QUIC_RSTREAM_STATE_RESET_RECVD:
 
-         return include_fin;
 
-     case QUIC_RSTREAM_STATE_DATA_READ:
 
-     case QUIC_RSTREAM_STATE_RESET_READ:
 
-         return 0;
 
-     }
 
- }
 
- /*
 
-  * QUIC Stream Map
 
-  * ===============
 
-  *
 
-  * The QUIC stream map:
 
-  *
 
-  *   - maps stream IDs to QUIC_STREAM objects;
 
-  *   - tracks which streams are 'active' (currently have data for transmission);
 
-  *   - allows iteration over the active streams only.
 
-  *
 
-  */
 
- struct quic_stream_map_st {
 
-     LHASH_OF(QUIC_STREAM)   *map;
 
-     QUIC_STREAM_LIST_NODE   active_list;
 
-     QUIC_STREAM_LIST_NODE   accept_list;
 
-     QUIC_STREAM_LIST_NODE   ready_for_gc_list;
 
-     size_t                  rr_stepping, rr_counter;
 
-     size_t                  num_accept_bidi, num_accept_uni, num_shutdown_flush;
 
-     QUIC_STREAM             *rr_cur;
 
-     uint64_t                (*get_stream_limit_cb)(int uni, void *arg);
 
-     void                    *get_stream_limit_cb_arg;
 
-     QUIC_RXFC               *max_streams_bidi_rxfc;
 
-     QUIC_RXFC               *max_streams_uni_rxfc;
 
-     int                     is_server;
 
- };
 
- /*
 
-  * get_stream_limit is a callback which is called to retrieve the current stream
 
-  * limit for streams created by us. This mechanism is not used for
 
-  * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if
 
-  * (x >> 2) < returned limit value; i.e., the returned value is exclusive.
 
-  *
 
-  * If uni is 1, get the limit for locally-initiated unidirectional streams, else
 
-  * get the limit for locally-initiated bidirectional streams.
 
-  *
 
-  * If the callback is NULL, stream limiting is not applied.
 
-  * Stream limiting is used to determine if frames can currently be produced for
 
-  * a stream.
 
-  */
 
- int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
 
-                               uint64_t (*get_stream_limit_cb)(int uni, void *arg),
 
-                               void *get_stream_limit_cb_arg,
 
-                               QUIC_RXFC *max_streams_bidi_rxfc,
 
-                               QUIC_RXFC *max_streams_uni_rxfc,
 
-                               int is_server);
 
- /*
 
-  * Any streams still in the map will be released as though
 
-  * ossl_quic_stream_map_release was called on them.
 
-  */
 
- void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
 
- /*
 
-  * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_*
 
-  * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate
 
-  * server-initiated streams as they will need to allocate a QUIC_STREAM
 
-  * structure to track any stream created by the server, etc.
 
-  *
 
-  * stream_id must be a valid value. Returns NULL if a stream already exists
 
-  * with the given ID.
 
-  */
 
- QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
 
-                                         uint64_t stream_id,
 
-                                         int type);
 
- /*
 
-  * Releases a stream object. Note that this must only be done once the teardown
 
-  * process is entirely complete and the object will never be referenced again.
 
-  */
 
- void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream);
 
- /*
 
-  * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque
 
-  * argument which is passed through.
 
-  */
 
- void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
 
-                                 void (*visit_cb)(QUIC_STREAM *stream, void *arg),
 
-                                 void *visit_cb_arg);
 
- /*
 
-  * Retrieves a stream by stream ID. Returns NULL if it does not exist.
 
-  */
 
- QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
 
-                                             uint64_t stream_id);
 
- /*
 
-  * Marks the given stream as active or inactive based on its state. Idempotent.
 
-  *
 
-  * When a stream is marked active, it becomes available in the iteration list,
 
-  * and when a stream is marked inactive, it no longer appears in the iteration
 
-  * list.
 
-  *
 
-  * Calling this function invalidates any iterator currently pointing at the
 
-  * given stream object, but iterators not currently pointing at the given stream
 
-  * object are not invalidated.
 
-  */
 
- void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
 
- /*
 
-  * Sets the RR stepping value, n. The RR rotation will be advanced every n
 
-  * packets. The default value is 1.
 
-  */
 
- void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
 
- /*
 
-  * Returns 1 if the stream ordinal given is allowed by the current stream count
 
-  * flow control limit, assuming a locally initiated stream of a type described
 
-  * by is_uni.
 
-  *
 
-  * Note that stream_ordinal is a stream ordinal, not a stream ID.
 
-  */
 
- int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm,
 
-                                                           uint64_t stream_ordinal,
 
-                                                           int is_uni);
 
- /*
 
-  * Stream Send Part
 
-  * ================
 
-  */
 
- /*
 
-  * Ensures that the sending part has transitioned out of the READY state (i.e.,
 
-  * to SEND, or a subsequent state). This function is named as it is because,
 
-  * while on paper the distinction between READY and SEND is whether we have
 
-  * started transmitting application data, in practice the meaningful distinction
 
-  * between the two states is whether we have allocated a stream ID to the stream
 
-  * or not. QUIC permits us to defer stream ID allocation until first STREAM (or
 
-  * STREAM_DATA_BLOCKED) frame transmission for locally-initiated streams.
 
-  *
 
-  * Our implementation does not currently do this and we allocate stream IDs up
 
-  * front, however we may revisit this in the future. Calling this represents a
 
-  * demand for a stream ID by the caller and ensures one has been allocated to
 
-  * the stream, and causes us to transition to SEND if we are still in the READY
 
-  * state.
 
-  *
 
-  * Returns 0 if there is no send part (caller error) and 1 otherwise.
 
-  */
 
- int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm,
 
-                                              QUIC_STREAM *qs);
 
- /*
 
-  * Transitions from SEND to the DATA_SENT state. Note that this is NOT the same
 
-  * as the point in time at which the final size of the stream becomes known
 
-  * (i.e., the time at which ossl_quic_sstream_fin()) is called as it occurs when
 
-  * we have SENT all data on a given stream send part, not merely buffered it.
 
-  * Note that this transition is NOT reversed in the event of some of that data
 
-  * being lost.
 
-  *
 
-  * Returns 1 if the state transition was successfully taken. Returns 0 if there
 
-  * is no send part (caller error) or if the state transition cannot be taken
 
-  * because the send part is not in the SEND state.
 
-  */
 
- int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,
 
-                                               QUIC_STREAM *qs);
 
- /*
 
-  * Transitions from the DATA_SENT to DATA_RECVD state; should be called
 
-  * when all transmitted stream data is ACKed by the peer.
 
-  *
 
-  * Returns 1 if the state transition was successfully taken. Returns 0 if there
 
-  * is no send part (caller error) or the state transition cannot be taken
 
-  * because the send part is not in the DATA_SENT state. Because
 
-  * ossl_quic_stream_map_notify_all_data_sent() should always be called prior to
 
-  * this function, the send state must already be in DATA_SENT in order for this
 
-  * function to succeed.
 
-  */
 
- int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,
 
-                                               QUIC_STREAM *qs);
 
- /*
 
-  * Resets the sending part of a stream. This is a transition from the READY,
 
-  * SEND or DATA_SENT send stream states to the RESET_SENT state.
 
-  *
 
-  * This function returns 1 if the transition is taken (i.e., if the send stream
 
-  * part was in one of the states above), or if it is already in the RESET_SENT
 
-  * state (idempotent operation), or if it has reached the RESET_RECVD state.
 
-  *
 
-  * It returns 0 if in the DATA_RECVD state, as a send stream cannot be reset
 
-  * in this state. It also returns 0 if there is no send part (caller error).
 
-  */
 
- int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
 
-                                                 QUIC_STREAM *qs,
 
-                                                 uint64_t aec);
 
- /*
 
-  * Transitions from the RESET_SENT to the RESET_RECVD state. This should be
 
-  * called when a sent RESET_STREAM frame has been acknowledged by the peer.
 
-  *
 
-  * This function returns 1 if the transition is taken (i.e., if the send stream
 
-  * part was in one of the states above) or if it is already in the RESET_RECVD
 
-  * state (idempotent operation).
 
-  *
 
-  * It returns 0 if not in the RESET_SENT or RESET_RECVD states, as this function
 
-  * should only be called after we have already sent a RESET_STREAM frame and
 
-  * entered the RESET_SENT state. It also returns 0 if there is no send part
 
-  * (caller error).
 
-  */
 
- int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,
 
-                                                    QUIC_STREAM *qs);
 
- /*
 
-  * Stream Receive Part
 
-  * ===================
 
-  */
 
- /*
 
-  * Transitions from the RECV receive stream state to the SIZE_KNOWN state. This
 
-  * should be called once a STREAM frame is received for the stream with the FIN
 
-  * bit set. final_size should be the final size of the stream in bytes.
 
-  *
 
-  * Returns 1 if the transition was taken.
 
-  */
 
- int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm,
 
-                                                      QUIC_STREAM *qs,
 
-                                                      uint64_t final_size);
 
- /*
 
-  * Transitions from the SIZE_KNOWN receive stream state to the DATA_RECVD state.
 
-  * This should be called once all data for a receive stream is received.
 
-  *
 
-  * Returns 1 if the transition was taken.
 
-  */
 
- int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,
 
-                                                  QUIC_STREAM *qs);
 
- /*
 
-  * Transitions from the DATA_RECVD receive stream state to the DATA_READ state.
 
-  * This should be called once all data for a receive stream is read by the
 
-  * application.
 
-  *
 
-  * Returns 1 if the transition was taken.
 
-  */
 
- int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
 
-                                              QUIC_STREAM *qs);
 
- /*
 
-  * Transitions from the RECV, SIZE_KNOWN or DATA_RECVD receive stream state to
 
-  * the RESET_RECVD state. This should be called on RESET_STREAM.
 
-  *
 
-  * Returns 1 if the transition was taken.
 
-  */
 
- int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
 
-                                                 QUIC_STREAM *qs,
 
-                                                 uint64_t app_error_code,
 
-                                                 uint64_t final_size);
 
- /*
 
-  * Transitions from the RESET_RECVD receive stream state to the RESET_READ
 
-  * receive stream state. This should be called when the application is notified
 
-  * of a stream reset.
 
-  */
 
- int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,
 
-                                                          QUIC_STREAM *qs);
 
- /*
 
-  * Marks the receiving part of a stream for STOP_SENDING. This is orthogonal to
 
-  * receive stream state as it does not affect it directly.
 
-  *
 
-  * Returns 1 if the receiving part of a stream was not already marked for
 
-  * STOP_SENDING.
 
-  * Returns 0 otherwise, which need not be considered an error.
 
-  */
 
- int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,
 
-                                                 QUIC_STREAM *qs,
 
-                                                 uint64_t aec);
 
- /*
 
-  * Marks the stream as wanting a STOP_SENDING frame transmitted. It is not valid
 
-  * to call this if ossl_quic_stream_map_stop_sending_recv_part() has not been
 
-  * called. For TXP use.
 
-  */
 
- int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm,
 
-                                                QUIC_STREAM *qs);
 
- /*
 
-  * Accept Queue Management
 
-  * =======================
 
-  */
 
- /*
 
-  * Adds a stream to the accept queue.
 
-  */
 
- void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
 
-                                             QUIC_STREAM *s);
 
- /*
 
-  * Returns the next item to be popped from the accept queue, or NULL if it is
 
-  * empty.
 
-  */
 
- QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm);
 
- /*
 
-  * Removes a stream from the accept queue. rtt is the estimated connection RTT.
 
-  * The stream is retired for the purposes of MAX_STREAMS RXFC.
 
-  *
 
-  * Precondition: s is in the accept queue.
 
-  */
 
- void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
 
-                                                    QUIC_STREAM *s,
 
-                                                    OSSL_TIME rtt);
 
- /* Returns the length of the accept queue for the given stream type. */
 
- size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni);
 
- /* Returns the total length of the accept queues for all stream types. */
 
- size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm);
 
- /*
 
-  * Shutdown Flush and GC
 
-  * =====================
 
-  */
 
- /*
 
-  * Delete streams ready for GC. Pointers to those QUIC_STREAM objects become
 
-  * invalid.
 
-  */
 
- void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm);
 
- /*
 
-  * Begins shutdown stream flush triage. Analyses all streams, including deleted
 
-  * but not yet GC'd streams, to determine if we should wait for that stream to
 
-  * be fully flushed before shutdown. After calling this, call
 
-  * ossl_quic_stream_map_is_shutdown_flush_finished() to determine if all
 
-  * shutdown flush eligible streams have been flushed.
 
-  */
 
- void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm);
 
- /*
 
-  * Returns 1 if all shutdown flush eligible streams have finished flushing,
 
-  * or if ossl_quic_stream_map_begin_shutdown_flush() has not been called.
 
-  */
 
- int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm);
 
- /*
 
-  * QUIC Stream Iterator
 
-  * ====================
 
-  *
 
-  * Allows the current set of active streams to be walked using a RR-based
 
-  * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm
 
-  * is stepped. The RR algorithm rotates the iteration order such that the next
 
-  * active stream is returned first after n calls to ossl_quic_stream_iter_init,
 
-  * where n is the stepping value configured via
 
-  * ossl_quic_stream_map_set_rr_stepping.
 
-  *
 
-  * Suppose there are three active streams and the configured stepping is n:
 
-  *
 
-  *   Iteration 0n:  [Stream 1] [Stream 2] [Stream 3]
 
-  *   Iteration 1n:  [Stream 2] [Stream 3] [Stream 1]
 
-  *   Iteration 2n:  [Stream 3] [Stream 1] [Stream 2]
 
-  *
 
-  */
 
- typedef struct quic_stream_iter_st {
 
-     QUIC_STREAM_MAP     *qsm;
 
-     QUIC_STREAM         *first_stream, *stream;
 
- } QUIC_STREAM_ITER;
 
- /*
 
-  * Initialise an iterator, advancing the RR algorithm as necessary (if
 
-  * advance_rr is 1). After calling this, it->stream will be the first stream in
 
-  * the iteration sequence, or NULL if there are no active streams.
 
-  */
 
- void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
 
-                                 int advance_rr);
 
- /*
 
-  * Advances to next stream in iteration sequence. You do not need to call this
 
-  * immediately after calling ossl_quic_stream_iter_init(). If the end of the
 
-  * list is reached, it->stream will be NULL after calling this.
 
-  */
 
- void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);
 
- # endif
 
- #endif
 
 
  |