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