Coverage Report

Created: 2025-12-04 06:33

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