Coverage Report

Created: 2025-08-25 06:30

/src/openssl/ssl/quic/quic_stream_map.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Copyright 2022-2024 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_stream_map.h"
11
#include "internal/nelem.h"
12
#include "internal/quic_channel.h"
13
14
/*
15
 * QUIC Stream Map
16
 * ===============
17
 */
18
DEFINE_LHASH_OF_EX(QUIC_STREAM);
19
20
static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs);
21
22
/* Circular list management. */
23
static void list_insert_tail(QUIC_STREAM_LIST_NODE *l,
24
                             QUIC_STREAM_LIST_NODE *n)
25
0
{
26
    /* Must not be in list. */
27
0
    assert(n->prev == NULL && n->next == NULL
28
0
           && l->prev != NULL && l->next != NULL);
29
30
0
    n->prev = l->prev;
31
0
    n->prev->next = n;
32
0
    l->prev = n;
33
0
    n->next = l;
34
0
}
35
36
static void list_remove(QUIC_STREAM_LIST_NODE *l,
37
                        QUIC_STREAM_LIST_NODE *n)
38
0
{
39
0
    assert(n->prev != NULL && n->next != NULL
40
0
           && n->prev != n && n->next != n);
41
42
0
    n->prev->next = n->next;
43
0
    n->next->prev = n->prev;
44
0
    n->next = n->prev = NULL;
45
0
}
46
47
static QUIC_STREAM *list_next(QUIC_STREAM_LIST_NODE *l, QUIC_STREAM_LIST_NODE *n,
48
                              size_t off)
49
0
{
50
0
    assert(n->prev != NULL && n->next != NULL
51
0
           && (n == l || (n->prev != n && n->next != n))
52
0
           && l->prev != NULL && l->next != NULL);
53
54
0
    n = n->next;
55
56
0
    if (n == l)
57
0
        n = n->next;
58
0
    if (n == l)
59
0
        return NULL;
60
61
0
    assert(n != NULL);
62
63
0
    return (QUIC_STREAM *)(((char *)n) - off);
64
0
}
65
66
0
#define active_next(l, s)       list_next((l), &(s)->active_node, \
67
0
                                          offsetof(QUIC_STREAM, active_node))
68
0
#define accept_next(l, s)       list_next((l), &(s)->accept_node, \
69
0
                                          offsetof(QUIC_STREAM, accept_node))
70
0
#define ready_for_gc_next(l, s) list_next((l), &(s)->ready_for_gc_node, \
71
0
                                          offsetof(QUIC_STREAM, ready_for_gc_node))
72
0
#define accept_head(l)          list_next((l), (l), \
73
0
                                          offsetof(QUIC_STREAM, accept_node))
74
0
#define ready_for_gc_head(l)    list_next((l), (l), \
75
0
                                          offsetof(QUIC_STREAM, ready_for_gc_node))
76
77
static unsigned long hash_stream(const QUIC_STREAM *s)
78
0
{
79
0
    return (unsigned long)s->id;
80
0
}
81
82
static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)
83
0
{
84
0
    if (a->id < b->id)
85
0
        return -1;
86
0
    if (a->id > b->id)
87
0
        return 1;
88
0
    return 0;
89
0
}
90
91
int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
92
                              uint64_t (*get_stream_limit_cb)(int uni, void *arg),
93
                              void *get_stream_limit_cb_arg,
94
                              QUIC_RXFC *max_streams_bidi_rxfc,
95
                              QUIC_RXFC *max_streams_uni_rxfc,
96
                              QUIC_CHANNEL *ch)
97
0
{
98
0
    qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);
99
0
    qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;
100
0
    qsm->accept_list.prev = qsm->accept_list.next = &qsm->accept_list;
101
0
    qsm->ready_for_gc_list.prev = qsm->ready_for_gc_list.next
102
0
        = &qsm->ready_for_gc_list;
103
0
    qsm->rr_stepping = 1;
104
0
    qsm->rr_counter  = 0;
105
0
    qsm->rr_cur      = NULL;
106
107
0
    qsm->num_accept_bidi    = 0;
108
0
    qsm->num_accept_uni     = 0;
109
0
    qsm->num_shutdown_flush = 0;
110
111
0
    qsm->get_stream_limit_cb        = get_stream_limit_cb;
