]> git.ipfire.org Git - thirdparty/openssl.git/blame - include/internal/quic_stream_map.h
QUIC DISPATCH/APL: Add SSL_stream_reset and status query APIs
[thirdparty/openssl.git] / include / internal / quic_stream_map.h
CommitLineData
a73078b7
HL
1/*
2* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3*
4* Licensed under the Apache License 2.0 (the "License"). You may not use
5* this file except in compliance with the License. You can obtain a copy
6* in the file LICENSE in the source distribution or at
7* https://www.openssl.org/source/license.html
8*/
9
10#ifndef OSSL_INTERNAL_QUIC_STREAM_MAP_H
11# define OSSL_INTERNAL_QUIC_STREAM_MAP_H
12# pragma once
13
cbe7f586
HL
14# include "internal/e_os.h"
15# include "internal/time.h"
16# include "internal/quic_types.h"
17# include "internal/quic_stream.h"
18# include "internal/quic_fc.h"
19# include <openssl/lhash.h>
20
21# ifndef OPENSSL_NO_QUIC
a73078b7
HL
22
23/*
24 * QUIC Stream
25 * ===========
26 *
27 * Logical QUIC stream composing all relevant send and receive components.
28 */
29typedef struct quic_stream_st QUIC_STREAM;
30
31typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE;
32
33struct quic_stream_list_node_st {
34 QUIC_STREAM_LIST_NODE *prev, *next;
35};
36
37struct quic_stream_st {
38 QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */
f20fdd16 39 QUIC_STREAM_LIST_NODE accept_node; /* accept queue of remotely-created streams */
a73078b7
HL
40
41 /* Temporary link used by TXP. */
42 QUIC_STREAM *txp_next;
43
44 /*
45 * QUIC Stream ID. Do not assume that this encodes a type as this is a
46 * version-specific property and may change between QUIC versions; instead,
47 * use the type field.
48 */
49 uint64_t id;
50
51 /*
52 * Application Error Code (AEC) used for STOP_SENDING frame.
53 * This is only valid if stop_sending is 1.
54 */
55 uint64_t stop_sending_aec;
56
57 /*
58 * Application Error Code (AEC) used for RESET_STREAM frame.
59 * This is only valid if reset_stream is 1.
60 */
61 uint64_t reset_stream_aec;
62
b6fc2294
HL
63 /*
64 * Application Error Code (AEC) for incoming STOP_SENDING frame.
65 * This is only valid if peer_stop_sending is 1.
66 */
67 uint64_t peer_stop_sending_aec;
68
69 /*
70 * Application Error Code (AEC) for incoming RESET_STREAM frame.
71 * This is only valid if peer_reset_stream is 1.
72 */
73 uint64_t peer_reset_stream_aec;
74
a73078b7
HL
75 /* Temporary value used by TXP. */
76 uint64_t txp_txfc_new_credit_consumed;
77
78 QUIC_SSTREAM *sstream; /* NULL if RX-only */
56a1a0ad 79 QUIC_RSTREAM *rstream; /* NULL if TX only */
a73078b7
HL
80 QUIC_TXFC txfc; /* NULL if RX-only */
81 QUIC_RXFC rxfc; /* NULL if TX-only */
82 unsigned int type : 8; /* QUIC_STREAM_INITIATOR_*, QUIC_STREAM_DIR_* */
83 unsigned int active : 1;
84
85 /*
cbe7f586
HL
86 * Has STOP_SENDING been requested (by us)? Note that this is not the same
87 * as want_stop_sending below, as a STOP_SENDING frame may already have been
a73078b7
HL
88 * sent and fully acknowledged.
89 */
90 unsigned int stop_sending : 1;
91
92 /*
cbe7f586
HL
93 * Has RESET_STREAM been requested (by us)? Works identically to
94 * STOP_SENDING for transmission purposes.
a73078b7
HL
95 */
96 unsigned int reset_stream : 1;
97
cbe7f586
HL
98 /* Has our peer sent a STOP_SENDING frame? */
99 unsigned int peer_stop_sending : 1;
100 /* Has our peer sent a RESET_STREAM frame? */
101 unsigned int peer_reset_stream : 1;
102
a73078b7
HL
103 /* Temporary flags used by TXP. */
104 unsigned int txp_sent_fc : 1;
105 unsigned int txp_sent_stop_sending : 1;
106 unsigned int txp_sent_reset_stream : 1;
107 unsigned int txp_drained : 1;
108 unsigned int txp_blocked : 1;
109
110 /* Frame regeneration flags. */
111 unsigned int want_max_stream_data : 1; /* used for regen only */
112 unsigned int want_stop_sending : 1; /* used for gen or regen */
113 unsigned int want_reset_stream : 1; /* used for gen or regen */
cbe7f586
HL
114
115 /* A FIN has been retired from the rstream buffer. */
116 unsigned int recv_fin_retired : 1;
2dbc39de
HL
117
118 /* The stream's XSO has been deleted. Pending GC. */
119 unsigned int deleted : 1;
a73078b7
HL
120};
121
a73078b7
HL
122/*
123 * QUIC Stream Map
124 * ===============
125 *
126 * The QUIC stream map:
127 *
128 * - maps stream IDs to QUIC_STREAM objects;
129 * - tracks which streams are 'active' (currently have data for transmission);
130 * - allows iteration over the active streams only.
131 *
132 */
133typedef struct quic_stream_map_st {
134 LHASH_OF(QUIC_STREAM) *map;
135 QUIC_STREAM_LIST_NODE active_list;
f20fdd16
HL
136 QUIC_STREAM_LIST_NODE accept_list;
137 size_t rr_stepping, rr_counter, num_accept;
a73078b7 138 QUIC_STREAM *rr_cur;
cbe7f586
HL
139 uint64_t (*get_stream_limit_cb)(int uni, void *arg);
140 void *get_stream_limit_cb_arg;
90cecc40
HL
141 QUIC_RXFC *max_streams_bidi_rxfc;
142 QUIC_RXFC *max_streams_uni_rxfc;
a73078b7
HL
143} QUIC_STREAM_MAP;
144
cbe7f586
HL
145/*
146 * get_stream_limit is a callback which is called to retrieve the current stream
147 * limit for streams created by us. This mechanism is not used for
148 * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if
149 * (x >> 2) < returned limit value; i.e., the returned value is exclusive.
150 *
151 * If uni is 1, get the limit for locally-initiated unidirectional streams, else
152 * get the limit for locally-initiated bidirectional streams.
153 *
154 * If the callback is NULL, stream limiting is not applied.
155 * Stream limiting is used to determine if frames can currently be produced for
156 * a stream.
157 */
158int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
159 uint64_t (*get_stream_limit_cb)(int uni, void *arg),
90cecc40
HL
160 void *get_stream_limit_cb_arg,
161 QUIC_RXFC *max_streams_bidi_rxfc,
162 QUIC_RXFC *max_streams_uni_rxfc);
a73078b7
HL
163
164/*
165 * Any streams still in the map will be released as though
166 * ossl_quic_stream_map_release was called on them.
167 */
168void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
169
170#define QUIC_STREAM_INITIATOR_CLIENT 0
171#define QUIC_STREAM_INITIATOR_SERVER 1
172#define QUIC_STREAM_INITIATOR_MASK 1
173
174#define QUIC_STREAM_DIR_BIDI 0
175#define QUIC_STREAM_DIR_UNI 2
176#define QUIC_STREAM_DIR_MASK 2
177
26ad16ea
HL
178static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(QUIC_STREAM *s)
179{
180 return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
181}
182
183static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(QUIC_STREAM *s)
184{
185 return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
186}
187
a73078b7
HL
188/*
189 * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_*
190 * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate
191 * server-initiated streams as they will need to allocate a QUIC_STREAM
192 * structure to track any stream created by the server, etc.
193 *
194 * stream_id must be a valid value. Returns NULL if a stream already exists
195 * with the given ID.
196 */
197QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
198 uint64_t stream_id,
199 int type);
200
201/*
202 * Releases a stream object. Note that this must only be done once the teardown
203 * process is entirely complete and the object will never be referenced again.
204 */
205void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream);
206
207/*
208 * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque
209 * argument which is passed through.
210 */
211void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
212 void (*visit_cb)(QUIC_STREAM *stream, void *arg),
213 void *visit_cb_arg);
214
215/*
216 * Retrieves a stream by stream ID. Returns NULL if it does not exist.
217 */
218QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
219 uint64_t stream_id);
220
221/*
222 * Marks the given stream as active or inactive based on its state. Idempotent.
223 *
224 * When a stream is marked active, it becomes available in the iteration list,
225 * and when a stream is marked inactive, it no longer appears in the iteration
226 * list.
227 *
228 * Calling this function invalidates any iterator currently pointing at the
229 * given stream object, but iterators not currently pointing at the given stream
230 * object are not invalidated.
231 */
232void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
233
234/*
235 * Sets the RR stepping value, n. The RR rotation will be advanced every n
236 * packets. The default value is 1.
237 */
238void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
239
b89c81e4
HL
240/*
241 * Resets the sending part of a stream.
e8b9f632
HL
242 *
243 * Returns 1 if the sending part of a stream was not already reset.
244 * Returns 0 otherwise, which need not be considered an error.
245 */
246int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
247 QUIC_STREAM *qs,
248 uint64_t aec);
249
250/*
251 * Marks the receiving part of a stream for STOP_SENDING.
252 *
253 * Returns 1 if the receiving part of a stream was not already marked for
254 * STOP_SENDING.
255 * Returns 0 otherwise, which need not be considered an error.
b89c81e4 256 */
e8b9f632
HL
257int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm,
258 QUIC_STREAM *qs,
259 uint64_t aec);
b89c81e4 260
f20fdd16
HL
261/*
262 * Adds a stream to the accept queue.
263 */
264void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
265 QUIC_STREAM *s);
266
267/*
268 * Returns the next item to be popped from the accept queue, or NULL if it is
269 * empty.
270 */
271QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm);
272
273/*
90cecc40
HL
274 * Removes a stream from the accept queue. rtt is the estimated connection RTT.
275 * The stream is retired for the purposes of MAX_STREAMS RXFC.
f20fdd16
HL
276 *
277 * Precondition: s is in the accept queue.
278 */
279void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
90cecc40
HL
280 QUIC_STREAM *s,
281 OSSL_TIME rtt);
f20fdd16
HL
282
283/* Returns the length of the accept queue. */
284size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm);
285
a73078b7
HL
286/*
287 * QUIC Stream Iterator
288 * ====================
289 *
290 * Allows the current set of active streams to be walked using a RR-based
291 * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm
292 * is stepped. The RR algorithm rotates the iteration order such that the next
293 * active stream is returned first after n calls to ossl_quic_stream_iter_init,
294 * where n is the stepping value configured via
295 * ossl_quic_stream_map_set_rr_stepping.
296 *
297 * Suppose there are three active streams and the configured stepping is n:
298 *
299 * Iteration 0n: [Stream 1] [Stream 2] [Stream 3]
300 * Iteration 1n: [Stream 2] [Stream 3] [Stream 1]
301 * Iteration 2n: [Stream 3] [Stream 1] [Stream 2]
302 *
303 */
304typedef struct quic_stream_iter_st {
305 QUIC_STREAM_MAP *qsm;
306 QUIC_STREAM *first_stream, *stream;
307} QUIC_STREAM_ITER;
308
309/*
310 * Initialise an iterator, advancing the RR algorithm as necessary (if
311 * advance_rr is 1). After calling this, it->stream will be the first stream in
312 * the iteration sequence, or NULL if there are no active streams.
313 */
314void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
315 int advance_rr);
316
317/*
318 * Advances to next stream in iteration sequence. You do not need to call this
319 * immediately after calling ossl_quic_stream_iter_init(). If the end of the
320 * list is reached, it->stream will be NULL after calling this.
321 */
322void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);
323
cbe7f586
HL
324# endif
325
a73078b7 326#endif