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