112
0
    qsm->get_stream_limit_cb_arg    = get_stream_limit_cb_arg;
113
0
    qsm->max_streams_bidi_rxfc      = max_streams_bidi_rxfc;
114
0
    qsm->max_streams_uni_rxfc       = max_streams_uni_rxfc;
115
0
    qsm->ch                         = ch;
116
0
    return 1;
117
0
}
118
119
static void release_each(QUIC_STREAM *stream, void *arg)
120
0
{
121
0
    QUIC_STREAM_MAP *qsm = arg;
122
123
0
    ossl_quic_stream_map_release(qsm, stream);
124
0
}
125
126
void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm)
127
0
{
128
0
    ossl_quic_stream_map_visit(qsm, release_each, qsm);
129
130
0
    lh_QUIC_STREAM_free(qsm->map);
131
0
    qsm->map = NULL;
132
0
}
133
134
void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
135
                                void (*visit_cb)(QUIC_STREAM *stream, void *arg),
136
                                void *visit_cb_arg)
137
0
{
138
0
    lh_QUIC_STREAM_doall_arg(qsm->map, visit_cb, visit_cb_arg);
139
0
}
140
141
QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
142
                                        uint64_t stream_id,
143
                                        int type)
144
0
{
145
0
    QUIC_STREAM *s;
146
0
    QUIC_STREAM key;
147
148
0
    key.id = stream_id;
149
150
0
    s = lh_QUIC_STREAM_retrieve(qsm->map, &key);
151
0
    if (s != NULL)
152
0
        return NULL;
153
154
0
    s = OPENSSL_zalloc(sizeof(*s));
155
0
    if (s == NULL)
156
0
        return NULL;
157
158
0
    s->id           = stream_id;
159
0
    s->type         = type;
160
0
    s->as_server    = ossl_quic_channel_is_server(qsm->ch);
161
0
    s->send_state   = (ossl_quic_stream_is_local_init(s)
162
0
                       || ossl_quic_stream_is_bidi(s))
163
0
        ? QUIC_SSTREAM_STATE_READY
164
0
        : QUIC_SSTREAM_STATE_NONE;
165
0
    s->recv_state   = (!ossl_quic_stream_is_local_init(s)
166
0
                       || ossl_quic_stream_is_bidi(s))
167
0
        ? QUIC_RSTREAM_STATE_RECV
168
0
        : QUIC_RSTREAM_STATE_NONE;
169
170
0
    s->send_final_size  = UINT64_MAX;
171
172
0
    lh_QUIC_STREAM_insert(qsm->map, s);
173
0
    return s;
174
0
}
175
176
void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream)
177
0
{
178
0
    if (stream == NULL)
179
0
        return;
180
181
0
    if (stream->active_node.next != NULL)
182
0
        list_remove(&qsm->active_list, &stream->active_node);
183
0
    if (stream->accept_node.next != NULL)
184
0
        list_remove(&qsm->accept_list, &stream->accept_node);
185
0
    if (stream->ready_for_gc_node.next != NULL)
186
0
        list_remove(&qsm->ready_for_gc_list, &stream->ready_for_gc_node);
187
188
0
    ossl_quic_sstream_free(stream->sstream);
189
0
    stream->sstream = NULL;
190
191
0
    ossl_quic_rstream_free(stream->rstream);
192
0
    stream->rstream = NULL;
193
194
0
    lh_QUIC_STREAM_delete(qsm->map, stream);
195
0
    OPENSSL_free(stream);
196
0
}
197
198
QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
199
                                            uint64_t stream_id)
