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