Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/ssl/quic/quic_stream_map.c
48266 views
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
{
25
/* Must not be in list. */
26
assert(n->prev == NULL && n->next == NULL
27
&& l->prev != NULL && l->next != NULL);
28
29
n->prev = l->prev;
30
n->prev->next = n;
31
l->prev = n;
32
n->next = l;
33
}
34
35
static void list_remove(QUIC_STREAM_LIST_NODE *l,
36
QUIC_STREAM_LIST_NODE *n)
37
{
38
assert(n->prev != NULL && n->next != NULL
39
&& n->prev != n && n->next != n);
40
41
n->prev->next = n->next;
42
n->next->prev = n->prev;
43
n->next = n->prev = NULL;
44
}
45
46
static QUIC_STREAM *list_next(QUIC_STREAM_LIST_NODE *l, QUIC_STREAM_LIST_NODE *n,
47
size_t off)
48
{
49
assert(n->prev != NULL && n->next != NULL
50
&& (n == l || (n->prev != n && n->next != n))
51
&& l->prev != NULL && l->next != NULL);
52
53
n = n->next;
54
55
if (n == l)
56
n = n->next;
57
if (n == l)
58
return NULL;
59
60
assert(n != NULL);
61
62
return (QUIC_STREAM *)(((char *)n) - off);
63
}
64
65
#define active_next(l, s) list_next((l), &(s)->active_node, \
66
offsetof(QUIC_STREAM, active_node))
67
#define accept_next(l, s) list_next((l), &(s)->accept_node, \
68
offsetof(QUIC_STREAM, accept_node))
69
#define ready_for_gc_next(l, s) list_next((l), &(s)->ready_for_gc_node, \
70
offsetof(QUIC_STREAM, ready_for_gc_node))
71
#define accept_head(l) list_next((l), (l), \
72
offsetof(QUIC_STREAM, accept_node))
73
#define ready_for_gc_head(l) list_next((l), (l), \
74
offsetof(QUIC_STREAM, ready_for_gc_node))
75
76
static unsigned long hash_stream(const QUIC_STREAM *s)
77
{
78
return (unsigned long)s->id;
79
}
80
81
static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b)
82
{
83
if (a->id < b->id)
84
return -1;
85
if (a->id > b->id)
86
return 1;
87
return 0;
88
}
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
{
97
qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);
98
qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;
99
qsm->accept_list.prev = qsm->accept_list.next = &qsm->accept_list;
100
qsm->ready_for_gc_list.prev = qsm->ready_for_gc_list.next
101
= &qsm->ready_for_gc_list;
102
qsm->rr_stepping = 1;
103
qsm->rr_counter = 0;
104
qsm->rr_cur = NULL;
105
106
qsm->num_accept_bidi = 0;
107
qsm->num_accept_uni = 0;
108
qsm->num_shutdown_flush = 0;
109
110
qsm->get_stream_limit_cb = get_stream_limit_cb;
111
qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;
112
qsm->max_streams_bidi_rxfc = max_streams_bidi_rxfc;
113
qsm->max_streams_uni_rxfc = max_streams_uni_rxfc;
114
qsm->is_server = is_server;
115
return 1;
116
}
117
118
static void release_each(QUIC_STREAM *stream, void *arg)
119
{
120
QUIC_STREAM_MAP *qsm = arg;
121
122
ossl_quic_stream_map_release(qsm, stream);
123
}
124
125
void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm)
126
{
127
ossl_quic_stream_map_visit(qsm, release_each, qsm);
128
129
lh_QUIC_STREAM_free(qsm->map);
130
qsm->map = NULL;
131
}
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
{
137
lh_QUIC_STREAM_doall_arg(qsm->map, visit_cb, visit_cb_arg);
138
}
139
140
QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
141
uint64_t stream_id,
142
int type)
143
{
144
QUIC_STREAM *s;
145
QUIC_STREAM key;
146
147
key.id = stream_id;
148
149
s = lh_QUIC_STREAM_retrieve(qsm->map, &key);
150
if (s != NULL)
151
return NULL;
152
153
s = OPENSSL_zalloc(sizeof(*s));
154
if (s == NULL)
155
return NULL;
156
157
s->id = stream_id;
158
s->type = type;
159
s->as_server = qsm->is_server;
160
s->send_state = (ossl_quic_stream_is_local_init(s)
161
|| ossl_quic_stream_is_bidi(s))
162
? QUIC_SSTREAM_STATE_READY
163
: QUIC_SSTREAM_STATE_NONE;
164
s->recv_state = (!ossl_quic_stream_is_local_init(s)
165
|| ossl_quic_stream_is_bidi(s))
166
? QUIC_RSTREAM_STATE_RECV
167
: QUIC_RSTREAM_STATE_NONE;
168
169
s->send_final_size = UINT64_MAX;
170
171
lh_QUIC_STREAM_insert(qsm->map, s);
172
return s;
173
}
174
175
void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream)
176
{
177
if (stream == NULL)
178
return;
179
180
if (stream->active_node.next != NULL)
181
list_remove(&qsm->active_list, &stream->active_node);
182
if (stream->accept_node.next != NULL)
183
list_remove(&qsm->accept_list, &stream->accept_node);
184
if (stream->ready_for_gc_node.next != NULL)
185
list_remove(&qsm->ready_for_gc_list, &stream->ready_for_gc_node);
186
187
ossl_quic_sstream_free(stream->sstream);
188
stream->sstream = NULL;
189
190
ossl_quic_rstream_free(stream->rstream);
191
stream->rstream = NULL;
192
193
lh_QUIC_STREAM_delete(qsm->map, stream);
194
OPENSSL_free(stream);
195
}
196
197
QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
198
uint64_t stream_id)
199
{
200
QUIC_STREAM key;
201
202
key.id = stream_id;
203
204
return lh_QUIC_STREAM_retrieve(qsm->map, &key);
205
}
206
207
static void stream_map_mark_active(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
208
{
209
if (s->active)
210
return;
211
212
list_insert_tail(&qsm->active_list, &s->active_node);
213
214
if (qsm->rr_cur == NULL)
215
qsm->rr_cur = s;
216
217
s->active = 1;
218
}
219
220
static void stream_map_mark_inactive(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
221
{
222
if (!s->active)
223
return;
224
225
if (qsm->rr_cur == s)
226
qsm->rr_cur = active_next(&qsm->active_list, s);
227
if (qsm->rr_cur == s)
228
qsm->rr_cur = NULL;
229
230
list_remove(&qsm->active_list, &s->active_node);
231
232
s->active = 0;
233
}
234
235
void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping)
236
{
237
qsm->rr_stepping = stepping;
238
qsm->rr_counter = 0;
239
}
240
241
static int stream_has_data_to_send(QUIC_STREAM *s)
242
{
243
OSSL_QUIC_FRAME_STREAM shdr;
244
OSSL_QTX_IOVEC iov[2];
245
size_t num_iov;
246
uint64_t fc_credit, fc_swm, fc_limit;
247
248
switch (s->send_state) {
249
case QUIC_SSTREAM_STATE_READY:
250
case QUIC_SSTREAM_STATE_SEND:
251
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
break;
257
default:
258
return 0; /* Nothing to send. */
259
}
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
num_iov = OSSL_NELEM(iov);
269
if (!ossl_quic_sstream_get_stream_frame(s->sstream, 0, &shdr, iov,
270
&num_iov))
271
return 0;
272
273
fc_credit = ossl_quic_txfc_get_credit(&s->txfc, 0);
274
fc_swm = ossl_quic_txfc_get_swm(&s->txfc);
275
fc_limit = fc_swm + fc_credit;
276
277
return (shdr.is_fin && shdr.len == 0) || shdr.offset < fc_limit;
278
}
279
280
static ossl_unused int qsm_send_part_permits_gc(const QUIC_STREAM *qs)
281
{
282
switch (qs->send_state) {
283
case QUIC_SSTREAM_STATE_NONE:
284
case QUIC_SSTREAM_STATE_DATA_RECVD:
285
case QUIC_SSTREAM_STATE_RESET_RECVD:
286
return 1;
287
default:
288
return 0;
289
}
290
}
291
292
static int qsm_ready_for_gc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
293
{
294
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
assert(!qs->deleted
301
|| !ossl_quic_stream_has_send(qs)
302
|| ossl_quic_stream_send_is_reset(qs)
303
|| ossl_quic_stream_send_get_final_size(qs, NULL));
304
305
return
306
qs->deleted
307
&& (!ossl_quic_stream_has_recv(qs)
308
|| recv_stream_fully_drained
309
|| qs->acked_stop_sending)
310
&& (!ossl_quic_stream_has_send(qs)
311
|| qs->send_state == QUIC_SSTREAM_STATE_DATA_RECVD
312
|| qs->send_state == QUIC_SSTREAM_STATE_RESET_RECVD);
313
}
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
{
319
uint64_t stream_limit;
320
321
if (qsm->get_stream_limit_cb == NULL)
322
return 1;
323
324
stream_limit = qsm->get_stream_limit_cb(is_uni, qsm->get_stream_limit_cb_arg);
325
return stream_ordinal < stream_limit;
326
}
327
328
void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
329
{
330
int should_be_active, allowed_by_stream_limit = 1;
331
332
if (ossl_quic_stream_is_server_init(s) == qsm->is_server) {
333
int is_uni = !ossl_quic_stream_is_bidi(s);
334
uint64_t stream_ordinal = s->id >> 2;
335
336
allowed_by_stream_limit
337
= ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm,
338
stream_ordinal,
339
is_uni);
340
}
341
342
if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT
343
&& ossl_quic_sstream_is_totally_acked(s->sstream))
344
ossl_quic_stream_map_notify_totally_acked(qsm, s);
345
else if (s->shutdown_flush
346
&& s->send_state == QUIC_SSTREAM_STATE_SEND
347
&& ossl_quic_sstream_is_totally_acked(s->sstream))
348
shutdown_flush_done(qsm, s);
349
350
if (!s->ready_for_gc) {
351
s->ready_for_gc = qsm_ready_for_gc(qsm, s);
352
if (s->ready_for_gc)
353
list_insert_tail(&qsm->ready_for_gc_list, &s->ready_for_gc_node);
354
}
355
356
should_be_active
357
= allowed_by_stream_limit
358
&& !s->ready_for_gc
359
&& ((ossl_quic_stream_has_recv(s)
360
&& !ossl_quic_stream_recv_is_reset(s)
361
&& (s->recv_state == QUIC_RSTREAM_STATE_RECV
362
&& (s->want_max_stream_data
363
|| ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))))
364
|| s->want_stop_sending
365
|| s->want_reset_stream
366
|| (!s->peer_stop_sending && stream_has_data_to_send(s)));
367
368
if (should_be_active)
369
stream_map_mark_active(qsm, s);
370
else
371
stream_map_mark_inactive(qsm, s);
372
}
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
{
382
switch (qs->send_state) {
383
case QUIC_SSTREAM_STATE_NONE:
384
/* Stream without send part - caller error. */
385
return 0;
386
387
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
qs->send_state = QUIC_SSTREAM_STATE_SEND;
393
return 1;
394
395
default:
396
/* Nothing to do. */
397
return 1;
398
}
399
}
400
401
int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm,
402
QUIC_STREAM *qs)
403
{
404
switch (qs->send_state) {
405
default:
406
/* Wrong state - caller error. */
407
case QUIC_SSTREAM_STATE_NONE:
408
/* Stream without send part - caller error. */
409
return 0;
410
411
case QUIC_SSTREAM_STATE_SEND:
412
if (!ossl_quic_sstream_get_final_size(qs->sstream, &qs->send_final_size))
413
return 0;
414
415
qs->send_state = QUIC_SSTREAM_STATE_DATA_SENT;
416
return 1;
417
}
418
}
419
420
static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
421
{
422
if (!qs->shutdown_flush)
423
return;
424
425
assert(qsm->num_shutdown_flush > 0);
426
qs->shutdown_flush = 0;
427
--qsm->num_shutdown_flush;
428
}
429
430
int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,
431
QUIC_STREAM *qs)
432
{
433
switch (qs->send_state) {
434
default:
435
/* Wrong state - caller error. */
436
case QUIC_SSTREAM_STATE_NONE:
437
/* Stream without send part - caller error. */
438
return 0;
439
440
case QUIC_SSTREAM_STATE_DATA_SENT:
441
qs->send_state = QUIC_SSTREAM_STATE_DATA_RECVD;
442
/* We no longer need a QUIC_SSTREAM in this state. */
443
ossl_quic_sstream_free(qs->sstream);
444
qs->sstream = NULL;
445
446
shutdown_flush_done(qsm, qs);
447
return 1;
448
}
449
}
450
451
int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
452
QUIC_STREAM *qs,
453
uint64_t aec)
454
{
455
switch (qs->send_state) {
456
default:
457
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
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
return 0;
469
470
case QUIC_SSTREAM_STATE_READY:
471
if (!ossl_quic_stream_map_ensure_send_part_id(qsm, qs))
472
return 0;
473
474
/* FALLTHROUGH */
475
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
qs->send_final_size = ossl_quic_txfc_get_swm(&qs->txfc);
488
489
/* FALLTHROUGH */
490
case QUIC_SSTREAM_STATE_DATA_SENT:
491
qs->reset_stream_aec = aec;
492
qs->want_reset_stream = 1;
493
qs->send_state = QUIC_SSTREAM_STATE_RESET_SENT;
494
495
ossl_quic_sstream_free(qs->sstream);
496
qs->sstream = NULL;
497
498
shutdown_flush_done(qsm, qs);
499
ossl_quic_stream_map_update_state(qsm, qs);
500
return 1;
501
502
case QUIC_SSTREAM_STATE_RESET_SENT:
503
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
return 1;
509
}
510
}
511
512
int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm,
513
QUIC_STREAM *qs)
514
{
515
switch (qs->send_state) {
516
default:
517
/* Wrong state - caller error. */
518
case QUIC_SSTREAM_STATE_NONE:
519
/* Stream without send part - caller error. */
520
return 0;
521
522
case QUIC_SSTREAM_STATE_RESET_SENT:
523
qs->send_state = QUIC_SSTREAM_STATE_RESET_RECVD;
524
return 1;
525
526
case QUIC_SSTREAM_STATE_RESET_RECVD:
527
/* Already in the correct state. */
528
return 1;
529
}
530
}
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
{
541
switch (qs->recv_state) {
542
default:
543
/* Wrong state - caller error. */
544
case QUIC_RSTREAM_STATE_NONE:
545
/* Stream without receive part - caller error. */
546
return 0;
547
548
case QUIC_RSTREAM_STATE_RECV:
549
qs->recv_state = QUIC_RSTREAM_STATE_SIZE_KNOWN;
550
return 1;
551
}
552
}
553
554
int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm,
555
QUIC_STREAM *qs)
556
{
557
switch (qs->recv_state) {
558
default:
559
/* Wrong state - caller error. */
560
case QUIC_RSTREAM_STATE_NONE:
561
/* Stream without receive part - caller error. */
562
return 0;
563
564
case QUIC_RSTREAM_STATE_SIZE_KNOWN:
565
qs->recv_state = QUIC_RSTREAM_STATE_DATA_RECVD;
566
qs->want_stop_sending = 0;
567
return 1;
568
}
569
}
570
571
int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm,
572
QUIC_STREAM *qs)
573
{
574
switch (qs->recv_state) {
575
default:
576
/* Wrong state - caller error. */
577
case QUIC_RSTREAM_STATE_NONE:
578
/* Stream without receive part - caller error. */
579
return 0;
580
581
case QUIC_RSTREAM_STATE_DATA_RECVD:
582
qs->recv_state = QUIC_RSTREAM_STATE_DATA_READ;
583
584
/* QUIC_RSTREAM is no longer needed */
585
ossl_quic_rstream_free(qs->rstream);
586
qs->rstream = NULL;
587
return 1;
588
}
589
}
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
{
596
uint64_t prev_final_size;
597
598
switch (qs->recv_state) {
599
default:
600
case QUIC_RSTREAM_STATE_NONE:
601
/* Stream without receive part - caller error. */
602
return 0;
603
604
case QUIC_RSTREAM_STATE_RECV:
605
case QUIC_RSTREAM_STATE_SIZE_KNOWN:
606
case QUIC_RSTREAM_STATE_DATA_RECVD:
607
if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size)
608
&& prev_final_size != final_size)
609
/* Cannot change previous final size. */
610
return 0;
611
612
qs->recv_state = QUIC_RSTREAM_STATE_RESET_RECVD;
613
qs->peer_reset_stream_aec = app_error_code;
614
615
/* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */
616
qs->want_stop_sending = 0;
617
618
/* QUIC_RSTREAM is no longer needed */
619
ossl_quic_rstream_free(qs->rstream);
620
qs->rstream = NULL;
621
622
ossl_quic_stream_map_update_state(qsm, qs);
623
return 1;
624
625
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
case QUIC_RSTREAM_STATE_RESET_RECVD:
631
case QUIC_RSTREAM_STATE_RESET_READ:
632
/* Could be a reordered/retransmitted frame - just ignore. */
633
return 1;
634
}
635
}
636
637
int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm,
638
QUIC_STREAM *qs)
639
{
640
switch (qs->recv_state) {
641
default:
642
/* Wrong state - caller error. */
643
case QUIC_RSTREAM_STATE_NONE:
644
/* Stream without receive part - caller error. */
645
return 0;
646
647
case QUIC_RSTREAM_STATE_RESET_RECVD:
648
qs->recv_state = QUIC_RSTREAM_STATE_RESET_READ;
649
return 1;
650
}
651
}
652
653
int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,
654
QUIC_STREAM *qs,
655
uint64_t aec)
656
{
657
if (qs->stop_sending)
658
return 0;
659
660
switch (qs->recv_state) {
661
default:
662
case QUIC_RSTREAM_STATE_NONE:
663
/* Send-only stream, so this makes no sense. */
664
case QUIC_RSTREAM_STATE_DATA_RECVD:
665
case QUIC_RSTREAM_STATE_DATA_READ:
666
/*
667
* Not really any point in STOP_SENDING if we already received all data.
668
*/
669
case QUIC_RSTREAM_STATE_RESET_RECVD:
670
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
return 0;
678
679
case QUIC_RSTREAM_STATE_RECV:
680
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
break;
691
}
692
693
qs->stop_sending = 1;
694
qs->stop_sending_aec = aec;
695
return ossl_quic_stream_map_schedule_stop_sending(qsm, qs);
696
}
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
{
701
if (!qs->stop_sending)
702
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
if (qs->want_stop_sending)
709
return 1;
710
711
switch (qs->recv_state) {
712
default:
713
return 1; /* ignore */
714
case QUIC_RSTREAM_STATE_RECV:
715
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
break;
725
}
726
727
qs->want_stop_sending = 1;
728
ossl_quic_stream_map_update_state(qsm, qs);
729
return 1;
730
}
731
732
QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)
733
{
734
return accept_head(&qsm->accept_list);
735
}
736
737
void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
738
QUIC_STREAM *s)
739
{
740
list_insert_tail(&qsm->accept_list, &s->accept_node);
741
if (ossl_quic_stream_is_bidi(s))
742
++qsm->num_accept_bidi;
743
else
744
++qsm->num_accept_uni;
745
}
746
747
static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
748
{
749
return ossl_quic_stream_is_bidi(s)
750
? qsm->max_streams_bidi_rxfc
751
: qsm->max_streams_uni_rxfc;
752
}
753
754
void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
755
QUIC_STREAM *s,
756
OSSL_TIME rtt)
757
{
758
QUIC_RXFC *max_streams_rxfc;
759
760
list_remove(&qsm->accept_list, &s->accept_node);
761
if (ossl_quic_stream_is_bidi(s))
762
--qsm->num_accept_bidi;
763
else
764
--qsm->num_accept_uni;
765
766
if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL)
767
(void)ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt);
768
}
769
770
size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni)
771
{
772
return is_uni ? qsm->num_accept_uni : qsm->num_accept_bidi;
773
}
774
775
size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm)
776
{
777
return ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/0)
778
+ ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/1);
779
}
780
781
void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm)
782
{
783
QUIC_STREAM *qs, *qs_head, *qsn = NULL;
784
785
for (qs = qs_head = ready_for_gc_head(&qsm->ready_for_gc_list);
786
qs != NULL && qs != qs_head;
787
qs = qsn)
788
{
789
qsn = ready_for_gc_next(&qsm->ready_for_gc_list, qs);
790
791
ossl_quic_stream_map_release(qsm, qs);
792
}
793
}
794
795
static int eligible_for_shutdown_flush(QUIC_STREAM *qs)
796
{
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
switch (qs->send_state) {
806
case QUIC_SSTREAM_STATE_SEND:
807
case QUIC_SSTREAM_STATE_DATA_SENT:
808
return !ossl_quic_sstream_is_totally_acked(qs->sstream);
809
default:
810
return 0;
811
}
812
}
813
814
static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg)
815
{
816
QUIC_STREAM_MAP *qsm = arg;
817
818
if (!eligible_for_shutdown_flush(qs) || qs->shutdown_flush)
819
return;
820
821
qs->shutdown_flush = 1;
822
++qsm->num_shutdown_flush;
823
}
824
825
void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm)
826
{
827
qsm->num_shutdown_flush = 0;
828
829
ossl_quic_stream_map_visit(qsm, begin_shutdown_flush_each, qsm);
830
}
831
832
int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm)
833
{
834
return qsm->num_shutdown_flush == 0;
835
}
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
{
844
it->qsm = qsm;
845
it->stream = it->first_stream = qsm->rr_cur;
846
if (advance_rr && it->stream != NULL
847
&& ++qsm->rr_counter >= qsm->rr_stepping) {
848
qsm->rr_counter = 0;
849
qsm->rr_cur = active_next(&qsm->active_list, qsm->rr_cur);
850
}
851
}
852
853
void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it)
854
{
855
if (it->stream == NULL)
856
return;
857
858
it->stream = active_next(&it->qsm->active_list, it->stream);
859
if (it->stream == it->first_stream)
860
it->stream = NULL;
861
}
862
863