200
0
{
201
0
    QUIC_STREAM key;
202
203
0
    key.id = stream_id;
204
205
0
    return lh_QUIC_STREAM_retrieve(qsm->map, &key);
206
0
}
207
208
static void stream_map_mark_active(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
209
0
{
210
0
    if (s->active)
211
0
        return;
212
213
0
    list_insert_tail(&qsm->active_list, &s->active_node);
214
215
0
    if (qsm->rr_cur == NULL)
216
0
        qsm->rr_cur = s;
217
218
0
    s->active = 1;
219
0
}
220
221
static void stream_map_mark_inactive(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
222
0
{
223
0
    if (!s->active)
224
0
        return;
225
226
0
    if (qsm->rr_cur == s)
227
0
        qsm->rr_cur = active_next(&qsm->active_list, s);
228
0
    if (qsm->rr_cur == s)
229
0
        qsm->rr_cur = NULL;
230
231
0
    list_remove(&qsm->active_list, &s->active_node);
232
233
0
    s->active = 0;
234
0
}
235
236
void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping)
237
0
{
238
0
    qsm->rr_stepping = stepping;
239
0
    qsm->rr_counter  = 0;
240
0
}
241
242
static int stream_has_data_to_send(QUIC_STREAM *s)
243
0
{
244
0
    OSSL_QUIC_FRAME_STREAM shdr;
245
0
    OSSL_QTX_IOVEC iov[2];
246
0
    size_t num_iov;
247
0
    uint64_t fc_credit, fc_swm, fc_limit;
248
249
0
    switch (s->send_state) {
250
0
    case QUIC_SSTREAM_STATE_READY:
251
0
    case QUIC_SSTREAM_STATE_SEND:
252
0
    case QUIC_SSTREAM_STATE_DATA_SENT:
253
        /*
254
         * We can still have data to send in DATA_SENT due to retransmissions,
255
         * etc.
256
         */
257
0
        break;
258
0
    default:
259
0
        return 0; /* Nothing to send. */
260
0
    }
261
262
    /*
263
     * We cannot determine if we have data to send simply by checking if
264
     * ossl_quic_txfc_get_credit() is zero, because we may also have older
265
     * stream data we need to retransmit. The SSTREAM returns older data first,
266
     * so we do a simple comparison of the next chunk the SSTREAM wants to send
267
     * against the TXFC CWM.
268
     */
269
0
    num_iov = OSSL_NELEM(iov);
270
0
    if (!ossl_quic_sstream_get_stream_frame(s->sstream, 0, &shdr, iov,
271
0
                                            &num_iov))
272
0
        return 0;
273
274
0
    fc_credit = ossl_quic_txfc_get_credit(&s->txfc, 0);
275
0
    fc_swm    = ossl_quic_txfc_get_swm(&s->txfc);
276
0
    fc_limit  = fc_swm + fc_credit;
277
278
0
    return (shdr.is_fin && shdr.len == 0) || shdr.offset < fc_limit;
279
0
}
280
281
static ossl_unused int qsm_send_part_permits_gc(const QUIC_STREAM *qs)
282
0
{
283
0
    switch (qs->send_state) {
284
0
    case QUIC_SSTREAM_STATE_NONE:
285
0
    case QUIC_SSTREAM_STATE_DATA_RECVD:
286
0
    case QUIC_SSTREAM_STATE_RESET_RECVD:
287
0
        return 1;
288
0
    default:
289
0
        return 0;
290
0
    }
291
0
}
292
293
static int qsm_ready_for_gc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
294
0
{
295
0
    int recv_stream_fully_drained = 0; /* TODO(QUIC FUTURE): Optimisation */
296
297
    /*
298
     * If sstream has no FIN, we auto-reset it at marked-for-deletion time, so
299
     * we don't need to worry about that here.
300
     */
301
0
    assert(!qs->deleted
302
0
           || !ossl_quic_stream_has_send(qs)
303
0
           || ossl_quic_stream_send_is_reset(qs)
304
0
           || ossl_quic_stream_send_get_final_size(qs, NULL));
305
306
0
    return
307
0
        qs->deleted
308
0
        && (!ossl_quic_stream_has_recv(qs)
309
0
            || recv_stream_fully_drained
310
0
            || qs->acked_stop_sending)
311
0
        && (!ossl_quic_stream_has_send(qs)
312
0
            || qs->send_state == QUIC_SSTREAM_STATE_DATA_RECVD
313
0
            || qs->send_state == QUIC_SSTREAM_STATE_RESET_RECVD);
314
0
}
315
316
int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm,
317
                                                          uint64_t stream_ordinal,
318
                                                          int is_uni)
