QUIC TXP: Add a function to query if the TXP wants to generate a packet
[openssl.git] / ssl / quic / quic_txp.c
1 /*
2  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "internal/quic_txp.h"
11 #include "internal/quic_fifd.h"
12 #include "internal/quic_stream_map.h"
13 #include "internal/common.h"
14 #include <openssl/err.h>
15
16 #define MIN_CRYPTO_HDR_SIZE             3
17
18 #define MIN_FRAME_SIZE_HANDSHAKE_DONE   1
19 #define MIN_FRAME_SIZE_MAX_DATA         2
20 #define MIN_FRAME_SIZE_ACK              5
21 #define MIN_FRAME_SIZE_CRYPTO           (MIN_CRYPTO_HDR_SIZE + 1)
22 #define MIN_FRAME_SIZE_STREAM           3 /* minimum useful size (for non-FIN) */
23 #define MIN_FRAME_SIZE_MAX_STREAMS_BIDI 2
24 #define MIN_FRAME_SIZE_MAX_STREAMS_UNI  2
25
26 struct ossl_quic_tx_packetiser_st {
27     OSSL_QUIC_TX_PACKETISER_ARGS args;
28
29     /*
30      * Opaque initial token blob provided by caller. TXP frees using the
31      * callback when it is no longer needed.
32      */
33     const unsigned char             *initial_token;
34     size_t                          initial_token_len;
35     ossl_quic_initial_token_free_fn *initial_token_free_cb;
36     void                            *initial_token_free_cb_arg;
37
38     /* Subcomponents of the TXP that we own. */
39     QUIC_FIFD       fifd;       /* QUIC Frame-in-Flight Dispatcher */
40
41     /* Internal state. */
42     uint64_t        next_pn[QUIC_PN_SPACE_NUM]; /* Next PN to use in given PN space. */
43     OSSL_TIME       last_tx_time;               /* Last time a packet was generated, or 0. */
44
45     /* Internal state - frame (re)generation flags. */
46     unsigned int    want_handshake_done     : 1;
47     unsigned int    want_max_data           : 1;
48     unsigned int    want_max_streams_bidi   : 1;
49     unsigned int    want_max_streams_uni    : 1;
50
51     /* Internal state - frame (re)generation flags - per PN space. */
52     unsigned int    want_ack                : QUIC_PN_SPACE_NUM;
53     unsigned int    force_ack_eliciting     : QUIC_PN_SPACE_NUM;
54
55     /*
56      * Internal state - connection close terminal state.
57      * Once this is set, it is not unset unlike other want_ flags - we keep
58      * sending it in every packet.
59      */
60     unsigned int    want_conn_close         : 1;
61
62     OSSL_QUIC_FRAME_CONN_CLOSE  conn_close_frame;
63
64     /* Internal state - packet assembly. */
65     unsigned char   *scratch;       /* scratch buffer for packet assembly */
66     size_t          scratch_len;    /* number of bytes allocated for scratch */
67     OSSL_QTX_IOVEC  *iovec;         /* scratch iovec array for use with QTX */
68     size_t          alloc_iovec;    /* size of iovec array */
69 };
70
71 /*
72  * The TX helper records state used while generating frames into packets. It
73  * enables serialization into the packet to be done "transactionally" where
74  * serialization of a frame can be rolled back if it fails midway (e.g. if it
75  * does not fit).
76  */
77 struct tx_helper {
78     OSSL_QUIC_TX_PACKETISER *txp;
79     /*
80      * The Maximum Packet Payload Length in bytes. This is the amount of
81      * space we have to generate frames into.
82      */
83     size_t max_ppl;
84     /*
85      * Number of bytes we have generated so far.
86      */
87     size_t bytes_appended;
88     /*
89      * Number of scratch bytes in txp->scratch we have used so far. Some iovecs
90      * will reference this scratch buffer. When we need to use more of it (e.g.
91      * when we need to put frame headers somewhere), we append to the scratch
92      * buffer, resizing if necessary, and increase this accordingly.
93      */
94     size_t scratch_bytes;
95     /*
96      * Bytes reserved in the MaxPPL budget. We keep this number of bytes spare
97      * until reserve_allowed is set to 1. Currently this is always at most 1, as
98      * a PING frame takes up one byte and this mechanism is only used to ensure
99      * we can encode a PING frame if we have been asked to ensure a packet is
100      * ACK-eliciting and we are unusure if we are going to add any other
101      * ACK-eliciting frames before we reach our MaxPPL budget.
102      */
103     size_t reserve;
104     /*
105      * Number of iovecs we have currently appended. This is the number of
106      * entries valid in txp->iovec.
107      */
108     size_t num_iovec;
109     /*
110      * Whether we are allowed to make use of the reserve bytes in our MaxPPL
111      * budget. This is used to ensure we have room to append a PING frame later
112      * if we need to. Once we know we will not need to append a PING frame, this
113      * is set to 1.
114      */
115     unsigned int reserve_allowed : 1;
116     /*
117      * Set to 1 if we have appended a STREAM frame with an implicit length. If
118      * this happens we should never append another frame after that frame as it
119      * cannot be validly encoded. This is just a safety check.
120      */
121     unsigned int done_implicit : 1;
122     struct {
123         /*
124          * The fields in this structure are valid if active is set, which means
125          * that a serialization transaction is currently in progress.
126          */
127         unsigned char   *data;
128         WPACKET         wpkt;
129         unsigned int    active : 1;
130     } txn;
131 };
132
133 static void tx_helper_rollback(struct tx_helper *h);
134 static int txp_ensure_iovec(OSSL_QUIC_TX_PACKETISER *txp, size_t num);
135
136 /* Initialises the TX helper. */
137 static int tx_helper_init(struct tx_helper *h, OSSL_QUIC_TX_PACKETISER *txp,
138                           size_t max_ppl, size_t reserve)
139 {
140     if (reserve > max_ppl)
141         return 0;
142
143     h->txp                  = txp;
144     h->max_ppl              = max_ppl;
145     h->reserve              = reserve;
146     h->num_iovec            = 0;
147     h->bytes_appended       = 0;
148     h->scratch_bytes        = 0;
149     h->reserve_allowed      = 0;
150     h->done_implicit        = 0;
151     h->txn.data             = NULL;
152     h->txn.active           = 0;
153
154     if (max_ppl > h->txp->scratch_len) {
155         unsigned char *scratch;
156
157         scratch = OPENSSL_realloc(h->txp->scratch, max_ppl);
158         if (scratch == NULL)
159             return 0;
160
161         h->txp->scratch     = scratch;
162         h->txp->scratch_len = max_ppl;
163     }
164
165     return 1;
166 }
167
168 static void tx_helper_cleanup(struct tx_helper *h)
169 {
170     if (h->txn.active)
171         tx_helper_rollback(h);
172
173     h->txp = NULL;
174 }
175
176 static void tx_helper_unrestrict(struct tx_helper *h)
177 {
178     h->reserve_allowed = 1;
179 }
180
181 /*
182  * Append an extent of memory to the iovec list. The memory must remain
183  * allocated until we finish generating the packet and call the QTX.
184  *
185  * In general, the buffers passed to this function will be from one of two
186  * ranges:
187  *
188  *   - Application data contained in stream buffers managed elsewhere
189  *     in the QUIC stack; or
190  *
191  *   - Control frame data appended into txp->scratch using tx_helper_begin and
192  *     tx_helper_commit.
193  *
194  */
195 static int tx_helper_append_iovec(struct tx_helper *h,
196                                   const unsigned char *buf,
197                                   size_t buf_len)
198 {
199     if (buf_len == 0)
200         return 1;
201
202     if (!ossl_assert(!h->done_implicit))
203         return 0;
204
205     if (!txp_ensure_iovec(h->txp, h->num_iovec + 1))
206         return 0;
207
208     h->txp->iovec[h->num_iovec].buf     = buf;
209     h->txp->iovec[h->num_iovec].buf_len = buf_len;
210
211     ++h->num_iovec;
212     h->bytes_appended += buf_len;
213     return 1;
214 }
215
216 /*
217  * How many more bytes of space do we have left in our plaintext packet payload?
218  */
219 static size_t tx_helper_get_space_left(struct tx_helper *h)
220 {
221     return h->max_ppl
222         - (h->reserve_allowed ? 0 : h->reserve) - h->bytes_appended;
223 }
224
225 /*
226  * Begin a control frame serialization transaction. This allows the
227  * serialization of the control frame to be backed out if it turns out it won't
228  * fit. Write the control frame to the returned WPACKET. Ensure you always
229  * call tx_helper_rollback or tx_helper_commit (or tx_helper_cleanup). Returns
230  * NULL on failure.
231  */
232 static WPACKET *tx_helper_begin(struct tx_helper *h)
233 {
234     size_t space_left, len;
235     unsigned char *data;
236
237     if (!ossl_assert(!h->txn.active))
238         return NULL;
239
240     if (!ossl_assert(!h->done_implicit))
241         return NULL;
242
243     data = (unsigned char *)h->txp->scratch + h->scratch_bytes;
244     len  = h->txp->scratch_len - h->scratch_bytes;
245
246     space_left = tx_helper_get_space_left(h);
247     if (!ossl_assert(space_left <= len))
248         return NULL;
249
250     if (!WPACKET_init_static_len(&h->txn.wpkt, data, len, 0))
251         return NULL;
252
253     if (!WPACKET_set_max_size(&h->txn.wpkt, space_left)) {
254         WPACKET_cleanup(&h->txn.wpkt);
255         return NULL;
256     }
257
258     h->txn.data     = data;
259     h->txn.active   = 1;
260     return &h->txn.wpkt;
261 }
262
263 static void tx_helper_end(struct tx_helper *h, int success)
264 {
265     if (success)
266         WPACKET_finish(&h->txn.wpkt);
267     else
268         WPACKET_cleanup(&h->txn.wpkt);
269
270     h->txn.active       = 0;
271     h->txn.data         = NULL;
272 }
273
274 /* Abort a control frame serialization transaction. */
275 static void tx_helper_rollback(struct tx_helper *h)
276 {
277     if (!h->txn.active)
278         return;
279
280     tx_helper_end(h, 0);
281 }
282
283 /* Commit a control frame. */
284 static int tx_helper_commit(struct tx_helper *h)
285 {
286     size_t l = 0;
287
288     if (!h->txn.active)
289         return 0;
290
291     if (!WPACKET_get_total_written(&h->txn.wpkt, &l)) {
292         tx_helper_end(h, 0);
293         return 0;
294     }
295
296     if (!tx_helper_append_iovec(h, h->txn.data, l)) {
297         tx_helper_end(h, 0);
298         return 0;
299     }
300
301     h->scratch_bytes += l;
302     tx_helper_end(h, 1);
303     return 1;
304 }
305
306 static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space,
307                                        void *arg);
308 static void on_regen_notify(uint64_t frame_type, uint64_t stream_id,
309                             QUIC_TXPIM_PKT *pkt, void *arg);
310 static int sstream_is_pending(QUIC_SSTREAM *sstream);
311 static int txp_el_pending(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level,
312                           uint32_t archetype);
313 static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level,
314                                uint32_t archetype,
315                                char is_last_in_dgram,
316                                char dgram_contains_initial);
317 static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp);
318 static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp,
319                                      size_t pl,
320                                      uint32_t enc_level,
321                                      size_t hdr_len,
322                                      size_t *r);
323 static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp);
324 static int txp_generate_for_el_actual(OSSL_QUIC_TX_PACKETISER *txp,
325                                       uint32_t enc_level,
326                                       uint32_t archetype,
327                                       size_t min_ppl,
328                                       size_t max_ppl,
329                                       size_t pkt_overhead,
330                                       QUIC_PKT_HDR *phdr);
331
332 OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args)
333 {
334     OSSL_QUIC_TX_PACKETISER *txp;
335
336     if (args == NULL
337         || args->qtx == NULL
338         || args->txpim == NULL
339         || args->cfq == NULL
340         || args->ackm == NULL
341         || args->qsm == NULL
342         || args->conn_txfc == NULL
343         || args->conn_rxfc == NULL) {
344         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
345         return NULL;
346     }
347
348     txp = OPENSSL_zalloc(sizeof(*txp));
349     if (txp == NULL)
350         return NULL;
351
352     txp->args           = *args;
353     txp->last_tx_time   = ossl_time_zero();
354
355     if (!ossl_quic_fifd_init(&txp->fifd,
356                              txp->args.cfq, txp->args.ackm, txp->args.txpim,
357                              get_sstream_by_id, txp,
358                              on_regen_notify, txp)) {
359         OPENSSL_free(txp);
360         return NULL;
361     }
362
363     return txp;
364 }
365
366 void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *txp)
367 {
368     if (txp == NULL)
369         return;
370
371     ossl_quic_tx_packetiser_set_initial_token(txp, NULL, 0, NULL, NULL);
372     ossl_quic_fifd_cleanup(&txp->fifd);
373     OPENSSL_free(txp->iovec);
374     OPENSSL_free(txp->conn_close_frame.reason);
375     OPENSSL_free(txp->scratch);
376     OPENSSL_free(txp);
377 }
378
379 void ossl_quic_tx_packetiser_set_initial_token(OSSL_QUIC_TX_PACKETISER *txp,
380                                                const unsigned char *token,
381                                                size_t token_len,
382                                                ossl_quic_initial_token_free_fn *free_cb,
383                                                void *free_cb_arg)
384 {
385     if (txp->initial_token != NULL && txp->initial_token_free_cb != NULL)
386         txp->initial_token_free_cb(txp->initial_token, txp->initial_token_len,
387                                    txp->initial_token_free_cb_arg);
388
389     txp->initial_token              = token;
390     txp->initial_token_len          = token_len;
391     txp->initial_token_free_cb      = free_cb;
392     txp->initial_token_free_cb_arg  = free_cb_arg;
393 }
394
395 int ossl_quic_tx_packetiser_set_cur_dcid(OSSL_QUIC_TX_PACKETISER *txp,
396                                          const QUIC_CONN_ID *dcid)
397 {
398     if (dcid == NULL) {
399         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
400         return 0;
401     }
402
403     txp->args.cur_dcid = *dcid;
404     return 1;
405 }
406
407 int ossl_quic_tx_packetiser_set_cur_scid(OSSL_QUIC_TX_PACKETISER *txp,
408                                          const QUIC_CONN_ID *scid)
409 {
410     if (scid == NULL) {
411         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
412         return 0;
413     }
414
415     txp->args.cur_scid = *scid;
416     return 1;
417 }
418
419 /* Change the destination L4 address the TXP uses to send datagrams. */
420 int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
421                                      const BIO_ADDR *peer)
422 {
423     if (peer == NULL) {
424         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
425         return 0;
426     }
427
428     txp->args.peer = *peer;
429     return 1;
430 }
431
432 int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
433                                               uint32_t enc_level)
434 {
435     if (enc_level >= QUIC_ENC_LEVEL_NUM) {
436         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
437         return 0;
438     }
439
440     if (enc_level != QUIC_ENC_LEVEL_0RTT)
441         txp->args.crypto[ossl_quic_enc_level_to_pn_space(enc_level)] = NULL;
442
443     ossl_qtx_discard_enc_level(txp->args.qtx, enc_level);
444     return 1;
445 }
446
447 void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp)
448 {
449     txp->want_handshake_done = 1;
450 }
451
452 void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp,
453                                                     uint32_t pn_space)
454 {
455     txp->force_ack_eliciting |= (1UL << pn_space);
456 }
457
458 #define TXP_ERR_INTERNAL     0  /* Internal (e.g. alloc) error */
459 #define TXP_ERR_SUCCESS      1  /* Success */
460 #define TXP_ERR_SPACE        2  /* Not enough room for another packet */
461 #define TXP_ERR_INPUT        3  /* Invalid/malformed input */
462
463 int ossl_quic_tx_packetiser_has_pending(OSSL_QUIC_TX_PACKETISER *txp,
464                                         uint32_t archetype,
465                                         uint32_t flags)
466 {
467     uint32_t enc_level;
468     int bypass_cc = ((flags & TX_PACKETISER_BYPASS_CC) != 0);
469
470     if (!bypass_cc && !txp->args.cc_method->can_send(txp->args.cc_data))
471         return 0;
472
473     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
474          enc_level < QUIC_ENC_LEVEL_NUM;
475          ++enc_level)
476         if (txp_el_pending(txp, enc_level, archetype))
477             return 1;
478
479     return 0;
480 }
481
482 /*
483  * Generates a datagram by polling the various ELs to determine if they want to
484  * generate any frames, and generating a datagram which coalesces packets for
485  * any ELs which do.
486  */
487 int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
488                                      uint32_t archetype)
489 {
490     uint32_t enc_level;
491     char have_pkt_for_el[QUIC_ENC_LEVEL_NUM], is_last_in_dgram;
492     size_t num_el_in_dgram = 0, pkts_done = 0;
493     int rc;
494
495     if (!txp->args.cc_method->can_send(txp->args.cc_data))
496         return TX_PACKETISER_RES_NO_PKT;
497
498     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
499          enc_level < QUIC_ENC_LEVEL_NUM;
500          ++enc_level) {
501         have_pkt_for_el[enc_level] = txp_el_pending(txp, enc_level, archetype);
502         if (have_pkt_for_el[enc_level])
503             ++num_el_in_dgram;
504     }
505
506     if (num_el_in_dgram == 0)
507         return TX_PACKETISER_RES_NO_PKT;
508
509     /*
510      * Should not be needed, but a sanity check in case anyone else has been
511      * using the QTX.
512      */
513     ossl_qtx_finish_dgram(txp->args.qtx);
514
515     for (enc_level = QUIC_ENC_LEVEL_INITIAL;
516          enc_level < QUIC_ENC_LEVEL_NUM;
517          ++enc_level) {
518         if (!have_pkt_for_el[enc_level])
519             continue;
520
521         is_last_in_dgram = (pkts_done + 1 == num_el_in_dgram);
522         rc = txp_generate_for_el(txp, enc_level, archetype, is_last_in_dgram,
523                                  have_pkt_for_el[QUIC_ENC_LEVEL_INITIAL]);
524
525         if (rc != TXP_ERR_SUCCESS) {
526             /*
527              * If we already successfully did at least one, make sure we report
528              * this via the return code.
529              */
530             if (pkts_done > 0)
531                 break;
532             else
533                 return TX_PACKETISER_RES_FAILURE;
534         }
535
536         ++pkts_done;
537     }
538
539     ossl_qtx_finish_dgram(txp->args.qtx);
540     return TX_PACKETISER_RES_SENT_PKT;
541 }
542
543 struct archetype_data {
544     unsigned int allow_ack                  : 1;
545     unsigned int allow_ping                 : 1;
546     unsigned int allow_crypto               : 1;
547     unsigned int allow_handshake_done       : 1;
548     unsigned int allow_path_challenge       : 1;
549     unsigned int allow_path_response        : 1;
550     unsigned int allow_new_conn_id          : 1;
551     unsigned int allow_retire_conn_id       : 1;
552     unsigned int allow_stream_rel           : 1;
553     unsigned int allow_conn_fc              : 1;
554     unsigned int allow_conn_close           : 1;
555     unsigned int allow_cfq_other            : 1;
556     unsigned int allow_new_token            : 1;
557     unsigned int allow_force_ack_eliciting  : 1;
558 };
559
560 static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_ARCHETYPE_NUM] = {
561     /* EL 0(INITIAL) */
562     {
563         /* EL 0(INITIAL) - Archetype 0(NORMAL) */
564         {
565             /*allow_ack                       =*/ 1,
566             /*allow_ping                      =*/ 1,
567             /*allow_crypto                    =*/ 1,
568             /*allow_handshake_done            =*/ 0,
569             /*allow_path_challenge            =*/ 0,
570             /*allow_path_response             =*/ 0,
571             /*allow_new_conn_id               =*/ 0,
572             /*allow_retire_conn_id            =*/ 0,
573             /*allow_stream_rel                =*/ 0,
574             /*allow_conn_fc                   =*/ 0,
575             /*allow_conn_close                =*/ 1,
576             /*allow_cfq_other                 =*/ 1,
577             /*allow_new_token                 =*/ 0,
578             /*allow_force_ack_eliciting       =*/ 1,
579         },
580         /* EL 0(INITIAL) - Archetype 1(ACK_ONLY) */
581         {
582             /*allow_ack                       =*/ 1,
583             /*allow_ping                      =*/ 0,
584             /*allow_crypto                    =*/ 0,
585             /*allow_handshake_done            =*/ 0,
586             /*allow_path_challenge            =*/ 0,
587             /*allow_path_response             =*/ 0,
588             /*allow_new_conn_id               =*/ 0,
589             /*allow_retire_conn_id            =*/ 0,
590             /*allow_stream_rel                =*/ 0,
591             /*allow_conn_fc                   =*/ 0,
592             /*allow_conn_close                =*/ 0,
593             /*allow_cfq_other                 =*/ 0,
594             /*allow_new_token                 =*/ 0,
595             /*allow_force_ack_eliciting       =*/ 1,
596         },
597     },
598     /* EL 1(HANDSHAKE) */
599     {
600         /* EL 1(HANDSHAKE) - Archetype 0(NORMAL) */
601         {
602             /*allow_ack                       =*/ 1,
603             /*allow_ping                      =*/ 1,
604             /*allow_crypto                    =*/ 1,
605             /*allow_handshake_done            =*/ 0,
606             /*allow_path_challenge            =*/ 0,
607             /*allow_path_response             =*/ 0,
608             /*allow_new_conn_id               =*/ 0,
609             /*allow_retire_conn_id            =*/ 0,
610             /*allow_stream_rel                =*/ 0,
611             /*allow_conn_fc                   =*/ 0,
612             /*allow_conn_close                =*/ 1,
613             /*allow_cfq_other                 =*/ 1,
614             /*allow_new_token                 =*/ 0,
615             /*allow_force_ack_eliciting       =*/ 1,
616         },
617         /* EL 1(HANDSHAKE) - Archetype 1(ACK_ONLY) */
618         {
619             /*allow_ack                       =*/ 1,
620             /*allow_ping                      =*/ 0,
621             /*allow_crypto                    =*/ 0,
622             /*allow_handshake_done            =*/ 0,
623             /*allow_path_challenge            =*/ 0,
624             /*allow_path_response             =*/ 0,
625             /*allow_new_conn_id               =*/ 0,
626             /*allow_retire_conn_id            =*/ 0,
627             /*allow_stream_rel                =*/ 0,
628             /*allow_conn_fc                   =*/ 0,
629             /*allow_conn_close                =*/ 0,
630             /*allow_cfq_other                 =*/ 0,
631             /*allow_new_token                 =*/ 0,
632             /*allow_force_ack_eliciting       =*/ 1,
633         },
634     },
635     /* EL 2(0RTT) */
636     {
637         /* EL 2(0RTT) - Archetype 0(NORMAL) */
638         {
639             /*allow_ack                       =*/ 0,
640             /*allow_ping                      =*/ 1,
641             /*allow_crypto                    =*/ 0,
642             /*allow_handshake_done            =*/ 0,
643             /*allow_path_challenge            =*/ 0,
644             /*allow_path_response             =*/ 0,
645             /*allow_new_conn_id               =*/ 1,
646             /*allow_retire_conn_id            =*/ 1,
647             /*allow_stream_rel                =*/ 1,
648             /*allow_conn_fc                   =*/ 1,
649             /*allow_conn_close                =*/ 1,
650             /*allow_cfq_other                 =*/ 0,
651             /*allow_new_token                 =*/ 0,
652             /*allow_force_ack_eliciting       =*/ 0,
653         },
654         /* EL 2(0RTT) - Archetype 1(ACK_ONLY) */
655         {
656             /*allow_ack                       =*/ 0,
657             /*allow_ping                      =*/ 0,
658             /*allow_crypto                    =*/ 0,
659             /*allow_handshake_done            =*/ 0,
660             /*allow_path_challenge            =*/ 0,
661             /*allow_path_response             =*/ 0,
662             /*allow_new_conn_id               =*/ 0,
663             /*allow_retire_conn_id            =*/ 0,
664             /*allow_stream_rel                =*/ 0,
665             /*allow_conn_fc                   =*/ 0,
666             /*allow_conn_close                =*/ 0,
667             /*allow_cfq_other                 =*/ 0,
668             /*allow_new_token                 =*/ 0,
669             /*allow_force_ack_eliciting       =*/ 0,
670         },
671     },
672     /* EL 3(1RTT) */
673     {
674         /* EL 3(1RTT) - Archetype 0(NORMAL) */
675         {
676             /*allow_ack                       =*/ 1,
677             /*allow_ping                      =*/ 1,
678             /*allow_crypto                    =*/ 1,
679             /*allow_handshake_done            =*/ 1,
680             /*allow_path_challenge            =*/ 0,
681             /*allow_path_response             =*/ 0,
682             /*allow_new_conn_id               =*/ 1,
683             /*allow_retire_conn_id            =*/ 1,
684             /*allow_stream_rel                =*/ 1,
685             /*allow_conn_fc                   =*/ 1,
686             /*allow_conn_close                =*/ 1,
687             /*allow_cfq_other                 =*/ 1,
688             /*allow_new_token                 =*/ 1,
689             /*allow_force_ack_eliciting       =*/ 1,
690         },
691         /* EL 3(1RTT) - Archetype 1(ACK_ONLY) */
692         {
693             /*allow_ack                       =*/ 1,
694             /*allow_ping                      =*/ 0,
695             /*allow_crypto                    =*/ 0,
696             /*allow_handshake_done            =*/ 0,
697             /*allow_path_challenge            =*/ 0,
698             /*allow_path_response             =*/ 0,
699             /*allow_new_conn_id               =*/ 0,
700             /*allow_retire_conn_id            =*/ 0,
701             /*allow_stream_rel                =*/ 0,
702             /*allow_conn_fc                   =*/ 0,
703             /*allow_conn_close                =*/ 0,
704             /*allow_cfq_other                 =*/ 0,
705             /*allow_new_token                 =*/ 0,
706             /*allow_force_ack_eliciting       =*/ 1,
707         }
708     }
709 };
710
711 static int txp_get_archetype_data(uint32_t enc_level,
712                                   uint32_t archetype,
713                                   struct archetype_data *a)
714 {
715     if (enc_level >= QUIC_ENC_LEVEL_NUM
716         || archetype >= TX_PACKETISER_ARCHETYPE_NUM)
717         return 0;
718
719     /* No need to avoid copying this as it should not exceed one int in size. */
720     *a = archetypes[enc_level][archetype];
721     return 1;
722 }
723
724 /*
725  * Returns 1 if the given EL wants to produce one or more frames.
726  * Always returns 0 if the given EL is discarded.
727  */
728 static int txp_el_pending(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level,
729                           uint32_t archetype)
730 {
731     struct archetype_data a;
732     uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
733     QUIC_CFQ_ITEM *cfq_item;
734
735     if (!ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level))
736         return 0;
737
738     if (!txp_get_archetype_data(enc_level, archetype, &a))
739         return 0;
740
741     /* Does the crypto stream for this EL want to produce anything? */
742     if (a.allow_crypto && sstream_is_pending(txp->args.crypto[pn_space]))
743         return 1;
744
745     /* Does the ACKM for this PN space want to produce anything? */
746     if (a.allow_ack && (ossl_ackm_is_ack_desired(txp->args.ackm, pn_space)
747                         || (txp->want_ack & (1UL << pn_space)) != 0))
748         return 1;
749
750     /* Do we need to force emission of an ACK-eliciting packet? */
751     if (a.allow_force_ack_eliciting
752         && (txp->force_ack_eliciting & (1UL << pn_space)) != 0)
753         return 1;
754
755     /* Does the connection-level RXFC want to produce a frame? */
756     if (a.allow_conn_fc && (txp->want_max_data
757         || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0)))
758         return 1;
759
760     /* Do we want to produce a MAX_STREAMS frame? */
761     if (a.allow_conn_fc && (txp->want_max_streams_bidi
762                             || txp->want_max_streams_uni))
763         return 1;
764
765     /* Do we want to produce a HANDSHAKE_DONE frame? */
766     if (a.allow_handshake_done && txp->want_handshake_done)
767         return 1;
768
769     /* Do we want to produce a CONNECTION_CLOSE frame? */
770     if (a.allow_conn_close && txp->want_conn_close)
771         return 1;
772
773     /* Does the CFQ have any frames queued for this PN space? */
774     if (enc_level != QUIC_ENC_LEVEL_0RTT)
775         for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space);
776              cfq_item != NULL;
777              cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) {
778             uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item);
779
780             switch (frame_type) {
781             case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
782                 if (a.allow_new_conn_id)
783                     return 1;
784                 break;
785             case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
786                 if (a.allow_retire_conn_id)
787                     return 1;
788                 break;
789             case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
790                 if (a.allow_new_token)
791                     return 1;
792                 break;
793             default:
794                 if (a.allow_cfq_other)
795                     return 1;
796                 break;
797             }
798        }
799
800     if (a.allow_stream_rel) {
801         QUIC_STREAM_ITER it;
802
803         /* If there are any active streams, 0/1-RTT wants to produce a packet.
804          * Whether a stream is on the active list is required to be precise
805          * (i.e., a stream is never on the active list if we cannot produce a
806          * frame for it), and all stream-related frames are governed by
807          * a.allow_stream_rel (i.e., if we can send one type of stream-related
808          * frame, we can send any of them), so we don't need to inspect
809          * individual streams on the active list, just confirm that the active
810          * list is non-empty.
811          */
812         ossl_quic_stream_iter_init(&it, txp->args.qsm, 0);
813         if (it.stream != NULL)
814             return 1;
815     }
816
817     return 0;
818 }
819
820 static int sstream_is_pending(QUIC_SSTREAM *sstream)
821 {
822     OSSL_QUIC_FRAME_STREAM hdr;
823     OSSL_QTX_IOVEC iov[2];
824     size_t num_iov = OSSL_NELEM(iov);
825
826     return ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, &num_iov);
827 }
828
829 /*
830  * Generates a packet for a given EL, coalescing it into the current datagram.
831  *
832  * is_last_in_dgram and dgram_contains_initial are used to determine padding
833  * requirements.
834  *
835  * Returns TXP_ERR_* value.
836  */
837 static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level,
838                                uint32_t archetype,
839                                char is_last_in_dgram,
840                                char dgram_contains_initial)
841 {
842     char must_pad = dgram_contains_initial && is_last_in_dgram;
843     size_t min_dpl, min_pl, min_ppl, cmpl, cmppl, running_total;
844     size_t mdpl, hdr_len, pkt_overhead, cc_limit;
845     uint64_t cc_limit_;
846     QUIC_PKT_HDR phdr;
847     OSSL_TIME time_since_last;
848
849     /* Determine the limit CC imposes on what we can send. */
850     if (ossl_time_is_zero(txp->last_tx_time))
851         time_since_last = ossl_time_zero();
852     else
853         time_since_last = ossl_time_subtract(txp->args.now(txp->args.now_arg),
854                                              txp->last_tx_time);
855
856     cc_limit_ = txp->args.cc_method->get_send_allowance(txp->args.cc_data,
857                                                         time_since_last,
858                                                         ossl_time_is_zero(time_since_last));
859
860     cc_limit = (cc_limit_ > SIZE_MAX ? SIZE_MAX : (size_t)cc_limit_);
861
862     /* Assemble packet header. */
863     phdr.type           = ossl_quic_enc_level_to_pkt_type(enc_level);
864     phdr.spin_bit       = 0;
865     phdr.pn_len         = txp_determine_pn_len(txp);
866     phdr.partial        = 0;
867     phdr.fixed          = 1;
868     phdr.version        = QUIC_VERSION_1;
869     phdr.dst_conn_id    = txp->args.cur_dcid;
870     phdr.src_conn_id    = txp->args.cur_scid;
871
872     /*
873      * We need to know the length of the payload to get an accurate header
874      * length for non-1RTT packets, because the Length field found in
875      * Initial/Handshake/0-RTT packets uses a variable-length encoding. However,
876      * we don't have a good idea of the length of our payload, because the
877      * length of the payload depends on the room in the datagram after fitting
878      * the header, which depends on the size of the header.
879      *
880      * In general, it does not matter if a packet is slightly shorter (because
881      * e.g. we predicted use of a 2-byte length field, but ended up only needing
882      * a 1-byte length field). However this does matter for Initial packets
883      * which must be at least 1200 bytes, which is also the assumed default MTU;
884      * therefore in many cases Initial packets will be padded to 1200 bytes,
885      * which means if we overestimated the header size, we will be short by a
886      * few bytes and the server will ignore the packet for being too short. In
887      * this case, however, such packets always *will* be padded to meet 1200
888      * bytes, which requires a 2-byte length field, so we don't actually need to
889      * worry about this. Thus we estimate the header length assuming a 2-byte
890      * length field here, which should in practice work well in all cases.
891      */
892     phdr.len            = OSSL_QUIC_VLINT_2B_MAX - phdr.pn_len;
893
894     if (enc_level == QUIC_ENC_LEVEL_INITIAL) {
895         phdr.token      = txp->initial_token;
896         phdr.token_len  = txp->initial_token_len;
897     } else {
898         phdr.token      = NULL;
899         phdr.token_len  = 0;
900     }
901
902     hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(phdr.dst_conn_id.id_len,
903                                                      &phdr);
904     if (hdr_len == 0)
905         return TXP_ERR_INPUT;
906
907     /* MinDPL: Minimum total datagram payload length. */
908     min_dpl = must_pad ? QUIC_MIN_INITIAL_DGRAM_LEN : 0;
909
910     /* How much data is already in the current datagram? */
911     running_total = ossl_qtx_get_cur_dgram_len_bytes(txp->args.qtx);
912
913     /* MinPL: Minimum length of the fully encoded packet. */
914     min_pl = running_total < min_dpl ? min_dpl - running_total : 0;
915     if ((uint64_t)min_pl > cc_limit)
916         /*
917          * Congestion control does not allow us to send a packet of adequate
918          * size.
919          */
920         return TXP_ERR_SPACE;
921
922     /* MinPPL: Minimum plaintext payload length needed to meet MinPL. */
923     if (!txp_determine_ppl_from_pl(txp, min_pl, enc_level, hdr_len, &min_ppl))
924         /* MinPL is less than a valid packet size, so just use a MinPPL of 0. */
925         min_ppl = 0;
926
927     /* MDPL: Maximum datagram payload length. */
928     mdpl = txp_get_mdpl(txp);
929
930     /*
931      * CMPL: Maximum encoded packet size we can put into this datagram given any
932      * previous packets coalesced into it.
933      */
934     if (running_total > mdpl)
935         /* Should not be possible, but if it happens: */
936         cmpl = 0;
937     else
938         cmpl = mdpl - running_total;
939
940     /* Clamp CMPL based on congestion control limit. */
941     if (cmpl > cc_limit)
942         cmpl = cc_limit;
943
944     /* CMPPL: Maximum amount we can put into the current datagram payload. */
945     if (!txp_determine_ppl_from_pl(txp, cmpl, enc_level, hdr_len, &cmppl))
946         return TXP_ERR_SPACE;
947
948     /* Packet overhead (size of headers, AEAD tag, etc.) */
949     pkt_overhead = cmpl - cmppl;
950
951     return txp_generate_for_el_actual(txp, enc_level, archetype, min_ppl, cmppl,
952                                       pkt_overhead, &phdr);
953 }
954
955 /* Determine how many bytes we should use for the encoded PN. */
956 static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp)
957 {
958     return 4; /* TODO(QUIC) */
959 }
960
961 /* Determine plaintext packet payload length from payload length. */
962 static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp,
963                                      size_t pl,
964                                      uint32_t enc_level,
965                                      size_t hdr_len,
966                                      size_t *r)
967 {
968     if (pl < hdr_len)
969         return 0;
970
971     pl -= hdr_len;
972
973     if (!ossl_qtx_calculate_plaintext_payload_len(txp->args.qtx, enc_level,
974                                                   pl, &pl))
975         return 0;
976
977     *r = pl;
978     return 1;
979 }
980
981 static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp)
982 {
983     return ossl_qtx_get_mdpl(txp->args.qtx);
984 }
985
986 static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space,
987                                        void *arg)
988 {
989     OSSL_QUIC_TX_PACKETISER *txp = arg;
990     QUIC_STREAM *s;
991
992     if (stream_id == UINT64_MAX)
993         return txp->args.crypto[pn_space];
994
995     s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
996     if (s == NULL)
997         return NULL;
998
999     return s->sstream;
1000 }
1001
1002 static void on_regen_notify(uint64_t frame_type, uint64_t stream_id,
1003                             QUIC_TXPIM_PKT *pkt, void *arg)
1004 {
1005     OSSL_QUIC_TX_PACKETISER *txp = arg;
1006
1007     switch (frame_type) {
1008         case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE:
1009             txp->want_handshake_done = 1;
1010             break;
1011         case OSSL_QUIC_FRAME_TYPE_MAX_DATA:
1012             txp->want_max_data = 1;
1013             break;
1014         case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
1015             txp->want_max_streams_bidi = 1;
1016             break;
1017         case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
1018             txp->want_max_streams_uni = 1;
1019             break;
1020         case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
1021             txp->want_ack |= (1UL << pkt->ackm_pkt.pkt_space);
1022             break;
1023         case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA:
1024             {
1025                 QUIC_STREAM *s
1026                     = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1027
1028                 if (s == NULL)
1029                     return;
1030
1031                 s->want_max_stream_data = 1;
1032                 ossl_quic_stream_map_update_state(txp->args.qsm, s);
1033             }
1034             break;
1035         case OSSL_QUIC_FRAME_TYPE_STOP_SENDING:
1036             {
1037                 QUIC_STREAM *s
1038                     = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1039
1040                 if (s == NULL)
1041                     return;
1042
1043                 s->want_stop_sending = 1;
1044                 ossl_quic_stream_map_update_state(txp->args.qsm, s);
1045             }
1046             break;
1047         case OSSL_QUIC_FRAME_TYPE_RESET_STREAM:
1048             {
1049                 QUIC_STREAM *s
1050                     = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1051
1052                 if (s == NULL)
1053                     return;
1054
1055                 s->want_reset_stream = 1;
1056                 ossl_quic_stream_map_update_state(txp->args.qsm, s);
1057             }
1058             break;
1059         default:
1060             assert(0);
1061             break;
1062     }
1063 }
1064
1065 static int txp_generate_pre_token(OSSL_QUIC_TX_PACKETISER *txp,
1066                                   struct tx_helper *h,
1067                                   QUIC_TXPIM_PKT *tpkt,
1068                                   uint32_t pn_space,
1069                                   struct archetype_data *a)
1070 {
1071     const OSSL_QUIC_FRAME_ACK *ack;
1072     OSSL_QUIC_FRAME_ACK ack2;
1073
1074     tpkt->ackm_pkt.largest_acked = QUIC_PN_INVALID;
1075
1076     /* ACK Frames (Regenerate) */
1077     if (a->allow_ack
1078         && tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_ACK
1079         && (txp->want_ack
1080             || ossl_ackm_is_ack_desired(txp->args.ackm, pn_space))
1081         && (ack = ossl_ackm_get_ack_frame(txp->args.ackm, pn_space)) != NULL) {
1082         WPACKET *wpkt = tx_helper_begin(h);
1083
1084         if (wpkt == NULL)
1085             return 0;
1086
1087         /* We do not currently support ECN */
1088         ack2 = *ack;
1089         ack2.ecn_present = 0;
1090
1091         if (ossl_quic_wire_encode_frame_ack(wpkt,
1092                                             txp->args.ack_delay_exponent,
1093                                             &ack2)) {
1094             if (!tx_helper_commit(h))
1095                 return 0;
1096
1097             tpkt->had_ack_frame = 1;
1098
1099             if (ack->num_ack_ranges > 0)
1100                 tpkt->ackm_pkt.largest_acked = ack->ack_ranges[0].end;
1101         } else {
1102             tx_helper_rollback(h);
1103         }
1104     }
1105
1106     /* CONNECTION_CLOSE Frames (Regenerate) */
1107     if (a->allow_conn_close && txp->want_conn_close) {
1108         WPACKET *wpkt = tx_helper_begin(h);
1109
1110         if (wpkt == NULL)
1111             return 0;
1112
1113         if (ossl_quic_wire_encode_frame_conn_close(wpkt,
1114                                                    &txp->conn_close_frame)) {
1115             if (!tx_helper_commit(h))
1116                 return 0;
1117         } else {
1118             tx_helper_rollback(h);
1119         }
1120     }
1121
1122     return 1;
1123 }
1124
1125 static int try_len(size_t space_left, size_t orig_len,
1126                    size_t base_hdr_len, size_t lenbytes,
1127                    uint64_t maxn, size_t *hdr_len, size_t *payload_len)
1128 {
1129     size_t n;
1130     size_t maxn_ = maxn > SIZE_MAX ? SIZE_MAX : (size_t)maxn;
1131
1132     *hdr_len = base_hdr_len + lenbytes;
1133
1134     n = orig_len;
1135     if (n > maxn_)
1136         n = maxn_;
1137     if (n + *hdr_len > space_left)
1138         n = (space_left >= *hdr_len) ? space_left - *hdr_len : 0;
1139
1140     *payload_len = n;
1141     return n > 0;
1142 }
1143
1144 static void determine_len(size_t space_left, size_t orig_len,
1145                           size_t base_hdr_len,
1146                           uint64_t *hlen, uint64_t *len)
1147 {
1148     size_t chosen_payload_len = 0;
1149     size_t chosen_hdr_len     = 0;
1150     size_t payload_len[4], hdr_len[4];
1151     int i, valid[4] = {0};
1152
1153     valid[0] = try_len(space_left, orig_len, base_hdr_len,
1154                        1, OSSL_QUIC_VLINT_1B_MAX,
1155                        &hdr_len[0], &payload_len[0]);
1156     valid[1] = try_len(space_left, orig_len, base_hdr_len,
1157                        2, OSSL_QUIC_VLINT_2B_MAX,
1158                        &hdr_len[1], &payload_len[1]);
1159     valid[2] = try_len(space_left, orig_len, base_hdr_len,
1160                        4, OSSL_QUIC_VLINT_4B_MAX,
1161                        &hdr_len[2], &payload_len[2]);
1162     valid[3] = try_len(space_left, orig_len, base_hdr_len,
1163                        8, OSSL_QUIC_VLINT_8B_MAX,
1164                        &hdr_len[3], &payload_len[3]);
1165
1166    for (i = OSSL_NELEM(valid) - 1; i >= 0; --i)
1167         if (valid[i] && payload_len[i] >= chosen_payload_len) {
1168             chosen_payload_len = payload_len[i];
1169             chosen_hdr_len     = hdr_len[i];
1170         }
1171
1172     *hlen = chosen_hdr_len;
1173     *len  = chosen_payload_len;
1174 }
1175
1176 /*
1177  * Given a CRYPTO frame header with accurate chdr->len and a budget
1178  * (space_left), try to find the optimal value of chdr->len to fill as much of
1179  * the budget as possible. This is slightly hairy because larger values of
1180  * chdr->len cause larger encoded sizes of the length field of the frame, which
1181  * in turn mean less space available for payload data. We check all possible
1182  * encodings and choose the optimal encoding.
1183  */
1184 static int determine_crypto_len(struct tx_helper *h,
1185                                 OSSL_QUIC_FRAME_CRYPTO *chdr,
1186                                 size_t space_left,
1187                                 uint64_t *hlen,
1188                                 uint64_t *len)
1189 {
1190     size_t orig_len;
1191     size_t base_hdr_len; /* CRYPTO header length without length field */
1192
1193     if (chdr->len > SIZE_MAX)
1194         return 0;
1195
1196     orig_len = (size_t)chdr->len;
1197
1198     chdr->len = 0;
1199     base_hdr_len = ossl_quic_wire_get_encoded_frame_len_crypto_hdr(chdr);
1200     chdr->len = orig_len;
1201     if (base_hdr_len == 0)
1202         return 0;
1203
1204     --base_hdr_len;
1205
1206     determine_len(space_left, orig_len, base_hdr_len, hlen, len);
1207     return 1;
1208 }
1209
1210 static int determine_stream_len(struct tx_helper *h,
1211                                 OSSL_QUIC_FRAME_STREAM *shdr,
1212                                 size_t space_left,
1213                                 uint64_t *hlen,
1214                                 uint64_t *len)
1215 {
1216     size_t orig_len;
1217     size_t base_hdr_len; /* STREAM header length without length field */
1218
1219     if (shdr->len > SIZE_MAX)
1220         return 0;
1221
1222     orig_len = (size_t)shdr->len;
1223
1224     shdr->len = 0;
1225     base_hdr_len = ossl_quic_wire_get_encoded_frame_len_stream_hdr(shdr);
1226     shdr->len = orig_len;
1227     if (base_hdr_len == 0)
1228         return 0;
1229
1230     if (shdr->has_explicit_len)
1231         --base_hdr_len;
1232
1233     determine_len(space_left, orig_len, base_hdr_len, hlen, len);
1234     return 1;
1235 }
1236
1237 static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp,
1238                                       struct tx_helper *h,
1239                                       uint32_t pn_space,
1240                                       QUIC_TXPIM_PKT *tpkt,
1241                                       char *have_ack_eliciting)
1242 {
1243     size_t num_stream_iovec;
1244     OSSL_QUIC_FRAME_STREAM shdr = {0};
1245     OSSL_QUIC_FRAME_CRYPTO chdr = {0};
1246     OSSL_QTX_IOVEC iov[2];
1247     uint64_t hdr_bytes;
1248     WPACKET *wpkt;
1249     QUIC_TXPIM_CHUNK chunk;
1250     size_t i, space_left;
1251
1252     for (i = 0;; ++i) {
1253         space_left = tx_helper_get_space_left(h);
1254
1255         if (space_left < MIN_FRAME_SIZE_CRYPTO)
1256             return 1; /* no point trying */
1257
1258         /* Do we have any CRYPTO data waiting? */
1259         num_stream_iovec = OSSL_NELEM(iov);
1260         if (!ossl_quic_sstream_get_stream_frame(txp->args.crypto[pn_space],
1261                                                 i, &shdr, iov,
1262                                                 &num_stream_iovec))
1263             return 1; /* nothing to do */
1264
1265         /* Convert STREAM frame header to CRYPTO frame header */
1266         chdr.offset = shdr.offset;
1267         chdr.len    = shdr.len;
1268
1269         if (chdr.len == 0)
1270             return 1; /* nothing to do */
1271
1272         /* Find best fit (header length, payload length) combination. */
1273         if (!determine_crypto_len(h, &chdr, space_left, &hdr_bytes,
1274                                   &chdr.len)
1275             || hdr_bytes == 0 || chdr.len == 0) {
1276             return 1; /* can't fit anything */
1277         }
1278
1279         /*
1280          * Truncate IOVs to match our chosen length.
1281          *
1282          * The length cannot be more than SIZE_MAX because this length comes
1283          * from our send stream buffer.
1284          */
1285         ossl_quic_sstream_adjust_iov((size_t)chdr.len, iov, num_stream_iovec);
1286
1287         /*
1288          * Ensure we have enough iovecs allocated (1 for the header, up to 2 for
1289          * the the stream data.)
1290          */
1291         if (!txp_ensure_iovec(txp, h->num_iovec + 3))
1292             return 0; /* alloc error */
1293
1294         /* Encode the header. */
1295         wpkt = tx_helper_begin(h);
1296         if (wpkt == NULL)
1297             return 0; /* alloc error */
1298
1299         if (!ossl_quic_wire_encode_frame_crypto_hdr(wpkt, &chdr)) {
1300             tx_helper_rollback(h);
1301             return 1; /* can't fit */
1302         }
1303
1304         if (!tx_helper_commit(h))
1305             return 0; /* alloc error */
1306
1307         /* Add payload iovecs to the helper (infallible). */
1308         for (i = 0; i < num_stream_iovec; ++i)
1309             tx_helper_append_iovec(h, iov[i].buf, iov[i].buf_len);
1310
1311         *have_ack_eliciting = 1;
1312         tx_helper_unrestrict(h); /* no longer need PING */
1313
1314         /* Log chunk to TXPIM. */
1315         chunk.stream_id = UINT64_MAX; /* crypto stream */
1316         chunk.start     = chdr.offset;
1317         chunk.end       = chdr.offset + chdr.len - 1;
1318         chunk.has_fin   = 0; /* Crypto stream never ends */
1319         if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
1320             return 0; /* alloc error */
1321     }
1322 }
1323
1324 struct chunk_info {
1325     OSSL_QUIC_FRAME_STREAM shdr;
1326     OSSL_QTX_IOVEC iov[2];
1327     size_t num_stream_iovec;
1328     char valid;
1329 };
1330
1331 static int txp_plan_stream_chunk(OSSL_QUIC_TX_PACKETISER *txp,
1332                                  struct tx_helper *h,
1333                                  QUIC_SSTREAM *sstream,
1334                                  QUIC_TXFC *stream_txfc,
1335                                  size_t skip,
1336                                  struct chunk_info *chunk)
1337 {
1338     uint64_t fc_credit, fc_swm, fc_limit;
1339
1340     chunk->num_stream_iovec = OSSL_NELEM(chunk->iov);
1341     chunk->valid = ossl_quic_sstream_get_stream_frame(sstream, skip,
1342                                                       &chunk->shdr,
1343                                                       chunk->iov,
1344                                                       &chunk->num_stream_iovec);
1345     if (!chunk->valid)
1346         return 1;
1347
1348     if (!ossl_assert(chunk->shdr.len > 0 || chunk->shdr.is_fin))
1349         /* Should only have 0-length chunk if FIN */
1350         return 0;
1351
1352     /* Clamp according to connection and stream-level TXFC. */
1353     fc_credit   = ossl_quic_txfc_get_credit(stream_txfc);
1354     fc_swm      = ossl_quic_txfc_get_swm(stream_txfc);
1355     fc_limit    = fc_swm + fc_credit;
1356
1357     if (chunk->shdr.len > 0 && chunk->shdr.offset + chunk->shdr.len > fc_limit) {
1358         chunk->shdr.len = (fc_limit <= chunk->shdr.offset)
1359             ? 0 : fc_limit - chunk->shdr.offset;
1360         chunk->shdr.is_fin = 0;
1361     }
1362
1363     if (chunk->shdr.len == 0 && !chunk->shdr.is_fin) {
1364         /*
1365          * Nothing to do due to TXFC. Since SSTREAM returns chunks in ascending
1366          * order of offset we don't need to check any later chunks, so stop
1367          * iterating here.
1368          */
1369         chunk->valid = 0;
1370         return 1;
1371     }
1372
1373     return 1;
1374 }
1375
1376 /*
1377  * Returns 0 on fatal error (e.g. allocation failure), 1 on success.
1378  * *packet_full is set to 1 if there is no longer enough room for another STREAM
1379  * frame, and *stream_drained is set to 1 if all stream buffers have now been
1380  * sent.
1381  */
1382 static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
1383                                       struct tx_helper *h,
1384                                       uint32_t pn_space,
1385                                       QUIC_TXPIM_PKT *tpkt,
1386                                       uint64_t id,
1387                                       QUIC_SSTREAM *sstream,
1388                                       QUIC_TXFC *stream_txfc,
1389                                       QUIC_STREAM *next_stream,
1390                                       size_t min_ppl,
1391                                       char *have_ack_eliciting,
1392                                       char *packet_full,
1393                                       char *stream_drained,
1394                                       uint64_t *new_credit_consumed)
1395 {
1396     int rc = 0;
1397     struct chunk_info chunks[2] = {0};
1398
1399     OSSL_QUIC_FRAME_STREAM *shdr;
1400     WPACKET *wpkt;
1401     QUIC_TXPIM_CHUNK chunk;
1402     size_t i, j, space_left;
1403     int needs_padding_if_implicit, can_fill_payload, use_explicit_len;
1404     int could_have_following_chunk;
1405     uint64_t hdr_len_implicit, payload_len_implicit;
1406     uint64_t hdr_len_explicit, payload_len_explicit;
1407     uint64_t fc_swm, fc_new_hwm;
1408
1409     fc_swm      = ossl_quic_txfc_get_swm(stream_txfc);
1410     fc_new_hwm  = fc_swm;
1411
1412     /*
1413      * Load the first two chunks if any offered by the send stream. We retrieve
1414      * the next chunk in advance so we can determine if we need to send any more
1415      * chunks from the same stream after this one, which is needed when
1416      * determining when we can use an implicit length in a STREAM frame.
1417      */
1418     for (i = 0; i < 2; ++i) {
1419         if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i, &chunks[i]))
1420             goto err;
1421
1422         if (i == 0 && !chunks[i].valid) {
1423             /* No chunks, nothing to do. */
1424             *stream_drained = 1;
1425             rc = 1;
1426             goto err;
1427         }
1428     }
1429
1430     for (i = 0;; ++i) {
1431         space_left = tx_helper_get_space_left(h);
1432
1433         if (space_left < MIN_FRAME_SIZE_STREAM) {
1434             *packet_full = 1;
1435             rc = 1;
1436             goto err;
1437         }
1438
1439         if (!chunks[i % 2].valid) {
1440             /* Out of chunks; we're done. */
1441             *stream_drained = 1;
1442             rc = 1;
1443             goto err;
1444         }
1445
1446         if (!ossl_assert(!h->done_implicit))
1447             /*
1448              * Logic below should have ensured we didn't append an
1449              * implicit-length unless we filled the packet or didn't have
1450              * another stream to handle, so this should not be possible.
1451              */
1452             goto err;
1453
1454         shdr = &chunks[i % 2].shdr;
1455         if (i > 0)
1456             /* Load next chunk for lookahead. */
1457             if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i + 1,
1458                                        &chunks[(i + 1) % 2]))
1459                 goto err;
1460
1461         /*
1462          * Find best fit (header length, payload length) combination for if we
1463          * use an implicit length.
1464          */
1465         shdr->has_explicit_len = 0;
1466         hdr_len_implicit = payload_len_implicit = 0;
1467         if (!determine_stream_len(h, shdr, space_left,
1468                                   &hdr_len_implicit, &payload_len_implicit)
1469             || hdr_len_implicit == 0 || payload_len_implicit == 0) {
1470             *packet_full = 1;
1471             rc = 1;
1472             goto err; /* can't fit anything */
1473         }
1474
1475         /*
1476          * If using the implicit-length representation would need padding, we
1477          * can't use it.
1478          */
1479         needs_padding_if_implicit = (h->bytes_appended + hdr_len_implicit
1480                                      + payload_len_implicit < min_ppl);
1481
1482         /*
1483          * If there is a next stream, we don't use the implicit length so we can
1484          * add more STREAM frames after this one, unless there is enough data
1485          * for this STREAM frame to fill the packet.
1486          */
1487         can_fill_payload = (hdr_len_implicit + payload_len_implicit
1488                             >= space_left);
1489
1490         /*
1491          * Is there is a stream after this one, or another chunk pending
1492          * transmission in this stream?
1493          */
1494         could_have_following_chunk
1495             = (next_stream != NULL || chunks[(i + 1) % 2].valid);
1496
1497         /* Choose between explicit or implicit length representations. */
1498         use_explicit_len = !((can_fill_payload || !could_have_following_chunk)
1499                              && !needs_padding_if_implicit);
1500
1501         if (use_explicit_len) {
1502             /*
1503              * Find best fit (header length, payload length) combination for if
1504              * we use an explicit length.
1505              */
1506             shdr->has_explicit_len = 1;
1507             hdr_len_explicit = payload_len_explicit = 0;
1508             if (!determine_stream_len(h, shdr, space_left,
1509                                       &hdr_len_explicit, &payload_len_explicit)
1510                 || hdr_len_explicit == 0 || payload_len_explicit == 0) {
1511                 *packet_full = 1;
1512                 rc = 1;
1513                 goto err; /* can't fit anything */
1514             }
1515
1516             shdr->len = payload_len_explicit;
1517         } else {
1518             shdr->has_explicit_len = 0;
1519             shdr->len = payload_len_implicit;
1520         }
1521
1522         /* Truncate IOVs to match our chosen length. */
1523         ossl_quic_sstream_adjust_iov((size_t)shdr->len, chunks[i % 2].iov,
1524                                      chunks[i % 2].num_stream_iovec);
1525
1526         /*
1527          * Ensure we have enough iovecs allocated (1 for the header, up to 2 for
1528          * the the stream data.)
1529          */
1530         if (!txp_ensure_iovec(txp, h->num_iovec + 3))
1531             goto err; /* alloc error */
1532
1533         /* Encode the header. */
1534         wpkt = tx_helper_begin(h);
1535         if (wpkt == NULL)
1536             goto err; /* alloc error */
1537
1538         shdr->stream_id = id;
1539         if (!ossl_assert(ossl_quic_wire_encode_frame_stream_hdr(wpkt, shdr))) {
1540             /* (Should not be possible.) */
1541             tx_helper_rollback(h);
1542             *packet_full = 1;
1543             rc = 1;
1544             goto err; /* can't fit */
1545         }
1546
1547         if (!tx_helper_commit(h))
1548             goto err; /* alloc error */
1549
1550         /* Add payload iovecs to the helper (infallible). */
1551         for (j = 0; j < chunks[i % 2].num_stream_iovec; ++j)
1552             tx_helper_append_iovec(h, chunks[i % 2].iov[j].buf,
1553                                    chunks[i % 2].iov[j].buf_len);
1554
1555         *have_ack_eliciting = 1;
1556         tx_helper_unrestrict(h); /* no longer need PING */
1557         if (!shdr->has_explicit_len)
1558             h->done_implicit = 1;
1559
1560         /* Log new TXFC credit which was consumed. */
1561         if (shdr->len > 0 && shdr->offset + shdr->len > fc_new_hwm)
1562             fc_new_hwm = shdr->offset + shdr->len;
1563
1564         /* Log chunk to TXPIM. */
1565         chunk.stream_id         = shdr->stream_id;
1566         chunk.start             = shdr->offset;
1567         chunk.end               = shdr->offset + shdr->len - 1;
1568         chunk.has_fin           = shdr->is_fin;
1569         chunk.has_stop_sending  = 0;
1570         chunk.has_reset_stream  = 0;
1571         if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
1572             goto err; /* alloc error */
1573     }
1574
1575 err:
1576     *new_credit_consumed = fc_new_hwm - fc_swm;
1577     return rc;
1578 }
1579
1580 static void txp_enlink_tmp(QUIC_STREAM **tmp_head, QUIC_STREAM *stream)
1581 {
1582     stream->txp_next = *tmp_head;
1583     *tmp_head = stream;
1584 }
1585
1586 static int txp_generate_stream_related(OSSL_QUIC_TX_PACKETISER *txp,
1587                                        struct tx_helper *h,
1588                                        uint32_t pn_space,
1589                                        QUIC_TXPIM_PKT *tpkt,
1590                                        size_t min_ppl,
1591                                        char *have_ack_eliciting,
1592                                        QUIC_STREAM **tmp_head)
1593 {
1594     QUIC_STREAM_ITER it;
1595     void *rstream;
1596     WPACKET *wpkt;
1597     uint64_t cwm;
1598     QUIC_STREAM *stream, *snext;
1599
1600     for (ossl_quic_stream_iter_init(&it, txp->args.qsm, 1);
1601          it.stream != NULL;) {
1602
1603         stream = it.stream;
1604         ossl_quic_stream_iter_next(&it);
1605         snext = it.stream;
1606
1607         stream->txp_sent_fc                  = 0;
1608         stream->txp_sent_stop_sending        = 0;
1609         stream->txp_sent_reset_stream        = 0;
1610         stream->txp_drained                  = 0;
1611         stream->txp_blocked                  = 0;
1612         stream->txp_txfc_new_credit_consumed = 0;
1613
1614         rstream = stream->rstream;
1615
1616         /* Stream Abort Frames (STOP_SENDING, RESET_STREAM) */
1617         if (stream->want_stop_sending) {
1618             OSSL_QUIC_FRAME_STOP_SENDING f;
1619
1620             wpkt = tx_helper_begin(h);
1621             if (wpkt == NULL)
1622                 return 0; /* alloc error */
1623
1624             f.stream_id         = stream->id;
1625             f.app_error_code    = stream->stop_sending_aec;
1626             if (!ossl_quic_wire_encode_frame_stop_sending(wpkt, &f)) {
1627                 tx_helper_rollback(h); /* can't fit */
1628                 txp_enlink_tmp(tmp_head, stream);
1629                 break;
1630             }
1631
1632             if (!tx_helper_commit(h))
1633                 return 0; /* alloc error */
1634
1635             *have_ack_eliciting = 1;
1636             tx_helper_unrestrict(h); /* no longer need PING */
1637             stream->txp_sent_stop_sending = 1;
1638         }
1639
1640         if (stream->want_reset_stream) {
1641             OSSL_QUIC_FRAME_RESET_STREAM f;
1642
1643             wpkt = tx_helper_begin(h);
1644             if (wpkt == NULL)
1645                 return 0; /* alloc error */
1646
1647             f.stream_id         = stream->id;
1648             f.app_error_code    = stream->reset_stream_aec;
1649             f.final_size        = ossl_quic_sstream_get_cur_size(stream->sstream);
1650             if (!ossl_quic_wire_encode_frame_reset_stream(wpkt, &f)) {
1651                 tx_helper_rollback(h); /* can't fit */
1652                 txp_enlink_tmp(tmp_head, stream);
1653                 break;
1654             }
1655
1656             if (!tx_helper_commit(h))
1657                 return 0; /* alloc error */
1658
1659             *have_ack_eliciting = 1;
1660             tx_helper_unrestrict(h); /* no longer need PING */
1661             stream->txp_sent_reset_stream = 1;
1662         }
1663
1664         /* Stream Flow Control Frames (MAX_STREAM_DATA) */
1665         if (rstream != NULL
1666             && (stream->want_max_stream_data
1667                 || ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 0))) {
1668
1669             wpkt = tx_helper_begin(h);
1670             if (wpkt == NULL)
1671                 return 0; /* alloc error */
1672
1673             cwm = ossl_quic_rxfc_get_cwm(&stream->rxfc);
1674
1675             if (!ossl_quic_wire_encode_frame_max_stream_data(wpkt, stream->id,
1676                                                              cwm)) {
1677                 tx_helper_rollback(h); /* can't fit */
1678                 txp_enlink_tmp(tmp_head, stream);
1679                 break;
1680             }
1681
1682             if (!tx_helper_commit(h))
1683                 return 0; /* alloc error */
1684
1685             *have_ack_eliciting = 1;
1686             tx_helper_unrestrict(h); /* no longer need PING */
1687             stream->txp_sent_fc = 1;
1688         }
1689
1690         /* Stream Data Frames (STREAM) */
1691         if (stream->sstream != NULL) {
1692             char packet_full = 0, stream_drained = 0;
1693
1694             if (!txp_generate_stream_frames(txp, h, pn_space, tpkt,
1695                                             stream->id, stream->sstream,
1696                                             &stream->txfc,
1697                                             snext, min_ppl,
1698                                             have_ack_eliciting,
1699                                             &packet_full,
1700                                             &stream_drained,
1701                                             &stream->txp_txfc_new_credit_consumed)) {
1702                 /* Fatal error (allocation, etc.) */
1703                 txp_enlink_tmp(tmp_head, stream);
1704                 return 0;
1705             }
1706
1707             if (stream_drained)
1708                 stream->txp_drained = 1;
1709
1710             if (packet_full) {
1711                 txp_enlink_tmp(tmp_head, stream);
1712                 break;
1713             }
1714         }
1715
1716         txp_enlink_tmp(tmp_head, stream);
1717     }
1718
1719     return 1;
1720 }
1721
1722 /*
1723  * Generates a packet for a given EL with the given minimum and maximum
1724  * plaintext packet payload lengths. Returns TXP_ERR_* value.
1725  */
1726 static int txp_generate_for_el_actual(OSSL_QUIC_TX_PACKETISER *txp,
1727                                       uint32_t enc_level,
1728                                       uint32_t archetype,
1729                                       size_t min_ppl,
1730                                       size_t max_ppl,
1731                                       size_t pkt_overhead,
1732                                       QUIC_PKT_HDR *phdr)
1733 {
1734     int rc = TXP_ERR_SUCCESS;
1735     struct archetype_data a;
1736     uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
1737     struct tx_helper h;
1738     char have_helper = 0, have_ack_eliciting = 0, done_pre_token = 0;
1739     char require_ack_eliciting;
1740     QUIC_CFQ_ITEM *cfq_item;
1741     QUIC_TXPIM_PKT *tpkt = NULL;
1742     OSSL_QTX_PKT pkt;
1743     QUIC_STREAM *tmp_head = NULL, *stream;
1744
1745     if (!txp_get_archetype_data(enc_level, archetype, &a))
1746         goto fatal_err;
1747
1748     require_ack_eliciting
1749         = (a.allow_force_ack_eliciting
1750            && (txp->force_ack_eliciting & (1UL << pn_space)));
1751
1752     /* Minimum cannot be bigger than maximum. */
1753     if (min_ppl > max_ppl)
1754         goto fatal_err;
1755
1756     /* Maximum PN reached? */
1757     if (txp->next_pn[pn_space] >= (((QUIC_PN)1) << 62))
1758         goto fatal_err;
1759
1760     if ((tpkt = ossl_quic_txpim_pkt_alloc(txp->args.txpim)) == NULL)
1761         goto fatal_err;
1762
1763     /*
1764      * Initialise TX helper. If we must be ACK eliciting, reserve 1 byte for
1765      * PING.
1766      */
1767     if (!tx_helper_init(&h, txp, max_ppl, require_ack_eliciting ? 1 : 0))
1768         goto fatal_err;
1769
1770     have_helper = 1;
1771
1772     /*
1773      * Frame Serialization
1774      * ===================
1775      *
1776      * We now serialize frames into the packet in descending order of priority.
1777      */
1778
1779     /* HANDSHAKE_DONE (Regenerate) */
1780     if (a.allow_handshake_done && txp->want_handshake_done
1781         && tx_helper_get_space_left(&h) >= MIN_FRAME_SIZE_HANDSHAKE_DONE) {
1782         WPACKET *wpkt = tx_helper_begin(&h);
1783
1784         if (wpkt == NULL)
1785             goto fatal_err;
1786
1787         if (ossl_quic_wire_encode_frame_handshake_done(wpkt)) {
1788             tpkt->had_handshake_done_frame = 1;
1789             have_ack_eliciting             = 1;
1790
1791             if (!tx_helper_commit(&h))
1792                 goto fatal_err;
1793
1794             tx_helper_unrestrict(&h); /* no longer need PING */
1795         } else {
1796             tx_helper_rollback(&h);
1797         }
1798     }
1799
1800     /* MAX_DATA (Regenerate) */
1801     if (a.allow_conn_fc
1802         && (txp->want_max_data
1803             || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0))
1804         && tx_helper_get_space_left(&h) >= MIN_FRAME_SIZE_MAX_DATA) {
1805         WPACKET *wpkt = tx_helper_begin(&h);
1806         uint64_t cwm = ossl_quic_rxfc_get_cwm(txp->args.conn_rxfc);
1807
1808         if (wpkt == NULL)
1809             goto fatal_err;
1810
1811         if (ossl_quic_wire_encode_frame_max_data(wpkt, cwm)) {
1812             tpkt->had_max_data_frame = 1;
1813             have_ack_eliciting       = 1;
1814
1815             if (!tx_helper_commit(&h))
1816                 goto fatal_err;
1817
1818             tx_helper_unrestrict(&h); /* no longer need PING */
1819         } else {
1820             tx_helper_rollback(&h);
1821         }
1822     }
1823
1824     /* MAX_STREAMS_BIDI (Regenerate) */
1825     /*
1826      * TODO(STREAMS): Once we support multiple streams, add stream count FC
1827      * and plug this in.
1828      */
1829     if (a.allow_conn_fc
1830         && txp->want_max_streams_bidi
1831         && tx_helper_get_space_left(&h) >= MIN_FRAME_SIZE_MAX_STREAMS_BIDI) {
1832         WPACKET *wpkt = tx_helper_begin(&h);
1833         uint64_t max_streams = 1; /* TODO */
1834
1835         if (wpkt == NULL)
1836             goto fatal_err;
1837
1838         if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/0,
1839                                                     max_streams)) {
1840             tpkt->had_max_streams_bidi_frame = 1;
1841             have_ack_eliciting               = 1;
1842
1843             if (!tx_helper_commit(&h))
1844                 goto fatal_err;
1845
1846             tx_helper_unrestrict(&h); /* no longer need PING */
1847         } else {
1848             tx_helper_rollback(&h);
1849         }
1850     }
1851
1852     /* MAX_STREAMS_UNI (Regenerate) */
1853     if (a.allow_conn_fc
1854         && txp->want_max_streams_uni
1855         && tx_helper_get_space_left(&h) >= MIN_FRAME_SIZE_MAX_STREAMS_UNI) {
1856         WPACKET *wpkt = tx_helper_begin(&h);
1857         uint64_t max_streams = 0; /* TODO */
1858
1859         if (wpkt == NULL)
1860             goto fatal_err;
1861
1862         if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/1,
1863                                                     max_streams)) {
1864             tpkt->had_max_streams_uni_frame = 1;
1865             have_ack_eliciting              = 1;
1866
1867             if (!tx_helper_commit(&h))
1868                 goto fatal_err;
1869
1870             tx_helper_unrestrict(&h); /* no longer need PING */
1871         } else {
1872             tx_helper_rollback(&h);
1873         }
1874     }
1875
1876     /* GCR Frames */
1877     for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space);
1878          cfq_item != NULL;
1879          cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) {
1880         uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item);
1881         const unsigned char *encoded = ossl_quic_cfq_item_get_encoded(cfq_item);
1882         size_t encoded_len = ossl_quic_cfq_item_get_encoded_len(cfq_item);
1883
1884         switch (frame_type) {
1885             case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
1886                 if (!a.allow_new_conn_id)
1887                     continue;
1888                 break;
1889             case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
1890                 if (!a.allow_retire_conn_id)
1891                     continue;
1892                 break;
1893             case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
1894                 if (!a.allow_new_token)
1895                     continue;
1896
1897                 /*
1898                  * NEW_TOKEN frames are handled via GCR, but some
1899                  * Regenerate-strategy frames should come before them (namely
1900                  * ACK, CONNECTION_CLOSE, PATH_CHALLENGE and PATH_RESPONSE). If
1901                  * we find a NEW_TOKEN frame, do these now. If there are no
1902                  * NEW_TOKEN frames in the GCR queue we will handle these below.
1903                  */
1904                 if (!done_pre_token)
1905                     if (txp_generate_pre_token(txp, &h, tpkt, pn_space, &a))
1906                         done_pre_token = 1;
1907
1908                 break;
1909             default:
1910                 if (!a.allow_cfq_other)
1911                     continue;
1912                 break;
1913         }
1914
1915         /*
1916          * If the frame is too big, don't try to schedule any more GCR frames in
1917          * this packet rather than sending subsequent ones out of order.
1918          */
1919         if (encoded_len > tx_helper_get_space_left(&h))
1920             break;
1921
1922         if (!tx_helper_append_iovec(&h, encoded, encoded_len))
1923             goto fatal_err;
1924
1925         ossl_quic_txpim_pkt_add_cfq_item(tpkt, cfq_item);
1926
1927         if (ossl_quic_frame_type_is_ack_eliciting(frame_type)) {
1928             have_ack_eliciting = 1;
1929             tx_helper_unrestrict(&h); /* no longer need PING */
1930         }
1931     }
1932
1933     /*
1934      * If we didn't generate ACK, CONNECTION_CLOSE, PATH_CHALLENGE or
1935      * PATH_RESPONSE (as desired) before, do so now.
1936      */
1937     if (!done_pre_token)
1938         if (txp_generate_pre_token(txp, &h, tpkt, pn_space, &a))
1939             done_pre_token = 1;
1940
1941     /* CRYPTO Frames */
1942     if (a.allow_crypto)
1943         if (!txp_generate_crypto_frames(txp, &h, pn_space, tpkt,
1944                                         &have_ack_eliciting))
1945             goto fatal_err;
1946
1947     /* Stream-specific frames */
1948     if (a.allow_stream_rel)
1949         if (!txp_generate_stream_related(txp, &h, pn_space, tpkt, min_ppl,
1950                                          &have_ack_eliciting,
1951                                          &tmp_head))
1952             goto fatal_err;
1953
1954     /* PING */
1955     tx_helper_unrestrict(&h);
1956
1957     if (require_ack_eliciting && !have_ack_eliciting && a.allow_ping) {
1958         WPACKET *wpkt;
1959
1960         wpkt = tx_helper_begin(&h);
1961         if (wpkt == NULL)
1962             goto fatal_err;
1963
1964         if (!ossl_quic_wire_encode_frame_ping(wpkt)
1965             || !tx_helper_commit(&h))
1966             /*
1967              * We treat a request to be ACK-eliciting as a requirement, so this
1968              * is an error.
1969              */
1970             goto fatal_err;
1971
1972         have_ack_eliciting = 1;
1973     }
1974
1975     /* PADDING */
1976     if (h.bytes_appended < min_ppl) {
1977         WPACKET *wpkt = tx_helper_begin(&h);
1978         if (wpkt == NULL)
1979             goto fatal_err;
1980
1981         if (!ossl_quic_wire_encode_padding(wpkt, min_ppl - h.bytes_appended)
1982             || !tx_helper_commit(&h))
1983             goto fatal_err;
1984     }
1985
1986     /*
1987      * Dispatch
1988      * ========
1989      */
1990     /* ACKM Data */
1991     tpkt->ackm_pkt.num_bytes        = h.bytes_appended + pkt_overhead;
1992     tpkt->ackm_pkt.pkt_num          = txp->next_pn[pn_space];
1993     /* largest_acked is set in txp_generate_pre_token */
1994     tpkt->ackm_pkt.pkt_space        = pn_space;
1995     tpkt->ackm_pkt.is_inflight      = 1;
1996     tpkt->ackm_pkt.is_ack_eliciting = have_ack_eliciting;
1997     tpkt->ackm_pkt.is_pto_probe     = 0;
1998     tpkt->ackm_pkt.is_mtu_probe     = 0;
1999     tpkt->ackm_pkt.time             = ossl_time_now();
2000
2001     /* Packet Information for QTX */
2002     pkt.hdr         = phdr;
2003     pkt.iovec       = txp->iovec;
2004     pkt.num_iovec   = h.num_iovec;
2005     pkt.local       = NULL;
2006     pkt.peer        = BIO_ADDR_family(&txp->args.peer) == AF_UNSPEC
2007         ? NULL : &txp->args.peer;
2008     pkt.pn          = txp->next_pn[pn_space];
2009     pkt.flags       = OSSL_QTX_PKT_FLAG_COALESCE; /* always try to coalesce */
2010
2011     /* Do TX key update if needed. */
2012     if (enc_level == QUIC_ENC_LEVEL_1RTT) {
2013         uint64_t cur_pkt_count, max_pkt_count;
2014
2015         cur_pkt_count = ossl_qtx_get_cur_epoch_pkt_count(txp->args.qtx, enc_level);
2016         max_pkt_count = ossl_qtx_get_max_epoch_pkt_count(txp->args.qtx, enc_level);
2017
2018         if (cur_pkt_count >= max_pkt_count / 2)
2019             if (!ossl_qtx_trigger_key_update(txp->args.qtx))
2020                 goto fatal_err;
2021     }
2022
2023     if (!ossl_assert(h.bytes_appended > 0))
2024         goto fatal_err;
2025
2026     /* Generate TXPIM chunks representing STOP_SENDING and RESET_STREAM frames. */
2027     for (stream = tmp_head; stream != NULL; stream = stream->txp_next)
2028         if (stream->txp_sent_stop_sending || stream->txp_sent_reset_stream) {
2029             /* Log STOP_SENDING chunk to TXPIM. */
2030             QUIC_TXPIM_CHUNK chunk;
2031
2032             chunk.stream_id         = stream->id;
2033             chunk.start             = UINT64_MAX;
2034             chunk.end               = 0;
2035             chunk.has_fin           = 0;
2036             chunk.has_stop_sending  = stream->txp_sent_stop_sending;
2037             chunk.has_reset_stream  = stream->txp_sent_reset_stream;
2038             if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
2039                 return 0; /* alloc error */
2040         }
2041
2042     /* Dispatch to FIFD. */
2043     if (!ossl_quic_fifd_pkt_commit(&txp->fifd, tpkt))
2044         goto fatal_err;
2045
2046     /* Send the packet. */
2047     if (!ossl_qtx_write_pkt(txp->args.qtx, &pkt))
2048         goto fatal_err;
2049
2050     ++txp->next_pn[pn_space];
2051
2052     /*
2053      * Record FC and stream abort frames as sent; deactivate streams which no
2054      * longer have anything to do.
2055      */
2056     for (stream = tmp_head; stream != NULL; stream = stream->txp_next) {
2057         if (stream->txp_sent_fc) {
2058             stream->want_max_stream_data = 0;
2059             ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 1);
2060         }
2061
2062         if (stream->txp_sent_stop_sending)
2063             stream->want_stop_sending = 0;
2064
2065         if (stream->txp_sent_reset_stream)
2066             stream->want_reset_stream = 0;
2067
2068         if (stream->txp_txfc_new_credit_consumed > 0) {
2069             if (!ossl_assert(ossl_quic_txfc_consume_credit(&stream->txfc,
2070                                                            stream->txp_txfc_new_credit_consumed)))
2071                 /*
2072                  * Should not be possible, but we should continue with our
2073                  * bookkeeping as we have already committed the packet to the
2074                  * FIFD. Just change the value we return.
2075                  */
2076                 rc = TXP_ERR_INTERNAL;
2077
2078             stream->txp_txfc_new_credit_consumed = 0;
2079         }
2080
2081         /*
2082          * If we no longer need to generate any flow control (MAX_STREAM_DATA),
2083          * STOP_SENDING or RESET_STREAM frames, nor any STREAM frames (because
2084          * the stream is drained of data or TXFC-blocked), we can mark the
2085          * stream as inactive.
2086          */
2087         ossl_quic_stream_map_update_state(txp->args.qsm, stream);
2088
2089         if (!stream->want_max_stream_data
2090             && !stream->want_stop_sending
2091             && !stream->want_reset_stream
2092             && (stream->txp_drained || stream->txp_blocked))
2093             assert(!stream->active);
2094     }
2095
2096     /* We have now sent the packet, so update state accordingly. */
2097     if (have_ack_eliciting)
2098         txp->force_ack_eliciting &= ~(1UL << pn_space);
2099
2100     if (tpkt->had_handshake_done_frame)
2101         txp->want_handshake_done = 0;
2102
2103     if (tpkt->had_max_data_frame) {
2104         txp->want_max_data = 0;
2105         ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 1);
2106     }
2107
2108     if (tpkt->had_max_streams_bidi_frame)
2109         txp->want_max_streams_bidi = 0;
2110
2111     if (tpkt->had_max_streams_uni_frame)
2112         txp->want_max_streams_uni = 0;
2113
2114     if (tpkt->had_ack_frame)
2115         txp->want_ack &= ~(1UL << pn_space);
2116
2117     /* Done. */
2118     tx_helper_cleanup(&h);
2119     return rc;
2120
2121 fatal_err:
2122     /*
2123      * Handler for fatal errors, i.e. errors causing us to abort the entire
2124      * packet rather than just one frame. Examples of such errors include
2125      * allocation errors.
2126      */
2127     if (have_helper)
2128         tx_helper_cleanup(&h);
2129     if (tpkt != NULL)
2130         ossl_quic_txpim_pkt_release(txp->args.txpim, tpkt);
2131     return TXP_ERR_INTERNAL;
2132 }
2133
2134 /* Ensure the iovec array is at least num elements long. */
2135 static int txp_ensure_iovec(OSSL_QUIC_TX_PACKETISER *txp, size_t num)
2136 {
2137     OSSL_QTX_IOVEC *iovec;
2138
2139     if (txp->alloc_iovec >= num)
2140         return 1;
2141
2142     num = txp->alloc_iovec != 0 ? txp->alloc_iovec * 2 : 8;
2143
2144     iovec = OPENSSL_realloc(txp->iovec, sizeof(OSSL_QTX_IOVEC) * num);
2145     if (iovec == NULL)
2146         return 0;
2147
2148     txp->iovec          = iovec;
2149     txp->alloc_iovec    = num;
2150     return 1;
2151 }
2152
2153 int ossl_quic_tx_packetiser_schedule_conn_close(OSSL_QUIC_TX_PACKETISER *txp,
2154                                                 const OSSL_QUIC_FRAME_CONN_CLOSE *f)
2155 {
2156     char *reason = NULL;
2157     size_t reason_len = f->reason_len;
2158     size_t max_reason_len = txp_get_mdpl(txp) / 2;
2159
2160     if (txp->want_conn_close)
2161         return 0;
2162
2163     /*
2164      * Arbitrarily limit the length of the reason length string to half of the
2165      * MDPL.
2166      */
2167     if (reason_len > max_reason_len)
2168         reason_len = max_reason_len;
2169
2170     if (reason_len > 0) {
2171         reason = OPENSSL_memdup(f->reason, reason_len);
2172         if (reason == NULL)
2173             return 0;
2174     }
2175
2176     txp->conn_close_frame               = *f;
2177     txp->conn_close_frame.reason        = reason;
2178     txp->conn_close_frame.reason_len    = reason_len;
2179     txp->want_conn_close                = 1;
2180     return 1;
2181 }