| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-03-20 20:07:54 +08:00
										 |  |  | * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | * | 
					
						
							|  |  |  | * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  | * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  | * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  | * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "internal/quic_stream_map.h"
 | 
					
						
							| 
									
										
										
										
											2022-11-24 16:54:01 +08:00
										 |  |  | #include "internal/nelem.h"
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * QUIC Stream Map | 
					
						
							|  |  |  |  * =============== | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | DEFINE_LHASH_OF_EX(QUIC_STREAM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 01:11:23 +08:00
										 |  |  | static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | /* Circular list management. */ | 
					
						
							|  |  |  | static void list_insert_tail(QUIC_STREAM_LIST_NODE *l, | 
					
						
							|  |  |  |                              QUIC_STREAM_LIST_NODE *n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* Must not be in list. */ | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     assert(n->prev == NULL && n->next == NULL | 
					
						
							|  |  |  |            && l->prev != NULL && l->next != NULL); | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     n->prev = l->prev; | 
					
						
							|  |  |  |     n->prev->next = n; | 
					
						
							|  |  |  |     l->prev = n; | 
					
						
							|  |  |  |     n->next = l; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void list_remove(QUIC_STREAM_LIST_NODE *l, | 
					
						
							|  |  |  |                         QUIC_STREAM_LIST_NODE *n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(n->prev != NULL && n->next != NULL | 
					
						
							|  |  |  |            && n->prev != n && n->next != n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     n->prev->next = n->next; | 
					
						
							|  |  |  |     n->next->prev = n->prev; | 
					
						
							|  |  |  |     n->next = n->prev = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | static QUIC_STREAM *list_next(QUIC_STREAM_LIST_NODE *l, QUIC_STREAM_LIST_NODE *n, | 
					
						
							|  |  |  |                               size_t off) | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     assert(n->prev != NULL && n->next != NULL | 
					
						
							|  |  |  |            && (n == l || (n->prev != n && n->next != n)) | 
					
						
							|  |  |  |            && l->prev != NULL && l->next != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  |     n = n->next; | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (n == l) | 
					
						
							|  |  |  |         n = n->next; | 
					
						
							|  |  |  |     if (n == l) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     assert(n != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  |     return (QUIC_STREAM *)(((char *)n) - off); | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | #define active_next(l, s)       list_next((l), &(s)->active_node, \
 | 
					
						
							|  |  |  |                                           offsetof(QUIC_STREAM, active_node)) | 
					
						
							|  |  |  | #define accept_next(l, s)       list_next((l), &(s)->accept_node, \
 | 
					
						
							|  |  |  |                                           offsetof(QUIC_STREAM, accept_node)) | 
					
						
							|  |  |  | #define ready_for_gc_next(l, s) list_next((l), &(s)->ready_for_gc_node, \
 | 
					
						
							|  |  |  |                                           offsetof(QUIC_STREAM, ready_for_gc_node)) | 
					
						
							|  |  |  | #define accept_head(l)          list_next((l), (l), \
 | 
					
						
							|  |  |  |                                           offsetof(QUIC_STREAM, accept_node)) | 
					
						
							|  |  |  | #define ready_for_gc_head(l)    list_next((l), (l), \
 | 
					
						
							|  |  |  |                                           offsetof(QUIC_STREAM, ready_for_gc_node)) | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | static unsigned long hash_stream(const QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return (unsigned long)s->id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (a->id < b->id) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     if (a->id > b->id) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  | int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                               uint64_t (*get_stream_limit_cb)(int uni, void *arg), | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |                               void *get_stream_limit_cb_arg, | 
					
						
							|  |  |  |                               QUIC_RXFC *max_streams_bidi_rxfc, | 
					
						
							| 
									
										
										
										
											2023-04-28 23:56:34 +08:00
										 |  |  |                               QUIC_RXFC *max_streams_uni_rxfc, | 
					
						
							|  |  |  |                               int is_server) | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream); | 
					
						
							|  |  |  |     qsm->active_list.prev = qsm->active_list.next = &qsm->active_list; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  |     qsm->accept_list.prev = qsm->accept_list.next = &qsm->accept_list; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     qsm->ready_for_gc_list.prev = qsm->ready_for_gc_list.next | 
					
						
							|  |  |  |         = &qsm->ready_for_gc_list; | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     qsm->rr_stepping = 1; | 
					
						
							|  |  |  |     qsm->rr_counter  = 0; | 
					
						
							|  |  |  |     qsm->rr_cur      = NULL; | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 20:21:11 +08:00
										 |  |  |     qsm->num_accept_bidi    = 0; | 
					
						
							|  |  |  |     qsm->num_accept_uni     = 0; | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  |     qsm->num_shutdown_flush = 0; | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     qsm->get_stream_limit_cb        = get_stream_limit_cb; | 
					
						
							|  |  |  |     qsm->get_stream_limit_cb_arg    = get_stream_limit_cb_arg; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |     qsm->max_streams_bidi_rxfc      = max_streams_bidi_rxfc; | 
					
						
							|  |  |  |     qsm->max_streams_uni_rxfc       = max_streams_uni_rxfc; | 
					
						
							| 
									
										
										
										
											2023-04-28 23:56:34 +08:00
										 |  |  |     qsm->is_server                  = is_server; | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void release_each(QUIC_STREAM *stream, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QUIC_STREAM_MAP *qsm = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ossl_quic_stream_map_release(qsm, stream); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ossl_quic_stream_map_visit(qsm, release_each, qsm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lh_QUIC_STREAM_free(qsm->map); | 
					
						
							|  |  |  |     qsm->map = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                 void (*visit_cb)(QUIC_STREAM *stream, void *arg), | 
					
						
							|  |  |  |                                 void *visit_cb_arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     lh_QUIC_STREAM_doall_arg(qsm->map, visit_cb, visit_cb_arg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                         uint64_t stream_id, | 
					
						
							|  |  |  |                                         int type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QUIC_STREAM *s; | 
					
						
							|  |  |  |     QUIC_STREAM key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     key.id = stream_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s = lh_QUIC_STREAM_retrieve(qsm->map, &key); | 
					
						
							|  |  |  |     if (s != NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s = OPENSSL_zalloc(sizeof(*s)); | 
					
						
							|  |  |  |     if (s == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     s->id           = stream_id; | 
					
						
							|  |  |  |     s->type         = type; | 
					
						
							|  |  |  |     s->as_server    = qsm->is_server; | 
					
						
							|  |  |  |     s->send_state   = (ossl_quic_stream_is_local_init(s) | 
					
						
							|  |  |  |                        || ossl_quic_stream_is_bidi(s)) | 
					
						
							|  |  |  |         ? QUIC_SSTREAM_STATE_READY | 
					
						
							|  |  |  |         : QUIC_SSTREAM_STATE_NONE; | 
					
						
							|  |  |  |     s->recv_state   = (!ossl_quic_stream_is_local_init(s) | 
					
						
							|  |  |  |                        || ossl_quic_stream_is_bidi(s)) | 
					
						
							|  |  |  |         ? QUIC_RSTREAM_STATE_RECV | 
					
						
							|  |  |  |         : QUIC_RSTREAM_STATE_NONE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     s->send_final_size  = UINT64_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     lh_QUIC_STREAM_insert(qsm->map, s); | 
					
						
							|  |  |  |     return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (stream == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     if (stream->active_node.next != NULL) | 
					
						
							|  |  |  |         list_remove(&qsm->active_list, &stream->active_node); | 
					
						
							|  |  |  |     if (stream->accept_node.next != NULL) | 
					
						
							|  |  |  |         list_remove(&qsm->accept_list, &stream->accept_node); | 
					
						
							|  |  |  |     if (stream->ready_for_gc_node.next != NULL) | 
					
						
							|  |  |  |         list_remove(&qsm->ready_for_gc_list, &stream->ready_for_gc_node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     ossl_quic_sstream_free(stream->sstream); | 
					
						
							|  |  |  |     stream->sstream = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 23:54:14 +08:00
										 |  |  |     ossl_quic_rstream_free(stream->rstream); | 
					
						
							|  |  |  |     stream->rstream = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     lh_QUIC_STREAM_delete(qsm->map, stream); | 
					
						
							|  |  |  |     OPENSSL_free(stream); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                             uint64_t stream_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QUIC_STREAM key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     key.id = stream_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return lh_QUIC_STREAM_retrieve(qsm->map, &key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void stream_map_mark_active(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (s->active) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     list_insert_tail(&qsm->active_list, &s->active_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (qsm->rr_cur == NULL) | 
					
						
							|  |  |  |         qsm->rr_cur = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->active = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void stream_map_mark_inactive(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!s->active) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (qsm->rr_cur == s) | 
					
						
							|  |  |  |         qsm->rr_cur = active_next(&qsm->active_list, s); | 
					
						
							|  |  |  |     if (qsm->rr_cur == s) | 
					
						
							|  |  |  |         qsm->rr_cur = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     list_remove(&qsm->active_list, &s->active_node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     s->active = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qsm->rr_stepping = stepping; | 
					
						
							|  |  |  |     qsm->rr_counter  = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int stream_has_data_to_send(QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     OSSL_QUIC_FRAME_STREAM shdr; | 
					
						
							|  |  |  |     OSSL_QTX_IOVEC iov[2]; | 
					
						
							|  |  |  |     size_t num_iov; | 
					
						
							|  |  |  |     uint64_t fc_credit, fc_swm, fc_limit; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     switch (s->send_state) { | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_READY: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_SEND: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_DATA_SENT: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * We can still have data to send in DATA_SENT due to retransmissions, | 
					
						
							|  |  |  |          * etc. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 0; /* Nothing to send. */ | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * We cannot determine if we have data to send simply by checking if | 
					
						
							|  |  |  |      * ossl_quic_txfc_get_credit() is zero, because we may also have older | 
					
						
							|  |  |  |      * stream data we need to retransmit. The SSTREAM returns older data first, | 
					
						
							|  |  |  |      * so we do a simple comparison of the next chunk the SSTREAM wants to send | 
					
						
							|  |  |  |      * against the TXFC CWM. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     num_iov = OSSL_NELEM(iov); | 
					
						
							|  |  |  |     if (!ossl_quic_sstream_get_stream_frame(s->sstream, 0, &shdr, iov, | 
					
						
							|  |  |  |                                             &num_iov)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-13 22:16:57 +08:00
										 |  |  |     fc_credit = ossl_quic_txfc_get_credit(&s->txfc, 0); | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  |     fc_swm    = ossl_quic_txfc_get_swm(&s->txfc); | 
					
						
							|  |  |  |     fc_limit  = fc_swm + fc_credit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (shdr.is_fin && shdr.len == 0) || shdr.offset < fc_limit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | static ossl_unused int qsm_send_part_permits_gc(const QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_NONE: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_DATA_RECVD: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_RESET_RECVD: | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | static int qsm_ready_for_gc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-25 00:05:47 +08:00
										 |  |  |     int recv_stream_fully_drained = 0; /* TODO(QUIC FUTURE): Optimisation */ | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If sstream has no FIN, we auto-reset it at marked-for-deletion time, so | 
					
						
							|  |  |  |      * we don't need to worry about that here. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     assert(!qs->deleted | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |            || !ossl_quic_stream_has_send(qs) | 
					
						
							|  |  |  |            || ossl_quic_stream_send_is_reset(qs) | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:12 +08:00
										 |  |  |            || ossl_quic_stream_send_get_final_size(qs, NULL)); | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return | 
					
						
							|  |  |  |         qs->deleted | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         && (!ossl_quic_stream_has_recv(qs) | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |             || recv_stream_fully_drained | 
					
						
							|  |  |  |             || qs->acked_stop_sending) | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         && (!ossl_quic_stream_has_send(qs) | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:12 +08:00
										 |  |  |             || qs->send_state == QUIC_SSTREAM_STATE_DATA_RECVD | 
					
						
							|  |  |  |             || qs->send_state == QUIC_SSTREAM_STATE_RESET_RECVD); | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-22 23:59:57 +08:00
										 |  |  | int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                           uint64_t stream_ordinal, | 
					
						
							|  |  |  |                                                           int is_uni) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint64_t stream_limit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (qsm->get_stream_limit_cb == NULL) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stream_limit = qsm->get_stream_limit_cb(is_uni, qsm->get_stream_limit_cb_arg); | 
					
						
							|  |  |  |     return stream_ordinal < stream_limit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  |     int should_be_active, allowed_by_stream_limit = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-22 23:59:57 +08:00
										 |  |  |     if (ossl_quic_stream_is_server_init(s) == qsm->is_server) { | 
					
						
							|  |  |  |         int is_uni = !ossl_quic_stream_is_bidi(s); | 
					
						
							|  |  |  |         uint64_t stream_ordinal = s->id >> 2; | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-22 23:59:57 +08:00
										 |  |  |         allowed_by_stream_limit | 
					
						
							|  |  |  |             = ossl_quic_stream_map_is_local_allowed_by_stream_limit(qsm, | 
					
						
							|  |  |  |                                                                     stream_ordinal, | 
					
						
							|  |  |  |                                                                     is_uni); | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:12 +08:00
										 |  |  |     if (s->send_state == QUIC_SSTREAM_STATE_DATA_SENT | 
					
						
							|  |  |  |         && ossl_quic_sstream_is_totally_acked(s->sstream)) | 
					
						
							|  |  |  |         ossl_quic_stream_map_notify_totally_acked(qsm, s); | 
					
						
							| 
									
										
										
										
											2023-07-25 01:11:23 +08:00
										 |  |  |     else if (s->shutdown_flush | 
					
						
							|  |  |  |              && s->send_state == QUIC_SSTREAM_STATE_SEND | 
					
						
							|  |  |  |              && ossl_quic_sstream_is_totally_acked(s->sstream)) | 
					
						
							|  |  |  |         shutdown_flush_done(qsm, s); | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     if (!s->ready_for_gc) { | 
					
						
							|  |  |  |         s->ready_for_gc = qsm_ready_for_gc(qsm, s); | 
					
						
							|  |  |  |         if (s->ready_for_gc) | 
					
						
							|  |  |  |             list_insert_tail(&qsm->ready_for_gc_list, &s->ready_for_gc_node); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  |     should_be_active | 
					
						
							|  |  |  |         = allowed_by_stream_limit | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |         && !s->ready_for_gc | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         && ((ossl_quic_stream_has_recv(s) | 
					
						
							|  |  |  |              && !ossl_quic_stream_recv_is_reset(s) | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  |              && (s->recv_state == QUIC_RSTREAM_STATE_RECV | 
					
						
							|  |  |  |                  && (s->want_max_stream_data | 
					
						
							|  |  |  |                      || ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0)))) | 
					
						
							| 
									
										
										
										
											2022-11-17 23:29:44 +08:00
										 |  |  |             || s->want_stop_sending | 
					
						
							|  |  |  |             || s->want_reset_stream | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |             || (!s->peer_stop_sending && stream_has_data_to_send(s))); | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (should_be_active) | 
					
						
							|  |  |  |         stream_map_mark_active(qsm, s); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         stream_map_mark_inactive(qsm, s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Stream Send Part State Management | 
					
						
							|  |  |  |  * ================================= | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                              QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without send part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_READY: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * We always allocate a stream ID upfront, so we don't need to do it | 
					
						
							|  |  |  |          * here. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         qs->send_state = QUIC_SSTREAM_STATE_SEND; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Nothing to do. */ | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                               QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without send part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_SEND: | 
					
						
							|  |  |  |         if (!ossl_quic_sstream_get_final_size(qs->sstream, &qs->send_final_size)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         qs->send_state = QUIC_SSTREAM_STATE_DATA_SENT; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  | static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!qs->shutdown_flush) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(qsm->num_shutdown_flush > 0); | 
					
						
							|  |  |  |     qs->shutdown_flush = 0; | 
					
						
							|  |  |  |     --qsm->num_shutdown_flush; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                               QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without send part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_DATA_SENT: | 
					
						
							|  |  |  |         qs->send_state = QUIC_SSTREAM_STATE_DATA_RECVD; | 
					
						
							|  |  |  |         /* We no longer need a QUIC_SSTREAM in this state. */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         ossl_quic_sstream_free(qs->sstream); | 
					
						
							|  |  |  |         qs->sstream = NULL; | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         shutdown_flush_done(qsm, qs); | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                 QUIC_STREAM *qs, | 
					
						
							|  |  |  |                                                 uint64_t aec) | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * RESET_STREAM pertains to sending part only, so we cannot reset a | 
					
						
							|  |  |  |          * receive-only stream. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_DATA_RECVD: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * RFC 9000 s. 3.3: A sender MUST NOT [...] send RESET_STREAM from a | 
					
						
							|  |  |  |          * terminal state. If the stream has already finished normally and the | 
					
						
							|  |  |  |          * peer has acknowledged this, we cannot reset it. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     case QUIC_SSTREAM_STATE_READY: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:12 +08:00
										 |  |  |         if (!ossl_quic_stream_map_ensure_send_part_id(qsm, qs)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* FALLTHROUGH */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     case QUIC_SSTREAM_STATE_SEND: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * If we already have a final size (e.g. because we are coming from | 
					
						
							|  |  |  |          * DATA_SENT), we have to be consistent with that, so don't change it. | 
					
						
							|  |  |  |          * If we don't already have a final size, determine a final size value. | 
					
						
							|  |  |  |          * This is the value which we will end up using for a RESET_STREAM frame | 
					
						
							|  |  |  |          * for flow control purposes. We could send the stream size (total | 
					
						
							|  |  |  |          * number of bytes appended to QUIC_SSTREAM by the application), but it | 
					
						
							|  |  |  |          * is in our interest to exclude any bytes we have not actually | 
					
						
							|  |  |  |          * transmitted yet, to avoid unnecessarily consuming flow control | 
					
						
							|  |  |  |          * credit. We can get this from the TXFC. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  |         qs->send_final_size = ossl_quic_txfc_get_swm(&qs->txfc); | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  |         /* FALLTHROUGH */ | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_DATA_SENT: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         qs->reset_stream_aec    = aec; | 
					
						
							|  |  |  |         qs->want_reset_stream   = 1; | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         qs->send_state          = QUIC_SSTREAM_STATE_RESET_SENT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ossl_quic_sstream_free(qs->sstream); | 
					
						
							|  |  |  |         qs->sstream = NULL; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  |         shutdown_flush_done(qsm, qs); | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         ossl_quic_stream_map_update_state(qsm, qs); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_RESET_SENT: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_RESET_RECVD: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Idempotent - no-op. In any case, do not send RESET_STREAM again - as | 
					
						
							|  |  |  |          * mentioned, we must not send it from a terminal state. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                    QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without send part - caller error. */ | 
					
						
							|  |  |  |          return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_RESET_SENT: | 
					
						
							|  |  |  |         qs->send_state = QUIC_SSTREAM_STATE_RESET_RECVD; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_RESET_RECVD: | 
					
						
							|  |  |  |         /* Already in the correct state. */ | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-03 20:15:12 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Stream Receive Part State Management | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |  * ==================================== | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm, | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |                                                      QUIC_STREAM *qs, | 
					
						
							|  |  |  |                                                      uint64_t final_size) | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without receive part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RECV: | 
					
						
							| 
									
										
										
										
											2023-07-03 20:15:12 +08:00
										 |  |  |         qs->recv_state = QUIC_RSTREAM_STATE_SIZE_KNOWN; | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                  QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without receive part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_SIZE_KNOWN: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         qs->recv_state          = QUIC_RSTREAM_STATE_DATA_RECVD; | 
					
						
							|  |  |  |         qs->want_stop_sending   = 0; | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                              QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without receive part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_DATA_RECVD: | 
					
						
							|  |  |  |         qs->recv_state = QUIC_RSTREAM_STATE_DATA_READ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* QUIC_RSTREAM is no longer needed */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         ossl_quic_rstream_free(qs->rstream); | 
					
						
							|  |  |  |         qs->rstream = NULL; | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                 QUIC_STREAM *qs, | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |                                                 uint64_t app_error_code, | 
					
						
							|  |  |  |                                                 uint64_t final_size) | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     uint64_t prev_final_size; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without receive part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RECV: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_SIZE_KNOWN: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_DATA_RECVD: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         if (ossl_quic_stream_recv_get_final_size(qs, &prev_final_size) | 
					
						
							|  |  |  |             && prev_final_size != final_size) | 
					
						
							|  |  |  |             /* Cannot change previous final size. */ | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         qs->recv_state              = QUIC_RSTREAM_STATE_RESET_RECVD; | 
					
						
							|  |  |  |         qs->peer_reset_stream_aec   = app_error_code; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* RFC 9000 s. 3.3: No point sending STOP_SENDING if already reset. */ | 
					
						
							|  |  |  |         qs->want_stop_sending       = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* QUIC_RSTREAM is no longer needed */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         ossl_quic_rstream_free(qs->rstream); | 
					
						
							|  |  |  |         qs->rstream = NULL; | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ossl_quic_stream_map_update_state(qsm, qs); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_DATA_READ: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * If we already retired the FIN to the application this is moot | 
					
						
							|  |  |  |          * - just ignore. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RESET_RECVD: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RESET_READ: | 
					
						
							|  |  |  |         /* Could be a reordered/retransmitted frame - just ignore. */ | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                          QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* Wrong state - caller error. */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Stream without receive part - caller error. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RESET_RECVD: | 
					
						
							|  |  |  |         qs->recv_state = QUIC_RSTREAM_STATE_RESET_READ; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                                 QUIC_STREAM *qs, | 
					
						
							|  |  |  |                                                 uint64_t aec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (qs->stop_sending) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_NONE: | 
					
						
							|  |  |  |         /* Send-only stream, so this makes no sense. */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_DATA_RECVD: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_DATA_READ: | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Not really any point in STOP_SENDING if we already received all data. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RESET_RECVD: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RESET_READ: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * RFC 9000 s. 3.5: "STOP_SENDING SHOULD only be sent for a stream that | 
					
						
							|  |  |  |          * has not been reset by the peer." | 
					
						
							|  |  |  |          * | 
					
						
							|  |  |  |          * No point in STOP_SENDING if the peer already reset their send part. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RECV: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_SIZE_KNOWN: | 
					
						
							|  |  |  |         /*
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  |          * RFC 9000 s. 3.5: "If the stream is in the Recv or Size Known state, | 
					
						
							|  |  |  |          * the transport SHOULD signal this by sending a STOP_SENDING frame to | 
					
						
							|  |  |  |          * prompt closure of the stream in the opposite direction." | 
					
						
							|  |  |  |          * | 
					
						
							|  |  |  |          * Note that it does make sense to send STOP_SENDING for a receive part | 
					
						
							|  |  |  |          * of a stream which has a known size (because we have received a FIN) | 
					
						
							|  |  |  |          * but which still has other (previous) stream data yet to be received. | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |          */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |     qs->stop_sending        = 1; | 
					
						
							|  |  |  |     qs->stop_sending_aec    = aec; | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     return ossl_quic_stream_map_schedule_stop_sending(qsm, qs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  | /* Called to mark STOP_SENDING for generation, or regeneration after loss. */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  | int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!qs->stop_sending) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Ignore the call as a no-op if already scheduled, or in a state | 
					
						
							|  |  |  |      * where it makes no sense to send STOP_SENDING. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (qs->want_stop_sending) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (qs->recv_state) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 1; /* ignore */ | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_RECV: | 
					
						
							|  |  |  |     case QUIC_RSTREAM_STATE_SIZE_KNOWN: | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:11 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * RFC 9000 s. 3.5: "An endpoint is expected to send another | 
					
						
							|  |  |  |          * STOP_SENDING frame if a packet containing a previous STOP_SENDING is | 
					
						
							|  |  |  |          * lost. However, once either all stream data or a RESET_STREAM frame | 
					
						
							|  |  |  |          * has been received for the stream -- that is, the stream is in any | 
					
						
							|  |  |  |          * state other than "Recv" or "Size Known" -- sending a STOP_SENDING | 
					
						
							|  |  |  |          * frame is unnecessary." | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 23:25:10 +08:00
										 |  |  |     qs->want_stop_sending = 1; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |     ossl_quic_stream_map_update_state(qsm, qs); | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return accept_head(&qsm->accept_list); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                             QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     list_insert_tail(&qsm->accept_list, &s->accept_node); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:21:11 +08:00
										 |  |  |     if (ossl_quic_stream_is_bidi(s)) | 
					
						
							|  |  |  |         ++qsm->num_accept_bidi; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         ++qsm->num_accept_uni; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | static QUIC_RXFC *qsm_get_max_streams_rxfc(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ossl_quic_stream_is_bidi(s) | 
					
						
							|  |  |  |         ? qsm->max_streams_bidi_rxfc | 
					
						
							|  |  |  |         : qsm->max_streams_uni_rxfc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm, | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |                                                    QUIC_STREAM *s, | 
					
						
							|  |  |  |                                                    OSSL_TIME rtt) | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  |     QUIC_RXFC *max_streams_rxfc; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  |     list_remove(&qsm->accept_list, &s->accept_node); | 
					
						
							| 
									
										
										
										
											2024-02-02 20:21:11 +08:00
										 |  |  |     if (ossl_quic_stream_is_bidi(s)) | 
					
						
							|  |  |  |         --qsm->num_accept_bidi; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         --qsm->num_accept_uni; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ((max_streams_rxfc = qsm_get_max_streams_rxfc(qsm, s)) != NULL) | 
					
						
							| 
									
										
										
										
											2024-07-04 16:20:27 +08:00
										 |  |  |         (void)ossl_quic_rxfc_on_retire(max_streams_rxfc, 1, rtt); | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-02 20:21:11 +08:00
										 |  |  | size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return is_uni ? qsm->num_accept_uni : qsm->num_accept_bidi; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm) | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-02 20:21:11 +08:00
										 |  |  |     return ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/0) | 
					
						
							|  |  |  |         + ossl_quic_stream_map_get_accept_queue_len(qsm, /*is_uni=*/1); | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     QUIC_STREAM *qs, *qs_head, *qsn = NULL; | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |     for (qs = qs_head = ready_for_gc_head(&qsm->ready_for_gc_list); | 
					
						
							|  |  |  |          qs != NULL && qs != qs_head; | 
					
						
							|  |  |  |          qs = qsn) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-04-19 02:30:56 +08:00
										 |  |  |          qsn = ready_for_gc_next(&qsm->ready_for_gc_list, qs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          ossl_quic_stream_map_release(qsm, qs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  | static int eligible_for_shutdown_flush(QUIC_STREAM *qs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * We only care about servicing the send part of a stream (if any) during | 
					
						
							| 
									
										
										
										
											2023-07-25 01:11:23 +08:00
										 |  |  |      * shutdown flush. We make sure we flush a stream if it is either | 
					
						
							|  |  |  |      * non-terminated or was terminated normally such as via | 
					
						
							|  |  |  |      * SSL_stream_conclude. A stream which was terminated via a reset is not | 
					
						
							|  |  |  |      * flushed, and we will have thrown away the send buffer in that case | 
					
						
							|  |  |  |      * anyway. | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-07-25 01:11:23 +08:00
										 |  |  |     switch (qs->send_state) { | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_SEND: | 
					
						
							|  |  |  |     case QUIC_SSTREAM_STATE_DATA_SENT: | 
					
						
							|  |  |  |         return !ossl_quic_sstream_is_totally_acked(qs->sstream); | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-18 23:13:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void begin_shutdown_flush_each(QUIC_STREAM *qs, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QUIC_STREAM_MAP *qsm = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!eligible_for_shutdown_flush(qs) || qs->shutdown_flush) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qs->shutdown_flush = 1; | 
					
						
							|  |  |  |     ++qsm->num_shutdown_flush; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qsm->num_shutdown_flush = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ossl_quic_stream_map_visit(qsm, begin_shutdown_flush_each, qsm); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return qsm->num_shutdown_flush == 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 00:06:59 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QUIC Stream Iterator | 
					
						
							|  |  |  |  * ==================== | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm, | 
					
						
							|  |  |  |                                 int advance_rr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     it->qsm    = qsm; | 
					
						
							|  |  |  |     it->stream = it->first_stream = qsm->rr_cur; | 
					
						
							|  |  |  |     if (advance_rr && it->stream != NULL | 
					
						
							|  |  |  |         && ++qsm->rr_counter >= qsm->rr_stepping) { | 
					
						
							|  |  |  |         qsm->rr_counter = 0; | 
					
						
							|  |  |  |         qsm->rr_cur     = active_next(&qsm->active_list, qsm->rr_cur); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (it->stream == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it->stream = active_next(&it->qsm->active_list, it->stream); | 
					
						
							|  |  |  |     if (it->stream == it->first_stream) | 
					
						
							|  |  |  |         it->stream = NULL; | 
					
						
							|  |  |  | } |