319
0
{
320
0
    uint64_t stream_limit;
321
322
0
    if (qsm->get_stream_limit_cb == NULL)
323
0
        return 1;
324
325
0
    stream_limit = qsm->get_stream_limit_cb(is_uni, qsm->get_stream_limit_cb_arg);
326
0
    return stream_ordinal < stream_limit;
327
0
}
328
329
void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
330
0
{
331
0
    int should_be_active, allowed_by_stream_limit = 1;
332
333
0
    if (ossl_quic_stream_is_server_init(s) == ossl_quic_channel_is_server(qsm->ch)) {
334
0
        int is_uni = !ossl_quic_stream_is_bidi(s);
335
0
        uint64_t stream_ordinal = s->id >> 2;
336
337
0
        allowed_by_stream_limit
338
0
            = ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm,
339
0
                                                                    stream_ordinal,
340
0
                                                                    is_uni);
341
0
    }
342
343
0
    if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT
344
0
        && ossl_quic_sstream_is_totally_acked(s->sstream))
345
0
        ossl_quic_stream_map_notify_totally_acked(qsm, s);
346
0
    else if (s->shutdown_flush
347
0
             && s->send_state == QUIC_SSTREAM_STATE_SEND
348
0
             && ossl_quic_sstream_is_totally_acked(s->sstream))
349
0
        shutdown_flush_done(qsm, s);
350
351
0
    if (!s->ready_for_gc) {
352
0
        s->ready_for_gc = qsm_ready_for_gc(qsm, s);
353
0
        if (s->ready_for_gc)
354
0
            list_insert_tail(&qsm->ready_for_gc_list, &s->ready_for_gc_node);
355
0
    }
356
357
0
    should_be_active
358
0
        = allowed_by_stream_limit
359
0
        && !s->ready_for_gc
360
0
        && ((ossl_quic_stream_has_recv(s)
361
0
             && !ossl_quic_stream_recv_is_reset(s)
362
0
             && (s->recv_state == QUIC_RSTREAM_STATE_RECV
363
0
                 && (s->want_max_stream_data
364
0
                     || ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))))
365
0
            || s->want_stop_sending
366
0
            || s->want_reset_stream
367
0
            || (!s->peer_stop_sending && stream_has_data_to_send(s)));
368
369
0
    if (should_be_active)
370
0
        stream_map_mark_active(qsm, s);
371
0
    else
372
0
        stream_map_mark_inactive(qsm, s);
373
0
}
374
375
/*
376
 * Stream Send Part State Management
377
 * =================================
378
 */
379
380
int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm,
381
                                             QUIC_STREAM *qs)
382
0
{
383
0
    switch (qs->send_state) {
384
0
    case QUIC_SSTREAM_STATE_NONE:
385
        /* Stream without send part - caller error. */
386
0
        return 0;
387
388
0
    case QUIC_SSTREAM_STATE_READY:
389
        /*
390
         * We always allocate a stream ID upfront, so we don't need to do it
391
         * here.
392
         */
393
0
        qs->send_state = QUIC_SSTREAM_STATE_SEND;
394
0
        return 1;
395
396
0
    default:
397
        /* Nothing to do. */
398
0
        return 1;
399
0
    }
400
0
}
401
402
int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,
403
                                              QUIC_STREAM *qs)
404
0
{
405
0
    switch (qs->send_state) {
406
0
    default:
407
        /* Wrong state - caller error. */
408
0
    case QUIC_SSTREAM_STATE_NONE:
409
        /* Stream without send part - caller error. */
410
0
        return 0;
411
412
0
    case QUIC_SSTREAM_STATE_SEND:
413
0
        if (!ossl_quic_sstream_get_final_size(qs->sstream, &qs->send_final_size))
414
0
            return 0;
415
416
0
        qs->send_state = QUIC_SSTREAM_STATE_DATA_SENT;
417
0
        return 1;
418
0
    }
419
0
}
420
421
static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
422
0
{
423
0
    if (!qs->shutdown_flush)
424
0
        return;
425
426
0
    assert(qsm->num_shutdown_flush > 0);
427
0
    qs->shutdown_flush = 0;
428
0
    --qsm->num_shutdown_flush;
429
430
    /*
431
     * when num_shutdown_flush becomes zero we need to poke
432
     * SSL_poll() it's time to poke to SSL_shutdown() to proceed
433
     * with shutdown process as all streams are gone (flushed).
434
     */
435
0
    if (qsm->num_shutdown_flush == 0)
436
0
        ossl_quic_channel_notify_flush_done(qsm->ch);
437
0
}
438
439
int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,
440
                                              QUIC_STREAM *qs)
