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