]>
Commit | Line | Data |
---|---|---|
a73078b7 | 1 | /* |
b6461792 | 2 | * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. |
a73078b7 HL |
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" | |
418e122c | 16 | # include "internal/common.h" |
cbe7f586 | 17 | # include "internal/quic_types.h" |
ff3a26b2 | 18 | # include "internal/quic_predef.h" |
cbe7f586 HL |
19 | # include "internal/quic_stream.h" |
20 | # include "internal/quic_fc.h" | |
21 | # include <openssl/lhash.h> | |
22 | ||
23 | # ifndef OPENSSL_NO_QUIC | |
a73078b7 HL |
24 | |
25 | /* | |
26 | * QUIC Stream | |
27 | * =========== | |
28 | * | |
29 | * Logical QUIC stream composing all relevant send and receive components. | |
30 | */ | |
a73078b7 HL |
31 | |
32 | typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE; | |
33 | ||
34 | struct quic_stream_list_node_st { | |
35 | QUIC_STREAM_LIST_NODE *prev, *next; | |
36 | }; | |
37 | ||
2f018d14 HL |
38 | /* |
39 | * QUIC Send Stream States | |
40 | * ----------------------- | |
41 | * | |
42 | * These correspond to the states defined in RFC 9000 s. 3.1, with the | |
43 | * exception of the NONE state which represents the absence of a send stream | |
44 | * part. | |
45 | * | |
46 | * Invariants in each state are noted in comments below. In particular, once all | |
47 | * data has been acknowledged received, or we have reset the stream, we don't | |
48 | * need to keep the QUIC_SSTREAM and data buffers around. Of course, we also | |
49 | * don't have a QUIC_SSTREAM on a receive-only stream. | |
50 | */ | |
51 | #define QUIC_SSTREAM_STATE_NONE 0 /* --- sstream == NULL */ | |
52 | #define QUIC_SSTREAM_STATE_READY 1 /* \ */ | |
53 | #define QUIC_SSTREAM_STATE_SEND 2 /* |-- sstream != NULL */ | |
54 | #define QUIC_SSTREAM_STATE_DATA_SENT 3 /* / */ | |
55 | #define QUIC_SSTREAM_STATE_DATA_RECVD 4 /* \ */ | |
56 | #define QUIC_SSTREAM_STATE_RESET_SENT 5 /* |-- sstream == NULL */ | |
57 | #define QUIC_SSTREAM_STATE_RESET_RECVD 6 /* / */ | |
58 | ||
59 | /* | |
60 | * QUIC Receive Stream States | |
61 | * -------------------------- | |
62 | * | |
63 | * These correspond to the states defined in RFC 9000 s. 3.2, with the exception | |
64 | * of the NONE state which represents the absence of a receive stream part. | |
65 | * | |
66 | * Invariants in each state are noted in comments below. In particular, once all | |
67 | * data has been read by the application, we don't need to keep the QUIC_RSTREAM | |
68 | * and data buffers around. If the receive part is instead reset before it is | |
69 | * finished, we also don't need to keep the QUIC_RSTREAM around. Finally, we | |
70 | * don't need a QUIC_RSTREAM on a send-only stream. | |
71 | */ | |
72 | #define QUIC_RSTREAM_STATE_NONE 0 /* --- rstream == NULL */ | |
73 | #define QUIC_RSTREAM_STATE_RECV 1 /* \ */ | |
74 | #define QUIC_RSTREAM_STATE_SIZE_KNOWN 2 /* |-- rstream != NULL */ | |
75 | #define QUIC_RSTREAM_STATE_DATA_RECVD 3 /* / */ | |
76 | #define QUIC_RSTREAM_STATE_DATA_READ 4 /* \ */ | |
77 | #define QUIC_RSTREAM_STATE_RESET_RECVD 5 /* |-- rstream == NULL */ | |
78 | #define QUIC_RSTREAM_STATE_RESET_READ 6 /* / */ | |
79 | ||
a73078b7 HL |
80 | struct quic_stream_st { |
81 | QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */ | |
f20fdd16 | 82 | QUIC_STREAM_LIST_NODE accept_node; /* accept queue of remotely-created streams */ |
0847e63e | 83 | QUIC_STREAM_LIST_NODE ready_for_gc_node; /* queue of streams now ready for GC */ |
a73078b7 HL |
84 | |
85 | /* Temporary link used by TXP. */ | |
86 | QUIC_STREAM *txp_next; | |
87 | ||
88 | /* | |
89 | * QUIC Stream ID. Do not assume that this encodes a type as this is a | |
90 | * version-specific property and may change between QUIC versions; instead, | |
91 | * use the type field. | |
92 | */ | |
93 | uint64_t id; | |
94 | ||
95 | /* | |
96 | * Application Error Code (AEC) used for STOP_SENDING frame. | |
97 | * This is only valid if stop_sending is 1. | |
98 | */ | |
99 | uint64_t stop_sending_aec; | |
100 | ||
101 | /* | |
102 | * Application Error Code (AEC) used for RESET_STREAM frame. | |
103 | * This is only valid if reset_stream is 1. | |
104 | */ | |
105 | uint64_t reset_stream_aec; | |
106 | ||
b6fc2294 HL |
107 | /* |
108 | * Application Error Code (AEC) for incoming STOP_SENDING frame. | |
109 | * This is only valid if peer_stop_sending is 1. | |
110 | */ | |
111 | uint64_t peer_stop_sending_aec; | |
112 | ||
113 | /* | |
114 | * Application Error Code (AEC) for incoming RESET_STREAM frame. | |
5fc256cd | 115 | * This is only valid if peer_reset_stream is 1. |
b6fc2294 HL |
116 | */ |
117 | uint64_t peer_reset_stream_aec; | |
118 | ||
a73078b7 HL |
119 | /* Temporary value used by TXP. */ |
120 | uint64_t txp_txfc_new_credit_consumed; | |
121 | ||
418e122c HL |
122 | /* |
123 | * The final size of the send stream. Although this information can be | |
124 | * discerned from a QUIC_SSTREAM, it is stored separately as we need to keep | |
125 | * track of this even if we have thrown away the QUIC_SSTREAM. Use | |
126 | * ossl_quic_stream_send_get_final_size to determine if this contain a | |
127 | * valid value or if there is no final size yet for a sending part. | |
128 | * | |
129 | * For the receive part, the final size is tracked by the stream-level RXFC; | |
130 | * use ossl_quic_stream_recv_get_final_size or | |
131 | * ossl_quic_rxfc_get_final_size. | |
132 | */ | |
133 | uint64_t send_final_size; | |
134 | ||
2f018d14 HL |
135 | /* |
136 | * Send stream part and receive stream part buffer management objects. | |
137 | * | |
138 | * DO NOT test these pointers (sstream, rstream) for NULL. Determine the | |
139 | * state of the send or receive stream part first using the appropriate | |
140 | * function; then the invariant of that state guarantees that sstream or | |
141 | * rstream either is or is not NULL respectively, therefore there is no | |
142 | * valid use case for testing these pointers for NULL. In particular, a | |
143 | * stream with a send part can still have sstream as NULL, and a stream with | |
144 | * a receive part can still have rstream as NULL. QUIC_SSTREAM and | |
145 | * QUIC_RSTREAM are stream buffer resource management objects which exist | |
146 | * only when they need to for buffer management purposes. The existence or | |
147 | * non-existence of a QUIC_SSTREAM or QUIC_RSTREAM object does not | |
148 | * correspond with whether a stream's respective send or receive part | |
149 | * logically exists or not. | |
150 | */ | |
a73078b7 | 151 | QUIC_SSTREAM *sstream; /* NULL if RX-only */ |
56a1a0ad | 152 | QUIC_RSTREAM *rstream; /* NULL if TX only */ |
2f018d14 HL |
153 | |
154 | /* Stream-level flow control managers. */ | |
a73078b7 HL |
155 | QUIC_TXFC txfc; /* NULL if RX-only */ |
156 | QUIC_RXFC rxfc; /* NULL if TX-only */ | |
2f018d14 HL |
157 | |
158 | unsigned int type : 8; /* QUIC_STREAM_INITIATOR_*, QUIC_STREAM_DIR_* */ | |
159 | ||
160 | unsigned int send_state : 8; /* QUIC_SSTREAM_STATE_* */ | |
161 | unsigned int recv_state : 8; /* QUIC_RSTREAM_STATE_* */ | |
162 | ||
163 | /* 1 iff this QUIC_STREAM is on the active queue (invariant). */ | |
a73078b7 HL |
164 | unsigned int active : 1; |
165 | ||
2f018d14 | 166 | /* |
1d547f8f | 167 | * This is a copy of the QUIC connection as_server value, indicating |
2f018d14 HL |
168 | * whether we are locally operating as a server or not. Having this |
169 | * significantly simplifies stream type determination relative to our | |
170 | * perspective. It never changes after a QUIC_STREAM is created and is the | |
171 | * same for all QUIC_STREAMS under a QUIC_STREAM_MAP. | |
172 | */ | |
173 | unsigned int as_server : 1; | |
174 | ||
a73078b7 | 175 | /* |
cbe7f586 HL |
176 | * Has STOP_SENDING been requested (by us)? Note that this is not the same |
177 | * as want_stop_sending below, as a STOP_SENDING frame may already have been | |
a73078b7 HL |
178 | * sent and fully acknowledged. |
179 | */ | |
180 | unsigned int stop_sending : 1; | |
181 | ||
182 | /* | |
cbe7f586 HL |
183 | * Has RESET_STREAM been requested (by us)? Works identically to |
184 | * STOP_SENDING for transmission purposes. | |
a73078b7 | 185 | */ |
cbe7f586 HL |
186 | /* Has our peer sent a STOP_SENDING frame? */ |
187 | unsigned int peer_stop_sending : 1; | |
cbe7f586 | 188 | |
a73078b7 HL |
189 | /* Temporary flags used by TXP. */ |
190 | unsigned int txp_sent_fc : 1; | |
191 | unsigned int txp_sent_stop_sending : 1; | |
192 | unsigned int txp_sent_reset_stream : 1; | |
193 | unsigned int txp_drained : 1; | |
194 | unsigned int txp_blocked : 1; | |
195 | ||
196 | /* Frame regeneration flags. */ | |
197 | unsigned int want_max_stream_data : 1; /* used for regen only */ | |
198 | unsigned int want_stop_sending : 1; /* used for gen or regen */ | |
199 | unsigned int want_reset_stream : 1; /* used for gen or regen */ | |
cbe7f586 | 200 | |
9cacba43 HL |
201 | /* Flags set when frames *we* sent were acknowledged. */ |
202 | unsigned int acked_stop_sending : 1; | |
9cacba43 | 203 | |
0847e63e HL |
204 | /* |
205 | * The stream's XSO has been deleted. Pending GC. | |
206 | * | |
207 | * Here is how stream deletion works: | |
208 | * | |
209 | * - A QUIC_STREAM cannot be deleted until it is neither in the accept | |
210 | * queue nor has an associated XSO. This condition occurs when and only | |
211 | * when deleted is true. | |
212 | * | |
22b1a96f | 213 | * - Once this is the case (i.e., no user-facing API object exposing the |
0847e63e HL |
214 | * stream), we can delete the stream once we determine that all of our |
215 | * protocol obligations requiring us to keep the QUIC_STREAM around have | |
216 | * been met. | |
217 | * | |
218 | * The following frames relate to the streams layer for a specific | |
219 | * stream: | |
220 | * | |
221 | * STREAM | |
222 | * | |
223 | * RX Obligations: | |
224 | * Ignore for a deleted stream. | |
225 | * | |
226 | * (This is different from our obligation for a | |
227 | * locally-initiated stream ID we have not created yet, | |
228 | * which we must treat as a protocol error. This can be | |
229 | * distinguished via a simple monotonic counter.) | |
230 | * | |
231 | * TX Obligations: | |
232 | * None, once we've decided to (someday) delete the stream. | |
233 | * | |
234 | * STOP_SENDING | |
235 | * | |
236 | * We cannot delete the stream until we have finished informing | |
237 | * the peer that we are not going to be listening to it | |
238 | * anymore. | |
239 | * | |
240 | * RX Obligations: | |
241 | * When we delete a stream we must have already had a FIN | |
242 | * or RESET_STREAM we transmitted acknowledged by the peer. | |
243 | * Thus we can ignore STOP_SENDING frames for deleted | |
244 | * streams (if they occur, they are probably just | |
245 | * retransmissions). | |
246 | * | |
247 | * TX Obligations: | |
248 | * _Acknowledged_ receipt of a STOP_SENDING frame by the | |
249 | * peer (unless the peer's send part has already FIN'd). | |
250 | * | |
251 | * RESET_STREAM | |
252 | * | |
253 | * We cannot delete the stream until we have finished informing | |
254 | * the peer that we are not going to be transmitting on it | |
255 | * anymore. | |
256 | * | |
257 | * RX Obligations: | |
258 | * This indicates the peer is not going to send any more | |
259 | * data on the stream. We don't need to care about this | |
260 | * since once a stream is marked for deletion we don't care | |
261 | * about any data it does send. We can ignore this for | |
262 | * deleted streams. The important criterion is that the | |
263 | * peer has been successfully delivered our STOP_SENDING | |
264 | * frame. | |
265 | * | |
266 | * TX Obligations: | |
267 | * _Acknowledged_ receipt of a RESET_STREAM frame or FIN by | |
268 | * the peer. | |
269 | * | |
270 | * MAX_STREAM_DATA | |
271 | * | |
272 | * RX Obligations: | |
273 | * Ignore. Since we are not going to be sending any more | |
274 | * data on a stream once it has been marked for deletion, | |
275 | * we don't need to care about flow control information. | |
276 | * | |
277 | * TX Obligations: | |
278 | * None. | |
279 | * | |
280 | * In other words, our protocol obligation is simply: | |
281 | * | |
282 | * - either: | |
283 | * - the peer has acknowledged receipt of a STOP_SENDING frame sent | |
284 | * by us; -or- | |
285 | * - we have received a FIN and all preceding segments from the peer | |
286 | * | |
287 | * [NOTE: The actual criterion required here is simply 'we have | |
288 | * received a FIN from the peer'. However, due to reordering and | |
289 | * retransmissions we might subsequently receive non-FIN segments | |
290 | * out of order. The FIN means we know the peer will stop | |
291 | * transmitting on the stream at *some* point, but by sending | |
292 | * STOP_SENDING we can avoid these needless retransmissions we | |
293 | * will just ignore anyway. In actuality we could just handle all | |
294 | * cases by sending a STOP_SENDING. The strategy we choose is to | |
295 | * only avoid sending a STOP_SENDING and rely on a received FIN | |
296 | * when we have received all preceding data, as this makes it | |
297 | * reasonably certain no benefit would be gained by sending | |
298 | * STOP_SENDING.] | |
299 | * | |
44cb36d0 TM |
300 | * TODO(QUIC FUTURE): Implement the latter case (currently we |
301 | just always do STOP_SENDING). | |
0847e63e HL |
302 | * |
303 | * and; | |
304 | * | |
305 | * - we have drained our send stream (for a finished send stream) | |
306 | * and got acknowledgement all parts of it including the FIN, or | |
307 | * sent a RESET_STREAM frame and got acknowledgement of that frame. | |
308 | * | |
309 | * Once these conditions are met, we can GC the QUIC_STREAM. | |
310 | * | |
311 | */ | |
2dbc39de | 312 | unsigned int deleted : 1; |
0847e63e HL |
313 | /* Set to 1 once the above conditions are actually met. */ |
314 | unsigned int ready_for_gc : 1; | |
b864110a HL |
315 | /* Set to 1 if this is currently counted in the shutdown flush stream count. */ |
316 | unsigned int shutdown_flush : 1; | |
a73078b7 HL |
317 | }; |
318 | ||
2f018d14 HL |
319 | #define QUIC_STREAM_INITIATOR_CLIENT 0 |
320 | #define QUIC_STREAM_INITIATOR_SERVER 1 | |
321 | #define QUIC_STREAM_INITIATOR_MASK 1 | |
322 | ||
323 | #define QUIC_STREAM_DIR_BIDI 0 | |
324 | #define QUIC_STREAM_DIR_UNI 2 | |
325 | #define QUIC_STREAM_DIR_MASK 2 | |
326 | ||
327 | void ossl_quic_stream_check(const QUIC_STREAM *s); | |
328 | ||
329 | /* | |
330 | * Returns 1 if the QUIC_STREAM was initiated by the endpoint with the server | |
331 | * role. | |
332 | */ | |
333 | static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(const QUIC_STREAM *s) | |
334 | { | |
335 | return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER; | |
336 | } | |
337 | ||
338 | /* | |
339 | * Returns 1 if the QUIC_STREAM is bidirectional and 0 if it is unidirectional. | |
340 | */ | |
341 | static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(const QUIC_STREAM *s) | |
342 | { | |
343 | return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI; | |
344 | } | |
345 | ||
346 | /* Returns 1 if the QUIC_STREAM was locally initiated. */ | |
347 | static ossl_inline ossl_unused int ossl_quic_stream_is_local_init(const QUIC_STREAM *s) | |
348 | { | |
349 | return ossl_quic_stream_is_server_init(s) == s->as_server; | |
350 | } | |
351 | ||
352 | /* | |
353 | * Returns 1 if the QUIC_STREAM has a sending part, based on its stream type. | |
354 | * | |
355 | * Do NOT use (s->sstream != NULL) to test this; use this function. Note that | |
356 | * even if this function returns 1, s->sstream might be NULL if the QUIC_SSTREAM | |
357 | * has been deemed no longer needed, for example due to a RESET_STREAM. | |
358 | */ | |
359 | static ossl_inline ossl_unused int ossl_quic_stream_has_send(const QUIC_STREAM *s) | |
360 | { | |
361 | return s->send_state != QUIC_SSTREAM_STATE_NONE; | |
362 | } | |
363 | ||
364 | /* | |
365 | * Returns 1 if the QUIC_STREAM has a receiving part, based on its stream type. | |
366 | * | |
367 | * Do NOT use (s->rstream != NULL) to test this; use this function. Note that | |
368 | * even if this function returns 1, s->rstream might be NULL if the QUIC_RSTREAM | |
369 | * has been deemed no longer needed, for example if the receive stream is | |
370 | * completely finished with. | |
371 | */ | |
372 | static ossl_inline ossl_unused int ossl_quic_stream_has_recv(const QUIC_STREAM *s) | |
373 | { | |
374 | return s->recv_state != QUIC_RSTREAM_STATE_NONE; | |
375 | } | |
376 | ||
377 | /* | |
378 | * Returns 1 if the QUIC_STREAM has a QUIC_SSTREAM send buffer associated with | |
379 | * it. If this returns 1, s->sstream is guaranteed to be non-NULL. The converse | |
380 | * is not necessarily true; erasure of a send stream buffer which is no longer | |
381 | * required is an optimisation which the QSM may, but is not obliged, to | |
382 | * perform. | |
383 | * | |
384 | * This call should be used where it is desired to do something with the send | |
385 | * stream buffer but there is no more specific send state restriction which is | |
386 | * applicable. | |
387 | * | |
388 | * Note: This does NOT indicate whether it is suitable to allow an application | |
389 | * to append to the buffer. DATA_SENT indicates all data (including FIN) has | |
390 | * been *sent*; the absence of DATA_SENT does not mean a FIN has not been queued | |
391 | * (meaning no more application data can be appended). This is enforced by | |
392 | * QUIC_SSTREAM. | |
393 | */ | |
394 | static ossl_inline ossl_unused int ossl_quic_stream_has_send_buffer(const QUIC_STREAM *s) | |
395 | { | |
396 | switch (s->send_state) { | |
397 | case QUIC_SSTREAM_STATE_READY: | |
398 | case QUIC_SSTREAM_STATE_SEND: | |
399 | case QUIC_SSTREAM_STATE_DATA_SENT: | |
400 | return 1; | |
401 | default: | |
402 | return 0; | |
403 | } | |
404 | } | |
405 | ||
406 | /* | |
407 | * Returns 1 if the QUIC_STREAM has a sending part which is in one of the reset | |
408 | * states. | |
409 | */ | |
410 | static ossl_inline ossl_unused int ossl_quic_stream_send_is_reset(const QUIC_STREAM *s) | |
411 | { | |
412 | return s->send_state == QUIC_SSTREAM_STATE_RESET_SENT | |
413 | || s->send_state == QUIC_SSTREAM_STATE_RESET_RECVD; | |
414 | } | |
415 | ||
416 | /* | |
417 | * Returns 1 if the QUIC_STREAM has a QUIC_RSTREAM receive buffer associated | |
418 | * with it. If this returns 1, s->rstream is guaranteed to be non-NULL. The | |
419 | * converse is not necessarily true; erasure of a receive stream buffer which is | |
420 | * no longer required is an optimisation which the QSM may, but is not obliged, | |
421 | * to perform. | |
422 | * | |
423 | * This call should be used where it is desired to do something with the receive | |
424 | * stream buffer but there is no more specific receive state restriction which is | |
425 | * applicable. | |
426 | */ | |
427 | static ossl_inline ossl_unused int ossl_quic_stream_has_recv_buffer(const QUIC_STREAM *s) | |
428 | { | |
429 | switch (s->recv_state) { | |
430 | case QUIC_RSTREAM_STATE_RECV: | |
431 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: | |
432 | case QUIC_RSTREAM_STATE_DATA_RECVD: | |
433 | return 1; | |
434 | default: | |
435 | return 0; | |
436 | } | |
437 | } | |
438 | ||
439 | /* | |
440 | * Returns 1 if the QUIC_STREAM has a receiving part which is in one of the | |
441 | * reset states. | |
442 | */ | |
443 | static ossl_inline ossl_unused int ossl_quic_stream_recv_is_reset(const QUIC_STREAM *s) | |
444 | { | |
445 | return s->recv_state == QUIC_RSTREAM_STATE_RESET_RECVD | |
446 | || s->recv_state == QUIC_RSTREAM_STATE_RESET_READ; | |
447 | } | |
448 | ||
418e122c HL |
449 | /* |
450 | * Returns 1 if the stream has a send part and that part has a final size. | |
451 | * | |
452 | * If final_size is non-NULL, *final_size is the final size (on success) or an | |
453 | * undefined value otherwise. | |
454 | */ | |
455 | static ossl_inline ossl_unused int ossl_quic_stream_send_get_final_size(const QUIC_STREAM *s, | |
456 | uint64_t *final_size) | |
457 | { | |
458 | switch (s->send_state) { | |
459 | default: | |
460 | case QUIC_SSTREAM_STATE_NONE: | |
461 | return 0; | |
462 | case QUIC_SSTREAM_STATE_SEND: | |
463 | /* | |
464 | * SEND may or may not have had a FIN - even if we have a FIN we do not | |
465 | * move to DATA_SENT until we have actually sent all the data. So | |
466 | * ask the QUIC_SSTREAM. | |
467 | */ | |
468 | return ossl_quic_sstream_get_final_size(s->sstream, final_size); | |
469 | case QUIC_SSTREAM_STATE_DATA_SENT: | |
470 | case QUIC_SSTREAM_STATE_DATA_RECVD: | |
471 | case QUIC_SSTREAM_STATE_RESET_SENT: | |
472 | case QUIC_SSTREAM_STATE_RESET_RECVD: | |
473 | if (final_size != NULL) | |
474 | *final_size = s->send_final_size; | |
475 | return 1; | |
476 | } | |
477 | } | |
478 | ||
479 | /* | |
480 | * Returns 1 if the stream has a receive part and that part has a final size. | |
481 | * | |
482 | * If final_size is non-NULL, *final_size is the final size (on success) or an | |
483 | * undefined value otherwise. | |
484 | */ | |
485 | static ossl_inline ossl_unused int ossl_quic_stream_recv_get_final_size(const QUIC_STREAM *s, | |
486 | uint64_t *final_size) | |
487 | { | |
488 | switch (s->recv_state) { | |
489 | default: | |
490 | case QUIC_RSTREAM_STATE_NONE: | |
491 | case QUIC_RSTREAM_STATE_RECV: | |
492 | return 0; | |
493 | ||
494 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: | |
495 | case QUIC_RSTREAM_STATE_DATA_RECVD: | |
496 | case QUIC_RSTREAM_STATE_DATA_READ: | |
497 | case QUIC_RSTREAM_STATE_RESET_RECVD: | |
498 | case QUIC_RSTREAM_STATE_RESET_READ: | |
499 | if (!ossl_assert(ossl_quic_rxfc_get_final_size(&s->rxfc, final_size))) | |
500 | return 0; | |
501 | ||
502 | return 1; | |
503 | } | |
504 | } | |
505 | ||
2f018d14 | 506 | /* |
a73078b7 HL |
507 | * QUIC Stream Map |
508 | * =============== | |
509 | * | |
510 | * The QUIC stream map: | |
511 | * | |
512 | * - maps stream IDs to QUIC_STREAM objects; | |
513 | * - tracks which streams are 'active' (currently have data for transmission); | |
514 | * - allows iteration over the active streams only. | |
515 | * | |
516 | */ | |
ff3a26b2 | 517 | struct quic_stream_map_st { |
a73078b7 HL |
518 | LHASH_OF(QUIC_STREAM) *map; |
519 | QUIC_STREAM_LIST_NODE active_list; | |
f20fdd16 | 520 | QUIC_STREAM_LIST_NODE accept_list; |
0847e63e | 521 | QUIC_STREAM_LIST_NODE ready_for_gc_list; |
b864110a | 522 | size_t rr_stepping, rr_counter; |
a5d16ac3 | 523 | size_t num_accept_bidi, num_accept_uni, num_shutdown_flush; |
a73078b7 | 524 | QUIC_STREAM *rr_cur; |
cbe7f586 HL |
525 | uint64_t (*get_stream_limit_cb)(int uni, void *arg); |
526 | void *get_stream_limit_cb_arg; | |
90cecc40 HL |
527 | QUIC_RXFC *max_streams_bidi_rxfc; |
528 | QUIC_RXFC *max_streams_uni_rxfc; | |
5915a900 | 529 | int is_server; |
ff3a26b2 | 530 | }; |
a73078b7 | 531 | |
cbe7f586 HL |
532 | /* |
533 | * get_stream_limit is a callback which is called to retrieve the current stream | |
534 | * limit for streams created by us. This mechanism is not used for | |
535 | * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if | |
536 | * (x >> 2) < returned limit value; i.e., the returned value is exclusive. | |
537 | * | |
538 | * If uni is 1, get the limit for locally-initiated unidirectional streams, else | |
539 | * get the limit for locally-initiated bidirectional streams. | |
540 | * | |
541 | * If the callback is NULL, stream limiting is not applied. | |
542 | * Stream limiting is used to determine if frames can currently be produced for | |
543 | * a stream. | |
544 | */ | |
545 | int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm, | |
546 | uint64_t (*get_stream_limit_cb)(int uni, void *arg), | |
90cecc40 HL |
547 | void *get_stream_limit_cb_arg, |
548 | QUIC_RXFC *max_streams_bidi_rxfc, | |
5915a900 HL |
549 | QUIC_RXFC *max_streams_uni_rxfc, |
550 | int is_server); | |
a73078b7 HL |
551 | |
552 | /* | |
553 | * Any streams still in the map will be released as though | |
554 | * ossl_quic_stream_map_release was called on them. | |
555 | */ | |
556 | void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm); | |
557 | ||
a73078b7 HL |
558 | /* |
559 | * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_* | |
560 | * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate | |
561 | * server-initiated streams as they will need to allocate a QUIC_STREAM | |
562 | * structure to track any stream created by the server, etc. | |
563 | * | |
564 | * stream_id must be a valid value. Returns NULL if a stream already exists | |
565 | * with the given ID. | |
566 | */ | |
567 | QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm, | |
568 | uint64_t stream_id, | |
569 | int type); | |
570 | ||
571 | /* | |
572 | * Releases a stream object. Note that this must only be done once the teardown | |
573 | * process is entirely complete and the object will never be referenced again. | |
574 | */ | |
575 | void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream); | |
576 | ||
577 | /* | |
578 | * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque | |
579 | * argument which is passed through. | |
580 | */ | |
581 | void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm, | |
582 | void (*visit_cb)(QUIC_STREAM *stream, void *arg), | |
583 | void *visit_cb_arg); | |
584 | ||
585 | /* | |
586 | * Retrieves a stream by stream ID. Returns NULL if it does not exist. | |
587 | */ | |
588 | QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm, | |
589 | uint64_t stream_id); | |
590 | ||
591 | /* | |
592 | * Marks the given stream as active or inactive based on its state. Idempotent. | |
593 | * | |
594 | * When a stream is marked active, it becomes available in the iteration list, | |
595 | * and when a stream is marked inactive, it no longer appears in the iteration | |
596 | * list. | |
597 | * | |
598 | * Calling this function invalidates any iterator currently pointing at the | |
599 | * given stream object, but iterators not currently pointing at the given stream | |
600 | * object are not invalidated. | |
601 | */ | |
602 | void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s); | |
603 | ||
604 | /* | |
605 | * Sets the RR stepping value, n. The RR rotation will be advanced every n | |
606 | * packets. The default value is 1. | |
607 | */ | |
608 | void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping); | |
609 | ||
9d6bd3d3 HL |
610 | /* |
611 | * Returns 1 if the stream ordinal given is allowed by the current stream count | |
612 | * flow control limit, assuming a locally initiated stream of a type described | |
613 | * by is_uni. | |
614 | * | |
615 | * Note that stream_ordinal is a stream ordinal, not a stream ID. | |
616 | */ | |
617 | int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm, | |
618 | uint64_t stream_ordinal, | |
619 | int is_uni); | |
620 | ||
2f018d14 HL |
621 | /* |
622 | * Stream Send Part | |
623 | * ================ | |
624 | */ | |
625 | ||
b89c81e4 | 626 | /* |
2f018d14 HL |
627 | * Ensures that the sending part has transitioned out of the READY state (i.e., |
628 | * to SEND, or a subsequent state). This function is named as it is because, | |
629 | * while on paper the distinction between READY and SEND is whether we have | |
630 | * started transmitting application data, in practice the meaningful distinction | |
631 | * between the two states is whether we have allocated a stream ID to the stream | |
632 | * or not. QUIC permits us to defer stream ID allocation until first STREAM (or | |
633 | * STREAM_DATA_BLOCKED) frame transmission for locally-initiated streams. | |
e8b9f632 | 634 | * |
2f018d14 | 635 | * Our implementation does not currently do this and we allocate stream IDs up |
96b7df60 HL |
636 | * front, however we may revisit this in the future. Calling this represents a |
637 | * demand for a stream ID by the caller and ensures one has been allocated to | |
638 | * the stream, and causes us to transition to SEND if we are still in the READY | |
639 | * state. | |
2f018d14 HL |
640 | * |
641 | * Returns 0 if there is no send part (caller error) and 1 otherwise. | |
642 | */ | |
643 | int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm, | |
644 | QUIC_STREAM *qs); | |
645 | ||
646 | /* | |
b3695154 HL |
647 | * Transitions from SEND to the DATA_SENT state. Note that this is NOT the same |
648 | * as the point in time at which the final size of the stream becomes known | |
649 | * (i.e., the time at which ossl_quic_sstream_fin()) is called as it occurs when | |
650 | * we have SENT all data on a given stream send part, not merely buffered it. | |
651 | * Note that this transition is NOT reversed in the event of some of that data | |
652 | * being lost. | |
2f018d14 HL |
653 | * |
654 | * Returns 1 if the state transition was successfully taken. Returns 0 if there | |
655 | * is no send part (caller error) or if the state transition cannot be taken | |
656 | * because the send part is not in the SEND state. | |
657 | */ | |
658 | int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm, | |
659 | QUIC_STREAM *qs); | |
660 | ||
661 | /* | |
662 | * Transitions from the DATA_SENT to DATA_RECVD state; should be called | |
663 | * when all transmitted stream data is ACKed by the peer. | |
664 | * | |
b3695154 HL |
665 | * Returns 1 if the state transition was successfully taken. Returns 0 if there |
666 | * is no send part (caller error) or the state transition cannot be taken | |
667 | * because the send part is not in the DATA_SENT state. Because | |
668 | * ossl_quic_stream_map_notify_all_data_sent() should always be called prior to | |
669 | * this function, the send state must already be in DATA_SENT in order for this | |
2f018d14 HL |
670 | * function to succeed. |
671 | */ | |
672 | int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm, | |
673 | QUIC_STREAM *qs); | |
674 | ||
675 | /* | |
676 | * Resets the sending part of a stream. This is a transition from the READY, | |
677 | * SEND or DATA_SENT send stream states to the RESET_SENT state. | |
678 | * | |
679 | * This function returns 1 if the transition is taken (i.e., if the send stream | |
680 | * part was in one of the states above), or if it is already in the RESET_SENT | |
681 | * state (idempotent operation), or if it has reached the RESET_RECVD state. | |
682 | * | |
683 | * It returns 0 if in the DATA_RECVD state, as a send stream cannot be reset | |
684 | * in this state. It also returns 0 if there is no send part (caller error). | |
e8b9f632 HL |
685 | */ |
686 | int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm, | |
687 | QUIC_STREAM *qs, | |
688 | uint64_t aec); | |
689 | ||
690 | /* | |
2f018d14 HL |
691 | * Transitions from the RESET_SENT to the RESET_RECVD state. This should be |
692 | * called when a sent RESET_STREAM frame has been acknowledged by the peer. | |
693 | * | |
694 | * This function returns 1 if the transition is taken (i.e., if the send stream | |
695 | * part was in one of the states above) or if it is already in the RESET_RECVD | |
696 | * state (idempotent operation). | |
697 | * | |
b3695154 HL |
698 | * It returns 0 if not in the RESET_SENT or RESET_RECVD states, as this function |
699 | * should only be called after we have already sent a RESET_STREAM frame and | |
700 | * entered the RESET_SENT state. It also returns 0 if there is no send part | |
701 | * (caller error). | |
2f018d14 HL |
702 | */ |
703 | int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm, | |
704 | QUIC_STREAM *qs); | |
705 | ||
706 | ||
707 | /* | |
708 | * Stream Receive Part | |
709 | * =================== | |
710 | */ | |
711 | ||
712 | /* | |
b3695154 HL |
713 | * Transitions from the RECV receive stream state to the SIZE_KNOWN state. This |
714 | * should be called once a STREAM frame is received for the stream with the FIN | |
715 | * bit set. final_size should be the final size of the stream in bytes. | |
e8b9f632 | 716 | * |
2f018d14 HL |
717 | * Returns 1 if the transition was taken. |
718 | */ | |
719 | int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm, | |
418e122c HL |
720 | QUIC_STREAM *qs, |
721 | uint64_t final_size); | |
2f018d14 | 722 | |
b3695154 HL |
723 | /* |
724 | * Transitions from the SIZE_KNOWN receive stream state to the DATA_RECVD state. | |
725 | * This should be called once all data for a receive stream is received. | |
726 | * | |
727 | * Returns 1 if the transition was taken. | |
728 | */ | |
2f018d14 HL |
729 | int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm, |
730 | QUIC_STREAM *qs); | |
731 | ||
b3695154 HL |
732 | /* |
733 | * Transitions from the DATA_RECVD receive stream state to the DATA_READ state. | |
1d547f8f | 734 | * This should be called once all data for a receive stream is read by the |
b3695154 HL |
735 | * application. |
736 | * | |
737 | * Returns 1 if the transition was taken. | |
738 | */ | |
2f018d14 HL |
739 | int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm, |
740 | QUIC_STREAM *qs); | |
741 | ||
b3695154 HL |
742 | /* |
743 | * Transitions from the RECV, SIZE_KNOWN or DATA_RECVD receive stream state to | |
744 | * the RESET_RECVD state. This should be called on RESET_STREAM. | |
745 | * | |
746 | * Returns 1 if the transition was taken. | |
747 | */ | |
2f018d14 HL |
748 | int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm, |
749 | QUIC_STREAM *qs, | |
2cc0e2dd HL |
750 | uint64_t app_error_code, |
751 | uint64_t final_size); | |
2f018d14 | 752 | |
b3695154 HL |
753 | /* |
754 | * Transitions from the RESET_RECVD receive stream state to the RESET_READ | |
755 | * receive stream state. This should be called when the application is notified | |
756 | * of a stream reset. | |
757 | */ | |
2f018d14 HL |
758 | int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm, |
759 | QUIC_STREAM *qs); | |
760 | ||
761 | /* | |
762 | * Marks the receiving part of a stream for STOP_SENDING. This is orthogonal to | |
763 | * receive stream state as it does not affect it directly. | |
764 | * | |
765 | * Returns 1 if the receiving part of a stream was not already marked for | |
e8b9f632 HL |
766 | * STOP_SENDING. |
767 | * Returns 0 otherwise, which need not be considered an error. | |
b89c81e4 | 768 | */ |
e8b9f632 HL |
769 | int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm, |
770 | QUIC_STREAM *qs, | |
771 | uint64_t aec); | |
b89c81e4 | 772 | |
418e122c HL |
773 | /* |
774 | * Marks the stream as wanting a STOP_SENDING frame transmitted. It is not valid | |
96b7df60 | 775 | * to call this if ossl_quic_stream_map_stop_sending_recv_part() has not been |
418e122c HL |
776 | * called. For TXP use. |
777 | */ | |
778 | int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, | |
779 | QUIC_STREAM *qs); | |
780 | ||
781 | ||
2f018d14 HL |
782 | /* |
783 | * Accept Queue Management | |
784 | * ======================= | |
785 | */ | |
786 | ||
f20fdd16 HL |
787 | /* |
788 | * Adds a stream to the accept queue. | |
789 | */ | |
790 | void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm, | |
791 | QUIC_STREAM *s); | |
792 | ||
793 | /* | |
794 | * Returns the next item to be popped from the accept queue, or NULL if it is | |
795 | * empty. | |
796 | */ | |
797 | QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm); | |
798 | ||
799 | /* | |
90cecc40 HL |
800 | * Removes a stream from the accept queue. rtt is the estimated connection RTT. |
801 | * The stream is retired for the purposes of MAX_STREAMS RXFC. | |
f20fdd16 HL |
802 | * |
803 | * Precondition: s is in the accept queue. | |
804 | */ | |
805 | void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm, | |
90cecc40 HL |
806 | QUIC_STREAM *s, |
807 | OSSL_TIME rtt); | |
f20fdd16 | 808 | |
a5d16ac3 HL |
809 | /* Returns the length of the accept queue for the given stream type. */ |
810 | size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni); | |
811 | ||
812 | /* Returns the total length of the accept queues for all stream types. */ | |
813 | size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm); | |
f20fdd16 | 814 | |
b864110a HL |
815 | /* |
816 | * Shutdown Flush and GC | |
817 | * ===================== | |
818 | */ | |
819 | ||
0847e63e HL |
820 | /* |
821 | * Delete streams ready for GC. Pointers to those QUIC_STREAM objects become | |
822 | * invalid. | |
823 | */ | |
824 | void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm); | |
825 | ||
b864110a HL |
826 | /* |
827 | * Begins shutdown stream flush triage. Analyses all streams, including deleted | |
828 | * but not yet GC'd streams, to determine if we should wait for that stream to | |
829 | * be fully flushed before shutdown. After calling this, call | |
830 | * ossl_quic_stream_map_is_shutdown_flush_finished() to determine if all | |
831 | * shutdown flush eligible streams have been flushed. | |
832 | */ | |
833 | void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm); | |
834 | ||
835 | /* | |
836 | * Returns 1 if all shutdown flush eligible streams have finished flushing, | |
837 | * or if ossl_quic_stream_map_begin_shutdown_flush() has not been called. | |
838 | */ | |
839 | int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm); | |
840 | ||
a73078b7 HL |
841 | /* |
842 | * QUIC Stream Iterator | |
843 | * ==================== | |
844 | * | |
845 | * Allows the current set of active streams to be walked using a RR-based | |
846 | * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm | |
847 | * is stepped. The RR algorithm rotates the iteration order such that the next | |
848 | * active stream is returned first after n calls to ossl_quic_stream_iter_init, | |
849 | * where n is the stepping value configured via | |
850 | * ossl_quic_stream_map_set_rr_stepping. | |
851 | * | |
852 | * Suppose there are three active streams and the configured stepping is n: | |
853 | * | |
854 | * Iteration 0n: [Stream 1] [Stream 2] [Stream 3] | |
855 | * Iteration 1n: [Stream 2] [Stream 3] [Stream 1] | |
856 | * Iteration 2n: [Stream 3] [Stream 1] [Stream 2] | |
857 | * | |
858 | */ | |
859 | typedef struct quic_stream_iter_st { | |
860 | QUIC_STREAM_MAP *qsm; | |
861 | QUIC_STREAM *first_stream, *stream; | |
862 | } QUIC_STREAM_ITER; | |
863 | ||
864 | /* | |
865 | * Initialise an iterator, advancing the RR algorithm as necessary (if | |
866 | * advance_rr is 1). After calling this, it->stream will be the first stream in | |
867 | * the iteration sequence, or NULL if there are no active streams. | |
868 | */ | |
869 | void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm, | |
870 | int advance_rr); | |
871 | ||
872 | /* | |
873 | * Advances to next stream in iteration sequence. You do not need to call this | |
874 | * immediately after calling ossl_quic_stream_iter_init(). If the end of the | |
875 | * list is reached, it->stream will be NULL after calling this. | |
876 | */ | |
877 | void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it); | |
878 | ||
cbe7f586 HL |
879 | # endif |
880 | ||
a73078b7 | 881 | #endif |