441
0
{
442
0
    switch (qs->send_state) {
443
0
    default:
444
        /* Wrong state - caller error. */
445
0
    case QUIC_SSTREAM_STATE_NONE:
446
        /* Stream without send part - caller error. */
447
0
        return 0;
448
449
0
    case QUIC_SSTREAM_STATE_DATA_SENT:
450
0
        qs->send_state = QUIC_SSTREAM_STATE_DATA_RECVD;
451
        /* We no longer need a QUIC_SSTREAM in this state. */
452
0
        ossl_quic_sstream_free(qs->sstream);
453
0
        qs->sstream = NULL;
454
455
0
        shutdown_flush_done(qsm, qs);
456
0
        return 1;
457
0
    }
458
0
}
459
460
int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
461
                                                QUIC_STREAM *qs,
462
                                                uint64_t aec)
463
0
{
464
0
    switch (qs->send_state) {
465
0
    default:
466
0
    case QUIC_SSTREAM_STATE_NONE:
467
        /*
468
         * RESET_STREAM pertains to sending part only, so we cannot reset a
469
         * receive-only stream.
470
         */
471
0
    case QUIC_SSTREAM_STATE_DATA_RECVD:
472
        /*
473
         * RFC 9000 s. 3.3: A sender MUST NOT [...] send RESET_STREAM from a
474
         * terminal state. If the stream has already finished normally and the
475
         * peer has acknowledged this, we cannot reset it.
476
         */
477
0
        return 0;
478
479
0
    case QUIC_SSTREAM_STATE_READY:
480
0
        if (!ossl_quic_stream_map_ensure_send_part_id(qsm, qs))
481
0
            return 0;
482
483
        /* FALLTHROUGH */
484
0
    case QUIC_SSTREAM_STATE_SEND:
485
        /*
486
         * If we already have a final size (e.g. because we are coming from
487
         * DATA_SENT), we have to be consistent with that, so don't change it.
488
         * If we don't already have a final size, determine a final size value.
489
         * This is the value which we will end up using for a RESET_STREAM frame
490
         * for flow control purposes. We could send the stream size (total
491
         * number of bytes appended to QUIC_SSTREAM by the application), but it
492
         * is in our interest to exclude any bytes we have not actually
493
         * transmitted yet, to avoid unnecessarily consuming flow control
494
         * credit. We can get this from the TXFC.
495
         */
496
0
        qs->send_final_size = ossl_quic_txfc_get_swm(&qs->txfc);
497
498
        /* FALLTHROUGH */
499
0
    case QUIC_SSTREAM_STATE_DATA_SENT:
500
0
        qs->reset_stream_aec    = aec;
501
0
        qs->want_reset_stream   = 1;
502
0
        qs->send_state          = QUIC_SSTREAM_STATE_RESET_SENT;
503
504
0
        ossl_quic_sstream_free(qs->sstream);
505
0
        qs->sstream = NULL;
506
507
0
        shutdown_flush_done(qsm, qs);
508
0
        ossl_quic_stream_map_update_state(qsm, qs);
509
0
        return 1;
510
511
0
    case QUIC_SSTREAM_STATE_RESET_SENT:
512
0
    case QUIC_SSTREAM_STATE_RESET_RECVD:
513
        /*
514
         * Idempotent - no-op. In any case, do not send RESET_STREAM again - as
515
         * mentioned, we must not send it from a terminal state.
516
         */
517
0
        return 1;
518
0
    }
519
0
}
520
521
int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,
522
                                                   QUIC_STREAM *qs)
523
0
{
524
0
    switch (qs->send_state) {
525
0
    default:
526
        /* Wrong state - caller error. */
527
0
    case QUIC_SSTREAM_STATE_NONE:
528
        /* Stream without send part - caller error. */
529
0
         return 0;
530
531
0
    case QUIC_SSTREAM_STATE_RESET_SENT:
532
0
        qs->send_state = QUIC_SSTREAM_STATE_RESET_RECVD;
533
0
        return 1;
534
535
0
    case QUIC_SSTREAM_STATE_RESET_RECVD:
536
        /* Already in the correct state. */
537
0
        return 1;
538
0
    }
539
0
}
540
541
/*
542
 * Stream Receive Part State Management
543
 * ====================================
544
 */
