Coverage Report

Created: 2026-09-12 06:55

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