Coverage Report

Created: 2026-02-14 07:20

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