545
546
int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm,
547
                                                     QUIC_STREAM *qs,
548
                                                     uint64_t final_size)
549
0
{
550
0
    switch (qs->recv_state) {
551
0
    default:
552
        /* Wrong state - caller error. */
553
0
    case QUIC_RSTREAM_STATE_NONE:
554
        /* Stream without receive part - caller error. */
555
0
        return 0;
556
557
0
    case QUIC_RSTREAM_STATE_RECV:
558
0
        qs->recv_state = QUIC_RSTREAM_STATE_SIZE_KNOWN;
559
0
        return 1;
560
0
    }
561
0
}
562
563
int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,
564
                                                 QUIC_STREAM *qs)
565
0
{
566
0
    switch (qs->recv_state) {
567
0
    default:
568
        /* Wrong state - caller error. */
569
0
    case QUIC_RSTREAM_STATE_NONE:
570
        /* Stream without receive part - caller error. */
571
0
        return 0;
572
573
0
    case QUIC_RSTREAM_STATE_SIZE_KNOWN:
574
0
        qs->recv_state          = QUIC_RSTREAM_STATE_DATA_RECVD;
575
0
        qs->want_stop_sending   = 0;
576
0
        return 1;
577
0
    }
578
0
}
579
580
int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
581
                                             QUIC_STREAM *qs)
582
0
{
583
0
    switch (qs->recv_state) {
584
0
    default:
585
        /* Wrong state - caller error. */
586
0
    case QUIC_RSTREAM_STATE_NONE:
587
        /* Stream without receive part - caller error. */
588
0
        return 0;
589
590
0
    case QUIC_RSTREAM_STATE_DATA_RECVD:
591
0
        qs->recv_state = QUIC_RSTREAM_STATE_DATA_READ;
592
593
        /* QUIC_RSTREAM is no longer needed */
594
0
        ossl_quic_rstream_free(qs->rstream);
595
0
        qs->rstream = NULL;
596
0
        return 1;
597
0
    }
598
0
}
599
600
int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm,
601
                                                QUIC_STREAM *qs,
602
                                                uint64_t app_error_code,
603
                                                uint64_t final_size)
604
0
{
605
0
    uint64_t prev_final_size;
606
607
0
    switch (qs->recv_state) {
608
0
    default:
609
0
    case QUIC_RSTREAM_STATE_NONE:
610
        /* Stream without receive part - caller error. */
611
0
        return 0;
612
613
0
    case QUIC_RSTREAM_STATE_RECV:
614
0
    case QUIC_RSTREAM_STATE_SIZE_KNOWN:
615
0
    case QUIC_RSTREAM_STATE_DATA_RECVD:
616
0
        if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size)
617
0
            && prev_final_size != final_size)
618
            /* Cannot change previous final size. */
619
0
            return 0;
620
621
0
        qs->recv_state              = QUIC_RSTREAM_STATE_RESET_RECVD;
622
0
        qs->peer_reset_stream_aec   = app_error_code;
623
624
        /* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */
625
0
        qs->want_stop_sending       = 0;
626
627
        /* QUIC_RSTREAM is no longer needed */
628
0
        ossl_quic_rstream_free(qs->rstream);
629
0
        qs->rstream = NULL;
630
631
0
        ossl_quic_stream_map_update_state(qsm, qs);
632
0
        return 1;
633
634
0
    case QUIC_RSTREAM_STATE_DATA_READ:
635
        /*
636
         * If we already retired the FIN to the application this is moot
637
         * - just ignore.
638
         */
639
0
    case QUIC_RSTREAM_STATE_RESET_RECVD:
640
0
    case QUIC_RSTREAM_STATE_RESET_READ:
641
        /* Could be a reordered/retransmitted frame - just ignore. */
642
0
        return 1;
643
0
    }
644
0
}
645
646
int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,
647
                                                         QUIC_STREAM *qs)
648
0
{
649
0
    switch (qs->recv_state) {
650
0
    default:
651
        /* Wrong state - caller error. */
652
0
    case QUIC_RSTREAM_STATE_NONE:
653
        /* Stream without receive part - caller error. */
654
0
        return 0;
655
656
0
    case QUIC_RSTREAM_STATE_RESET_RECVD:
657
0
        qs->recv_state = QUIC_RSTREAM_STATE_RESET_READ;
658
0
        return 1;
659
0
    }
660
0
}
661
662
int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,
663
                                                QUIC_STREAM *qs,
