Coverage Report

Created: 2025-12-31 06:58

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