Home | History | Annotate | Line # | Download | only in quic
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos #include "internal/quic_txp.h"
     11      1.1  christos #include "internal/quic_fifd.h"
     12      1.1  christos #include "internal/quic_stream_map.h"
     13      1.1  christos #include "internal/quic_error.h"
     14      1.1  christos #include "internal/common.h"
     15      1.1  christos #include <openssl/err.h>
     16      1.1  christos 
     17  1.1.1.2  christos #define MIN_CRYPTO_HDR_SIZE 3
     18      1.1  christos 
     19  1.1.1.2  christos #define MIN_FRAME_SIZE_HANDSHAKE_DONE 1
     20  1.1.1.2  christos #define MIN_FRAME_SIZE_MAX_DATA 2
     21  1.1.1.2  christos #define MIN_FRAME_SIZE_ACK 5
     22  1.1.1.2  christos #define MIN_FRAME_SIZE_CRYPTO (MIN_CRYPTO_HDR_SIZE + 1)
     23  1.1.1.2  christos #define MIN_FRAME_SIZE_STREAM 3 /* minimum useful size (for non-FIN) */
     24      1.1  christos #define MIN_FRAME_SIZE_MAX_STREAMS_BIDI 2
     25  1.1.1.2  christos #define MIN_FRAME_SIZE_MAX_STREAMS_UNI 2
     26      1.1  christos 
     27      1.1  christos /*
     28      1.1  christos  * Packet Archetypes
     29      1.1  christos  * =================
     30      1.1  christos  */
     31      1.1  christos 
     32      1.1  christos /* Generate normal packets containing most frame types, subject to EL. */
     33  1.1.1.2  christos #define TX_PACKETISER_ARCHETYPE_NORMAL 0
     34      1.1  christos 
     35      1.1  christos /*
     36      1.1  christos  * A probe packet is different in that:
     37      1.1  christos  *   - It bypasses CC, but *is* counted as in flight for purposes of CC;
     38      1.1  christos  *   - It must be ACK-eliciting.
     39      1.1  christos  */
     40  1.1.1.2  christos #define TX_PACKETISER_ARCHETYPE_PROBE 1
     41      1.1  christos 
     42      1.1  christos /*
     43      1.1  christos  * An ACK-only packet is different in that:
     44      1.1  christos  *   - It bypasses CC, and is considered a 'non-inflight' packet;
     45      1.1  christos  *   - It may not contain anything other than an ACK frame, not even padding.
     46      1.1  christos  */
     47  1.1.1.2  christos #define TX_PACKETISER_ARCHETYPE_ACK_ONLY 2
     48      1.1  christos 
     49  1.1.1.2  christos #define TX_PACKETISER_ARCHETYPE_NUM 3
     50      1.1  christos 
     51      1.1  christos struct ossl_quic_tx_packetiser_st {
     52      1.1  christos     OSSL_QUIC_TX_PACKETISER_ARGS args;
     53      1.1  christos 
     54      1.1  christos     /*
     55      1.1  christos      * Opaque initial token blob provided by caller. TXP frees using the
     56      1.1  christos      * callback when it is no longer needed.
     57      1.1  christos      */
     58  1.1.1.2  christos     const unsigned char *initial_token;
     59  1.1.1.2  christos     size_t initial_token_len;
     60      1.1  christos     ossl_quic_initial_token_free_fn *initial_token_free_cb;
     61  1.1.1.2  christos     void *initial_token_free_cb_arg;
     62      1.1  christos 
     63      1.1  christos     /* Subcomponents of the TXP that we own. */
     64  1.1.1.2  christos     QUIC_FIFD fifd; /* QUIC Frame-in-Flight Dispatcher */
     65      1.1  christos 
     66      1.1  christos     /* Internal state. */
     67  1.1.1.2  christos     uint64_t next_pn[QUIC_PN_SPACE_NUM]; /* Next PN to use in given PN space. */
     68  1.1.1.2  christos     OSSL_TIME last_tx_time; /* Last time a packet was generated, or 0. */
     69      1.1  christos 
     70  1.1.1.2  christos     size_t unvalidated_credit; /* Limit of data we can send until validated */
     71      1.1  christos 
     72      1.1  christos     /* Internal state - frame (re)generation flags. */
     73  1.1.1.2  christos     unsigned int want_handshake_done : 1;
     74  1.1.1.2  christos     unsigned int want_max_data : 1;
     75  1.1.1.2  christos     unsigned int want_max_streams_bidi : 1;
     76  1.1.1.2  christos     unsigned int want_max_streams_uni : 1;
     77      1.1  christos 
     78      1.1  christos     /* Internal state - frame (re)generation flags - per PN space. */
     79  1.1.1.2  christos     unsigned int want_ack : QUIC_PN_SPACE_NUM;
     80  1.1.1.2  christos     unsigned int force_ack_eliciting : QUIC_PN_SPACE_NUM;
     81      1.1  christos 
     82      1.1  christos     /*
     83      1.1  christos      * Internal state - connection close terminal state.
     84      1.1  christos      * Once this is set, it is not unset unlike other want_ flags - we keep
     85      1.1  christos      * sending it in every packet.
     86      1.1  christos      */
     87  1.1.1.2  christos     unsigned int want_conn_close : 1;
     88      1.1  christos 
     89      1.1  christos     /* Has the handshake been completed? */
     90  1.1.1.2  christos     unsigned int handshake_complete : 1;
     91      1.1  christos 
     92  1.1.1.2  christos     OSSL_QUIC_FRAME_CONN_CLOSE conn_close_frame;
     93      1.1  christos 
     94      1.1  christos     /*
     95      1.1  christos      * Counts of the number of bytes received and sent while in the closing
     96      1.1  christos      * state.
     97      1.1  christos      */
     98  1.1.1.2  christos     uint64_t closing_bytes_recv;
     99  1.1.1.2  christos     uint64_t closing_bytes_xmit;
    100      1.1  christos 
    101      1.1  christos     /* Internal state - packet assembly. */
    102      1.1  christos     struct txp_el {
    103  1.1.1.2  christos         unsigned char *scratch; /* scratch buffer for packet assembly */
    104  1.1.1.2  christos         size_t scratch_len; /* number of bytes allocated for scratch */
    105  1.1.1.2  christos         OSSL_QTX_IOVEC *iovec; /* scratch iovec array for use with QTX */
    106  1.1.1.2  christos         size_t alloc_iovec; /* size of iovec array */
    107      1.1  christos     } el[QUIC_ENC_LEVEL_NUM];
    108      1.1  christos 
    109      1.1  christos     /* Message callback related arguments */
    110      1.1  christos     ossl_msg_cb msg_callback;
    111      1.1  christos     void *msg_callback_arg;
    112      1.1  christos     SSL *msg_callback_ssl;
    113      1.1  christos 
    114      1.1  christos     /* Callbacks. */
    115  1.1.1.2  christos     void (*ack_tx_cb)(const OSSL_QUIC_FRAME_ACK *ack,
    116  1.1.1.2  christos         uint32_t pn_space,
    117  1.1.1.2  christos         void *arg);
    118  1.1.1.2  christos     void *ack_tx_cb_arg;
    119      1.1  christos };
    120      1.1  christos 
    121      1.1  christos /*
    122      1.1  christos  * The TX helper records state used while generating frames into packets. It
    123      1.1  christos  * enables serialization into the packet to be done "transactionally" where
    124      1.1  christos  * serialization of a frame can be rolled back if it fails midway (e.g. if it
    125      1.1  christos  * does not fit).
    126      1.1  christos  */
    127      1.1  christos struct tx_helper {
    128      1.1  christos     OSSL_QUIC_TX_PACKETISER *txp;
    129      1.1  christos     /*
    130      1.1  christos      * The Maximum Packet Payload Length in bytes. This is the amount of
    131      1.1  christos      * space we have to generate frames into.
    132      1.1  christos      */
    133      1.1  christos     size_t max_ppl;
    134      1.1  christos     /*
    135      1.1  christos      * Number of bytes we have generated so far.
    136      1.1  christos      */
    137      1.1  christos     size_t bytes_appended;
    138      1.1  christos     /*
    139      1.1  christos      * Number of scratch bytes in txp->scratch we have used so far. Some iovecs
    140      1.1  christos      * will reference this scratch buffer. When we need to use more of it (e.g.
    141      1.1  christos      * when we need to put frame headers somewhere), we append to the scratch
    142      1.1  christos      * buffer, resizing if necessary, and increase this accordingly.
    143      1.1  christos      */
    144      1.1  christos     size_t scratch_bytes;
    145      1.1  christos     /*
    146      1.1  christos      * Bytes reserved in the MaxPPL budget. We keep this number of bytes spare
    147      1.1  christos      * until reserve_allowed is set to 1. Currently this is always at most 1, as
    148      1.1  christos      * a PING frame takes up one byte and this mechanism is only used to ensure
    149      1.1  christos      * we can encode a PING frame if we have been asked to ensure a packet is
    150      1.1  christos      * ACK-eliciting and we are unusure if we are going to add any other
    151      1.1  christos      * ACK-eliciting frames before we reach our MaxPPL budget.
    152      1.1  christos      */
    153      1.1  christos     size_t reserve;
    154      1.1  christos     /*
    155      1.1  christos      * Number of iovecs we have currently appended. This is the number of
    156      1.1  christos      * entries valid in txp->iovec.
    157      1.1  christos      */
    158      1.1  christos     size_t num_iovec;
    159      1.1  christos     /* The EL this TX helper is being used for. */
    160      1.1  christos     uint32_t enc_level;
    161      1.1  christos     /*
    162      1.1  christos      * Whether we are allowed to make use of the reserve bytes in our MaxPPL
    163      1.1  christos      * budget. This is used to ensure we have room to append a PING frame later
    164      1.1  christos      * if we need to. Once we know we will not need to append a PING frame, this
    165      1.1  christos      * is set to 1.
    166      1.1  christos      */
    167      1.1  christos     unsigned int reserve_allowed : 1;
    168      1.1  christos     /*
    169      1.1  christos      * Set to 1 if we have appended a STREAM frame with an implicit length. If
    170      1.1  christos      * this happens we should never append another frame after that frame as it
    171      1.1  christos      * cannot be validly encoded. This is just a safety check.
    172      1.1  christos      */
    173      1.1  christos     unsigned int done_implicit : 1;
    174      1.1  christos     struct {
    175      1.1  christos         /*
    176      1.1  christos          * The fields in this structure are valid if active is set, which means
    177      1.1  christos          * that a serialization transaction is currently in progress.
    178      1.1  christos          */
    179  1.1.1.2  christos         unsigned char *data;
    180  1.1.1.2  christos         WPACKET wpkt;
    181  1.1.1.2  christos         unsigned int active : 1;
    182      1.1  christos     } txn;
    183      1.1  christos };
    184      1.1  christos 
    185      1.1  christos static void tx_helper_rollback(struct tx_helper *h);
    186      1.1  christos static int txp_el_ensure_iovec(struct txp_el *el, size_t num);
    187      1.1  christos 
    188      1.1  christos /* Initialises the TX helper. */
    189      1.1  christos static int tx_helper_init(struct tx_helper *h, OSSL_QUIC_TX_PACKETISER *txp,
    190  1.1.1.2  christos     uint32_t enc_level, size_t max_ppl, size_t reserve)
    191      1.1  christos {
    192      1.1  christos     if (reserve > max_ppl)
    193      1.1  christos         return 0;
    194      1.1  christos 
    195  1.1.1.2  christos     h->txp = txp;
    196  1.1.1.2  christos     h->enc_level = enc_level;
    197  1.1.1.2  christos     h->max_ppl = max_ppl;
    198  1.1.1.2  christos     h->reserve = reserve;
    199  1.1.1.2  christos     h->num_iovec = 0;
    200  1.1.1.2  christos     h->bytes_appended = 0;
    201  1.1.1.2  christos     h->scratch_bytes = 0;
    202  1.1.1.2  christos     h->reserve_allowed = 0;
    203  1.1.1.2  christos     h->done_implicit = 0;
    204  1.1.1.2  christos     h->txn.data = NULL;
    205  1.1.1.2  christos     h->txn.active = 0;
    206      1.1  christos 
    207      1.1  christos     if (max_ppl > h->txp->el[enc_level].scratch_len) {
    208      1.1  christos         unsigned char *scratch;
    209      1.1  christos 
    210      1.1  christos         scratch = OPENSSL_realloc(h->txp->el[enc_level].scratch, max_ppl);
    211      1.1  christos         if (scratch == NULL)
    212      1.1  christos             return 0;
    213      1.1  christos 
    214  1.1.1.2  christos         h->txp->el[enc_level].scratch = scratch;
    215      1.1  christos         h->txp->el[enc_level].scratch_len = max_ppl;
    216      1.1  christos     }
    217      1.1  christos 
    218      1.1  christos     return 1;
    219      1.1  christos }
    220      1.1  christos 
    221      1.1  christos static void tx_helper_cleanup(struct tx_helper *h)
    222      1.1  christos {
    223      1.1  christos     if (h->txn.active)
    224      1.1  christos         tx_helper_rollback(h);
    225      1.1  christos 
    226      1.1  christos     h->txp = NULL;
    227      1.1  christos }
    228      1.1  christos 
    229      1.1  christos static void tx_helper_unrestrict(struct tx_helper *h)
    230      1.1  christos {
    231      1.1  christos     h->reserve_allowed = 1;
    232      1.1  christos }
    233      1.1  christos 
    234      1.1  christos /*
    235      1.1  christos  * Append an extent of memory to the iovec list. The memory must remain
    236      1.1  christos  * allocated until we finish generating the packet and call the QTX.
    237      1.1  christos  *
    238      1.1  christos  * In general, the buffers passed to this function will be from one of two
    239      1.1  christos  * ranges:
    240      1.1  christos  *
    241      1.1  christos  *   - Application data contained in stream buffers managed elsewhere
    242      1.1  christos  *     in the QUIC stack; or
    243      1.1  christos  *
    244      1.1  christos  *   - Control frame data appended into txp->scratch using tx_helper_begin and
    245      1.1  christos  *     tx_helper_commit.
    246      1.1  christos  *
    247      1.1  christos  */
    248      1.1  christos static int tx_helper_append_iovec(struct tx_helper *h,
    249  1.1.1.2  christos     const unsigned char *buf,
    250  1.1.1.2  christos     size_t buf_len)
    251      1.1  christos {
    252      1.1  christos     struct txp_el *el = &h->txp->el[h->enc_level];
    253      1.1  christos 
    254      1.1  christos     if (buf_len == 0)
    255      1.1  christos         return 1;
    256      1.1  christos 
    257      1.1  christos     if (!ossl_assert(!h->done_implicit))
    258      1.1  christos         return 0;
    259      1.1  christos 
    260      1.1  christos     if (!txp_el_ensure_iovec(el, h->num_iovec + 1))
    261      1.1  christos         return 0;
    262      1.1  christos 
    263  1.1.1.2  christos     el->iovec[h->num_iovec].buf = buf;
    264      1.1  christos     el->iovec[h->num_iovec].buf_len = buf_len;
    265      1.1  christos 
    266      1.1  christos     ++h->num_iovec;
    267      1.1  christos     h->bytes_appended += buf_len;
    268      1.1  christos     return 1;
    269      1.1  christos }
    270      1.1  christos 
    271      1.1  christos /*
    272      1.1  christos  * How many more bytes of space do we have left in our plaintext packet payload?
    273      1.1  christos  */
    274      1.1  christos static size_t tx_helper_get_space_left(struct tx_helper *h)
    275      1.1  christos {
    276      1.1  christos     return h->max_ppl
    277      1.1  christos         - (h->reserve_allowed ? 0 : h->reserve) - h->bytes_appended;
    278      1.1  christos }
    279      1.1  christos 
    280      1.1  christos /*
    281      1.1  christos  * Begin a control frame serialization transaction. This allows the
    282      1.1  christos  * serialization of the control frame to be backed out if it turns out it won't
    283      1.1  christos  * fit. Write the control frame to the returned WPACKET. Ensure you always
    284      1.1  christos  * call tx_helper_rollback or tx_helper_commit (or tx_helper_cleanup). Returns
    285      1.1  christos  * NULL on failure.
    286      1.1  christos  */
    287      1.1  christos static WPACKET *tx_helper_begin(struct tx_helper *h)
    288      1.1  christos {
    289      1.1  christos     size_t space_left, len;
    290      1.1  christos     unsigned char *data;
    291      1.1  christos     struct txp_el *el = &h->txp->el[h->enc_level];
    292      1.1  christos 
    293      1.1  christos     if (!ossl_assert(!h->txn.active))
    294      1.1  christos         return NULL;
    295      1.1  christos 
    296      1.1  christos     if (!ossl_assert(!h->done_implicit))
    297      1.1  christos         return NULL;
    298      1.1  christos 
    299      1.1  christos     data = (unsigned char *)el->scratch + h->scratch_bytes;
    300  1.1.1.2  christos     len = el->scratch_len - h->scratch_bytes;
    301      1.1  christos 
    302      1.1  christos     space_left = tx_helper_get_space_left(h);
    303      1.1  christos     if (!ossl_assert(space_left <= len))
    304      1.1  christos         return NULL;
    305      1.1  christos 
    306      1.1  christos     if (!WPACKET_init_static_len(&h->txn.wpkt, data, len, 0))
    307      1.1  christos         return NULL;
    308      1.1  christos 
    309      1.1  christos     if (!WPACKET_set_max_size(&h->txn.wpkt, space_left)) {
    310      1.1  christos         WPACKET_cleanup(&h->txn.wpkt);
    311      1.1  christos         return NULL;
    312      1.1  christos     }
    313      1.1  christos 
    314  1.1.1.2  christos     h->txn.data = data;
    315  1.1.1.2  christos     h->txn.active = 1;
    316      1.1  christos     return &h->txn.wpkt;
    317      1.1  christos }
    318      1.1  christos 
    319      1.1  christos static void tx_helper_end(struct tx_helper *h, int success)
    320      1.1  christos {
    321      1.1  christos     if (success)
    322      1.1  christos         WPACKET_finish(&h->txn.wpkt);
    323      1.1  christos     else
    324      1.1  christos         WPACKET_cleanup(&h->txn.wpkt);
    325      1.1  christos 
    326  1.1.1.2  christos     h->txn.active = 0;
    327  1.1.1.2  christos     h->txn.data = NULL;
    328      1.1  christos }
    329      1.1  christos 
    330      1.1  christos /* Abort a control frame serialization transaction. */
    331      1.1  christos static void tx_helper_rollback(struct tx_helper *h)
    332      1.1  christos {
    333      1.1  christos     if (!h->txn.active)
    334      1.1  christos         return;
    335      1.1  christos 
    336      1.1  christos     tx_helper_end(h, 0);
    337      1.1  christos }
    338      1.1  christos 
    339      1.1  christos /* Commit a control frame. */
    340      1.1  christos static int tx_helper_commit(struct tx_helper *h)
    341      1.1  christos {
    342      1.1  christos     size_t l = 0;
    343      1.1  christos 
    344      1.1  christos     if (!h->txn.active)
    345      1.1  christos         return 0;
    346      1.1  christos 
    347      1.1  christos     if (!WPACKET_get_total_written(&h->txn.wpkt, &l)) {
    348      1.1  christos         tx_helper_end(h, 0);
    349      1.1  christos         return 0;
    350      1.1  christos     }
    351      1.1  christos 
    352      1.1  christos     if (!tx_helper_append_iovec(h, h->txn.data, l)) {
    353      1.1  christos         tx_helper_end(h, 0);
    354      1.1  christos         return 0;
    355      1.1  christos     }
    356      1.1  christos 
    357      1.1  christos     if (h->txp->msg_callback != NULL && l > 0) {
    358      1.1  christos         uint64_t ftype;
    359      1.1  christos         int ctype = SSL3_RT_QUIC_FRAME_FULL;
    360      1.1  christos         PACKET pkt;
    361      1.1  christos 
    362      1.1  christos         if (!PACKET_buf_init(&pkt, h->txn.data, l)
    363  1.1.1.2  christos             || !ossl_quic_wire_peek_frame_header(&pkt, &ftype, NULL)) {
    364      1.1  christos             tx_helper_end(h, 0);
    365      1.1  christos             return 0;
    366      1.1  christos         }
    367      1.1  christos 
    368      1.1  christos         if (ftype == OSSL_QUIC_FRAME_TYPE_PADDING)
    369      1.1  christos             ctype = SSL3_RT_QUIC_FRAME_PADDING;
    370      1.1  christos         else if (OSSL_QUIC_FRAME_TYPE_IS_STREAM(ftype)
    371  1.1.1.2  christos             || ftype == OSSL_QUIC_FRAME_TYPE_CRYPTO)
    372      1.1  christos             ctype = SSL3_RT_QUIC_FRAME_HEADER;
    373      1.1  christos 
    374      1.1  christos         h->txp->msg_callback(1, OSSL_QUIC1_VERSION, ctype, h->txn.data, l,
    375  1.1.1.2  christos             h->txp->msg_callback_ssl,
    376  1.1.1.2  christos             h->txp->msg_callback_arg);
    377      1.1  christos     }
    378      1.1  christos 
    379      1.1  christos     h->scratch_bytes += l;
    380      1.1  christos     tx_helper_end(h, 1);
    381      1.1  christos     return 1;
    382      1.1  christos }
    383      1.1  christos 
    384      1.1  christos struct archetype_data {
    385  1.1.1.2  christos     unsigned int allow_ack : 1;
    386  1.1.1.2  christos     unsigned int allow_ping : 1;
    387  1.1.1.2  christos     unsigned int allow_crypto : 1;
    388  1.1.1.2  christos     unsigned int allow_handshake_done : 1;
    389  1.1.1.2  christos     unsigned int allow_path_challenge : 1;
    390  1.1.1.2  christos     unsigned int allow_path_response : 1;
    391  1.1.1.2  christos     unsigned int allow_new_conn_id : 1;
    392  1.1.1.2  christos     unsigned int allow_retire_conn_id : 1;
    393  1.1.1.2  christos     unsigned int allow_stream_rel : 1;
    394  1.1.1.2  christos     unsigned int allow_conn_fc : 1;
    395  1.1.1.2  christos     unsigned int allow_conn_close : 1;
    396  1.1.1.2  christos     unsigned int allow_cfq_other : 1;
    397  1.1.1.2  christos     unsigned int allow_new_token : 1;
    398  1.1.1.2  christos     unsigned int allow_force_ack_eliciting : 1;
    399  1.1.1.2  christos     unsigned int allow_padding : 1;
    400  1.1.1.2  christos     unsigned int require_ack_eliciting : 1;
    401  1.1.1.2  christos     unsigned int bypass_cc : 1;
    402      1.1  christos };
    403      1.1  christos 
    404      1.1  christos struct txp_pkt_geom {
    405  1.1.1.2  christos     size_t cmpl, cmppl, hwm, pkt_overhead;
    406  1.1.1.2  christos     uint32_t archetype;
    407  1.1.1.2  christos     struct archetype_data adata;
    408      1.1  christos };
    409      1.1  christos 
    410      1.1  christos struct txp_pkt {
    411  1.1.1.2  christos     struct tx_helper h;
    412  1.1.1.2  christos     int h_valid;
    413  1.1.1.2  christos     QUIC_TXPIM_PKT *tpkt;
    414  1.1.1.2  christos     QUIC_STREAM *stream_head;
    415  1.1.1.2  christos     QUIC_PKT_HDR phdr;
    416      1.1  christos     struct txp_pkt_geom geom;
    417  1.1.1.2  christos     int force_pad;
    418      1.1  christos };
    419      1.1  christos 
    420      1.1  christos static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space,
    421  1.1.1.2  christos     void *arg);
    422      1.1  christos static void on_regen_notify(uint64_t frame_type, uint64_t stream_id,
    423  1.1.1.2  christos     QUIC_TXPIM_PKT *pkt, void *arg);
    424      1.1  christos static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id,
    425  1.1.1.2  christos     QUIC_TXPIM_PKT *pkt, void *arg);
    426      1.1  christos static void on_sstream_updated(uint64_t stream_id, void *arg);
    427      1.1  christos static int sstream_is_pending(QUIC_SSTREAM *sstream);
    428      1.1  christos static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp,
    429  1.1.1.2  christos     uint32_t enc_level,
    430  1.1.1.2  christos     uint32_t archetype,
    431  1.1.1.2  christos     uint64_t cc_limit,
    432  1.1.1.2  christos     uint32_t *conn_close_enc_level);
    433      1.1  christos static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp);
    434      1.1  christos static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp,
    435  1.1.1.2  christos     size_t pl,
    436  1.1.1.2  christos     uint32_t enc_level,
    437  1.1.1.2  christos     size_t hdr_len,
    438  1.1.1.2  christos     size_t *r);
    439      1.1  christos static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp);
    440      1.1  christos static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp,
    441  1.1.1.2  christos     struct txp_pkt *pkt,
    442  1.1.1.2  christos     int chosen_for_conn_close);
    443      1.1  christos static int txp_pkt_init(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp,
    444  1.1.1.2  christos     uint32_t enc_level, uint32_t archetype,
    445  1.1.1.2  christos     size_t running_total);
    446      1.1  christos static void txp_pkt_cleanup(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp);
    447      1.1  christos static int txp_pkt_postgen_update_pkt_overhead(struct txp_pkt *pkt,
    448  1.1.1.2  christos     OSSL_QUIC_TX_PACKETISER *txp);
    449      1.1  christos static int txp_pkt_append_padding(struct txp_pkt *pkt,
    450  1.1.1.2  christos     OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes);
    451      1.1  christos static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, struct txp_pkt *pkt,
    452  1.1.1.2  christos     uint32_t archetype, int *txpim_pkt_reffed);
    453      1.1  christos static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
    454  1.1.1.2  christos     uint64_t cc_limit);
    455      1.1  christos 
    456      1.1  christos /**
    457      1.1  christos  * Sets the validated state of a QUIC TX packetiser.
    458      1.1  christos  *
    459      1.1  christos  * This function marks the provided QUIC TX packetiser as having its credit
    460      1.1  christos  * fully validated by setting its `unvalidated_credit` field to `SIZE_MAX`.
    461      1.1  christos  *
    462      1.1  christos  * @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update.
    463      1.1  christos  */
    464      1.1  christos void ossl_quic_tx_packetiser_set_validated(OSSL_QUIC_TX_PACKETISER *txp)
    465      1.1  christos {
    466      1.1  christos     txp->unvalidated_credit = SIZE_MAX;
    467      1.1  christos     return;
    468      1.1  christos }
    469      1.1  christos 
    470      1.1  christos /**
    471      1.1  christos  * Adds unvalidated credit to a QUIC TX packetiser.
    472      1.1  christos  *
    473      1.1  christos  * This function increases the unvalidated credit of the provided QUIC TX
    474      1.1  christos  * packetiser. If the current unvalidated credit is not `SIZE_MAX`, the
    475      1.1  christos  * function adds three times the specified `credit` value, ensuring it does
    476      1.1  christos  * not exceed the maximum allowable value (`SIZE_MAX - 1`). If the addition
    477      1.1  christos  * would cause an overflow, the unvalidated credit is capped at
    478      1.1  christos  * `SIZE_MAX - 1`. If the current unvalidated credit is already `SIZE_MAX`,
    479      1.1  christos  * the function does nothing.
    480      1.1  christos  *
    481      1.1  christos  * @param txp    A pointer to the OSSL_QUIC_TX_PACKETISER structure to update.
    482      1.1  christos  * @param credit The amount of credit to add, multiplied by 3.
    483      1.1  christos  */
    484      1.1  christos void ossl_quic_tx_packetiser_add_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp,
    485  1.1.1.2  christos     size_t credit)
    486      1.1  christos {
    487      1.1  christos     if (txp->unvalidated_credit != SIZE_MAX) {
    488      1.1  christos         if ((SIZE_MAX - txp->unvalidated_credit) > (credit * 3))
    489      1.1  christos             txp->unvalidated_credit += credit * 3;
    490      1.1  christos         else
    491      1.1  christos             txp->unvalidated_credit = SIZE_MAX - 1;
    492      1.1  christos     }
    493      1.1  christos 
    494      1.1  christos     return;
    495      1.1  christos }
    496      1.1  christos 
    497      1.1  christos /**
    498      1.1  christos  * Consumes unvalidated credit from a QUIC TX packetiser.
    499      1.1  christos  *
    500      1.1  christos  * This function decreases the unvalidated credit of the specified
    501      1.1  christos  * QUIC TX packetiser by the given `credit` value. If the unvalidated credit
    502      1.1  christos  * is set to `SIZE_MAX`, the function does nothing, as `SIZE_MAX` represents
    503      1.1  christos  * an unlimited credit state.
    504      1.1  christos  *
    505      1.1  christos  * @param txp    A pointer to the OSSL_QUIC_TX_PACKETISER structure to update.
    506      1.1  christos  * @param credit The amount of credit to consume.
    507      1.1  christos  */
    508      1.1  christos void ossl_quic_tx_packetiser_consume_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp,
    509  1.1.1.2  christos     size_t credit)
    510      1.1  christos {
    511      1.1  christos     if (txp->unvalidated_credit != SIZE_MAX) {
    512      1.1  christos         if (txp->unvalidated_credit < credit)
    513      1.1  christos             txp->unvalidated_credit = 0;
    514      1.1  christos         else
    515      1.1  christos             txp->unvalidated_credit -= credit;
    516      1.1  christos     }
    517      1.1  christos }
    518      1.1  christos 
    519      1.1  christos /**
    520      1.1  christos  * Checks if the QUIC TX packetiser has sufficient unvalidated credit.
    521      1.1  christos  *
    522      1.1  christos  * This function determines whether the unvalidated credit of the specified
    523      1.1  christos  * QUIC TX packetiser exceeds the required credit value (`req_credit`).
    524      1.1  christos  * If the unvalidated credit is greater than `req_credit`, the function
    525      1.1  christos  * returns 1 (true); otherwise, it returns 0 (false).
    526      1.1  christos  *
    527      1.1  christos  * @param txp        A pointer to the OSSL_QUIC_TX_PACKETISER structure to check.
    528      1.1  christos  * @param req_credit The required credit value to compare against.
    529      1.1  christos  *
    530      1.1  christos  * @return 1 if the unvalidated credit exceeds `req_credit`, 0 otherwise.
    531      1.1  christos  */
    532      1.1  christos int ossl_quic_tx_packetiser_check_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp,
    533  1.1.1.2  christos     size_t req_credit)
    534      1.1  christos {
    535      1.1  christos     return (txp->unvalidated_credit > req_credit);
    536      1.1  christos }
    537      1.1  christos 
    538      1.1  christos OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args)
    539      1.1  christos {
    540      1.1  christos     OSSL_QUIC_TX_PACKETISER *txp;
    541      1.1  christos 
    542      1.1  christos     if (args == NULL
    543      1.1  christos         || args->qtx == NULL
    544      1.1  christos         || args->txpim == NULL
    545      1.1  christos         || args->cfq == NULL
    546      1.1  christos         || args->ackm == NULL
    547      1.1  christos         || args->qsm == NULL
    548      1.1  christos         || args->conn_txfc == NULL
    549      1.1  christos         || args->conn_rxfc == NULL
    550      1.1  christos         || args->max_streams_bidi_rxfc == NULL
    551      1.1  christos         || args->max_streams_uni_rxfc == NULL
    552      1.1  christos         || args->protocol_version == 0) {
    553      1.1  christos         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
    554      1.1  christos         return NULL;
    555      1.1  christos     }
    556      1.1  christos 
    557      1.1  christos     txp = OPENSSL_zalloc(sizeof(*txp));
    558      1.1  christos     if (txp == NULL)
    559      1.1  christos         return NULL;
    560      1.1  christos 
    561  1.1.1.2  christos     txp->args = *args;
    562  1.1.1.2  christos     txp->last_tx_time = ossl_time_zero();
    563      1.1  christos 
    564      1.1  christos     if (!ossl_quic_fifd_init(&txp->fifd,
    565  1.1.1.2  christos             txp->args.cfq, txp->args.ackm, txp->args.txpim,
    566  1.1.1.2  christos             get_sstream_by_id, txp,
    567  1.1.1.2  christos             on_regen_notify, txp,
    568  1.1.1.2  christos             on_confirm_notify, txp,
    569  1.1.1.2  christos             on_sstream_updated, txp,
    570  1.1.1.2  christos             args->get_qlog_cb,
    571  1.1.1.2  christos             args->get_qlog_cb_arg)) {
    572      1.1  christos         OPENSSL_free(txp);
    573      1.1  christos         return NULL;
    574      1.1  christos     }
    575      1.1  christos 
    576      1.1  christos     return txp;
    577      1.1  christos }
    578      1.1  christos 
    579      1.1  christos void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *txp)
    580      1.1  christos {
    581      1.1  christos     uint32_t enc_level;
    582      1.1  christos 
    583      1.1  christos     if (txp == NULL)
    584      1.1  christos         return;
    585      1.1  christos 
    586      1.1  christos     ossl_quic_tx_packetiser_set_initial_token(txp, NULL, 0, NULL, NULL);
    587      1.1  christos     ossl_quic_fifd_cleanup(&txp->fifd);
    588      1.1  christos     OPENSSL_free(txp->conn_close_frame.reason);
    589      1.1  christos 
    590      1.1  christos     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
    591  1.1.1.2  christos         enc_level < QUIC_ENC_LEVEL_NUM;
    592  1.1.1.2  christos         ++enc_level) {
    593      1.1  christos         OPENSSL_free(txp->el[enc_level].iovec);
    594      1.1  christos         OPENSSL_free(txp->el[enc_level].scratch);
    595      1.1  christos     }
    596      1.1  christos 
    597      1.1  christos     OPENSSL_free(txp);
    598      1.1  christos }
    599      1.1  christos 
    600      1.1  christos /*
    601      1.1  christos  * Determine if an Initial packet token length is reasonable based on the
    602      1.1  christos  * current MDPL, returning 1 if it is OK.
    603      1.1  christos  *
    604      1.1  christos  * The real PMTU to the peer could differ from our (pessimistic) understanding
    605      1.1  christos  * of the PMTU, therefore it is possible we could receive an Initial token from
    606      1.1  christos  * a server in a Retry packet which is bigger than the MDPL. In this case it is
    607      1.1  christos  * impossible for us ever to make forward progress and we need to error out
    608      1.1  christos  * and fail the connection attempt.
    609      1.1  christos  *
    610      1.1  christos  * The specific boundary condition is complex: for example, after the size of
    611      1.1  christos  * the Initial token, there are the Initial packet header overheads and then
    612      1.1  christos  * encryption/AEAD tag overheads. After that, the minimum room for frame data in
    613      1.1  christos  * order to guarantee forward progress must be guaranteed. For example, a crypto
    614      1.1  christos  * stream needs to always be able to serialize at least one byte in a CRYPTO
    615      1.1  christos  * frame in order to make forward progress. Because the offset field of a CRYPTO
    616      1.1  christos  * frame uses a variable-length integer, the number of bytes needed to ensure
    617      1.1  christos  * this also varies.
    618      1.1  christos  *
    619      1.1  christos  * Rather than trying to get this boundary condition check actually right,
    620      1.1  christos  * require a reasonable amount of slack to avoid pathological behaviours. (After
    621      1.1  christos  * all, transmitting a CRYPTO stream one byte at a time is probably not
    622      1.1  christos  * desirable anyway.)
    623      1.1  christos  *
    624      1.1  christos  * We choose 160 bytes as the required margin, which is double the rough
    625      1.1  christos  * estimation of the minimum we would require to guarantee forward progress
    626      1.1  christos  * under worst case packet overheads.
    627      1.1  christos  */
    628  1.1.1.2  christos #define TXP_REQUIRED_TOKEN_MARGIN 160
    629      1.1  christos 
    630      1.1  christos static int txp_check_token_len(size_t token_len, size_t mdpl)
    631      1.1  christos {
    632      1.1  christos     if (token_len == 0)
    633      1.1  christos         return 1;
    634      1.1  christos 
    635      1.1  christos     if (token_len >= mdpl)
    636      1.1  christos         return 0;
    637      1.1  christos 
    638      1.1  christos     if (TXP_REQUIRED_TOKEN_MARGIN >= mdpl)
    639      1.1  christos         /* (should not be possible because MDPL must be at least 1200) */
    640      1.1  christos         return 0;
    641      1.1  christos 
    642      1.1  christos     if (token_len > mdpl - TXP_REQUIRED_TOKEN_MARGIN)
    643      1.1  christos         return 0;
    644      1.1  christos 
    645      1.1  christos     return 1;
    646      1.1  christos }
    647      1.1  christos 
    648      1.1  christos int ossl_quic_tx_packetiser_set_initial_token(OSSL_QUIC_TX_PACKETISER *txp,
    649  1.1.1.2  christos     const unsigned char *token,
    650  1.1.1.2  christos     size_t token_len,
    651  1.1.1.2  christos     ossl_quic_initial_token_free_fn *free_cb,
    652  1.1.1.2  christos     void *free_cb_arg)
    653      1.1  christos {
    654      1.1  christos     if (!txp_check_token_len(token_len, txp_get_mdpl(txp)))
    655      1.1  christos         return 0;
    656      1.1  christos 
    657      1.1  christos     if (txp->initial_token != NULL && txp->initial_token_free_cb != NULL)
    658      1.1  christos         txp->initial_token_free_cb(txp->initial_token, txp->initial_token_len,
    659  1.1.1.2  christos             txp->initial_token_free_cb_arg);
    660      1.1  christos 
    661  1.1.1.2  christos     txp->initial_token = token;
    662  1.1.1.2  christos     txp->initial_token_len = token_len;
    663  1.1.1.2  christos     txp->initial_token_free_cb = free_cb;
    664  1.1.1.2  christos     txp->initial_token_free_cb_arg = free_cb_arg;
    665      1.1  christos     return 1;
    666      1.1  christos }
    667      1.1  christos 
    668      1.1  christos int ossl_quic_tx_packetiser_set_protocol_version(OSSL_QUIC_TX_PACKETISER *txp,
    669  1.1.1.2  christos     uint32_t protocol_version)
    670      1.1  christos {
    671      1.1  christos     txp->args.protocol_version = protocol_version;
    672      1.1  christos     return 1;
    673      1.1  christos }
    674      1.1  christos 
    675      1.1  christos int ossl_quic_tx_packetiser_set_cur_dcid(OSSL_QUIC_TX_PACKETISER *txp,
    676  1.1.1.2  christos     const QUIC_CONN_ID *dcid)
    677      1.1  christos {
    678      1.1  christos     if (dcid == NULL) {
    679      1.1  christos         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
    680      1.1  christos         return 0;
    681      1.1  christos     }
    682      1.1  christos 
    683      1.1  christos     txp->args.cur_dcid = *dcid;
    684      1.1  christos     return 1;
    685      1.1  christos }
    686      1.1  christos 
    687      1.1  christos int ossl_quic_tx_packetiser_set_cur_scid(OSSL_QUIC_TX_PACKETISER *txp,
    688  1.1.1.2  christos     const QUIC_CONN_ID *scid)
    689      1.1  christos {
    690      1.1  christos     if (scid == NULL) {
    691      1.1  christos         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
    692      1.1  christos         return 0;
    693      1.1  christos     }
    694      1.1  christos 
    695      1.1  christos     txp->args.cur_scid = *scid;
    696      1.1  christos     return 1;
    697      1.1  christos }
    698      1.1  christos 
    699      1.1  christos /* Change the destination L4 address the TXP uses to send datagrams. */
    700      1.1  christos int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
    701  1.1.1.2  christos     const BIO_ADDR *peer)
    702      1.1  christos {
    703      1.1  christos     if (peer == NULL) {
    704      1.1  christos         BIO_ADDR_clear(&txp->args.peer);
    705      1.1  christos         return 1;
    706      1.1  christos     }
    707      1.1  christos 
    708      1.1  christos     return BIO_ADDR_copy(&txp->args.peer, peer);
    709      1.1  christos }
    710      1.1  christos 
    711      1.1  christos void ossl_quic_tx_packetiser_set_ack_tx_cb(OSSL_QUIC_TX_PACKETISER *txp,
    712  1.1.1.2  christos     void (*cb)(const OSSL_QUIC_FRAME_ACK *ack,
    713  1.1.1.2  christos         uint32_t pn_space,
    714  1.1.1.2  christos         void *arg),
    715  1.1.1.2  christos     void *cb_arg)
    716      1.1  christos {
    717  1.1.1.2  christos     txp->ack_tx_cb = cb;
    718  1.1.1.2  christos     txp->ack_tx_cb_arg = cb_arg;
    719      1.1  christos }
    720      1.1  christos 
    721      1.1  christos void ossl_quic_tx_packetiser_set_qlog_cb(OSSL_QUIC_TX_PACKETISER *txp,
    722  1.1.1.2  christos     QLOG *(*get_qlog_cb)(void *arg),
    723  1.1.1.2  christos     void *get_qlog_cb_arg)
    724      1.1  christos {
    725      1.1  christos     ossl_quic_fifd_set_qlog_cb(&txp->fifd, get_qlog_cb, get_qlog_cb_arg);
    726      1.1  christos }
    727      1.1  christos 
    728      1.1  christos int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
    729  1.1.1.2  christos     uint32_t enc_level)
    730      1.1  christos {
    731      1.1  christos     if (enc_level >= QUIC_ENC_LEVEL_NUM) {
    732      1.1  christos         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
    733      1.1  christos         return 0;
    734      1.1  christos     }
    735      1.1  christos 
    736      1.1  christos     if (enc_level != QUIC_ENC_LEVEL_0RTT)
    737      1.1  christos         txp->args.crypto[ossl_quic_enc_level_to_pn_space(enc_level)] = NULL;
    738      1.1  christos 
    739      1.1  christos     return 1;
    740      1.1  christos }
    741      1.1  christos 
    742      1.1  christos void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp)
    743      1.1  christos {
    744      1.1  christos     txp->handshake_complete = 1;
    745      1.1  christos }
    746      1.1  christos 
    747      1.1  christos void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp)
    748      1.1  christos {
    749      1.1  christos     txp->want_handshake_done = 1;
    750      1.1  christos }
    751      1.1  christos 
    752      1.1  christos void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp,
    753  1.1.1.2  christos     uint32_t pn_space)
    754      1.1  christos {
    755      1.1  christos     txp->force_ack_eliciting |= (1UL << pn_space);
    756      1.1  christos }
    757      1.1  christos 
    758      1.1  christos void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp,
    759  1.1.1.2  christos     uint32_t pn_space)
    760      1.1  christos {
    761      1.1  christos     txp->want_ack |= (1UL << pn_space);
    762      1.1  christos }
    763      1.1  christos 
    764  1.1.1.2  christos #define TXP_ERR_INTERNAL 0 /* Internal (e.g. alloc) error */
    765  1.1.1.2  christos #define TXP_ERR_SUCCESS 1 /* Success */
    766  1.1.1.2  christos #define TXP_ERR_SPACE 2 /* Not enough room for another packet */
    767  1.1.1.2  christos #define TXP_ERR_INPUT 3 /* Invalid/malformed input */
    768      1.1  christos 
    769      1.1  christos /*
    770      1.1  christos  * Generates a datagram by polling the various ELs to determine if they want to
    771      1.1  christos  * generate any frames, and generating a datagram which coalesces packets for
    772      1.1  christos  * any ELs which do.
    773      1.1  christos  */
    774      1.1  christos int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
    775  1.1.1.2  christos     QUIC_TXP_STATUS *status)
    776      1.1  christos {
    777      1.1  christos     /*
    778      1.1  christos      * Called to generate one or more datagrams, each containing one or more
    779      1.1  christos      * packets.
    780      1.1  christos      *
    781      1.1  christos      * There are some tricky things to note here:
    782      1.1  christos      *
    783      1.1  christos      *   - The TXP is only concerned with generating encrypted packets;
    784      1.1  christos      *     other packets use a different path.
    785      1.1  christos      *
    786      1.1  christos      *   - Any datagram containing an Initial packet must have a payload length
    787      1.1  christos      *     (DPL) of at least 1200 bytes. This padding need not necessarily be
    788      1.1  christos      *     found in the Initial packet.
    789      1.1  christos      *
    790      1.1  christos      *     - It is desirable to be able to coalesce an Initial packet
    791      1.1  christos      *       with a Handshake packet. Since, before generating the Handshake
    792      1.1  christos      *       packet, we do not know how long it will be, we cannot know the
    793      1.1  christos      *       correct amount of padding to ensure a DPL of at least 1200 bytes.
    794      1.1  christos      *       Thus this padding must added to the Handshake packet (or whatever
    795      1.1  christos      *       packet is the last in the datagram).
    796      1.1  christos      *
    797      1.1  christos      *     - However, at the time that we generate the Initial packet,
    798      1.1  christos      *       we do not actually know for sure that we will be followed
    799      1.1  christos      *       in the datagram by another packet. For example, suppose we have
    800      1.1  christos      *       some queued data (e.g. crypto stream data for the HANDSHAKE EL)
    801      1.1  christos      *       it looks like we will want to send on the HANDSHAKE EL.
    802      1.1  christos      *       We could assume padding will be placed in the Handshake packet
    803      1.1  christos      *       subsequently and avoid adding any padding to the Initial packet
    804      1.1  christos      *       (which would leave no room for the Handshake packet in the
    805      1.1  christos      *       datagram).
    806      1.1  christos      *
    807      1.1  christos      *       However, this is not actually a safe assumption. Suppose that we
    808      1.1  christos      *       are using a link with a MDPL of 1200 bytes, the minimum allowed by
    809      1.1  christos      *       QUIC. Suppose that the Initial packet consumes 1195 bytes in total.
    810      1.1  christos      *       Since it is not possible to fit a Handshake packet in just 5 bytes,
    811      1.1  christos      *       upon trying to add a Handshake packet after generating the Initial
    812      1.1  christos      *       packet, we will discover we have no room to fit it! This is not a
    813      1.1  christos      *       problem in itself as another datagram can be sent subsequently, but
    814      1.1  christos      *       it is a problem because we were counting to use that packet to hold
    815      1.1  christos      *       the essential padding. But if we have already finished encrypting
    816      1.1  christos      *       the Initial packet, we cannot go and add padding to it anymore.
    817      1.1  christos      *       This leaves us stuck.
    818      1.1  christos      *
    819      1.1  christos      * Because of this, we have to plan multiple packets simultaneously, such
    820      1.1  christos      * that we can start generating a Handshake (or 0-RTT or 1-RTT, or so on)
    821      1.1  christos      * packet while still having the option to go back and add padding to the
    822      1.1  christos      * Initial packet if it turns out to be needed.
    823      1.1  christos      *
    824      1.1  christos      * Trying to predict ahead of time (e.g. during Initial packet generation)
    825      1.1  christos      * whether we will successfully generate a subsequent packet is fraught with
    826      1.1  christos      * error as it relies on a large number of variables:
    827      1.1  christos      *
    828      1.1  christos      *   - Do we have room to fit a packet header? (Consider that due to
    829      1.1  christos      *     variable-length integer encoding this is highly variable and can even
    830      1.1  christos      *     depend on payload length due to a variable-length Length field.)
    831      1.1  christos      *
    832      1.1  christos      *   - Can we fit even a single one of the frames we want to put in this
    833      1.1  christos      *     packet in the packet? (Each frame type has a bespoke encoding. While
    834      1.1  christos      *     our encodings of some frame types are adaptive based on the available
    835      1.1  christos      *     room - e.g. STREAM frames - ultimately all frame types have some
    836      1.1  christos      *     absolute minimum number of bytes to be successfully encoded. For
    837      1.1  christos      *     example, if after an Initial packet there is enough room to encode
    838      1.1  christos      *     only one byte of frame data, it is quite likely we can't send any of
    839      1.1  christos      *     the frames we wanted to send.) While this is not strictly a problem
    840      1.1  christos      *     because we could just fill the packet with padding frames, this is a
    841      1.1  christos      *     pointless packet and is wasteful.
    842      1.1  christos      *
    843      1.1  christos      * Thus we adopt a multi-phase architecture:
    844      1.1  christos      *
    845      1.1  christos      *   1. Archetype Selection: Determine desired packet archetype.
    846      1.1  christos      *
    847      1.1  christos      *   2. Packet Staging: Generation of packet information and packet payload
    848      1.1  christos      *      data (frame data) into staging areas.
    849      1.1  christos      *
    850      1.1  christos      *   3. Packet Adjustment: Adjustment of staged packets, adding padding to
    851      1.1  christos      *      the staged packets if needed.
    852      1.1  christos      *
    853      1.1  christos      *   4. Commit: The packets are sent to the QTX and recorded as having been
    854      1.1  christos      *      sent to the FIFM.
    855      1.1  christos      *
    856      1.1  christos      */
    857      1.1  christos     int res = 0, rc;
    858      1.1  christos     uint32_t archetype, enc_level;
    859      1.1  christos     uint32_t conn_close_enc_level = QUIC_ENC_LEVEL_NUM;
    860      1.1  christos     struct txp_pkt pkt[QUIC_ENC_LEVEL_NUM];
    861      1.1  christos     size_t pkts_done = 0;
    862      1.1  christos     uint64_t cc_limit = txp->args.cc_method->get_tx_allowance(txp->args.cc_data);
    863      1.1  christos     int need_padding = 0, txpim_pkt_reffed;
    864      1.1  christos 
    865      1.1  christos     memset(status, 0, sizeof(*status));
    866      1.1  christos 
    867      1.1  christos     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
    868  1.1.1.2  christos         enc_level < QUIC_ENC_LEVEL_NUM;
    869  1.1.1.2  christos         ++enc_level)
    870      1.1  christos         pkt[enc_level].h_valid = 0;
    871      1.1  christos 
    872      1.1  christos     /*
    873      1.1  christos      * Should not be needed, but a sanity check in case anyone else has been
    874      1.1  christos      * using the QTX.
    875      1.1  christos      */
    876      1.1  christos     ossl_qtx_finish_dgram(txp->args.qtx);
    877      1.1  christos 
    878      1.1  christos     /* 1. Archetype Selection */
    879      1.1  christos     archetype = txp_determine_archetype(txp, cc_limit);
    880      1.1  christos 
    881      1.1  christos     /* 2. Packet Staging */
    882      1.1  christos     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
    883  1.1.1.2  christos         enc_level < QUIC_ENC_LEVEL_NUM;
    884  1.1.1.2  christos         ++enc_level) {
    885      1.1  christos         size_t running_total = (enc_level > QUIC_ENC_LEVEL_INITIAL)
    886  1.1.1.2  christos             ? pkt[enc_level - 1].geom.hwm
    887  1.1.1.2  christos             : 0;
    888      1.1  christos 
    889      1.1  christos         pkt[enc_level].geom.hwm = running_total;
    890      1.1  christos 
    891      1.1  christos         if (!txp_should_try_staging(txp, enc_level, archetype, cc_limit,
    892  1.1.1.2  christos                 &conn_close_enc_level))
    893      1.1  christos             continue;
    894      1.1  christos 
    895      1.1  christos         if (!txp_pkt_init(&pkt[enc_level], txp, enc_level, archetype,
    896  1.1.1.2  christos                 running_total))
    897      1.1  christos             /*
    898      1.1  christos              * If this fails this is not a fatal error - it means the geometry
    899      1.1  christos              * planning determined there was not enough space for another
    900      1.1  christos              * packet. So just proceed with what we've already planned for.
    901      1.1  christos              */
    902      1.1  christos             break;
    903      1.1  christos 
    904      1.1  christos         rc = txp_generate_for_el(txp, &pkt[enc_level],
    905  1.1.1.2  christos             conn_close_enc_level == enc_level);
    906      1.1  christos         if (rc != TXP_ERR_SUCCESS)
    907      1.1  christos             goto out;
    908      1.1  christos 
    909      1.1  christos         if (pkt[enc_level].force_pad)
    910      1.1  christos             /*
    911      1.1  christos              * txp_generate_for_el emitted a frame which forces packet padding.
    912      1.1  christos              */
    913      1.1  christos             need_padding = 1;
    914      1.1  christos 
    915      1.1  christos         pkt[enc_level].geom.hwm = running_total
    916      1.1  christos             + pkt[enc_level].h.bytes_appended
    917      1.1  christos             + pkt[enc_level].geom.pkt_overhead;
    918      1.1  christos     }
    919      1.1  christos 
    920      1.1  christos     /* 3. Packet Adjustment */
    921      1.1  christos     if (pkt[QUIC_ENC_LEVEL_INITIAL].h_valid
    922      1.1  christos         && pkt[QUIC_ENC_LEVEL_INITIAL].h.bytes_appended > 0)
    923      1.1  christos         /*
    924      1.1  christos          * We have an Initial packet in this datagram, so we need to make sure
    925      1.1  christos          * the total size of the datagram is adequate.
    926      1.1  christos          */
    927      1.1  christos         need_padding = 1;
    928      1.1  christos 
    929      1.1  christos     if (need_padding) {
    930      1.1  christos         size_t total_dgram_size = 0;
    931      1.1  christos         const size_t min_dpl = QUIC_MIN_INITIAL_DGRAM_LEN;
    932      1.1  christos         uint32_t pad_el = QUIC_ENC_LEVEL_NUM;
    933      1.1  christos 
    934      1.1  christos         for (enc_level = QUIC_ENC_LEVEL_INITIAL;
    935  1.1.1.2  christos             enc_level < QUIC_ENC_LEVEL_NUM;
    936  1.1.1.2  christos             ++enc_level)
    937      1.1  christos             if (pkt[enc_level].h_valid && pkt[enc_level].h.bytes_appended > 0) {
    938      1.1  christos                 if (pad_el == QUIC_ENC_LEVEL_NUM
    939      1.1  christos                     /*
    940      1.1  christos                      * We might not be able to add padding, for example if we
    941      1.1  christos                      * are using the ACK_ONLY archetype.
    942      1.1  christos                      */
    943      1.1  christos                     && pkt[enc_level].geom.adata.allow_padding
    944      1.1  christos                     && !pkt[enc_level].h.done_implicit)
    945      1.1  christos                     pad_el = enc_level;
    946      1.1  christos 
    947      1.1  christos                 txp_pkt_postgen_update_pkt_overhead(&pkt[enc_level], txp);
    948      1.1  christos                 total_dgram_size += pkt[enc_level].geom.pkt_overhead
    949      1.1  christos                     + pkt[enc_level].h.bytes_appended;
    950      1.1  christos             }
    951      1.1  christos 
    952      1.1  christos         if (pad_el != QUIC_ENC_LEVEL_NUM && total_dgram_size < min_dpl) {
    953      1.1  christos             size_t deficit = min_dpl - total_dgram_size;
    954      1.1  christos 
    955      1.1  christos             if (!txp_pkt_append_padding(&pkt[pad_el], txp, deficit))
    956      1.1  christos                 goto out;
    957      1.1  christos 
    958      1.1  christos             total_dgram_size += deficit;
    959      1.1  christos 
    960      1.1  christos             /*
    961      1.1  christos              * Padding frames make a packet ineligible for being a non-inflight
    962      1.1  christos              * packet.
    963      1.1  christos              */
    964      1.1  christos             pkt[pad_el].tpkt->ackm_pkt.is_inflight = 1;
    965      1.1  christos         }
    966      1.1  christos 
    967      1.1  christos         /*
    968      1.1  christos          * If we have failed to make a datagram of adequate size, for example
    969      1.1  christos          * because we have a padding requirement but are using the ACK_ONLY
    970      1.1  christos          * archetype (because we are CC limited), which precludes us from
    971      1.1  christos          * sending padding, give up on generating the datagram - there is
    972      1.1  christos          * nothing we can do.
    973      1.1  christos          */
    974      1.1  christos         if (total_dgram_size < min_dpl) {
    975      1.1  christos             res = 1;
    976      1.1  christos             goto out;
    977      1.1  christos         }
    978      1.1  christos     }
    979      1.1  christos 
    980      1.1  christos     /* 4. Commit */
    981      1.1  christos     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
    982  1.1.1.2  christos         enc_level < QUIC_ENC_LEVEL_NUM;
    983  1.1.1.2  christos         ++enc_level) {
    984      1.1  christos 
    985      1.1  christos         if (!pkt[enc_level].h_valid)
    986      1.1  christos             /* Did not attempt to generate a packet for this EL. */
    987      1.1  christos             continue;
    988      1.1  christos 
    989      1.1  christos         if (pkt[enc_level].h.bytes_appended == 0)
    990      1.1  christos             /* Nothing was generated for this EL, so skip. */
    991      1.1  christos             continue;
    992      1.1  christos 
    993      1.1  christos         if (!ossl_quic_tx_packetiser_check_unvalidated_credit(txp,
    994  1.1.1.2  christos                 pkt[enc_level].h.bytes_appended)) {
    995      1.1  christos             res = TXP_ERR_SPACE;
    996      1.1  christos             goto out;
    997      1.1  christos         }
    998      1.1  christos         ossl_quic_tx_packetiser_consume_unvalidated_credit(txp, pkt[enc_level].h.bytes_appended);
    999      1.1  christos 
   1000      1.1  christos         rc = txp_pkt_commit(txp, &pkt[enc_level], archetype,
   1001  1.1.1.2  christos             &txpim_pkt_reffed);
   1002      1.1  christos         if (rc) {
   1003      1.1  christos             status->sent_ack_eliciting
   1004      1.1  christos                 = status->sent_ack_eliciting
   1005      1.1  christos                 || pkt[enc_level].tpkt->ackm_pkt.is_ack_eliciting;
   1006      1.1  christos 
   1007      1.1  christos             if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE)
   1008      1.1  christos                 status->sent_handshake
   1009      1.1  christos                     = (pkt[enc_level].h_valid
   1010  1.1.1.2  christos                         && pkt[enc_level].h.bytes_appended > 0);
   1011      1.1  christos         }
   1012      1.1  christos 
   1013      1.1  christos         if (txpim_pkt_reffed)
   1014      1.1  christos             pkt[enc_level].tpkt = NULL; /* don't free */
   1015      1.1  christos 
   1016      1.1  christos         if (!rc)
   1017      1.1  christos             goto out;
   1018      1.1  christos 
   1019      1.1  christos         ++pkts_done;
   1020      1.1  christos     }
   1021      1.1  christos 
   1022      1.1  christos     /* Flush & Cleanup */
   1023      1.1  christos     res = 1;
   1024      1.1  christos out:
   1025      1.1  christos     ossl_qtx_finish_dgram(txp->args.qtx);
   1026      1.1  christos 
   1027      1.1  christos     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
   1028  1.1.1.2  christos         enc_level < QUIC_ENC_LEVEL_NUM;
   1029  1.1.1.2  christos         ++enc_level)
   1030      1.1  christos         txp_pkt_cleanup(&pkt[enc_level], txp);
   1031      1.1  christos 
   1032      1.1  christos     status->sent_pkt = pkts_done;
   1033      1.1  christos 
   1034      1.1  christos     return res;
   1035      1.1  christos }
   1036      1.1  christos 
   1037      1.1  christos static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_ARCHETYPE_NUM] = {
   1038      1.1  christos     /* EL 0(INITIAL) */
   1039      1.1  christos     {
   1040      1.1  christos         /* EL 0(INITIAL) - Archetype 0(NORMAL) */
   1041      1.1  christos         {
   1042  1.1.1.2  christos             /*allow_ack                       =*/1,
   1043  1.1.1.2  christos             /*allow_ping                      =*/1,
   1044  1.1.1.2  christos             /*allow_crypto                    =*/1,
   1045  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1046  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1047  1.1.1.2  christos             /*allow_path_response             =*/0,
   1048  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1049  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1050  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1051  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1052  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1053  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1054  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1055  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1056  1.1.1.2  christos             /*allow_padding                   =*/1,
   1057  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1058  1.1.1.2  christos             /*bypass_cc                       =*/0,
   1059      1.1  christos         },
   1060      1.1  christos         /* EL 0(INITIAL) - Archetype 1(PROBE) */
   1061      1.1  christos         {
   1062  1.1.1.2  christos             /*allow_ack                       =*/1,
   1063  1.1.1.2  christos             /*allow_ping                      =*/1,
   1064  1.1.1.2  christos             /*allow_crypto                    =*/1,
   1065  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1066  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1067  1.1.1.2  christos             /*allow_path_response             =*/0,
   1068  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1069  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1070  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1071  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1072  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1073  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1074  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1075  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1076  1.1.1.2  christos             /*allow_padding                   =*/1,
   1077  1.1.1.2  christos             /*require_ack_eliciting           =*/1,
   1078  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1079      1.1  christos         },
   1080      1.1  christos         /* EL 0(INITIAL) - Archetype 2(ACK_ONLY) */
   1081      1.1  christos         {
   1082  1.1.1.2  christos             /*allow_ack                       =*/1,
   1083  1.1.1.2  christos             /*allow_ping                      =*/0,
   1084  1.1.1.2  christos             /*allow_crypto                    =*/0,
   1085  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1086  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1087  1.1.1.2  christos             /*allow_path_response             =*/0,
   1088  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1089  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1090  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1091  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1092  1.1.1.2  christos             /*allow_conn_close                =*/0,
   1093  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1094  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1095  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1096  1.1.1.2  christos             /*allow_padding                   =*/0,
   1097  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1098  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1099      1.1  christos         },
   1100      1.1  christos     },
   1101      1.1  christos     /* EL 1(0RTT) */
   1102      1.1  christos     {
   1103      1.1  christos         /* EL 1(0RTT) - Archetype 0(NORMAL) */
   1104      1.1  christos         {
   1105  1.1.1.2  christos             /*allow_ack                       =*/0,
   1106  1.1.1.2  christos             /*allow_ping                      =*/1,
   1107  1.1.1.2  christos             /*allow_crypto                    =*/0,
   1108  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1109  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1110  1.1.1.2  christos             /*allow_path_response             =*/0,
   1111  1.1.1.2  christos             /*allow_new_conn_id               =*/1,
   1112  1.1.1.2  christos             /*allow_retire_conn_id            =*/1,
   1113  1.1.1.2  christos             /*allow_stream_rel                =*/1,
   1114  1.1.1.2  christos             /*allow_conn_fc                   =*/1,
   1115  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1116  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1117  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1118  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/0,
   1119  1.1.1.2  christos             /*allow_padding                   =*/1,
   1120  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1121  1.1.1.2  christos             /*bypass_cc                       =*/0,
   1122      1.1  christos         },
   1123      1.1  christos         /* EL 1(0RTT) - Archetype 1(PROBE) */
   1124      1.1  christos         {
   1125  1.1.1.2  christos             /*allow_ack                       =*/0,
   1126  1.1.1.2  christos             /*allow_ping                      =*/1,
   1127  1.1.1.2  christos             /*allow_crypto                    =*/0,
   1128  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1129  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1130  1.1.1.2  christos             /*allow_path_response             =*/0,
   1131  1.1.1.2  christos             /*allow_new_conn_id               =*/1,
   1132  1.1.1.2  christos             /*allow_retire_conn_id            =*/1,
   1133  1.1.1.2  christos             /*allow_stream_rel                =*/1,
   1134  1.1.1.2  christos             /*allow_conn_fc                   =*/1,
   1135  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1136  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1137  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1138  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/0,
   1139  1.1.1.2  christos             /*allow_padding                   =*/1,
   1140  1.1.1.2  christos             /*require_ack_eliciting           =*/1,
   1141  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1142      1.1  christos         },
   1143      1.1  christos         /* EL 1(0RTT) - Archetype 2(ACK_ONLY) */
   1144      1.1  christos         {
   1145  1.1.1.2  christos             /*allow_ack                       =*/0,
   1146  1.1.1.2  christos             /*allow_ping                      =*/0,
   1147  1.1.1.2  christos             /*allow_crypto                    =*/0,
   1148  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1149  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1150  1.1.1.2  christos             /*allow_path_response             =*/0,
   1151  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1152  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1153  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1154  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1155  1.1.1.2  christos             /*allow_conn_close                =*/0,
   1156  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1157  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1158  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/0,
   1159  1.1.1.2  christos             /*allow_padding                   =*/0,
   1160  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1161  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1162      1.1  christos         },
   1163      1.1  christos     },
   1164      1.1  christos     /* EL (HANDSHAKE) */
   1165      1.1  christos     {
   1166      1.1  christos         /* EL 2(HANDSHAKE) - Archetype 0(NORMAL) */
   1167      1.1  christos         {
   1168  1.1.1.2  christos             /*allow_ack                       =*/1,
   1169  1.1.1.2  christos             /*allow_ping                      =*/1,
   1170  1.1.1.2  christos             /*allow_crypto                    =*/1,
   1171  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1172  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1173  1.1.1.2  christos             /*allow_path_response             =*/0,
   1174  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1175  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1176  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1177  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1178  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1179  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1180  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1181  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1182  1.1.1.2  christos             /*allow_padding                   =*/1,
   1183  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1184  1.1.1.2  christos             /*bypass_cc                       =*/0,
   1185      1.1  christos         },
   1186      1.1  christos         /* EL 2(HANDSHAKE) - Archetype 1(PROBE) */
   1187      1.1  christos         {
   1188  1.1.1.2  christos             /*allow_ack                       =*/1,
   1189  1.1.1.2  christos             /*allow_ping                      =*/1,
   1190  1.1.1.2  christos             /*allow_crypto                    =*/1,
   1191  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1192  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1193  1.1.1.2  christos             /*allow_path_response             =*/0,
   1194  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1195  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1196  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1197  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1198  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1199  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1200  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1201  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1202  1.1.1.2  christos             /*allow_padding                   =*/1,
   1203  1.1.1.2  christos             /*require_ack_eliciting           =*/1,
   1204  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1205      1.1  christos         },
   1206      1.1  christos         /* EL 2(HANDSHAKE) - Archetype 2(ACK_ONLY) */
   1207      1.1  christos         {
   1208  1.1.1.2  christos             /*allow_ack                       =*/1,
   1209  1.1.1.2  christos             /*allow_ping                      =*/0,
   1210  1.1.1.2  christos             /*allow_crypto                    =*/0,
   1211  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1212  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1213  1.1.1.2  christos             /*allow_path_response             =*/0,
   1214  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1215  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1216  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1217  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1218  1.1.1.2  christos             /*allow_conn_close                =*/0,
   1219  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1220  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1221  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1222  1.1.1.2  christos             /*allow_padding                   =*/0,
   1223  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1224  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1225      1.1  christos         },
   1226      1.1  christos     },
   1227      1.1  christos     /* EL 3(1RTT) */
   1228      1.1  christos     {
   1229      1.1  christos         /* EL 3(1RTT) - Archetype 0(NORMAL) */
   1230      1.1  christos         {
   1231  1.1.1.2  christos             /*allow_ack                       =*/1,
   1232  1.1.1.2  christos             /*allow_ping                      =*/1,
   1233  1.1.1.2  christos             /*allow_crypto                    =*/1,
   1234  1.1.1.2  christos             /*allow_handshake_done            =*/1,
   1235  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1236  1.1.1.2  christos             /*allow_path_response             =*/1,
   1237  1.1.1.2  christos             /*allow_new_conn_id               =*/1,
   1238  1.1.1.2  christos             /*allow_retire_conn_id            =*/1,
   1239  1.1.1.2  christos             /*allow_stream_rel                =*/1,
   1240  1.1.1.2  christos             /*allow_conn_fc                   =*/1,
   1241  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1242  1.1.1.2  christos             /*allow_cfq_other                 =*/1,
   1243  1.1.1.2  christos             /*allow_new_token                 =*/1,
   1244  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1245  1.1.1.2  christos             /*allow_padding                   =*/1,
   1246  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1247  1.1.1.2  christos             /*bypass_cc                       =*/0,
   1248      1.1  christos         },
   1249      1.1  christos         /* EL 3(1RTT) - Archetype 1(PROBE) */
   1250      1.1  christos         {
   1251  1.1.1.2  christos             /*allow_ack                       =*/1,
   1252  1.1.1.2  christos             /*allow_ping                      =*/1,
   1253  1.1.1.2  christos             /*allow_crypto                    =*/1,
   1254  1.1.1.2  christos             /*allow_handshake_done            =*/1,
   1255  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1256  1.1.1.2  christos             /*allow_path_response             =*/1,
   1257  1.1.1.2  christos             /*allow_new_conn_id               =*/1,
   1258  1.1.1.2  christos             /*allow_retire_conn_id            =*/1,
   1259  1.1.1.2  christos             /*allow_stream_rel                =*/1,
   1260  1.1.1.2  christos             /*allow_conn_fc                   =*/1,
   1261  1.1.1.2  christos             /*allow_conn_close                =*/1,
   1262  1.1.1.2  christos             /*allow_cfq_other                 =*/1,
   1263  1.1.1.2  christos             /*allow_new_token                 =*/1,
   1264  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1265  1.1.1.2  christos             /*allow_padding                   =*/1,
   1266  1.1.1.2  christos             /*require_ack_eliciting           =*/1,
   1267  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1268      1.1  christos         },
   1269      1.1  christos         /* EL 3(1RTT) - Archetype 2(ACK_ONLY) */
   1270      1.1  christos         {
   1271  1.1.1.2  christos             /*allow_ack                       =*/1,
   1272  1.1.1.2  christos             /*allow_ping                      =*/0,
   1273  1.1.1.2  christos             /*allow_crypto                    =*/0,
   1274  1.1.1.2  christos             /*allow_handshake_done            =*/0,
   1275  1.1.1.2  christos             /*allow_path_challenge            =*/0,
   1276  1.1.1.2  christos             /*allow_path_response             =*/0,
   1277  1.1.1.2  christos             /*allow_new_conn_id               =*/0,
   1278  1.1.1.2  christos             /*allow_retire_conn_id            =*/0,
   1279  1.1.1.2  christos             /*allow_stream_rel                =*/0,
   1280  1.1.1.2  christos             /*allow_conn_fc                   =*/0,
   1281  1.1.1.2  christos             /*allow_conn_close                =*/0,
   1282  1.1.1.2  christos             /*allow_cfq_other                 =*/0,
   1283  1.1.1.2  christos             /*allow_new_token                 =*/0,
   1284  1.1.1.2  christos             /*allow_force_ack_eliciting       =*/1,
   1285  1.1.1.2  christos             /*allow_padding                   =*/0,
   1286  1.1.1.2  christos             /*require_ack_eliciting           =*/0,
   1287  1.1.1.2  christos             /*bypass_cc                       =*/1,
   1288  1.1.1.2  christos         } }
   1289      1.1  christos };
   1290      1.1  christos 
   1291      1.1  christos static int txp_get_archetype_data(uint32_t enc_level,
   1292  1.1.1.2  christos     uint32_t archetype,
   1293  1.1.1.2  christos     struct archetype_data *a)
   1294      1.1  christos {
   1295      1.1  christos     if (enc_level >= QUIC_ENC_LEVEL_NUM
   1296      1.1  christos         || archetype >= TX_PACKETISER_ARCHETYPE_NUM)
   1297      1.1  christos         return 0;
   1298      1.1  christos 
   1299      1.1  christos     /* No need to avoid copying this as it should not exceed one int in size. */
   1300      1.1  christos     *a = archetypes[enc_level][archetype];
   1301      1.1  christos     return 1;
   1302      1.1  christos }
   1303      1.1  christos 
   1304      1.1  christos static int txp_determine_geometry(OSSL_QUIC_TX_PACKETISER *txp,
   1305  1.1.1.2  christos     uint32_t archetype,
   1306  1.1.1.2  christos     uint32_t enc_level,
   1307  1.1.1.2  christos     size_t running_total,
   1308  1.1.1.2  christos     QUIC_PKT_HDR *phdr,
   1309  1.1.1.2  christos     struct txp_pkt_geom *geom)
   1310      1.1  christos {
   1311      1.1  christos     size_t mdpl, cmpl, hdr_len;
   1312      1.1  christos 
   1313      1.1  christos     /* Get information about packet archetype. */
   1314      1.1  christos     if (!txp_get_archetype_data(enc_level, archetype, &geom->adata))
   1315  1.1.1.2  christos         return 0;
   1316      1.1  christos 
   1317      1.1  christos     /* Assemble packet header. */
   1318  1.1.1.2  christos     phdr->type = ossl_quic_enc_level_to_pkt_type(enc_level);
   1319  1.1.1.2  christos     phdr->spin_bit = 0;
   1320  1.1.1.2  christos     phdr->pn_len = txp_determine_pn_len(txp);
   1321  1.1.1.2  christos     phdr->partial = 0;
   1322  1.1.1.2  christos     phdr->fixed = 1;
   1323  1.1.1.2  christos     phdr->reserved = 0;
   1324  1.1.1.2  christos     phdr->version = txp->args.protocol_version;
   1325  1.1.1.2  christos     phdr->dst_conn_id = txp->args.cur_dcid;
   1326  1.1.1.2  christos     phdr->src_conn_id = txp->args.cur_scid;
   1327      1.1  christos 
   1328      1.1  christos     /*
   1329      1.1  christos      * We need to know the length of the payload to get an accurate header
   1330      1.1  christos      * length for non-1RTT packets, because the Length field found in
   1331      1.1  christos      * Initial/Handshake/0-RTT packets uses a variable-length encoding. However,
   1332      1.1  christos      * we don't have a good idea of the length of our payload, because the
   1333      1.1  christos      * length of the payload depends on the room in the datagram after fitting
   1334      1.1  christos      * the header, which depends on the size of the header.
   1335      1.1  christos      *
   1336      1.1  christos      * In general, it does not matter if a packet is slightly shorter (because
   1337      1.1  christos      * e.g. we predicted use of a 2-byte length field, but ended up only needing
   1338      1.1  christos      * a 1-byte length field). However this does matter for Initial packets
   1339      1.1  christos      * which must be at least 1200 bytes, which is also the assumed default MTU;
   1340      1.1  christos      * therefore in many cases Initial packets will be padded to 1200 bytes,
   1341      1.1  christos      * which means if we overestimated the header size, we will be short by a
   1342      1.1  christos      * few bytes and the server will ignore the packet for being too short. In
   1343      1.1  christos      * this case, however, such packets always *will* be padded to meet 1200
   1344      1.1  christos      * bytes, which requires a 2-byte length field, so we don't actually need to
   1345      1.1  christos      * worry about this. Thus we estimate the header length assuming a 2-byte
   1346      1.1  christos      * length field here, which should in practice work well in all cases.
   1347      1.1  christos      */
   1348  1.1.1.2  christos     phdr->len = OSSL_QUIC_VLINT_2B_MAX - phdr->pn_len;
   1349      1.1  christos 
   1350      1.1  christos     if (enc_level == QUIC_ENC_LEVEL_INITIAL) {
   1351  1.1.1.2  christos         phdr->token = txp->initial_token;
   1352      1.1  christos         phdr->token_len = txp->initial_token_len;
   1353      1.1  christos     } else {
   1354  1.1.1.2  christos         phdr->token = NULL;
   1355      1.1  christos         phdr->token_len = 0;
   1356      1.1  christos     }
   1357      1.1  christos 
   1358      1.1  christos     hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(phdr->dst_conn_id.id_len,
   1359  1.1.1.2  christos         phdr);
   1360      1.1  christos     if (hdr_len == 0)
   1361      1.1  christos         return 0;
   1362      1.1  christos 
   1363      1.1  christos     /* MDPL: Maximum datagram payload length. */
   1364      1.1  christos     mdpl = txp_get_mdpl(txp);
   1365      1.1  christos 
   1366      1.1  christos     /*
   1367      1.1  christos      * CMPL: Maximum encoded packet size we can put into this datagram given any
   1368      1.1  christos      * previous packets coalesced into it.
   1369      1.1  christos      */
   1370      1.1  christos     if (running_total > mdpl)
   1371      1.1  christos         /* Should not be possible, but if it happens: */
   1372      1.1  christos         cmpl = 0;
   1373      1.1  christos     else
   1374      1.1  christos         cmpl = mdpl - running_total;
   1375      1.1  christos 
   1376      1.1  christos     /* CMPPL: Maximum amount we can put into the current packet payload */
   1377      1.1  christos     if (!txp_determine_ppl_from_pl(txp, cmpl, enc_level, hdr_len, &geom->cmppl))
   1378      1.1  christos         return 0;
   1379      1.1  christos 
   1380  1.1.1.2  christos     geom->cmpl = cmpl;
   1381  1.1.1.2  christos     geom->pkt_overhead = cmpl - geom->cmppl;
   1382  1.1.1.2  christos     geom->archetype = archetype;
   1383      1.1  christos     return 1;
   1384      1.1  christos }
   1385      1.1  christos 
   1386      1.1  christos static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
   1387  1.1.1.2  christos     uint64_t cc_limit)
   1388      1.1  christos {
   1389      1.1  christos     OSSL_ACKM_PROBE_INFO *probe_info
   1390      1.1  christos         = ossl_ackm_get0_probe_request(txp->args.ackm);
   1391      1.1  christos     uint32_t pn_space;
   1392      1.1  christos 
   1393      1.1  christos     /*
   1394      1.1  christos      * If ACKM has requested probe generation (e.g. due to PTO), we generate a
   1395      1.1  christos      * Probe-archetype packet. Actually, we determine archetype on a
   1396      1.1  christos      * per-datagram basis, so if any EL wants a probe, do a pass in which
   1397      1.1  christos      * we try and generate a probe (if needed) for all ELs.
   1398      1.1  christos      */
   1399      1.1  christos     if (probe_info->anti_deadlock_initial > 0
   1400      1.1  christos         || probe_info->anti_deadlock_handshake > 0)
   1401      1.1  christos         return TX_PACKETISER_ARCHETYPE_PROBE;
   1402      1.1  christos 
   1403      1.1  christos     for (pn_space = QUIC_PN_SPACE_INITIAL;
   1404  1.1.1.2  christos         pn_space < QUIC_PN_SPACE_NUM;
   1405  1.1.1.2  christos         ++pn_space)
   1406      1.1  christos         if (probe_info->pto[pn_space] > 0)
   1407      1.1  christos             return TX_PACKETISER_ARCHETYPE_PROBE;
   1408      1.1  christos 
   1409      1.1  christos     /*
   1410      1.1  christos      * If we are out of CC budget, we cannot send a normal packet,
   1411      1.1  christos      * but we can do an ACK-only packet (potentially, if we
   1412      1.1  christos      * want to send an ACK).
   1413      1.1  christos      */
   1414      1.1  christos     if (cc_limit == 0)
   1415      1.1  christos         return TX_PACKETISER_ARCHETYPE_ACK_ONLY;
   1416      1.1  christos 
   1417      1.1  christos     /* All other packets. */
   1418      1.1  christos     return TX_PACKETISER_ARCHETYPE_NORMAL;
   1419      1.1  christos }
   1420      1.1  christos 
   1421      1.1  christos static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp,
   1422  1.1.1.2  christos     uint32_t enc_level,
   1423  1.1.1.2  christos     uint32_t archetype,
   1424  1.1.1.2  christos     uint64_t cc_limit,
   1425  1.1.1.2  christos     uint32_t *conn_close_enc_level)
   1426      1.1  christos {
   1427      1.1  christos     struct archetype_data a;
   1428      1.1  christos     uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   1429      1.1  christos     QUIC_CFQ_ITEM *cfq_item;
   1430      1.1  christos 
   1431      1.1  christos     if (!ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level))
   1432      1.1  christos         return 0;
   1433      1.1  christos 
   1434      1.1  christos     if (!txp_get_archetype_data(enc_level, archetype, &a))
   1435      1.1  christos         return 0;
   1436      1.1  christos 
   1437      1.1  christos     if (!a.bypass_cc && cc_limit == 0)
   1438      1.1  christos         /* CC not allowing us to send. */
   1439      1.1  christos         return 0;
   1440      1.1  christos 
   1441      1.1  christos     /*
   1442      1.1  christos      * We can produce CONNECTION_CLOSE frames on any EL in principle, which
   1443      1.1  christos      * means we need to choose which EL we would prefer to use. After a
   1444      1.1  christos      * connection is fully established we have only one provisioned EL and this
   1445      1.1  christos      * is a non-issue. Where multiple ELs are provisioned, it is possible the
   1446      1.1  christos      * peer does not have the keys for the EL yet, which suggests in general it
   1447      1.1  christos      * is preferable to use the lowest EL which is still provisioned.
   1448      1.1  christos      *
   1449      1.1  christos      * However (RFC 9000 s. 10.2.3 & 12.5) we are also required to not send
   1450      1.1  christos      * application CONNECTION_CLOSE frames in non-1-RTT ELs, so as to not
   1451      1.1  christos      * potentially leak application data on a connection which has yet to be
   1452      1.1  christos      * authenticated. Thus when we have an application CONNECTION_CLOSE frame
   1453      1.1  christos      * queued and need to send it on a non-1-RTT EL, we have to convert it
   1454      1.1  christos      * into a transport CONNECTION_CLOSE frame which contains no application
   1455      1.1  christos      * data. Since this loses information, it suggests we should use the 1-RTT
   1456      1.1  christos      * EL to avoid this if possible, even if a lower EL is also available.
   1457      1.1  christos      *
   1458      1.1  christos      * At the same time, just because we have the 1-RTT EL provisioned locally
   1459      1.1  christos      * does not necessarily mean the peer does, for example if a handshake
   1460      1.1  christos      * CRYPTO frame has been lost. It is fairly important that CONNECTION_CLOSE
   1461      1.1  christos      * is signalled in a way we know our peer can decrypt, as we stop processing
   1462      1.1  christos      * connection retransmission logic for real after connection close and
   1463      1.1  christos      * simply 'blindly' retransmit the same CONNECTION_CLOSE frame.
   1464      1.1  christos      *
   1465      1.1  christos      * This is not a major concern for clients, since if a client has a 1-RTT EL
   1466      1.1  christos      * provisioned the server is guaranteed to also have a 1-RTT EL provisioned.
   1467      1.1  christos      *
   1468      1.1  christos      * TODO(QUIC FUTURE): Revisit this when when have reached a decision on how
   1469      1.1  christos      * best to implement this
   1470      1.1  christos      */
   1471      1.1  christos     if (*conn_close_enc_level > enc_level
   1472      1.1  christos         && *conn_close_enc_level != QUIC_ENC_LEVEL_1RTT)
   1473      1.1  christos         *conn_close_enc_level = enc_level;
   1474      1.1  christos 
   1475      1.1  christos     /* Do we need to send a PTO probe? */
   1476      1.1  christos     if (a.allow_force_ack_eliciting) {
   1477      1.1  christos         OSSL_ACKM_PROBE_INFO *probe_info
   1478      1.1  christos             = ossl_ackm_get0_probe_request(txp->args.ackm);
   1479      1.1  christos 
   1480      1.1  christos         if ((enc_level == QUIC_ENC_LEVEL_INITIAL
   1481  1.1.1.2  christos                 && probe_info->anti_deadlock_initial > 0)
   1482      1.1  christos             || (enc_level == QUIC_ENC_LEVEL_HANDSHAKE
   1483      1.1  christos                 && probe_info->anti_deadlock_handshake > 0)
   1484      1.1  christos             || probe_info->pto[pn_space] > 0)
   1485      1.1  christos             return 1;
   1486      1.1  christos     }
   1487      1.1  christos 
   1488      1.1  christos     /* Does the crypto stream for this EL want to produce anything? */
   1489      1.1  christos     if (a.allow_crypto && sstream_is_pending(txp->args.crypto[pn_space]))
   1490      1.1  christos         return 1;
   1491      1.1  christos 
   1492      1.1  christos     /* Does the ACKM for this PN space want to produce anything? */
   1493  1.1.1.2  christos     if (a.allow_ack && (ossl_ackm_is_ack_desired(txp->args.ackm, pn_space) || (txp->want_ack & (1UL << pn_space)) != 0))
   1494      1.1  christos         return 1;
   1495      1.1  christos 
   1496      1.1  christos     /* Do we need to force emission of an ACK-eliciting packet? */
   1497      1.1  christos     if (a.allow_force_ack_eliciting
   1498      1.1  christos         && (txp->force_ack_eliciting & (1UL << pn_space)) != 0)
   1499      1.1  christos         return 1;
   1500      1.1  christos 
   1501      1.1  christos     /* Does the connection-level RXFC want to produce a frame? */
   1502  1.1.1.2  christos     if (a.allow_conn_fc && (txp->want_max_data || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0)))
   1503      1.1  christos         return 1;
   1504      1.1  christos 
   1505      1.1  christos     /* Do we want to produce a MAX_STREAMS frame? */
   1506      1.1  christos     if (a.allow_conn_fc
   1507      1.1  christos         && (txp->want_max_streams_bidi
   1508      1.1  christos             || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc,
   1509  1.1.1.2  christos                 0)
   1510      1.1  christos             || txp->want_max_streams_uni
   1511      1.1  christos             || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc,
   1512  1.1.1.2  christos                 0)))
   1513      1.1  christos         return 1;
   1514      1.1  christos 
   1515      1.1  christos     /* Do we want to produce a HANDSHAKE_DONE frame? */
   1516      1.1  christos     if (a.allow_handshake_done && txp->want_handshake_done)
   1517      1.1  christos         return 1;
   1518      1.1  christos 
   1519      1.1  christos     /* Do we want to produce a CONNECTION_CLOSE frame? */
   1520  1.1.1.2  christos     if (a.allow_conn_close && txp->want_conn_close && *conn_close_enc_level == enc_level)
   1521      1.1  christos         /*
   1522      1.1  christos          * This is a bit of a special case since CONNECTION_CLOSE can appear in
   1523      1.1  christos          * most packet types, and when we decide we want to send it this status
   1524      1.1  christos          * isn't tied to a specific EL. So if we want to send it, we send it
   1525      1.1  christos          * only on the lowest non-dropped EL.
   1526      1.1  christos          */
   1527      1.1  christos         return 1;
   1528      1.1  christos 
   1529      1.1  christos     /* Does the CFQ have any frames queued for this PN space? */
   1530      1.1  christos     if (enc_level != QUIC_ENC_LEVEL_0RTT)
   1531      1.1  christos         for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space);
   1532  1.1.1.2  christos             cfq_item != NULL;
   1533  1.1.1.2  christos             cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) {
   1534      1.1  christos             uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item);
   1535      1.1  christos 
   1536      1.1  christos             switch (frame_type) {
   1537      1.1  christos             case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
   1538      1.1  christos                 if (a.allow_new_conn_id)
   1539      1.1  christos                     return 1;
   1540      1.1  christos                 break;
   1541      1.1  christos             case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
   1542      1.1  christos                 if (a.allow_retire_conn_id)
   1543      1.1  christos                     return 1;
   1544      1.1  christos                 break;
   1545      1.1  christos             case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
   1546      1.1  christos                 if (a.allow_new_token)
   1547      1.1  christos                     return 1;
   1548      1.1  christos                 break;
   1549      1.1  christos             case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
   1550      1.1  christos                 if (a.allow_path_response)
   1551      1.1  christos                     return 1;
   1552      1.1  christos                 break;
   1553      1.1  christos             default:
   1554      1.1  christos                 if (a.allow_cfq_other)
   1555      1.1  christos                     return 1;
   1556      1.1  christos                 break;
   1557      1.1  christos             }
   1558  1.1.1.2  christos         }
   1559      1.1  christos 
   1560      1.1  christos     if (a.allow_stream_rel && txp->handshake_complete) {
   1561      1.1  christos         QUIC_STREAM_ITER it;
   1562      1.1  christos 
   1563      1.1  christos         /* If there are any active streams, 0/1-RTT wants to produce a packet.
   1564      1.1  christos          * Whether a stream is on the active list is required to be precise
   1565      1.1  christos          * (i.e., a stream is never on the active list if we cannot produce a
   1566      1.1  christos          * frame for it), and all stream-related frames are governed by
   1567      1.1  christos          * a.allow_stream_rel (i.e., if we can send one type of stream-related
   1568      1.1  christos          * frame, we can send any of them), so we don't need to inspect
   1569      1.1  christos          * individual streams on the active list, just confirm that the active
   1570      1.1  christos          * list is non-empty.
   1571      1.1  christos          */
   1572      1.1  christos         ossl_quic_stream_iter_init(&it, txp->args.qsm, 0);
   1573      1.1  christos         if (it.stream != NULL)
   1574      1.1  christos             return 1;
   1575      1.1  christos     }
   1576      1.1  christos 
   1577      1.1  christos     return 0;
   1578      1.1  christos }
   1579      1.1  christos 
   1580      1.1  christos static int sstream_is_pending(QUIC_SSTREAM *sstream)
   1581      1.1  christos {
   1582      1.1  christos     OSSL_QUIC_FRAME_STREAM hdr;
   1583      1.1  christos     OSSL_QTX_IOVEC iov[2];
   1584      1.1  christos     size_t num_iov = OSSL_NELEM(iov);
   1585      1.1  christos 
   1586      1.1  christos     return ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, &num_iov);
   1587      1.1  christos }
   1588      1.1  christos 
   1589      1.1  christos /* Determine how many bytes we should use for the encoded PN. */
   1590      1.1  christos static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp)
   1591      1.1  christos {
   1592      1.1  christos     return 4; /* TODO(QUIC FUTURE) */
   1593      1.1  christos }
   1594      1.1  christos 
   1595      1.1  christos /* Determine plaintext packet payload length from payload length. */
   1596      1.1  christos static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp,
   1597  1.1.1.2  christos     size_t pl,
   1598  1.1.1.2  christos     uint32_t enc_level,
   1599  1.1.1.2  christos     size_t hdr_len,
   1600  1.1.1.2  christos     size_t *r)
   1601      1.1  christos {
   1602      1.1  christos     if (pl < hdr_len)
   1603      1.1  christos         return 0;
   1604      1.1  christos 
   1605      1.1  christos     pl -= hdr_len;
   1606      1.1  christos 
   1607      1.1  christos     if (!ossl_qtx_calculate_plaintext_payload_len(txp->args.qtx, enc_level,
   1608  1.1.1.2  christos             pl, &pl))
   1609      1.1  christos         return 0;
   1610      1.1  christos 
   1611      1.1  christos     *r = pl;
   1612      1.1  christos     return 1;
   1613      1.1  christos }
   1614      1.1  christos 
   1615      1.1  christos static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp)
   1616      1.1  christos {
   1617      1.1  christos     return ossl_qtx_get_mdpl(txp->args.qtx);
   1618      1.1  christos }
   1619      1.1  christos 
   1620      1.1  christos static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space,
   1621  1.1.1.2  christos     void *arg)
   1622      1.1  christos {
   1623      1.1  christos     OSSL_QUIC_TX_PACKETISER *txp = arg;
   1624      1.1  christos     QUIC_STREAM *s;
   1625      1.1  christos 
   1626      1.1  christos     if (stream_id == UINT64_MAX)
   1627      1.1  christos         return txp->args.crypto[pn_space];
   1628      1.1  christos 
   1629      1.1  christos     s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1630      1.1  christos     if (s == NULL)
   1631      1.1  christos         return NULL;
   1632      1.1  christos 
   1633      1.1  christos     return s->sstream;
   1634      1.1  christos }
   1635      1.1  christos 
   1636      1.1  christos static void on_regen_notify(uint64_t frame_type, uint64_t stream_id,
   1637  1.1.1.2  christos     QUIC_TXPIM_PKT *pkt, void *arg)
   1638      1.1  christos {
   1639      1.1  christos     OSSL_QUIC_TX_PACKETISER *txp = arg;
   1640      1.1  christos 
   1641      1.1  christos     switch (frame_type) {
   1642  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE:
   1643  1.1.1.2  christos         txp->want_handshake_done = 1;
   1644  1.1.1.2  christos         break;
   1645  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_MAX_DATA:
   1646  1.1.1.2  christos         txp->want_max_data = 1;
   1647  1.1.1.2  christos         break;
   1648  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
   1649  1.1.1.2  christos         txp->want_max_streams_bidi = 1;
   1650  1.1.1.2  christos         break;
   1651  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
   1652  1.1.1.2  christos         txp->want_max_streams_uni = 1;
   1653  1.1.1.2  christos         break;
   1654  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
   1655  1.1.1.2  christos         txp->want_ack |= (1UL << pkt->ackm_pkt.pkt_space);
   1656  1.1.1.2  christos         break;
   1657  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA: {
   1658  1.1.1.2  christos         QUIC_STREAM *s
   1659  1.1.1.2  christos             = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1660  1.1.1.2  christos 
   1661  1.1.1.2  christos         if (s == NULL)
   1662  1.1.1.2  christos             return;
   1663  1.1.1.2  christos 
   1664  1.1.1.2  christos         s->want_max_stream_data = 1;
   1665  1.1.1.2  christos         ossl_quic_stream_map_update_state(txp->args.qsm, s);
   1666  1.1.1.2  christos     } break;
   1667  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: {
   1668  1.1.1.2  christos         QUIC_STREAM *s
   1669  1.1.1.2  christos             = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1670  1.1.1.2  christos 
   1671  1.1.1.2  christos         if (s == NULL)
   1672  1.1.1.2  christos             return;
   1673  1.1.1.2  christos 
   1674  1.1.1.2  christos         ossl_quic_stream_map_schedule_stop_sending(txp->args.qsm, s);
   1675  1.1.1.2  christos     } break;
   1676  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: {
   1677  1.1.1.2  christos         QUIC_STREAM *s
   1678  1.1.1.2  christos             = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1679  1.1.1.2  christos 
   1680  1.1.1.2  christos         if (s == NULL)
   1681  1.1.1.2  christos             return;
   1682  1.1.1.2  christos 
   1683  1.1.1.2  christos         s->want_reset_stream = 1;
   1684  1.1.1.2  christos         ossl_quic_stream_map_update_state(txp->args.qsm, s);
   1685  1.1.1.2  christos     } break;
   1686  1.1.1.2  christos     default:
   1687  1.1.1.2  christos         assert(0);
   1688  1.1.1.2  christos         break;
   1689      1.1  christos     }
   1690      1.1  christos }
   1691      1.1  christos 
   1692      1.1  christos static int txp_need_ping(OSSL_QUIC_TX_PACKETISER *txp,
   1693  1.1.1.2  christos     uint32_t pn_space,
   1694  1.1.1.2  christos     const struct archetype_data *adata)
   1695      1.1  christos {
   1696      1.1  christos     return adata->allow_ping
   1697      1.1  christos         && (adata->require_ack_eliciting
   1698      1.1  christos             || (txp->force_ack_eliciting & (1UL << pn_space)) != 0);
   1699      1.1  christos }
   1700      1.1  christos 
   1701      1.1  christos static int txp_pkt_init(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp,
   1702  1.1.1.2  christos     uint32_t enc_level, uint32_t archetype,
   1703  1.1.1.2  christos     size_t running_total)
   1704      1.1  christos {
   1705      1.1  christos     uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   1706      1.1  christos 
   1707      1.1  christos     if (!txp_determine_geometry(txp, archetype, enc_level,
   1708  1.1.1.2  christos             running_total, &pkt->phdr, &pkt->geom))
   1709      1.1  christos         return 0;
   1710      1.1  christos 
   1711      1.1  christos     /*
   1712      1.1  christos      * Initialise TX helper. If we must be ACK eliciting, reserve 1 byte for
   1713      1.1  christos      * PING.
   1714      1.1  christos      */
   1715      1.1  christos     if (!tx_helper_init(&pkt->h, txp, enc_level,
   1716  1.1.1.2  christos             pkt->geom.cmppl,
   1717  1.1.1.2  christos             txp_need_ping(txp, pn_space, &pkt->geom.adata) ? 1 : 0))
   1718      1.1  christos         return 0;
   1719      1.1  christos 
   1720  1.1.1.2  christos     pkt->h_valid = 1;
   1721  1.1.1.2  christos     pkt->tpkt = NULL;
   1722  1.1.1.2  christos     pkt->stream_head = NULL;
   1723  1.1.1.2  christos     pkt->force_pad = 0;
   1724      1.1  christos     return 1;
   1725      1.1  christos }
   1726      1.1  christos 
   1727      1.1  christos static void txp_pkt_cleanup(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp)
   1728      1.1  christos {
   1729      1.1  christos     if (!pkt->h_valid)
   1730      1.1  christos         return;
   1731      1.1  christos 
   1732      1.1  christos     tx_helper_cleanup(&pkt->h);
   1733      1.1  christos     pkt->h_valid = 0;
   1734      1.1  christos 
   1735      1.1  christos     if (pkt->tpkt != NULL) {
   1736      1.1  christos         ossl_quic_txpim_pkt_release(txp->args.txpim, pkt->tpkt);
   1737      1.1  christos         pkt->tpkt = NULL;
   1738      1.1  christos     }
   1739      1.1  christos }
   1740      1.1  christos 
   1741      1.1  christos static int txp_pkt_postgen_update_pkt_overhead(struct txp_pkt *pkt,
   1742  1.1.1.2  christos     OSSL_QUIC_TX_PACKETISER *txp)
   1743      1.1  christos {
   1744      1.1  christos     /*
   1745      1.1  christos      * After we have staged and generated our packets, but before we commit
   1746      1.1  christos      * them, it is possible for the estimated packet overhead (packet header +
   1747      1.1  christos      * AEAD tag size) to shrink slightly because we generated a short packet
   1748      1.1  christos      * whose which can be represented in fewer bytes as a variable-length
   1749      1.1  christos      * integer than we were (pessimistically) budgeting for. We need to account
   1750      1.1  christos      * for this to ensure that we get our padding calculation exactly right.
   1751      1.1  christos      *
   1752      1.1  christos      * Update pkt_overhead to be accurate now that we know how much data is
   1753      1.1  christos      * going in a packet.
   1754      1.1  christos      */
   1755      1.1  christos     size_t hdr_len, ciphertext_len;
   1756      1.1  christos 
   1757      1.1  christos     if (pkt->h.enc_level == QUIC_ENC_LEVEL_INITIAL)
   1758      1.1  christos         /*
   1759      1.1  christos          * Don't update overheads for the INITIAL EL - we have not finished
   1760      1.1  christos          * appending padding to it and would potentially miscalculate the
   1761      1.1  christos          * correct padding if we now update the pkt_overhead field to switch to
   1762      1.1  christos          * e.g. a 1-byte length field in the packet header. Since we are padding
   1763      1.1  christos          * to QUIC_MIN_INITIAL_DGRAM_LEN which requires a 2-byte length field,
   1764      1.1  christos          * this is guaranteed to be moot anyway. See comment in
   1765      1.1  christos          * txp_determine_geometry for more information.
   1766      1.1  christos          */
   1767      1.1  christos         return 1;
   1768      1.1  christos 
   1769      1.1  christos     if (!ossl_qtx_calculate_ciphertext_payload_len(txp->args.qtx, pkt->h.enc_level,
   1770  1.1.1.2  christos             pkt->h.bytes_appended,
   1771  1.1.1.2  christos             &ciphertext_len))
   1772      1.1  christos         return 0;
   1773      1.1  christos 
   1774      1.1  christos     pkt->phdr.len = ciphertext_len;
   1775      1.1  christos 
   1776      1.1  christos     hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(pkt->phdr.dst_conn_id.id_len,
   1777  1.1.1.2  christos         &pkt->phdr);
   1778      1.1  christos 
   1779      1.1  christos     pkt->geom.pkt_overhead = hdr_len + ciphertext_len - pkt->h.bytes_appended;
   1780      1.1  christos     return 1;
   1781      1.1  christos }
   1782      1.1  christos 
   1783      1.1  christos static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id,
   1784  1.1.1.2  christos     QUIC_TXPIM_PKT *pkt, void *arg)
   1785      1.1  christos {
   1786      1.1  christos     OSSL_QUIC_TX_PACKETISER *txp = arg;
   1787      1.1  christos 
   1788      1.1  christos     switch (frame_type) {
   1789  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: {
   1790  1.1.1.2  christos         QUIC_STREAM *s
   1791  1.1.1.2  christos             = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1792  1.1.1.2  christos 
   1793  1.1.1.2  christos         if (s == NULL)
   1794  1.1.1.2  christos             return;
   1795  1.1.1.2  christos 
   1796  1.1.1.2  christos         s->acked_stop_sending = 1;
   1797  1.1.1.2  christos         ossl_quic_stream_map_update_state(txp->args.qsm, s);
   1798  1.1.1.2  christos     } break;
   1799  1.1.1.2  christos     case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: {
   1800  1.1.1.2  christos         QUIC_STREAM *s
   1801  1.1.1.2  christos             = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1802      1.1  christos 
   1803  1.1.1.2  christos         if (s == NULL)
   1804  1.1.1.2  christos             return;
   1805      1.1  christos 
   1806  1.1.1.2  christos         /*
   1807  1.1.1.2  christos          * We must already be in RESET_SENT or RESET_RECVD if we are
   1808  1.1.1.2  christos          * here, so we don't need to check state here.
   1809  1.1.1.2  christos          */
   1810  1.1.1.2  christos         ossl_quic_stream_map_notify_reset_stream_acked(txp->args.qsm, s);
   1811  1.1.1.2  christos         ossl_quic_stream_map_update_state(txp->args.qsm, s);
   1812  1.1.1.2  christos     } break;
   1813  1.1.1.2  christos     default:
   1814  1.1.1.2  christos         assert(0);
   1815  1.1.1.2  christos         break;
   1816      1.1  christos     }
   1817      1.1  christos }
   1818      1.1  christos 
   1819      1.1  christos static int txp_pkt_append_padding(struct txp_pkt *pkt,
   1820  1.1.1.2  christos     OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes)
   1821      1.1  christos {
   1822      1.1  christos     WPACKET *wpkt;
   1823      1.1  christos 
   1824      1.1  christos     if (num_bytes == 0)
   1825      1.1  christos         return 1;
   1826      1.1  christos 
   1827      1.1  christos     if (!ossl_assert(pkt->h_valid))
   1828      1.1  christos         return 0;
   1829      1.1  christos 
   1830      1.1  christos     if (!ossl_assert(pkt->tpkt != NULL))
   1831      1.1  christos         return 0;
   1832      1.1  christos 
   1833      1.1  christos     wpkt = tx_helper_begin(&pkt->h);
   1834      1.1  christos     if (wpkt == NULL)
   1835      1.1  christos         return 0;
   1836      1.1  christos 
   1837      1.1  christos     if (!ossl_quic_wire_encode_padding(wpkt, num_bytes)) {
   1838      1.1  christos         tx_helper_rollback(&pkt->h);
   1839      1.1  christos         return 0;
   1840      1.1  christos     }
   1841      1.1  christos 
   1842      1.1  christos     if (!tx_helper_commit(&pkt->h))
   1843      1.1  christos         return 0;
   1844      1.1  christos 
   1845  1.1.1.2  christos     pkt->tpkt->ackm_pkt.num_bytes += num_bytes;
   1846      1.1  christos     /* Cannot be non-inflight if we have a PADDING frame */
   1847  1.1.1.2  christos     pkt->tpkt->ackm_pkt.is_inflight = 1;
   1848      1.1  christos     return 1;
   1849      1.1  christos }
   1850      1.1  christos 
   1851      1.1  christos static void on_sstream_updated(uint64_t stream_id, void *arg)
   1852      1.1  christos {
   1853      1.1  christos     OSSL_QUIC_TX_PACKETISER *txp = arg;
   1854      1.1  christos     QUIC_STREAM *s;
   1855      1.1  christos 
   1856      1.1  christos     s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
   1857      1.1  christos     if (s == NULL)
   1858      1.1  christos         return;
   1859      1.1  christos 
   1860      1.1  christos     ossl_quic_stream_map_update_state(txp->args.qsm, s);
   1861      1.1  christos }
   1862      1.1  christos 
   1863      1.1  christos /*
   1864      1.1  christos  * Returns 1 if we can send that many bytes in closing state, 0 otherwise.
   1865      1.1  christos  * Also maintains the bytes sent state if it returns a success.
   1866      1.1  christos  */
   1867      1.1  christos static int try_commit_conn_close(OSSL_QUIC_TX_PACKETISER *txp, size_t n)
   1868      1.1  christos {
   1869      1.1  christos     int res;
   1870      1.1  christos 
   1871      1.1  christos     /* We can always send the first connection close frame */
   1872      1.1  christos     if (txp->closing_bytes_recv == 0)
   1873      1.1  christos         return 1;
   1874      1.1  christos 
   1875      1.1  christos     /*
   1876      1.1  christos      * RFC 9000 s. 10.2.1 Closing Connection State:
   1877      1.1  christos      *      To avoid being used for an amplification attack, such
   1878      1.1  christos      *      endpoints MUST limit the cumulative size of packets it sends
   1879      1.1  christos      *      to three times the cumulative size of the packets that are
   1880      1.1  christos      *      received and attributed to the connection.
   1881      1.1  christos      * and:
   1882      1.1  christos      *      An endpoint in the closing state MUST either discard packets
   1883      1.1  christos      *      received from an unvalidated address or limit the cumulative
   1884      1.1  christos      *      size of packets it sends to an unvalidated address to three
   1885      1.1  christos      *      times the size of packets it receives from that address.
   1886      1.1  christos      */
   1887      1.1  christos     res = txp->closing_bytes_xmit + n <= txp->closing_bytes_recv * 3;
   1888      1.1  christos 
   1889      1.1  christos     /*
   1890      1.1  christos      * Attribute the bytes to the connection, if we are allowed to send them
   1891      1.1  christos      * and this isn't the first closing frame.
   1892      1.1  christos      */
   1893      1.1  christos     if (res && txp->closing_bytes_recv != 0)
   1894      1.1  christos         txp->closing_bytes_xmit += n;
   1895      1.1  christos     return res;
   1896      1.1  christos }
   1897      1.1  christos 
   1898      1.1  christos void ossl_quic_tx_packetiser_record_received_closing_bytes(
   1899  1.1.1.2  christos     OSSL_QUIC_TX_PACKETISER *txp, size_t n)
   1900      1.1  christos {
   1901      1.1  christos     txp->closing_bytes_recv += n;
   1902      1.1  christos }
   1903      1.1  christos 
   1904      1.1  christos static int txp_generate_pre_token(OSSL_QUIC_TX_PACKETISER *txp,
   1905  1.1.1.2  christos     struct txp_pkt *pkt,
   1906  1.1.1.2  christos     int chosen_for_conn_close,
   1907  1.1.1.2  christos     int *can_be_non_inflight)
   1908      1.1  christos {
   1909      1.1  christos     const uint32_t enc_level = pkt->h.enc_level;
   1910      1.1  christos     const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   1911      1.1  christos     const struct archetype_data *a = &pkt->geom.adata;
   1912      1.1  christos     QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
   1913      1.1  christos     struct tx_helper *h = &pkt->h;
   1914      1.1  christos     const OSSL_QUIC_FRAME_ACK *ack;
   1915      1.1  christos     OSSL_QUIC_FRAME_ACK ack2;
   1916      1.1  christos 
   1917      1.1  christos     tpkt->ackm_pkt.largest_acked = QUIC_PN_INVALID;
   1918      1.1  christos 
   1919      1.1  christos     /* ACK Frames (Regenerate) */
   1920      1.1  christos     if (a->allow_ack
   1921      1.1  christos         && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_ACK
   1922      1.1  christos         && (((txp->want_ack & (1UL << pn_space)) != 0)
   1923      1.1  christos             || ossl_ackm_is_ack_desired(txp->args.ackm, pn_space))
   1924      1.1  christos         && (ack = ossl_ackm_get_ack_frame(txp->args.ackm, pn_space)) != NULL) {
   1925      1.1  christos         WPACKET *wpkt = tx_helper_begin(h);
   1926      1.1  christos 
   1927      1.1  christos         if (wpkt == NULL)
   1928      1.1  christos             return 0;
   1929      1.1  christos 
   1930      1.1  christos         /* We do not currently support ECN */
   1931      1.1  christos         ack2 = *ack;
   1932      1.1  christos         ack2.ecn_present = 0;
   1933      1.1  christos 
   1934      1.1  christos         if (ossl_quic_wire_encode_frame_ack(wpkt,
   1935  1.1.1.2  christos                 txp->args.ack_delay_exponent,
   1936  1.1.1.2  christos                 &ack2)) {
   1937      1.1  christos             if (!tx_helper_commit(h))
   1938      1.1  christos                 return 0;
   1939      1.1  christos 
   1940      1.1  christos             tpkt->had_ack_frame = 1;
   1941      1.1  christos 
   1942      1.1  christos             if (ack->num_ack_ranges > 0)
   1943      1.1  christos                 tpkt->ackm_pkt.largest_acked = ack->ack_ranges[0].end;
   1944      1.1  christos 
   1945      1.1  christos             if (txp->ack_tx_cb != NULL)
   1946      1.1  christos                 txp->ack_tx_cb(&ack2, pn_space, txp->ack_tx_cb_arg);
   1947      1.1  christos         } else {
   1948      1.1  christos             tx_helper_rollback(h);
   1949      1.1  christos         }
   1950      1.1  christos     }
   1951      1.1  christos 
   1952      1.1  christos     /* CONNECTION_CLOSE Frames (Regenerate) */
   1953      1.1  christos     if (a->allow_conn_close && txp->want_conn_close && chosen_for_conn_close) {
   1954      1.1  christos         WPACKET *wpkt = tx_helper_begin(h);
   1955      1.1  christos         OSSL_QUIC_FRAME_CONN_CLOSE f, *pf = &txp->conn_close_frame;
   1956      1.1  christos         size_t l;
   1957      1.1  christos 
   1958      1.1  christos         if (wpkt == NULL)
   1959      1.1  christos             return 0;
   1960      1.1  christos 
   1961      1.1  christos         /*
   1962      1.1  christos          * Application CONNECTION_CLOSE frames may only be sent in the
   1963      1.1  christos          * Application PN space, as otherwise they may be sent before a
   1964      1.1  christos          * connection is authenticated and leak application data. Therefore, if
   1965      1.1  christos          * we need to send a CONNECTION_CLOSE frame in another PN space and were
   1966      1.1  christos          * given an application CONNECTION_CLOSE frame, convert it into a
   1967      1.1  christos          * transport CONNECTION_CLOSE frame, removing any sensitive application
   1968      1.1  christos          * data.
   1969      1.1  christos          *
   1970      1.1  christos          * RFC 9000 s. 10.2.3: "A CONNECTION_CLOSE of type 0x1d MUST be replaced
   1971      1.1  christos          * by a CONNECTION_CLOSE of type 0x1c when sending the frame in Initial
   1972      1.1  christos          * or Handshake packets. Otherwise, information about the application
   1973      1.1  christos          * state might be revealed. Endpoints MUST clear the value of the Reason
   1974      1.1  christos          * Phrase field and SHOULD use the APPLICATION_ERROR code when
   1975      1.1  christos          * converting to a CONNECTION_CLOSE of type 0x1c."
   1976      1.1  christos          */
   1977      1.1  christos         if (pn_space != QUIC_PN_SPACE_APP && pf->is_app) {
   1978      1.1  christos             pf = &f;
   1979  1.1.1.2  christos             pf->is_app = 0;
   1980  1.1.1.2  christos             pf->frame_type = 0;
   1981  1.1.1.2  christos             pf->error_code = OSSL_QUIC_ERR_APPLICATION_ERROR;
   1982  1.1.1.2  christos             pf->reason = NULL;
   1983  1.1.1.2  christos             pf->reason_len = 0;
   1984      1.1  christos         }
   1985      1.1  christos 
   1986      1.1  christos         if (ossl_quic_wire_encode_frame_conn_close(wpkt, pf)
   1987  1.1.1.2  christos             && WPACKET_get_total_written(wpkt, &l)
   1988  1.1.1.2  christos             && try_commit_conn_close(txp, l)) {
   1989      1.1  christos             if (!tx_helper_commit(h))
   1990      1.1  christos                 return 0;
   1991      1.1  christos 
   1992      1.1  christos             tpkt->had_conn_close = 1;
   1993      1.1  christos             *can_be_non_inflight = 0;
   1994      1.1  christos         } else {
   1995      1.1  christos             tx_helper_rollback(h);
   1996      1.1  christos         }
   1997      1.1  christos     }
   1998      1.1  christos 
   1999      1.1  christos     return 1;
   2000      1.1  christos }
   2001      1.1  christos 
   2002      1.1  christos static int try_len(size_t space_left, size_t orig_len,
   2003  1.1.1.2  christos     size_t base_hdr_len, size_t lenbytes,
   2004  1.1.1.2  christos     uint64_t maxn, size_t *hdr_len, size_t *payload_len)
   2005      1.1  christos {
   2006      1.1  christos     size_t n;
   2007      1.1  christos     size_t maxn_ = maxn > SIZE_MAX ? SIZE_MAX : (size_t)maxn;
   2008      1.1  christos 
   2009      1.1  christos     *hdr_len = base_hdr_len + lenbytes;
   2010      1.1  christos 
   2011      1.1  christos     if (orig_len == 0 && space_left >= *hdr_len) {
   2012      1.1  christos         *payload_len = 0;
   2013      1.1  christos         return 1;
   2014      1.1  christos     }
   2015      1.1  christos 
   2016      1.1  christos     n = orig_len;
   2017      1.1  christos     if (n > maxn_)
   2018      1.1  christos         n = maxn_;
   2019      1.1  christos     if (n + *hdr_len > space_left)
   2020      1.1  christos         n = (space_left >= *hdr_len) ? space_left - *hdr_len : 0;
   2021      1.1  christos 
   2022      1.1  christos     *payload_len = n;
   2023      1.1  christos     return n > 0;
   2024      1.1  christos }
   2025      1.1  christos 
   2026      1.1  christos static int determine_len(size_t space_left, size_t orig_len,
   2027  1.1.1.2  christos     size_t base_hdr_len,
   2028  1.1.1.2  christos     uint64_t *hlen, uint64_t *len)
   2029      1.1  christos {
   2030      1.1  christos     int ok = 0;
   2031      1.1  christos     size_t chosen_payload_len = 0;
   2032  1.1.1.2  christos     size_t chosen_hdr_len = 0;
   2033      1.1  christos     size_t payload_len[4], hdr_len[4];
   2034  1.1.1.2  christos     int i, valid[4] = { 0 };
   2035      1.1  christos 
   2036      1.1  christos     valid[0] = try_len(space_left, orig_len, base_hdr_len,
   2037  1.1.1.2  christos         1, OSSL_QUIC_VLINT_1B_MAX,
   2038  1.1.1.2  christos         &hdr_len[0], &payload_len[0]);
   2039      1.1  christos     valid[1] = try_len(space_left, orig_len, base_hdr_len,
   2040  1.1.1.2  christos         2, OSSL_QUIC_VLINT_2B_MAX,
   2041  1.1.1.2  christos         &hdr_len[1], &payload_len[1]);
   2042      1.1  christos     valid[2] = try_len(space_left, orig_len, base_hdr_len,
   2043  1.1.1.2  christos         4, OSSL_QUIC_VLINT_4B_MAX,
   2044  1.1.1.2  christos         &hdr_len[2], &payload_len[2]);
   2045      1.1  christos     valid[3] = try_len(space_left, orig_len, base_hdr_len,
   2046  1.1.1.2  christos         8, OSSL_QUIC_VLINT_8B_MAX,
   2047  1.1.1.2  christos         &hdr_len[3], &payload_len[3]);
   2048      1.1  christos 
   2049  1.1.1.2  christos     for (i = OSSL_NELEM(valid) - 1; i >= 0; --i)
   2050      1.1  christos         if (valid[i] && payload_len[i] >= chosen_payload_len) {
   2051      1.1  christos             chosen_payload_len = payload_len[i];
   2052  1.1.1.2  christos             chosen_hdr_len = hdr_len[i];
   2053  1.1.1.2  christos             ok = 1;
   2054      1.1  christos         }
   2055      1.1  christos 
   2056      1.1  christos     *hlen = chosen_hdr_len;
   2057  1.1.1.2  christos     *len = chosen_payload_len;
   2058      1.1  christos     return ok;
   2059      1.1  christos }
   2060      1.1  christos 
   2061      1.1  christos /*
   2062      1.1  christos  * Given a CRYPTO frame header with accurate chdr->len and a budget
   2063      1.1  christos  * (space_left), try to find the optimal value of chdr->len to fill as much of
   2064      1.1  christos  * the budget as possible. This is slightly hairy because larger values of
   2065      1.1  christos  * chdr->len cause larger encoded sizes of the length field of the frame, which
   2066      1.1  christos  * in turn mean less space available for payload data. We check all possible
   2067      1.1  christos  * encodings and choose the optimal encoding.
   2068      1.1  christos  */
   2069      1.1  christos static int determine_crypto_len(struct tx_helper *h,
   2070  1.1.1.2  christos     OSSL_QUIC_FRAME_CRYPTO *chdr,
   2071  1.1.1.2  christos     size_t space_left,
   2072  1.1.1.2  christos     uint64_t *hlen,
   2073  1.1.1.2  christos     uint64_t *len)
   2074      1.1  christos {
   2075      1.1  christos     size_t orig_len;
   2076      1.1  christos     size_t base_hdr_len; /* CRYPTO header length without length field */
   2077      1.1  christos 
   2078      1.1  christos     if (chdr->len > SIZE_MAX)
   2079      1.1  christos         return 0;
   2080      1.1  christos 
   2081      1.1  christos     orig_len = (size_t)chdr->len;
   2082      1.1  christos 
   2083      1.1  christos     chdr->len = 0;
   2084      1.1  christos     base_hdr_len = ossl_quic_wire_get_encoded_frame_len_crypto_hdr(chdr);
   2085      1.1  christos     chdr->len = orig_len;
   2086      1.1  christos     if (base_hdr_len == 0)
   2087      1.1  christos         return 0;
   2088      1.1  christos 
   2089      1.1  christos     --base_hdr_len;
   2090      1.1  christos 
   2091      1.1  christos     return determine_len(space_left, orig_len, base_hdr_len, hlen, len);
   2092      1.1  christos }
   2093      1.1  christos 
   2094      1.1  christos static int determine_stream_len(struct tx_helper *h,
   2095  1.1.1.2  christos     OSSL_QUIC_FRAME_STREAM *shdr,
   2096  1.1.1.2  christos     size_t space_left,
   2097  1.1.1.2  christos     uint64_t *hlen,
   2098  1.1.1.2  christos     uint64_t *len)
   2099      1.1  christos {
   2100      1.1  christos     size_t orig_len;
   2101      1.1  christos     size_t base_hdr_len; /* STREAM header length without length field */
   2102      1.1  christos 
   2103      1.1  christos     if (shdr->len > SIZE_MAX)
   2104      1.1  christos         return 0;
   2105      1.1  christos 
   2106      1.1  christos     orig_len = (size_t)shdr->len;
   2107      1.1  christos 
   2108      1.1  christos     shdr->len = 0;
   2109      1.1  christos     base_hdr_len = ossl_quic_wire_get_encoded_frame_len_stream_hdr(shdr);
   2110      1.1  christos     shdr->len = orig_len;
   2111      1.1  christos     if (base_hdr_len == 0)
   2112      1.1  christos         return 0;
   2113      1.1  christos 
   2114      1.1  christos     if (shdr->has_explicit_len)
   2115      1.1  christos         --base_hdr_len;
   2116      1.1  christos 
   2117      1.1  christos     return determine_len(space_left, orig_len, base_hdr_len, hlen, len);
   2118      1.1  christos }
   2119      1.1  christos 
   2120      1.1  christos static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp,
   2121  1.1.1.2  christos     struct txp_pkt *pkt,
   2122  1.1.1.2  christos     int *have_ack_eliciting)
   2123      1.1  christos {
   2124      1.1  christos     const uint32_t enc_level = pkt->h.enc_level;
   2125      1.1  christos     const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   2126      1.1  christos     QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
   2127      1.1  christos     struct tx_helper *h = &pkt->h;
   2128      1.1  christos     size_t num_stream_iovec;
   2129  1.1.1.2  christos     OSSL_QUIC_FRAME_STREAM shdr = { 0 };
   2130  1.1.1.2  christos     OSSL_QUIC_FRAME_CRYPTO chdr = { 0 };
   2131      1.1  christos     OSSL_QTX_IOVEC iov[2];
   2132      1.1  christos     uint64_t hdr_bytes;
   2133      1.1  christos     WPACKET *wpkt;
   2134  1.1.1.2  christos     QUIC_TXPIM_CHUNK chunk = { 0 };
   2135      1.1  christos     size_t i, space_left;
   2136      1.1  christos 
   2137      1.1  christos     for (i = 0;; ++i) {
   2138      1.1  christos         space_left = tx_helper_get_space_left(h);
   2139      1.1  christos 
   2140      1.1  christos         if (space_left < MIN_FRAME_SIZE_CRYPTO)
   2141      1.1  christos             return 1; /* no point trying */
   2142      1.1  christos 
   2143      1.1  christos         /* Do we have any CRYPTO data waiting? */
   2144      1.1  christos         num_stream_iovec = OSSL_NELEM(iov);
   2145      1.1  christos         if (!ossl_quic_sstream_get_stream_frame(txp->args.crypto[pn_space],
   2146  1.1.1.2  christos                 i, &shdr, iov,
   2147  1.1.1.2  christos                 &num_stream_iovec))
   2148      1.1  christos             return 1; /* nothing to do */
   2149      1.1  christos 
   2150      1.1  christos         /* Convert STREAM frame header to CRYPTO frame header */
   2151      1.1  christos         chdr.offset = shdr.offset;
   2152  1.1.1.2  christos         chdr.len = shdr.len;
   2153      1.1  christos 
   2154      1.1  christos         if (chdr.len == 0)
   2155      1.1  christos             return 1; /* nothing to do */
   2156      1.1  christos 
   2157      1.1  christos         /* Find best fit (header length, payload length) combination. */
   2158      1.1  christos         if (!determine_crypto_len(h, &chdr, space_left, &hdr_bytes,
   2159  1.1.1.2  christos                 &chdr.len))
   2160      1.1  christos             return 1; /* can't fit anything */
   2161      1.1  christos 
   2162      1.1  christos         /*
   2163      1.1  christos          * Truncate IOVs to match our chosen length.
   2164      1.1  christos          *
   2165      1.1  christos          * The length cannot be more than SIZE_MAX because this length comes
   2166      1.1  christos          * from our send stream buffer.
   2167      1.1  christos          */
   2168      1.1  christos         ossl_quic_sstream_adjust_iov((size_t)chdr.len, iov, num_stream_iovec);
   2169      1.1  christos 
   2170      1.1  christos         /*
   2171      1.1  christos          * Ensure we have enough iovecs allocated (1 for the header, up to 2 for
   2172      1.1  christos          * the stream data.)
   2173      1.1  christos          */
   2174      1.1  christos         if (!txp_el_ensure_iovec(&txp->el[enc_level], h->num_iovec + 3))
   2175      1.1  christos             return 0; /* alloc error */
   2176      1.1  christos 
   2177      1.1  christos         /* Encode the header. */
   2178      1.1  christos         wpkt = tx_helper_begin(h);
   2179      1.1  christos         if (wpkt == NULL)
   2180      1.1  christos             return 0; /* alloc error */
   2181      1.1  christos 
   2182      1.1  christos         if (!ossl_quic_wire_encode_frame_crypto_hdr(wpkt, &chdr)) {
   2183      1.1  christos             tx_helper_rollback(h);
   2184      1.1  christos             return 1; /* can't fit */
   2185      1.1  christos         }
   2186      1.1  christos 
   2187      1.1  christos         if (!tx_helper_commit(h))
   2188      1.1  christos             return 0; /* alloc error */
   2189      1.1  christos 
   2190      1.1  christos         /* Add payload iovecs to the helper (infallible). */
   2191      1.1  christos         for (i = 0; i < num_stream_iovec; ++i)
   2192      1.1  christos             tx_helper_append_iovec(h, iov[i].buf, iov[i].buf_len);
   2193      1.1  christos 
   2194      1.1  christos         *have_ack_eliciting = 1;
   2195      1.1  christos         tx_helper_unrestrict(h); /* no longer need PING */
   2196      1.1  christos 
   2197      1.1  christos         /* Log chunk to TXPIM. */
   2198      1.1  christos         chunk.stream_id = UINT64_MAX; /* crypto stream */
   2199  1.1.1.2  christos         chunk.start = chdr.offset;
   2200  1.1.1.2  christos         chunk.end = chdr.offset + chdr.len - 1;
   2201  1.1.1.2  christos         chunk.has_fin = 0; /* Crypto stream never ends */
   2202      1.1  christos         if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
   2203      1.1  christos             return 0; /* alloc error */
   2204      1.1  christos     }
   2205      1.1  christos }
   2206      1.1  christos 
   2207      1.1  christos struct chunk_info {
   2208      1.1  christos     OSSL_QUIC_FRAME_STREAM shdr;
   2209      1.1  christos     uint64_t orig_len;
   2210      1.1  christos     OSSL_QTX_IOVEC iov[2];
   2211      1.1  christos     size_t num_stream_iovec;
   2212      1.1  christos     int valid;
   2213      1.1  christos };
   2214      1.1  christos 
   2215      1.1  christos static int txp_plan_stream_chunk(OSSL_QUIC_TX_PACKETISER *txp,
   2216  1.1.1.2  christos     struct tx_helper *h,
   2217  1.1.1.2  christos     QUIC_SSTREAM *sstream,
   2218  1.1.1.2  christos     QUIC_TXFC *stream_txfc,
   2219  1.1.1.2  christos     size_t skip,
   2220  1.1.1.2  christos     struct chunk_info *chunk,
   2221  1.1.1.2  christos     uint64_t consumed)
   2222      1.1  christos {
   2223      1.1  christos     uint64_t fc_credit, fc_swm, fc_limit;
   2224      1.1  christos 
   2225      1.1  christos     chunk->num_stream_iovec = OSSL_NELEM(chunk->iov);
   2226      1.1  christos     chunk->valid = ossl_quic_sstream_get_stream_frame(sstream, skip,
   2227  1.1.1.2  christos         &chunk->shdr,
   2228  1.1.1.2  christos         chunk->iov,
   2229  1.1.1.2  christos         &chunk->num_stream_iovec);
   2230      1.1  christos     if (!chunk->valid)
   2231      1.1  christos         return 1;
   2232      1.1  christos 
   2233      1.1  christos     if (!ossl_assert(chunk->shdr.len > 0 || chunk->shdr.is_fin))
   2234      1.1  christos         /* Should only have 0-length chunk if FIN */
   2235      1.1  christos         return 0;
   2236      1.1  christos 
   2237      1.1  christos     chunk->orig_len = chunk->shdr.len;
   2238      1.1  christos 
   2239      1.1  christos     /* Clamp according to connection and stream-level TXFC. */
   2240  1.1.1.2  christos     fc_credit = ossl_quic_txfc_get_credit(stream_txfc, consumed);
   2241  1.1.1.2  christos     fc_swm = ossl_quic_txfc_get_swm(stream_txfc);
   2242  1.1.1.2  christos     fc_limit = fc_swm + fc_credit;
   2243      1.1  christos 
   2244      1.1  christos     if (chunk->shdr.len > 0 && chunk->shdr.offset + chunk->shdr.len > fc_limit) {
   2245      1.1  christos         chunk->shdr.len = (fc_limit <= chunk->shdr.offset)
   2246  1.1.1.2  christos             ? 0
   2247  1.1.1.2  christos             : fc_limit - chunk->shdr.offset;
   2248      1.1  christos         chunk->shdr.is_fin = 0;
   2249      1.1  christos     }
   2250      1.1  christos 
   2251      1.1  christos     if (chunk->shdr.len == 0 && !chunk->shdr.is_fin) {
   2252      1.1  christos         /*
   2253      1.1  christos          * Nothing to do due to TXFC. Since SSTREAM returns chunks in ascending
   2254      1.1  christos          * order of offset we don't need to check any later chunks, so stop
   2255      1.1  christos          * iterating here.
   2256      1.1  christos          */
   2257      1.1  christos         chunk->valid = 0;
   2258      1.1  christos         return 1;
   2259      1.1  christos     }
   2260      1.1  christos 
   2261      1.1  christos     return 1;
   2262      1.1  christos }
   2263      1.1  christos 
   2264      1.1  christos /*
   2265      1.1  christos  * Returns 0 on fatal error (e.g. allocation failure), 1 on success.
   2266      1.1  christos  * *packet_full is set to 1 if there is no longer enough room for another STREAM
   2267      1.1  christos  * frame.
   2268      1.1  christos  */
   2269      1.1  christos static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
   2270  1.1.1.2  christos     struct txp_pkt *pkt,
   2271  1.1.1.2  christos     uint64_t id,
   2272  1.1.1.2  christos     QUIC_SSTREAM *sstream,
   2273  1.1.1.2  christos     QUIC_TXFC *stream_txfc,
   2274  1.1.1.2  christos     QUIC_STREAM *next_stream,
   2275  1.1.1.2  christos     int *have_ack_eliciting,
   2276  1.1.1.2  christos     int *packet_full,
   2277  1.1.1.2  christos     uint64_t *new_credit_consumed,
   2278  1.1.1.2  christos     uint64_t conn_consumed)
   2279      1.1  christos {
   2280      1.1  christos     int rc = 0;
   2281  1.1.1.2  christos     struct chunk_info chunks[2] = { 0 };
   2282      1.1  christos     const uint32_t enc_level = pkt->h.enc_level;
   2283      1.1  christos     QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
   2284      1.1  christos     struct tx_helper *h = &pkt->h;
   2285      1.1  christos     OSSL_QUIC_FRAME_STREAM *shdr;
   2286      1.1  christos     WPACKET *wpkt;
   2287      1.1  christos     QUIC_TXPIM_CHUNK chunk;
   2288      1.1  christos     size_t i, j, space_left;
   2289      1.1  christos     int can_fill_payload, use_explicit_len;
   2290      1.1  christos     int could_have_following_chunk;
   2291      1.1  christos     uint64_t orig_len;
   2292      1.1  christos     uint64_t hdr_len_implicit, payload_len_implicit;
   2293      1.1  christos     uint64_t hdr_len_explicit, payload_len_explicit;
   2294      1.1  christos     uint64_t fc_swm, fc_new_hwm;
   2295      1.1  christos 
   2296  1.1.1.2  christos     fc_swm = ossl_quic_txfc_get_swm(stream_txfc);
   2297  1.1.1.2  christos     fc_new_hwm = fc_swm;
   2298      1.1  christos 
   2299      1.1  christos     /*
   2300      1.1  christos      * Load the first two chunks if any offered by the send stream. We retrieve
   2301      1.1  christos      * the next chunk in advance so we can determine if we need to send any more
   2302      1.1  christos      * chunks from the same stream after this one, which is needed when
   2303      1.1  christos      * determining when we can use an implicit length in a STREAM frame.
   2304      1.1  christos      */
   2305      1.1  christos     for (i = 0; i < 2; ++i) {
   2306      1.1  christos         if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i, &chunks[i],
   2307  1.1.1.2  christos                 conn_consumed))
   2308      1.1  christos             goto err;
   2309      1.1  christos 
   2310      1.1  christos         if (i == 0 && !chunks[i].valid) {
   2311      1.1  christos             /* No chunks, nothing to do. */
   2312      1.1  christos             rc = 1;
   2313      1.1  christos             goto err;
   2314      1.1  christos         }
   2315      1.1  christos         chunks[i].shdr.stream_id = id;
   2316      1.1  christos     }
   2317      1.1  christos 
   2318      1.1  christos     for (i = 0;; ++i) {
   2319      1.1  christos         space_left = tx_helper_get_space_left(h);
   2320      1.1  christos 
   2321      1.1  christos         if (!chunks[i % 2].valid) {
   2322      1.1  christos             /* Out of chunks; we're done. */
   2323      1.1  christos             rc = 1;
   2324      1.1  christos             goto err;
   2325      1.1  christos         }
   2326      1.1  christos 
   2327      1.1  christos         if (space_left < MIN_FRAME_SIZE_STREAM) {
   2328      1.1  christos             *packet_full = 1;
   2329      1.1  christos             rc = 1;
   2330      1.1  christos             goto err;
   2331      1.1  christos         }
   2332      1.1  christos 
   2333      1.1  christos         if (!ossl_assert(!h->done_implicit))
   2334      1.1  christos             /*
   2335      1.1  christos              * Logic below should have ensured we didn't append an
   2336      1.1  christos              * implicit-length unless we filled the packet or didn't have
   2337      1.1  christos              * another stream to handle, so this should not be possible.
   2338      1.1  christos              */
   2339      1.1  christos             goto err;
   2340      1.1  christos 
   2341      1.1  christos         shdr = &chunks[i % 2].shdr;
   2342      1.1  christos         orig_len = chunks[i % 2].orig_len;
   2343      1.1  christos         if (i > 0)
   2344      1.1  christos             /* Load next chunk for lookahead. */
   2345      1.1  christos             if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i + 1,
   2346  1.1.1.2  christos                     &chunks[(i + 1) % 2], conn_consumed))
   2347      1.1  christos                 goto err;
   2348      1.1  christos 
   2349      1.1  christos         /*
   2350      1.1  christos          * Find best fit (header length, payload length) combination for if we
   2351      1.1  christos          * use an implicit length.
   2352      1.1  christos          */
   2353      1.1  christos         shdr->has_explicit_len = 0;
   2354      1.1  christos         hdr_len_implicit = payload_len_implicit = 0;
   2355      1.1  christos         if (!determine_stream_len(h, shdr, space_left,
   2356  1.1.1.2  christos                 &hdr_len_implicit, &payload_len_implicit)) {
   2357      1.1  christos             *packet_full = 1;
   2358      1.1  christos             rc = 1;
   2359      1.1  christos             goto err; /* can't fit anything */
   2360      1.1  christos         }
   2361      1.1  christos 
   2362      1.1  christos         /*
   2363      1.1  christos          * If there is a next stream, we don't use the implicit length so we can
   2364      1.1  christos          * add more STREAM frames after this one, unless there is enough data
   2365      1.1  christos          * for this STREAM frame to fill the packet.
   2366      1.1  christos          */
   2367      1.1  christos         can_fill_payload = (hdr_len_implicit + payload_len_implicit
   2368  1.1.1.2  christos             >= space_left);
   2369      1.1  christos 
   2370      1.1  christos         /*
   2371      1.1  christos          * Is there is a stream after this one, or another chunk pending
   2372      1.1  christos          * transmission in this stream?
   2373      1.1  christos          */
   2374      1.1  christos         could_have_following_chunk
   2375      1.1  christos             = (next_stream != NULL || chunks[(i + 1) % 2].valid);
   2376      1.1  christos 
   2377      1.1  christos         /* Choose between explicit or implicit length representations. */
   2378      1.1  christos         use_explicit_len = !((can_fill_payload || !could_have_following_chunk)
   2379  1.1.1.2  christos             && !pkt->force_pad);
   2380      1.1  christos 
   2381      1.1  christos         if (use_explicit_len) {
   2382      1.1  christos             /*
   2383      1.1  christos              * Find best fit (header length, payload length) combination for if
   2384      1.1  christos              * we use an explicit length.
   2385      1.1  christos              */
   2386      1.1  christos             shdr->has_explicit_len = 1;
   2387      1.1  christos             hdr_len_explicit = payload_len_explicit = 0;
   2388      1.1  christos             if (!determine_stream_len(h, shdr, space_left,
   2389  1.1.1.2  christos                     &hdr_len_explicit, &payload_len_explicit)) {
   2390      1.1  christos                 *packet_full = 1;
   2391      1.1  christos                 rc = 1;
   2392      1.1  christos                 goto err; /* can't fit anything */
   2393      1.1  christos             }
   2394      1.1  christos 
   2395      1.1  christos             shdr->len = payload_len_explicit;
   2396      1.1  christos         } else {
   2397      1.1  christos             *packet_full = 1;
   2398      1.1  christos             shdr->has_explicit_len = 0;
   2399      1.1  christos             shdr->len = payload_len_implicit;
   2400      1.1  christos         }
   2401      1.1  christos 
   2402      1.1  christos         /* If this is a FIN, don't keep filling the packet with more FINs. */
   2403      1.1  christos         if (shdr->is_fin)
   2404      1.1  christos             chunks[(i + 1) % 2].valid = 0;
   2405      1.1  christos 
   2406      1.1  christos         /*
   2407      1.1  christos          * We are now committed to our length (shdr->len can't change).
   2408      1.1  christos          * If we truncated the chunk, clear the FIN bit.
   2409      1.1  christos          */
   2410      1.1  christos         if (shdr->len < orig_len)
   2411      1.1  christos             shdr->is_fin = 0;
   2412      1.1  christos 
   2413      1.1  christos         /* Truncate IOVs to match our chosen length. */
   2414      1.1  christos         ossl_quic_sstream_adjust_iov((size_t)shdr->len, chunks[i % 2].iov,
   2415  1.1.1.2  christos             chunks[i % 2].num_stream_iovec);
   2416      1.1  christos 
   2417      1.1  christos         /*
   2418      1.1  christos          * Ensure we have enough iovecs allocated (1 for the header, up to 2 for
   2419      1.1  christos          * the stream data.)
   2420      1.1  christos          */
   2421      1.1  christos         if (!txp_el_ensure_iovec(&txp->el[enc_level], h->num_iovec + 3))
   2422      1.1  christos             goto err; /* alloc error */
   2423      1.1  christos 
   2424      1.1  christos         /* Encode the header. */
   2425      1.1  christos         wpkt = tx_helper_begin(h);
   2426      1.1  christos         if (wpkt == NULL)
   2427      1.1  christos             goto err; /* alloc error */
   2428      1.1  christos 
   2429      1.1  christos         if (!ossl_assert(ossl_quic_wire_encode_frame_stream_hdr(wpkt, shdr))) {
   2430      1.1  christos             /* (Should not be possible.) */
   2431      1.1  christos             tx_helper_rollback(h);
   2432      1.1  christos             *packet_full = 1;
   2433      1.1  christos             rc = 1;
   2434      1.1  christos             goto err; /* can't fit */
   2435      1.1  christos         }
   2436      1.1  christos 
   2437      1.1  christos         if (!tx_helper_commit(h))
   2438      1.1  christos             goto err; /* alloc error */
   2439      1.1  christos 
   2440      1.1  christos         /* Add payload iovecs to the helper (infallible). */
   2441      1.1  christos         for (j = 0; j < chunks[i % 2].num_stream_iovec; ++j)
   2442      1.1  christos             tx_helper_append_iovec(h, chunks[i % 2].iov[j].buf,
   2443  1.1.1.2  christos                 chunks[i % 2].iov[j].buf_len);
   2444      1.1  christos 
   2445      1.1  christos         *have_ack_eliciting = 1;
   2446      1.1  christos         tx_helper_unrestrict(h); /* no longer need PING */
   2447      1.1  christos         if (!shdr->has_explicit_len)
   2448      1.1  christos             h->done_implicit = 1;
   2449      1.1  christos 
   2450      1.1  christos         /* Log new TXFC credit which was consumed. */
   2451      1.1  christos         if (shdr->len > 0 && shdr->offset + shdr->len > fc_new_hwm)
   2452      1.1  christos             fc_new_hwm = shdr->offset + shdr->len;
   2453      1.1  christos 
   2454      1.1  christos         /* Log chunk to TXPIM. */
   2455  1.1.1.2  christos         chunk.stream_id = shdr->stream_id;
   2456  1.1.1.2  christos         chunk.start = shdr->offset;
   2457  1.1.1.2  christos         chunk.end = shdr->offset + shdr->len - 1;
   2458  1.1.1.2  christos         chunk.has_fin = shdr->is_fin;
   2459  1.1.1.2  christos         chunk.has_stop_sending = 0;
   2460  1.1.1.2  christos         chunk.has_reset_stream = 0;
   2461      1.1  christos         if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
   2462      1.1  christos             goto err; /* alloc error */
   2463      1.1  christos 
   2464      1.1  christos         if (shdr->len < orig_len) {
   2465      1.1  christos             /*
   2466      1.1  christos              * If we did not serialize all of this chunk we definitely do not
   2467      1.1  christos              * want to try the next chunk
   2468      1.1  christos              */
   2469      1.1  christos             rc = 1;
   2470      1.1  christos             goto err;
   2471      1.1  christos         }
   2472      1.1  christos     }
   2473      1.1  christos 
   2474      1.1  christos err:
   2475      1.1  christos     *new_credit_consumed = fc_new_hwm - fc_swm;
   2476      1.1  christos     return rc;
   2477      1.1  christos }
   2478      1.1  christos 
   2479      1.1  christos static void txp_enlink_tmp(QUIC_STREAM **tmp_head, QUIC_STREAM *stream)
   2480      1.1  christos {
   2481      1.1  christos     stream->txp_next = *tmp_head;
   2482      1.1  christos     *tmp_head = stream;
   2483      1.1  christos }
   2484      1.1  christos 
   2485      1.1  christos static int txp_generate_stream_related(OSSL_QUIC_TX_PACKETISER *txp,
   2486  1.1.1.2  christos     struct txp_pkt *pkt,
   2487  1.1.1.2  christos     int *have_ack_eliciting,
   2488  1.1.1.2  christos     QUIC_STREAM **tmp_head)
   2489      1.1  christos {
   2490      1.1  christos     QUIC_STREAM_ITER it;
   2491      1.1  christos     WPACKET *wpkt;
   2492      1.1  christos     uint64_t cwm;
   2493      1.1  christos     QUIC_STREAM *stream, *snext;
   2494      1.1  christos     struct tx_helper *h = &pkt->h;
   2495      1.1  christos     uint64_t conn_consumed = 0;
   2496      1.1  christos 
   2497      1.1  christos     for (ossl_quic_stream_iter_init(&it, txp->args.qsm, 1);
   2498  1.1.1.2  christos         it.stream != NULL;) {
   2499      1.1  christos 
   2500      1.1  christos         stream = it.stream;
   2501      1.1  christos         ossl_quic_stream_iter_next(&it);
   2502      1.1  christos         snext = it.stream;
   2503      1.1  christos 
   2504  1.1.1.2  christos         stream->txp_sent_fc = 0;
   2505  1.1.1.2  christos         stream->txp_sent_stop_sending = 0;
   2506  1.1.1.2  christos         stream->txp_sent_reset_stream = 0;
   2507  1.1.1.2  christos         stream->txp_blocked = 0;
   2508      1.1  christos         stream->txp_txfc_new_credit_consumed = 0;
   2509      1.1  christos 
   2510      1.1  christos         /* Stream Abort Frames (STOP_SENDING, RESET_STREAM) */
   2511      1.1  christos         if (stream->want_stop_sending) {
   2512      1.1  christos             OSSL_QUIC_FRAME_STOP_SENDING f;
   2513      1.1  christos 
   2514      1.1  christos             wpkt = tx_helper_begin(h);
   2515      1.1  christos             if (wpkt == NULL)
   2516      1.1  christos                 return 0; /* alloc error */
   2517      1.1  christos 
   2518  1.1.1.2  christos             f.stream_id = stream->id;
   2519  1.1.1.2  christos             f.app_error_code = stream->stop_sending_aec;
   2520      1.1  christos             if (!ossl_quic_wire_encode_frame_stop_sending(wpkt, &f)) {
   2521      1.1  christos                 tx_helper_rollback(h); /* can't fit */
   2522      1.1  christos                 txp_enlink_tmp(tmp_head, stream);
   2523      1.1  christos                 break;
   2524      1.1  christos             }
   2525      1.1  christos 
   2526      1.1  christos             if (!tx_helper_commit(h))
   2527      1.1  christos                 return 0; /* alloc error */
   2528      1.1  christos 
   2529      1.1  christos             *have_ack_eliciting = 1;
   2530      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2531      1.1  christos             stream->txp_sent_stop_sending = 1;
   2532      1.1  christos         }
   2533      1.1  christos 
   2534      1.1  christos         if (stream->want_reset_stream) {
   2535      1.1  christos             OSSL_QUIC_FRAME_RESET_STREAM f;
   2536      1.1  christos 
   2537      1.1  christos             if (!ossl_assert(stream->send_state == QUIC_SSTREAM_STATE_RESET_SENT))
   2538      1.1  christos                 return 0;
   2539      1.1  christos 
   2540      1.1  christos             wpkt = tx_helper_begin(h);
   2541      1.1  christos             if (wpkt == NULL)
   2542      1.1  christos                 return 0; /* alloc error */
   2543      1.1  christos 
   2544  1.1.1.2  christos             f.stream_id = stream->id;
   2545  1.1.1.2  christos             f.app_error_code = stream->reset_stream_aec;
   2546      1.1  christos             if (!ossl_quic_stream_send_get_final_size(stream, &f.final_size))
   2547      1.1  christos                 return 0; /* should not be possible */
   2548      1.1  christos 
   2549      1.1  christos             if (!ossl_quic_wire_encode_frame_reset_stream(wpkt, &f)) {
   2550      1.1  christos                 tx_helper_rollback(h); /* can't fit */
   2551      1.1  christos                 txp_enlink_tmp(tmp_head, stream);
   2552      1.1  christos                 break;
   2553      1.1  christos             }
   2554      1.1  christos 
   2555      1.1  christos             if (!tx_helper_commit(h))
   2556      1.1  christos                 return 0; /* alloc error */
   2557      1.1  christos 
   2558      1.1  christos             *have_ack_eliciting = 1;
   2559      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2560      1.1  christos             stream->txp_sent_reset_stream = 1;
   2561      1.1  christos 
   2562      1.1  christos             /*
   2563      1.1  christos              * The final size of the stream as indicated by RESET_STREAM is used
   2564      1.1  christos              * to ensure a consistent view of flow control state by both
   2565      1.1  christos              * parties; if we happen to send a RESET_STREAM that consumes more
   2566      1.1  christos              * flow control credit, make sure we account for that.
   2567      1.1  christos              */
   2568      1.1  christos             if (!ossl_assert(f.final_size <= ossl_quic_txfc_get_swm(&stream->txfc)))
   2569      1.1  christos                 return 0;
   2570      1.1  christos 
   2571      1.1  christos             stream->txp_txfc_new_credit_consumed
   2572      1.1  christos                 = f.final_size - ossl_quic_txfc_get_swm(&stream->txfc);
   2573      1.1  christos         }
   2574      1.1  christos 
   2575      1.1  christos         /*
   2576      1.1  christos          * Stream Flow Control Frames (MAX_STREAM_DATA)
   2577      1.1  christos          *
   2578      1.1  christos          * RFC 9000 s. 13.3: "An endpoint SHOULD stop sending MAX_STREAM_DATA
   2579      1.1  christos          * frames when the receiving part of the stream enters a "Size Known" or
   2580      1.1  christos          * "Reset Recvd" state." -- In practice, RECV is the only state
   2581      1.1  christos          * in which it makes sense to generate more MAX_STREAM_DATA frames.
   2582      1.1  christos          */
   2583      1.1  christos         if (stream->recv_state == QUIC_RSTREAM_STATE_RECV
   2584      1.1  christos             && (stream->want_max_stream_data
   2585      1.1  christos                 || ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 0))) {
   2586      1.1  christos 
   2587      1.1  christos             wpkt = tx_helper_begin(h);
   2588      1.1  christos             if (wpkt == NULL)
   2589      1.1  christos                 return 0; /* alloc error */
   2590      1.1  christos 
   2591      1.1  christos             cwm = ossl_quic_rxfc_get_cwm(&stream->rxfc);
   2592      1.1  christos 
   2593      1.1  christos             if (!ossl_quic_wire_encode_frame_max_stream_data(wpkt, stream->id,
   2594  1.1.1.2  christos                     cwm)) {
   2595      1.1  christos                 tx_helper_rollback(h); /* can't fit */
   2596      1.1  christos                 txp_enlink_tmp(tmp_head, stream);
   2597      1.1  christos                 break;
   2598      1.1  christos             }
   2599      1.1  christos 
   2600      1.1  christos             if (!tx_helper_commit(h))
   2601      1.1  christos                 return 0; /* alloc error */
   2602      1.1  christos 
   2603      1.1  christos             *have_ack_eliciting = 1;
   2604      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2605      1.1  christos             stream->txp_sent_fc = 1;
   2606      1.1  christos         }
   2607      1.1  christos 
   2608      1.1  christos         /*
   2609      1.1  christos          * Stream Data Frames (STREAM)
   2610      1.1  christos          *
   2611      1.1  christos          * RFC 9000 s. 3.3: A sender MUST NOT send a STREAM [...] frame for a
   2612      1.1  christos          * stream in the "Reset Sent" state [or any terminal state]. We don't
   2613      1.1  christos          * send any more STREAM frames if we are sending, have sent, or are
   2614      1.1  christos          * planning to send, RESET_STREAM. The other terminal state is Data
   2615      1.1  christos          * Recvd, but txp_generate_stream_frames() is guaranteed to generate
   2616      1.1  christos          * nothing in this case.
   2617      1.1  christos          */
   2618      1.1  christos         if (ossl_quic_stream_has_send_buffer(stream)
   2619      1.1  christos             && !ossl_quic_stream_send_is_reset(stream)) {
   2620      1.1  christos             int packet_full = 0;
   2621      1.1  christos 
   2622      1.1  christos             if (!ossl_assert(!stream->want_reset_stream))
   2623      1.1  christos                 return 0;
   2624      1.1  christos 
   2625      1.1  christos             if (!txp_generate_stream_frames(txp, pkt,
   2626  1.1.1.2  christos                     stream->id, stream->sstream,
   2627  1.1.1.2  christos                     &stream->txfc,
   2628  1.1.1.2  christos                     snext,
   2629  1.1.1.2  christos                     have_ack_eliciting,
   2630  1.1.1.2  christos                     &packet_full,
   2631  1.1.1.2  christos                     &stream->txp_txfc_new_credit_consumed,
   2632  1.1.1.2  christos                     conn_consumed)) {
   2633      1.1  christos                 /* Fatal error (allocation, etc.) */
   2634      1.1  christos                 txp_enlink_tmp(tmp_head, stream);
   2635      1.1  christos                 return 0;
   2636      1.1  christos             }
   2637      1.1  christos             conn_consumed += stream->txp_txfc_new_credit_consumed;
   2638      1.1  christos 
   2639      1.1  christos             if (packet_full) {
   2640      1.1  christos                 txp_enlink_tmp(tmp_head, stream);
   2641      1.1  christos                 break;
   2642      1.1  christos             }
   2643      1.1  christos         }
   2644      1.1  christos 
   2645      1.1  christos         txp_enlink_tmp(tmp_head, stream);
   2646      1.1  christos     }
   2647      1.1  christos 
   2648      1.1  christos     return 1;
   2649      1.1  christos }
   2650      1.1  christos 
   2651      1.1  christos static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp,
   2652  1.1.1.2  christos     struct txp_pkt *pkt,
   2653  1.1.1.2  christos     int chosen_for_conn_close)
   2654      1.1  christos {
   2655      1.1  christos     int rc = TXP_ERR_SUCCESS;
   2656      1.1  christos     const uint32_t enc_level = pkt->h.enc_level;
   2657      1.1  christos     const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   2658      1.1  christos     int have_ack_eliciting = 0, done_pre_token = 0;
   2659      1.1  christos     const struct archetype_data a = pkt->geom.adata;
   2660      1.1  christos     /*
   2661      1.1  christos      * Cleared if we encode any non-ACK-eliciting frame type which rules out the
   2662      1.1  christos      * packet being a non-inflight frame. This means any non-ACK ACK-eliciting
   2663      1.1  christos      * frame, even PADDING frames. ACK eliciting frames always cause a packet to
   2664      1.1  christos      * become ineligible for non-inflight treatment so it is not necessary to
   2665      1.1  christos      * clear this in cases where have_ack_eliciting is set, as it is ignored in
   2666      1.1  christos      * that case.
   2667      1.1  christos      */
   2668      1.1  christos     int can_be_non_inflight = 1;
   2669      1.1  christos     QUIC_CFQ_ITEM *cfq_item;
   2670      1.1  christos     QUIC_TXPIM_PKT *tpkt = NULL;
   2671      1.1  christos     struct tx_helper *h = &pkt->h;
   2672      1.1  christos 
   2673      1.1  christos     /* Maximum PN reached? */
   2674      1.1  christos     if (!ossl_quic_pn_valid(txp->next_pn[pn_space]))
   2675      1.1  christos         goto fatal_err;
   2676      1.1  christos 
   2677      1.1  christos     if (!ossl_assert(pkt->tpkt == NULL))
   2678      1.1  christos         goto fatal_err;
   2679      1.1  christos 
   2680      1.1  christos     if ((pkt->tpkt = tpkt = ossl_quic_txpim_pkt_alloc(txp->args.txpim)) == NULL)
   2681      1.1  christos         goto fatal_err;
   2682      1.1  christos 
   2683      1.1  christos     /*
   2684      1.1  christos      * Frame Serialization
   2685      1.1  christos      * ===================
   2686      1.1  christos      *
   2687      1.1  christos      * We now serialize frames into the packet in descending order of priority.
   2688      1.1  christos      */
   2689      1.1  christos 
   2690      1.1  christos     /* HANDSHAKE_DONE (Regenerate) */
   2691      1.1  christos     if (a.allow_handshake_done && txp->want_handshake_done
   2692      1.1  christos         && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_HANDSHAKE_DONE) {
   2693      1.1  christos         WPACKET *wpkt = tx_helper_begin(h);
   2694      1.1  christos 
   2695      1.1  christos         if (wpkt == NULL)
   2696      1.1  christos             goto fatal_err;
   2697      1.1  christos 
   2698      1.1  christos         if (ossl_quic_wire_encode_frame_handshake_done(wpkt)) {
   2699      1.1  christos             tpkt->had_handshake_done_frame = 1;
   2700  1.1.1.2  christos             have_ack_eliciting = 1;
   2701      1.1  christos 
   2702      1.1  christos             if (!tx_helper_commit(h))
   2703      1.1  christos                 goto fatal_err;
   2704      1.1  christos 
   2705      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2706      1.1  christos         } else {
   2707      1.1  christos             tx_helper_rollback(h);
   2708      1.1  christos         }
   2709      1.1  christos     }
   2710      1.1  christos 
   2711      1.1  christos     /* MAX_DATA (Regenerate) */
   2712      1.1  christos     if (a.allow_conn_fc
   2713      1.1  christos         && (txp->want_max_data
   2714      1.1  christos             || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0))
   2715      1.1  christos         && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_DATA) {
   2716      1.1  christos         WPACKET *wpkt = tx_helper_begin(h);
   2717      1.1  christos         uint64_t cwm = ossl_quic_rxfc_get_cwm(txp->args.conn_rxfc);
   2718      1.1  christos 
   2719      1.1  christos         if (wpkt == NULL)
   2720      1.1  christos             goto fatal_err;
   2721      1.1  christos 
   2722      1.1  christos         if (ossl_quic_wire_encode_frame_max_data(wpkt, cwm)) {
   2723      1.1  christos             tpkt->had_max_data_frame = 1;
   2724  1.1.1.2  christos             have_ack_eliciting = 1;
   2725      1.1  christos 
   2726      1.1  christos             if (!tx_helper_commit(h))
   2727      1.1  christos                 goto fatal_err;
   2728      1.1  christos 
   2729      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2730      1.1  christos         } else {
   2731      1.1  christos             tx_helper_rollback(h);
   2732      1.1  christos         }
   2733      1.1  christos     }
   2734      1.1  christos 
   2735      1.1  christos     /* MAX_STREAMS_BIDI (Regenerate) */
   2736      1.1  christos     if (a.allow_conn_fc
   2737      1.1  christos         && (txp->want_max_streams_bidi
   2738      1.1  christos             || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 0))
   2739      1.1  christos         && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_STREAMS_BIDI) {
   2740      1.1  christos         WPACKET *wpkt = tx_helper_begin(h);
   2741      1.1  christos         uint64_t max_streams
   2742      1.1  christos             = ossl_quic_rxfc_get_cwm(txp->args.max_streams_bidi_rxfc);
   2743      1.1  christos 
   2744      1.1  christos         if (wpkt == NULL)
   2745      1.1  christos             goto fatal_err;
   2746      1.1  christos 
   2747      1.1  christos         if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/0,
   2748  1.1.1.2  christos                 max_streams)) {
   2749      1.1  christos             tpkt->had_max_streams_bidi_frame = 1;
   2750  1.1.1.2  christos             have_ack_eliciting = 1;
   2751      1.1  christos 
   2752      1.1  christos             if (!tx_helper_commit(h))
   2753      1.1  christos                 goto fatal_err;
   2754      1.1  christos 
   2755      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2756      1.1  christos         } else {
   2757      1.1  christos             tx_helper_rollback(h);
   2758      1.1  christos         }
   2759      1.1  christos     }
   2760      1.1  christos 
   2761      1.1  christos     /* MAX_STREAMS_UNI (Regenerate) */
   2762      1.1  christos     if (a.allow_conn_fc
   2763      1.1  christos         && (txp->want_max_streams_uni
   2764      1.1  christos             || ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 0))
   2765      1.1  christos         && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_STREAMS_UNI) {
   2766      1.1  christos         WPACKET *wpkt = tx_helper_begin(h);
   2767      1.1  christos         uint64_t max_streams
   2768      1.1  christos             = ossl_quic_rxfc_get_cwm(txp->args.max_streams_uni_rxfc);
   2769      1.1  christos 
   2770      1.1  christos         if (wpkt == NULL)
   2771      1.1  christos             goto fatal_err;
   2772      1.1  christos 
   2773      1.1  christos         if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/1,
   2774  1.1.1.2  christos                 max_streams)) {
   2775      1.1  christos             tpkt->had_max_streams_uni_frame = 1;
   2776  1.1.1.2  christos             have_ack_eliciting = 1;
   2777      1.1  christos 
   2778      1.1  christos             if (!tx_helper_commit(h))
   2779      1.1  christos                 goto fatal_err;
   2780      1.1  christos 
   2781      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2782      1.1  christos         } else {
   2783      1.1  christos             tx_helper_rollback(h);
   2784      1.1  christos         }
   2785      1.1  christos     }
   2786      1.1  christos 
   2787      1.1  christos     /* GCR Frames */
   2788      1.1  christos     for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space);
   2789  1.1.1.2  christos         cfq_item != NULL;
   2790  1.1.1.2  christos         cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) {
   2791      1.1  christos         uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item);
   2792      1.1  christos         const unsigned char *encoded = ossl_quic_cfq_item_get_encoded(cfq_item);
   2793      1.1  christos         size_t encoded_len = ossl_quic_cfq_item_get_encoded_len(cfq_item);
   2794      1.1  christos 
   2795      1.1  christos         switch (frame_type) {
   2796  1.1.1.2  christos         case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
   2797  1.1.1.2  christos             if (!a.allow_new_conn_id)
   2798  1.1.1.2  christos                 continue;
   2799  1.1.1.2  christos             break;
   2800  1.1.1.2  christos         case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
   2801  1.1.1.2  christos             if (!a.allow_retire_conn_id)
   2802  1.1.1.2  christos                 continue;
   2803  1.1.1.2  christos             break;
   2804  1.1.1.2  christos         case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
   2805  1.1.1.2  christos             if (!a.allow_new_token)
   2806  1.1.1.2  christos                 continue;
   2807      1.1  christos 
   2808  1.1.1.2  christos             /*
   2809  1.1.1.2  christos              * NEW_TOKEN frames are handled via GCR, but some
   2810  1.1.1.2  christos              * Regenerate-strategy frames should come before them (namely
   2811  1.1.1.2  christos              * ACK, CONNECTION_CLOSE, PATH_CHALLENGE and PATH_RESPONSE). If
   2812  1.1.1.2  christos              * we find a NEW_TOKEN frame, do these now. If there are no
   2813  1.1.1.2  christos              * NEW_TOKEN frames in the GCR queue we will handle these below.
   2814  1.1.1.2  christos              */
   2815  1.1.1.2  christos             if (!done_pre_token)
   2816  1.1.1.2  christos                 if (txp_generate_pre_token(txp, pkt,
   2817  1.1.1.2  christos                         chosen_for_conn_close,
   2818  1.1.1.2  christos                         &can_be_non_inflight))
   2819  1.1.1.2  christos                     done_pre_token = 1;
   2820      1.1  christos 
   2821  1.1.1.2  christos             break;
   2822  1.1.1.2  christos         case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
   2823  1.1.1.2  christos             if (!a.allow_path_response)
   2824  1.1.1.2  christos                 continue;
   2825      1.1  christos 
   2826  1.1.1.2  christos             /*
   2827  1.1.1.2  christos              * RFC 9000 s. 8.2.2: An endpoint MUST expand datagrams that
   2828  1.1.1.2  christos              * contain a PATH_RESPONSE frame to at least the smallest
   2829  1.1.1.2  christos              * allowed maximum datagram size of 1200 bytes.
   2830  1.1.1.2  christos              */
   2831  1.1.1.2  christos             pkt->force_pad = 1;
   2832  1.1.1.2  christos             break;
   2833  1.1.1.2  christos         default:
   2834  1.1.1.2  christos             if (!a.allow_cfq_other)
   2835  1.1.1.2  christos                 continue;
   2836  1.1.1.2  christos             break;
   2837      1.1  christos         }
   2838      1.1  christos 
   2839      1.1  christos         /*
   2840      1.1  christos          * If the frame is too big, don't try to schedule any more GCR frames in
   2841      1.1  christos          * this packet rather than sending subsequent ones out of order.
   2842      1.1  christos          */
   2843      1.1  christos         if (encoded_len > tx_helper_get_space_left(h))
   2844      1.1  christos             break;
   2845      1.1  christos 
   2846      1.1  christos         if (!tx_helper_append_iovec(h, encoded, encoded_len))
   2847      1.1  christos             goto fatal_err;
   2848      1.1  christos 
   2849      1.1  christos         ossl_quic_txpim_pkt_add_cfq_item(tpkt, cfq_item);
   2850      1.1  christos 
   2851      1.1  christos         if (ossl_quic_frame_type_is_ack_eliciting(frame_type)) {
   2852      1.1  christos             have_ack_eliciting = 1;
   2853      1.1  christos             tx_helper_unrestrict(h); /* no longer need PING */
   2854      1.1  christos         }
   2855      1.1  christos     }
   2856      1.1  christos 
   2857      1.1  christos     /*
   2858      1.1  christos      * If we didn't generate ACK, CONNECTION_CLOSE, PATH_CHALLENGE or
   2859      1.1  christos      * PATH_RESPONSE (as desired) before, do so now.
   2860      1.1  christos      */
   2861      1.1  christos     if (!done_pre_token)
   2862      1.1  christos         if (txp_generate_pre_token(txp, pkt,
   2863  1.1.1.2  christos                 chosen_for_conn_close,
   2864  1.1.1.2  christos                 &can_be_non_inflight))
   2865      1.1  christos             done_pre_token = 1;
   2866      1.1  christos 
   2867      1.1  christos     /* CRYPTO Frames */
   2868      1.1  christos     if (a.allow_crypto)
   2869      1.1  christos         if (!txp_generate_crypto_frames(txp, pkt, &have_ack_eliciting))
   2870      1.1  christos             goto fatal_err;
   2871      1.1  christos 
   2872      1.1  christos     /* Stream-specific frames */
   2873      1.1  christos     if (a.allow_stream_rel && txp->handshake_complete)
   2874      1.1  christos         if (!txp_generate_stream_related(txp, pkt,
   2875  1.1.1.2  christos                 &have_ack_eliciting,
   2876  1.1.1.2  christos                 &pkt->stream_head))
   2877      1.1  christos             goto fatal_err;
   2878      1.1  christos 
   2879      1.1  christos     /* PING */
   2880      1.1  christos     tx_helper_unrestrict(h);
   2881      1.1  christos 
   2882      1.1  christos     if (!have_ack_eliciting && txp_need_ping(txp, pn_space, &a)) {
   2883      1.1  christos         WPACKET *wpkt;
   2884      1.1  christos 
   2885      1.1  christos         assert(h->reserve > 0);
   2886      1.1  christos         wpkt = tx_helper_begin(h);
   2887      1.1  christos         if (wpkt == NULL)
   2888      1.1  christos             goto fatal_err;
   2889      1.1  christos 
   2890      1.1  christos         if (!ossl_quic_wire_encode_frame_ping(wpkt)
   2891      1.1  christos             || !tx_helper_commit(h))
   2892      1.1  christos             /*
   2893      1.1  christos              * We treat a request to be ACK-eliciting as a requirement, so this
   2894      1.1  christos              * is an error.
   2895      1.1  christos              */
   2896      1.1  christos             goto fatal_err;
   2897      1.1  christos 
   2898      1.1  christos         have_ack_eliciting = 1;
   2899      1.1  christos     }
   2900      1.1  christos 
   2901      1.1  christos     /* PADDING is added by ossl_quic_tx_packetiser_generate(). */
   2902      1.1  christos 
   2903      1.1  christos     /*
   2904      1.1  christos      * ACKM Data
   2905      1.1  christos      * =========
   2906      1.1  christos      */
   2907      1.1  christos     if (have_ack_eliciting)
   2908      1.1  christos         can_be_non_inflight = 0;
   2909      1.1  christos 
   2910      1.1  christos     /* ACKM Data */
   2911  1.1.1.2  christos     tpkt->ackm_pkt.num_bytes = h->bytes_appended + pkt->geom.pkt_overhead;
   2912  1.1.1.2  christos     tpkt->ackm_pkt.pkt_num = txp->next_pn[pn_space];
   2913      1.1  christos     /* largest_acked is set in txp_generate_pre_token */
   2914  1.1.1.2  christos     tpkt->ackm_pkt.pkt_space = pn_space;
   2915  1.1.1.2  christos     tpkt->ackm_pkt.is_inflight = !can_be_non_inflight;
   2916      1.1  christos     tpkt->ackm_pkt.is_ack_eliciting = have_ack_eliciting;
   2917  1.1.1.2  christos     tpkt->ackm_pkt.is_pto_probe = 0;
   2918  1.1.1.2  christos     tpkt->ackm_pkt.is_mtu_probe = 0;
   2919  1.1.1.2  christos     tpkt->ackm_pkt.time = txp->args.now(txp->args.now_arg);
   2920  1.1.1.2  christos     tpkt->pkt_type = pkt->phdr.type;
   2921      1.1  christos 
   2922      1.1  christos     /* Done. */
   2923      1.1  christos     return rc;
   2924      1.1  christos 
   2925      1.1  christos fatal_err:
   2926      1.1  christos     /*
   2927      1.1  christos      * Handler for fatal errors, i.e. errors causing us to abort the entire
   2928      1.1  christos      * packet rather than just one frame. Examples of such errors include
   2929      1.1  christos      * allocation errors.
   2930      1.1  christos      */
   2931      1.1  christos     if (tpkt != NULL) {
   2932      1.1  christos         ossl_quic_txpim_pkt_release(txp->args.txpim, tpkt);
   2933      1.1  christos         pkt->tpkt = NULL;
   2934      1.1  christos     }
   2935      1.1  christos     return TXP_ERR_INTERNAL;
   2936      1.1  christos }
   2937      1.1  christos 
   2938      1.1  christos /*
   2939      1.1  christos  * Commits and queues a packet for transmission. There is no backing out after
   2940      1.1  christos  * this.
   2941      1.1  christos  *
   2942      1.1  christos  * This:
   2943      1.1  christos  *
   2944      1.1  christos  *   - Sends the packet to the QTX for encryption and transmission;
   2945      1.1  christos  *
   2946      1.1  christos  *   - Records the packet as having been transmitted in FIFM. ACKM is informed,
   2947      1.1  christos  *     etc. and the TXPIM record is filed.
   2948      1.1  christos  *
   2949      1.1  christos  *   - Informs various subsystems of frames that were sent and clears frame
   2950      1.1  christos  *     wanted flags so that we do not generate the same frames again.
   2951      1.1  christos  *
   2952      1.1  christos  * Assumptions:
   2953      1.1  christos  *
   2954      1.1  christos  *   - pkt is a txp_pkt for the correct EL;
   2955      1.1  christos  *
   2956      1.1  christos  *   - pkt->tpkt is valid;
   2957      1.1  christos  *
   2958      1.1  christos  *   - pkt->tpkt->ackm_pkt has been fully filled in;
   2959      1.1  christos  *
   2960      1.1  christos  *   - Stream chunk records have been appended to pkt->tpkt for STREAM and
   2961      1.1  christos  *     CRYPTO frames, but not for RESET_STREAM or STOP_SENDING frames;
   2962      1.1  christos  *
   2963      1.1  christos  *   - The chosen stream list for the packet can be fully walked from
   2964      1.1  christos  *     pkt->stream_head using stream->txp_next;
   2965      1.1  christos  *
   2966      1.1  christos  *   - pkt->has_ack_eliciting is set correctly.
   2967      1.1  christos  *
   2968      1.1  christos  */
   2969      1.1  christos static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp,
   2970  1.1.1.2  christos     struct txp_pkt *pkt,
   2971  1.1.1.2  christos     uint32_t archetype,
   2972  1.1.1.2  christos     int *txpim_pkt_reffed)
   2973      1.1  christos {
   2974      1.1  christos     int rc = 1;
   2975      1.1  christos     uint32_t enc_level = pkt->h.enc_level;
   2976      1.1  christos     uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   2977      1.1  christos     QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
   2978      1.1  christos     QUIC_STREAM *stream;
   2979      1.1  christos     OSSL_QTX_PKT txpkt;
   2980      1.1  christos     struct archetype_data a;
   2981      1.1  christos 
   2982      1.1  christos     *txpim_pkt_reffed = 0;
   2983      1.1  christos 
   2984      1.1  christos     /* Cannot send a packet with an empty payload. */
   2985      1.1  christos     if (pkt->h.bytes_appended == 0)
   2986      1.1  christos         return 0;
   2987      1.1  christos 
   2988      1.1  christos     if (!txp_get_archetype_data(enc_level, archetype, &a))
   2989      1.1  christos         return 0;
   2990      1.1  christos 
   2991      1.1  christos     /* Packet Information for QTX */
   2992  1.1.1.2  christos     txpkt.hdr = &pkt->phdr;
   2993  1.1.1.2  christos     txpkt.iovec = txp->el[enc_level].iovec;
   2994      1.1  christos     txpkt.num_iovec = pkt->h.num_iovec;
   2995  1.1.1.2  christos     txpkt.local = NULL;
   2996  1.1.1.2  christos     txpkt.peer = BIO_ADDR_family(&txp->args.peer) == AF_UNSPEC
   2997  1.1.1.2  christos         ? NULL
   2998  1.1.1.2  christos         : &txp->args.peer;
   2999  1.1.1.2  christos     txpkt.pn = txp->next_pn[pn_space];
   3000  1.1.1.2  christos     txpkt.flags = OSSL_QTX_PKT_FLAG_COALESCE; /* always try to coalesce */
   3001      1.1  christos 
   3002      1.1  christos     /* Generate TXPIM chunks representing STOP_SENDING and RESET_STREAM frames. */
   3003      1.1  christos     for (stream = pkt->stream_head; stream != NULL; stream = stream->txp_next)
   3004      1.1  christos         if (stream->txp_sent_stop_sending || stream->txp_sent_reset_stream) {
   3005      1.1  christos             /* Log STOP_SENDING/RESET_STREAM chunk to TXPIM. */
   3006      1.1  christos             QUIC_TXPIM_CHUNK chunk;
   3007      1.1  christos 
   3008  1.1.1.2  christos             chunk.stream_id = stream->id;
   3009  1.1.1.2  christos             chunk.start = UINT64_MAX;
   3010  1.1.1.2  christos             chunk.end = 0;
   3011  1.1.1.2  christos             chunk.has_fin = 0;
   3012  1.1.1.2  christos             chunk.has_stop_sending = stream->txp_sent_stop_sending;
   3013  1.1.1.2  christos             chunk.has_reset_stream = stream->txp_sent_reset_stream;
   3014      1.1  christos             if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
   3015      1.1  christos                 return 0; /* alloc error */
   3016      1.1  christos         }
   3017      1.1  christos 
   3018      1.1  christos     /* Dispatch to FIFD. */
   3019      1.1  christos     if (!ossl_quic_fifd_pkt_commit(&txp->fifd, tpkt))
   3020      1.1  christos         return 0;
   3021      1.1  christos 
   3022      1.1  christos     /*
   3023      1.1  christos      * Transmission and Post-Packet Generation Bookkeeping
   3024      1.1  christos      * ===================================================
   3025      1.1  christos      *
   3026      1.1  christos      * No backing out anymore - at this point the ACKM has recorded the packet
   3027      1.1  christos      * as having been sent, so we need to increment our next PN counter, or
   3028      1.1  christos      * the ACKM will complain when we try to record a duplicate packet with
   3029      1.1  christos      * the same PN later. At this point actually sending the packet may still
   3030      1.1  christos      * fail. In this unlikely event it will simply be handled as though it
   3031      1.1  christos      * were a lost packet.
   3032      1.1  christos      */
   3033      1.1  christos     ++txp->next_pn[pn_space];
   3034      1.1  christos     *txpim_pkt_reffed = 1;
   3035      1.1  christos 
   3036      1.1  christos     /* Send the packet. */
   3037      1.1  christos     if (!ossl_qtx_write_pkt(txp->args.qtx, &txpkt))
   3038      1.1  christos         return 0;
   3039      1.1  christos 
   3040      1.1  christos     /*
   3041      1.1  christos      * Record FC and stream abort frames as sent; deactivate streams which no
   3042      1.1  christos      * longer have anything to do.
   3043      1.1  christos      */
   3044      1.1  christos     for (stream = pkt->stream_head; stream != NULL; stream = stream->txp_next) {
   3045      1.1  christos         if (stream->txp_sent_fc) {
   3046      1.1  christos             stream->want_max_stream_data = 0;
   3047      1.1  christos             ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 1);
   3048      1.1  christos         }
   3049      1.1  christos 
   3050      1.1  christos         if (stream->txp_sent_stop_sending)
   3051      1.1  christos             stream->want_stop_sending = 0;
   3052      1.1  christos 
   3053      1.1  christos         if (stream->txp_sent_reset_stream)
   3054      1.1  christos             stream->want_reset_stream = 0;
   3055      1.1  christos 
   3056      1.1  christos         if (stream->txp_txfc_new_credit_consumed > 0) {
   3057      1.1  christos             if (!ossl_assert(ossl_quic_txfc_consume_credit(&stream->txfc,
   3058  1.1.1.2  christos                     stream->txp_txfc_new_credit_consumed)))
   3059      1.1  christos                 /*
   3060      1.1  christos                  * Should not be possible, but we should continue with our
   3061      1.1  christos                  * bookkeeping as we have already committed the packet to the
   3062      1.1  christos                  * FIFD. Just change the value we return.
   3063      1.1  christos                  */
   3064      1.1  christos                 rc = 0;
   3065      1.1  christos 
   3066      1.1  christos             stream->txp_txfc_new_credit_consumed = 0;
   3067      1.1  christos         }
   3068      1.1  christos 
   3069      1.1  christos         /*
   3070      1.1  christos          * If we no longer need to generate any flow control (MAX_STREAM_DATA),
   3071      1.1  christos          * STOP_SENDING or RESET_STREAM frames, nor any STREAM frames (because
   3072      1.1  christos          * the stream is drained of data or TXFC-blocked), we can mark the
   3073      1.1  christos          * stream as inactive.
   3074      1.1  christos          */
   3075      1.1  christos         ossl_quic_stream_map_update_state(txp->args.qsm, stream);
   3076      1.1  christos 
   3077      1.1  christos         if (ossl_quic_stream_has_send_buffer(stream)
   3078      1.1  christos             && !ossl_quic_sstream_has_pending(stream->sstream)
   3079      1.1  christos             && ossl_quic_sstream_get_final_size(stream->sstream, NULL))
   3080      1.1  christos             /*
   3081      1.1  christos              * Transition to DATA_SENT if stream has a final size and we have
   3082      1.1  christos              * sent all data.
   3083      1.1  christos              */
   3084      1.1  christos             ossl_quic_stream_map_notify_all_data_sent(txp->args.qsm, stream);
   3085      1.1  christos     }
   3086      1.1  christos 
   3087      1.1  christos     /* We have now sent the packet, so update state accordingly. */
   3088      1.1  christos     if (tpkt->ackm_pkt.is_ack_eliciting)
   3089      1.1  christos         txp->force_ack_eliciting &= ~(1UL << pn_space);
   3090      1.1  christos 
   3091      1.1  christos     if (tpkt->had_handshake_done_frame)
   3092      1.1  christos         txp->want_handshake_done = 0;
   3093      1.1  christos 
   3094      1.1  christos     if (tpkt->had_max_data_frame) {
   3095      1.1  christos         txp->want_max_data = 0;
   3096      1.1  christos         ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 1);
   3097      1.1  christos     }
   3098      1.1  christos 
   3099      1.1  christos     if (tpkt->had_max_streams_bidi_frame) {
   3100      1.1  christos         txp->want_max_streams_bidi = 0;
   3101      1.1  christos         ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 1);
   3102      1.1  christos     }
   3103      1.1  christos 
   3104      1.1  christos     if (tpkt->had_max_streams_uni_frame) {
   3105      1.1  christos         txp->want_max_streams_uni = 0;
   3106      1.1  christos         ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 1);
   3107      1.1  christos     }
   3108      1.1  christos 
   3109      1.1  christos     if (tpkt->had_ack_frame)
   3110      1.1  christos         txp->want_ack &= ~(1UL << pn_space);
   3111      1.1  christos 
   3112      1.1  christos     if (tpkt->had_conn_close)
   3113      1.1  christos         txp->want_conn_close = 0;
   3114      1.1  christos 
   3115      1.1  christos     /*
   3116      1.1  christos      * Decrement probe request counts if we have sent a packet that meets
   3117      1.1  christos      * the requirement of a probe, namely being ACK-eliciting.
   3118      1.1  christos      */
   3119      1.1  christos     if (tpkt->ackm_pkt.is_ack_eliciting) {
   3120      1.1  christos         OSSL_ACKM_PROBE_INFO *probe_info
   3121      1.1  christos             = ossl_ackm_get0_probe_request(txp->args.ackm);
   3122      1.1  christos 
   3123      1.1  christos         if (enc_level == QUIC_ENC_LEVEL_INITIAL
   3124      1.1  christos             && probe_info->anti_deadlock_initial > 0)
   3125      1.1  christos             --probe_info->anti_deadlock_initial;
   3126      1.1  christos 
   3127      1.1  christos         if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE
   3128      1.1  christos             && probe_info->anti_deadlock_handshake > 0)
   3129      1.1  christos             --probe_info->anti_deadlock_handshake;
   3130      1.1  christos 
   3131      1.1  christos         if (a.allow_force_ack_eliciting /* (i.e., not for 0-RTT) */
   3132      1.1  christos             && probe_info->pto[pn_space] > 0)
   3133      1.1  christos             --probe_info->pto[pn_space];
   3134      1.1  christos     }
   3135      1.1  christos 
   3136      1.1  christos     return rc;
   3137      1.1  christos }
   3138      1.1  christos 
   3139      1.1  christos /* Ensure the iovec array is at least num elements long. */
   3140      1.1  christos static int txp_el_ensure_iovec(struct txp_el *el, size_t num)
   3141      1.1  christos {
   3142      1.1  christos     OSSL_QTX_IOVEC *iovec;
   3143      1.1  christos 
   3144      1.1  christos     if (el->alloc_iovec >= num)
   3145      1.1  christos         return 1;
   3146      1.1  christos 
   3147      1.1  christos     num = el->alloc_iovec != 0 ? el->alloc_iovec * 2 : 8;
   3148      1.1  christos 
   3149      1.1  christos     iovec = OPENSSL_realloc(el->iovec, sizeof(OSSL_QTX_IOVEC) * num);
   3150      1.1  christos     if (iovec == NULL)
   3151      1.1  christos         return 0;
   3152      1.1  christos 
   3153  1.1.1.2  christos     el->iovec = iovec;
   3154  1.1.1.2  christos     el->alloc_iovec = num;
   3155      1.1  christos     return 1;
   3156      1.1  christos }
   3157      1.1  christos 
   3158      1.1  christos int ossl_quic_tx_packetiser_schedule_conn_close(OSSL_QUIC_TX_PACKETISER *txp,
   3159  1.1.1.2  christos     const OSSL_QUIC_FRAME_CONN_CLOSE *f)
   3160      1.1  christos {
   3161      1.1  christos     char *reason = NULL;
   3162      1.1  christos     size_t reason_len = f->reason_len;
   3163      1.1  christos     size_t max_reason_len = txp_get_mdpl(txp) / 2;
   3164      1.1  christos 
   3165      1.1  christos     if (txp->want_conn_close)
   3166      1.1  christos         return 0;
   3167      1.1  christos 
   3168      1.1  christos     /*
   3169      1.1  christos      * Arbitrarily limit the length of the reason length string to half of the
   3170      1.1  christos      * MDPL.
   3171      1.1  christos      */
   3172      1.1  christos     if (reason_len > max_reason_len)
   3173      1.1  christos         reason_len = max_reason_len;
   3174      1.1  christos 
   3175      1.1  christos     if (reason_len > 0) {
   3176      1.1  christos         reason = OPENSSL_memdup(f->reason, reason_len);
   3177      1.1  christos         if (reason == NULL)
   3178      1.1  christos             return 0;
   3179      1.1  christos     }
   3180      1.1  christos 
   3181  1.1.1.2  christos     txp->conn_close_frame = *f;
   3182  1.1.1.2  christos     txp->conn_close_frame.reason = reason;
   3183  1.1.1.2  christos     txp->conn_close_frame.reason_len = reason_len;
   3184  1.1.1.2  christos     txp->want_conn_close = 1;
   3185      1.1  christos     return 1;
   3186      1.1  christos }
   3187      1.1  christos 
   3188      1.1  christos void ossl_quic_tx_packetiser_set_msg_callback(OSSL_QUIC_TX_PACKETISER *txp,
   3189  1.1.1.2  christos     ossl_msg_cb msg_callback,
   3190  1.1.1.2  christos     SSL *msg_callback_ssl)
   3191      1.1  christos {
   3192      1.1  christos     txp->msg_callback = msg_callback;
   3193      1.1  christos     txp->msg_callback_ssl = msg_callback_ssl;
   3194      1.1  christos }
   3195      1.1  christos 
   3196      1.1  christos void ossl_quic_tx_packetiser_set_msg_callback_arg(OSSL_QUIC_TX_PACKETISER *txp,
   3197  1.1.1.2  christos     void *msg_callback_arg)
   3198      1.1  christos {
   3199      1.1  christos     txp->msg_callback_arg = msg_callback_arg;
   3200      1.1  christos }
   3201      1.1  christos 
   3202      1.1  christos QUIC_PN ossl_quic_tx_packetiser_get_next_pn(OSSL_QUIC_TX_PACKETISER *txp,
   3203  1.1.1.2  christos     uint32_t pn_space)
   3204      1.1  christos {
   3205      1.1  christos     if (pn_space >= QUIC_PN_SPACE_NUM)
   3206      1.1  christos         return UINT64_MAX;
   3207      1.1  christos 
   3208      1.1  christos     return txp->next_pn[pn_space];
   3209      1.1  christos }
   3210      1.1  christos 
   3211      1.1  christos OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp)
   3212      1.1  christos {
   3213      1.1  christos     /*
   3214      1.1  christos      * TXP-specific deadline computations which rely on TXP innards. This is in
   3215      1.1  christos      * turn relied on by the QUIC_CHANNEL code to determine the channel event
   3216      1.1  christos      * handling deadline.
   3217      1.1  christos      */
   3218      1.1  christos     OSSL_TIME deadline = ossl_time_infinite();
   3219      1.1  christos     uint32_t enc_level, pn_space;
   3220      1.1  christos 
   3221      1.1  christos     /*
   3222      1.1  christos      * ACK generation is not CC-gated - packets containing only ACKs are allowed
   3223      1.1  christos      * to bypass CC. We want to generate ACK frames even if we are currently
   3224      1.1  christos      * restricted by CC so the peer knows we have received data. The generate
   3225      1.1  christos      * call will take care of selecting the correct packet archetype.
   3226      1.1  christos      */
   3227      1.1  christos     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
   3228  1.1.1.2  christos         enc_level < QUIC_ENC_LEVEL_NUM;
   3229  1.1.1.2  christos         ++enc_level)
   3230      1.1  christos         if (ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level)) {
   3231      1.1  christos             pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
   3232      1.1  christos             deadline = ossl_time_min(deadline,
   3233  1.1.1.2  christos                 ossl_ackm_get_ack_deadline(txp->args.ackm, pn_space));
   3234      1.1  christos         }
   3235      1.1  christos 
   3236      1.1  christos     /* When will CC let us send more? */
   3237      1.1  christos     if (txp->args.cc_method->get_tx_allowance(txp->args.cc_data) == 0)
   3238      1.1  christos         deadline = ossl_time_min(deadline,
   3239  1.1.1.2  christos             txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data));
   3240      1.1  christos 
   3241      1.1  christos     return deadline;
   3242      1.1  christos }
   3243