664
                                                uint64_t aec)
665
0
{
666
0
    if (qs->stop_sending)
667
0
        return 0;
668
669
0
    switch (qs->recv_state) {
670
0
    default:
671
0
    case QUIC_RSTREAM_STATE_NONE:
672
        /* Send-only stream, so this makes no sense. */
673
0
    case QUIC_RSTREAM_STATE_DATA_RECVD:
674
0
    case QUIC_RSTREAM_STATE_DATA_READ:
675
        /*
676
         * Not really any point in STOP_SENDING if we already received all data.
677
         */
678
0
    case QUIC_RSTREAM_STATE_RESET_RECVD:
679
0
    case QUIC_RSTREAM_STATE_RESET_READ:
680
        /*
681
         * RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that
682
         * has not been reset by the peer."
683
         *
684
         * No point in STOP_SENDING if the peer already reset their send part.
685
         */
686
0
        return 0;
687
688
0
    case QUIC_RSTREAM_STATE_RECV:
689
0
    case QUIC_RSTREAM_STATE_SIZE_KNOWN:
690
        /*
691
         * RFC 9000 s. 3.5: "If the stream is in the Recv or Size Known state,
692
         * the transport SHOULD signal this by sending a STOP_SENDING frame to
693
         * prompt closure of the stream in the opposite direction."
694
         *
695
         * Note that it does make sense to send STOP_SENDING for a receive part
696
         * of a stream which has a known size (because we have received a FIN)
697
         * but which still has other (previous) stream data yet to be received.
698
         */
699
0
        break;
700
0
    }
701
702
0
    qs->stop_sending        = 1;
703
0
    qs->stop_sending_aec    = aec;
704
0
    return ossl_quic_stream_map_schedule_stop_sending(qsm, qs);
705
0
}
706
707
/* Called to mark STOP_SENDING for generation, or regeneration after loss. */
708
int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
709
0
{
710
0
    if (!qs->stop_sending)
711
0
        return 0;
712
713
    /*
714
     * Ignore the call as a no-op if already scheduled, or in a state
715
     * where it makes no sense to send STOP_SENDING.
716
     */
717
0
    if (qs->want_stop_sending)
718
0
        return 1;
719
720
0
    switch (qs->recv_state) {
721
0
    default:
722
0
        return 1; /* ignore */
723
0
    case QUIC_RSTREAM_STATE_RECV:
724
0
    case QUIC_RSTREAM_STATE_SIZE_KNOWN:
725
        /*
726
         * RFC 9000 s. 3.5: "An endpoint is expected to send another
727
         * STOP_SENDING frame if a packet containing a previous STOP_SENDING is
728
         * lost. However, once either all stream data or a RESET_STREAM frame
729
         * has been received for the stream -- that is, the stream is in any
730
         * state other than "Recv" or "Size Known" -- sending a STOP_SENDING
731
         * frame is unnecessary."
732
         */
733
0
        break;
734
0
    }
735
736
0
    qs->want_stop_sending = 1;
737
0
    ossl_quic_stream_map_update_state(qsm, qs);
738
0
    return 1;
739
0
}
740
741
QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)
742
0
{
743
0
    return accept_head(&qsm->accept_list);
744
0
}
745
746
QUIC_STREAM *ossl_quic_stream_map_find_in_accept_queue(QUIC_STREAM_MAP *qsm,
747
                                                       int is_uni)
748
0
{
749
0
    QUIC_STREAM *qs;
750
751
0
    if (ossl_quic_stream_map_get_accept_queue_len(qsm, is_uni) == 0)
752
0
        return NULL;
753
754
0
    qs = ossl_quic_stream_map_peek_accept_queue(qsm);
755
0
    while (qs != NULL) {
756
0
        if ((is_uni && !ossl_quic_stream_is_bidi(qs))
757
0
            || (!is_uni && ossl_quic_stream_is_bidi(qs)))
758
0
            break;
759
0
        qs = accept_next(&qsm->accept_list, qs);
760
0
    }
761
0
    return qs;
762
0
}
763
764
void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
765
                                            QUIC_STREAM *s)
766
0
{
767
0
    list_insert_tail(&qsm->accept_list, &s->accept_node);
768
0
    if (ossl_quic_stream_is_bidi(s))
769
0
        ++qsm->num_accept_bidi;
770
0
    else
771
0
        ++qsm->num_accept_uni;
772
0
}
773
774
static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
775
0
{
776
0
    return ossl_quic_stream_is_bidi(s)
777
0
        ? qsm->max_streams_bidi_rxfc
778
0
        : qsm->max_streams_uni_rxfc;
779
0
}
780
781
void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
782
                                                   QUIC_STREAM *s,
783
                                                   OSSL_TIME rtt)
784
0
{
785
0
    QUIC_RXFC *max_streams_rxfc;
786
787
0
    list_remove(&qsm->accept_list, &s->accept_node);
788
0
    if (ossl_quic_stream_is_bidi(s))
789
0
        --qsm->num_accept_bidi;
790
0
    else
791
0
        --qsm->num_accept_uni;
792
793
0
    if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL)
794
0
        (void)ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt);
795
0
}
796
797
size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni)
798
0
{
799
0
    return is_uni ? qsm->num_accept_uni : qsm->num_accept_bidi;
800
0
}
801
802
size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm)
803
0
{
804
0
    return ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/0)
805
0
        + ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/1);
806
0
}
807
808
void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm)
809
0
{
810
0
    QUIC_STREAM *qs, *qs_head, *qsn = NULL;
811
812
0
    for (qs = qs_head = ready_for_gc_head(&qsm->ready_for_gc_list);
813
0
         qs != NULL && qs != qs_head;
814
0
         qs = qsn)
815
0
    {
816
0
         qsn = ready_for_gc_next(&qsm->ready_for_gc_list, qs);
817
818
0
         ossl_quic_stream_map_release(qsm, qs);
819
0
    }
820
0
}
821
822
static int eligible_for_shutdown_flush(QUIC_STREAM *qs)
823
0
{
824
    /*
825
     * We only care about servicing the send part of a stream (if any) during
826
     * shutdown flush. We make sure we flush a stream if it is either
827
     * non-terminated or was terminated normally such as via
828
     * SSL_stream_conclude. A stream which was terminated via a reset is not
829
     * flushed, and we will have thrown away the send buffer in that case
830
     * anyway.
831
     */
832
0
    switch (qs->send_state) {
833
0
    case QUIC_SSTREAM_STATE_SEND:
834
0
    case QUIC_SSTREAM_STATE_DATA_SENT:
835
0
        return !ossl_quic_sstream_is_totally_acked(qs->sstream);
836
0
    default:
837
0
        return 0;
838
0
    }
839
0
}
840
841
static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg)
842
0
{
843
0
    QUIC_STREAM_MAP *qsm = arg;
844
845
0
    if (!eligible_for_shutdown_flush(qs) || qs->shutdown_flush)
846
0
        return;
847
848
0
    qs->shutdown_flush = 1;
849
0
    ++qsm->num_shutdown_flush;
850
0
}
851
852
void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm)
853
0
{
854
0
    qsm->num_shutdown_flush = 0;
855
856
0
    ossl_quic_stream_map_visit(qsm, begin_shutdown_flush_each, qsm);
857
0
}
858
859
int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm)
860
0
{
861
0
    return qsm->num_shutdown_flush == 0;
862
0
}
863
864
/*
865
 * QUIC Stream Iterator
866
 * ====================
867
 */
868
void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
869
                                int advance_rr)
870
0
{
871
0
    it->qsm    = qsm;
872
0
    it->stream = it->first_stream = qsm->rr_cur;
873
0
    if (advance_rr && it->stream != NULL
874
0
        && ++qsm->rr_counter >= qsm->rr_stepping) {
875
0
        qsm->rr_counter = 0;
876
0
        qsm->rr_cur     = active_next(&qsm->active_list, qsm->rr_cur);
877
0
    }
878
0
}
879
880
void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it)
881
0
{
882
0
    if (it->stream == NULL)
883
0
        return;
884
885
0
    it->stream = active_next(&it->qsm->active_list, it->stream);
886
0
    if (it->stream == it->first_stream)
887
0
        it->stream = NULL;
888
0
}