]>
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" | |
418e122c | 16 | # include "internal/common.h" |
cbe7f586 HL |
17 | # include "internal/quic_types.h" |
18 | # include "internal/quic_stream.h" | |
19 | # include "internal/quic_fc.h" | |
20 | # include <openssl/lhash.h> | |
21 | ||
22 | # ifndef OPENSSL_NO_QUIC | |
a73078b7 HL |
23 | |
24 | /* | |
25 | * QUIC Stream | |
26 | * =========== | |
27 | * | |
28 | * Logical QUIC stream composing all relevant send and receive components. | |
29 | */ | |
30 | typedef struct quic_stream_st QUIC_STREAM; | |
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 | * | |
300 | * TODO(QUIC): Implement the latter case (currently we just | |
301 | * always do STOP_SENDING). | |
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; | |
a73078b7 HL |
315 | }; |
316 | ||
2f018d14 HL |
317 | #define QUIC_STREAM_INITIATOR_CLIENT 0 |
318 | #define QUIC_STREAM_INITIATOR_SERVER 1 | |
319 | #define QUIC_STREAM_INITIATOR_MASK 1 | |
320 | ||
321 | #define QUIC_STREAM_DIR_BIDI 0 | |
322 | #define QUIC_STREAM_DIR_UNI 2 | |
323 | #define QUIC_STREAM_DIR_MASK 2 | |
324 | ||
325 | void ossl_quic_stream_check(const QUIC_STREAM *s); | |
326 | ||
327 | /* | |
328 | * Returns 1 if the QUIC_STREAM was initiated by the endpoint with the server | |
329 | * role. | |
330 | */ | |
331 | static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(const QUIC_STREAM *s) | |
332 | { | |
333 | return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER; | |
334 | } | |
335 | ||
336 | /* | |
337 | * Returns 1 if the QUIC_STREAM is bidirectional and 0 if it is unidirectional. | |
338 | */ | |
339 | static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(const QUIC_STREAM *s) | |
340 | { | |
341 | return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI; | |
342 | } | |
343 | ||
344 | /* Returns 1 if the QUIC_STREAM was locally initiated. */ | |
345 | static ossl_inline ossl_unused int ossl_quic_stream_is_local_init(const QUIC_STREAM *s) | |
346 | { | |
347 | return ossl_quic_stream_is_server_init(s) == s->as_server; | |
348 | } | |
349 | ||
350 | /* | |
351 | * Returns 1 if the QUIC_STREAM has a sending part, based on its stream type. | |
352 | * | |
353 | * Do NOT use (s->sstream != NULL) to test this; use this function. Note that | |
354 | * even if this function returns 1, s->sstream might be NULL if the QUIC_SSTREAM | |
355 | * has been deemed no longer needed, for example due to a RESET_STREAM. | |
356 | */ | |
357 | static ossl_inline ossl_unused int ossl_quic_stream_has_send(const QUIC_STREAM *s) | |
358 | { | |
359 | return s->send_state != QUIC_SSTREAM_STATE_NONE; | |
360 | } | |
361 | ||
362 | /* | |
363 | * Returns 1 if the QUIC_STREAM has a receiving part, based on its stream type. | |
364 | * | |
365 | * Do NOT use (s->rstream != NULL) to test this; use this function. Note that | |
366 | * even if this function returns 1, s->rstream might be NULL if the QUIC_RSTREAM | |
367 | * has been deemed no longer needed, for example if the receive stream is | |
368 | * completely finished with. | |
369 | */ | |
370 | static ossl_inline ossl_unused int ossl_quic_stream_has_recv(const QUIC_STREAM *s) | |
371 | { | |
372 | return s->recv_state != QUIC_RSTREAM_STATE_NONE; | |
373 | } | |
374 | ||
375 | /* | |
376 | * Returns 1 if the QUIC_STREAM has a QUIC_SSTREAM send buffer associated with | |
377 | * it. If this returns 1, s->sstream is guaranteed to be non-NULL. The converse | |
378 | * is not necessarily true; erasure of a send stream buffer which is no longer | |
379 | * required is an optimisation which the QSM may, but is not obliged, to | |
380 | * perform. | |
381 | * | |
382 | * This call should be used where it is desired to do something with the send | |
383 | * stream buffer but there is no more specific send state restriction which is | |
384 | * applicable. | |
385 | * | |
386 | * Note: This does NOT indicate whether it is suitable to allow an application | |
387 | * to append to the buffer. DATA_SENT indicates all data (including FIN) has | |
388 | * been *sent*; the absence of DATA_SENT does not mean a FIN has not been queued | |
389 | * (meaning no more application data can be appended). This is enforced by | |
390 | * QUIC_SSTREAM. | |
391 | */ | |
392 | static ossl_inline ossl_unused int ossl_quic_stream_has_send_buffer(const QUIC_STREAM *s) | |
393 | { | |
394 | switch (s->send_state) { | |
395 | case QUIC_SSTREAM_STATE_READY: | |
396 | case QUIC_SSTREAM_STATE_SEND: | |
397 | case QUIC_SSTREAM_STATE_DATA_SENT: | |
398 | return 1; | |
399 | default: | |
400 | return 0; | |
401 | } | |
402 | } | |
403 | ||
404 | /* | |
405 | * Returns 1 if the QUIC_STREAM has a sending part which is in one of the reset | |
406 | * states. | |
407 | */ | |
408 | static ossl_inline ossl_unused int ossl_quic_stream_send_is_reset(const QUIC_STREAM *s) | |
409 | { | |
410 | return s->send_state == QUIC_SSTREAM_STATE_RESET_SENT | |
411 | || s->send_state == QUIC_SSTREAM_STATE_RESET_RECVD; | |
412 | } | |
413 | ||
414 | /* | |
415 | * Returns 1 if the QUIC_STREAM has a QUIC_RSTREAM receive buffer associated | |
416 | * with it. If this returns 1, s->rstream is guaranteed to be non-NULL. The | |
417 | * converse is not necessarily true; erasure of a receive stream buffer which is | |
418 | * no longer required is an optimisation which the QSM may, but is not obliged, | |
419 | * to perform. | |
420 | * | |
421 | * This call should be used where it is desired to do something with the receive | |
422 | * stream buffer but there is no more specific receive state restriction which is | |
423 | * applicable. | |
424 | */ | |
425 | static ossl_inline ossl_unused int ossl_quic_stream_has_recv_buffer(const QUIC_STREAM *s) | |
426 | { | |
427 | switch (s->recv_state) { | |
428 | case QUIC_RSTREAM_STATE_RECV: | |
429 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: | |
430 | case QUIC_RSTREAM_STATE_DATA_RECVD: | |
431 | return 1; | |
432 | default: | |
433 | return 0; | |
434 | } | |
435 | } | |
436 | ||
437 | /* | |
438 | * Returns 1 if the QUIC_STREAM has a receiving part which is in one of the | |
439 | * reset states. | |
440 | */ | |
441 | static ossl_inline ossl_unused int ossl_quic_stream_recv_is_reset(const QUIC_STREAM *s) | |
442 | { | |
443 | return s->recv_state == QUIC_RSTREAM_STATE_RESET_RECVD | |
444 | || s->recv_state == QUIC_RSTREAM_STATE_RESET_READ; | |
445 | } | |
446 | ||
418e122c HL |
447 | /* |
448 | * Returns 1 if the stream has a send part and that part has a final size. | |
449 | * | |
450 | * If final_size is non-NULL, *final_size is the final size (on success) or an | |
451 | * undefined value otherwise. | |
452 | */ | |
453 | static ossl_inline ossl_unused int ossl_quic_stream_send_get_final_size(const QUIC_STREAM *s, | |
454 | uint64_t *final_size) | |
455 | { | |
456 | switch (s->send_state) { | |
457 | default: | |
458 | case QUIC_SSTREAM_STATE_NONE: | |
459 | return 0; | |
460 | case QUIC_SSTREAM_STATE_SEND: | |
461 | /* | |
462 | * SEND may or may not have had a FIN - even if we have a FIN we do not | |
463 | * move to DATA_SENT until we have actually sent all the data. So | |
464 | * ask the QUIC_SSTREAM. | |
465 | */ | |
466 | return ossl_quic_sstream_get_final_size(s->sstream, final_size); | |
467 | case QUIC_SSTREAM_STATE_DATA_SENT: | |
468 | case QUIC_SSTREAM_STATE_DATA_RECVD: | |
469 | case QUIC_SSTREAM_STATE_RESET_SENT: | |
470 | case QUIC_SSTREAM_STATE_RESET_RECVD: | |
471 | if (final_size != NULL) | |
472 | *final_size = s->send_final_size; | |
473 | return 1; | |
474 | } | |
475 | } | |
476 | ||
477 | /* | |
478 | * Returns 1 if the stream has a receive part and that part has a final size. | |
479 | * | |
480 | * If final_size is non-NULL, *final_size is the final size (on success) or an | |
481 | * undefined value otherwise. | |
482 | */ | |
483 | static ossl_inline ossl_unused int ossl_quic_stream_recv_get_final_size(const QUIC_STREAM *s, | |
484 | uint64_t *final_size) | |
485 | { | |
486 | switch (s->recv_state) { | |
487 | default: | |
488 | case QUIC_RSTREAM_STATE_NONE: | |
489 | case QUIC_RSTREAM_STATE_RECV: | |
490 | return 0; | |
491 | ||
492 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: | |
493 | case QUIC_RSTREAM_STATE_DATA_RECVD: | |
494 | case QUIC_RSTREAM_STATE_DATA_READ: | |
495 | case QUIC_RSTREAM_STATE_RESET_RECVD: | |
496 | case QUIC_RSTREAM_STATE_RESET_READ: | |
497 | if (!ossl_assert(ossl_quic_rxfc_get_final_size(&s->rxfc, final_size))) | |
498 | return 0; | |
499 | ||
500 | return 1; | |
501 | } | |
502 | } | |
503 | ||
2f018d14 | 504 | /* |
a73078b7 HL |
505 | * QUIC Stream Map |
506 | * =============== | |
507 | * | |
508 | * The QUIC stream map: | |
509 | * | |
510 | * - maps stream IDs to QUIC_STREAM objects; | |
511 | * - tracks which streams are 'active' (currently have data for transmission); | |
512 | * - allows iteration over the active streams only. | |
513 | * | |
514 | */ | |
515 | typedef struct quic_stream_map_st { | |
516 | LHASH_OF(QUIC_STREAM) *map; | |
517 | QUIC_STREAM_LIST_NODE active_list; | |
f20fdd16 | 518 | QUIC_STREAM_LIST_NODE accept_list; |
0847e63e | 519 | QUIC_STREAM_LIST_NODE ready_for_gc_list; |
f20fdd16 | 520 | size_t rr_stepping, rr_counter, num_accept; |
a73078b7 | 521 | QUIC_STREAM *rr_cur; |
cbe7f586 HL |
522 | uint64_t (*get_stream_limit_cb)(int uni, void *arg); |
523 | void *get_stream_limit_cb_arg; | |
90cecc40 HL |
524 | QUIC_RXFC *max_streams_bidi_rxfc; |
525 | QUIC_RXFC *max_streams_uni_rxfc; | |
5915a900 | 526 | int is_server; |
a73078b7 HL |
527 | } QUIC_STREAM_MAP; |
528 | ||
cbe7f586 HL |
529 | /* |
530 | * get_stream_limit is a callback which is called to retrieve the current stream | |
531 | * limit for streams created by us. This mechanism is not used for | |
532 | * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if | |
533 | * (x >> 2) < returned limit value; i.e., the returned value is exclusive. | |
534 | * | |
535 | * If uni is 1, get the limit for locally-initiated unidirectional streams, else | |
536 | * get the limit for locally-initiated bidirectional streams. | |
537 | * | |
538 | * If the callback is NULL, stream limiting is not applied. | |
539 | * Stream limiting is used to determine if frames can currently be produced for | |
540 | * a stream. | |
541 | */ | |
542 | int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm, | |
543 | uint64_t (*get_stream_limit_cb)(int uni, void *arg), | |
90cecc40 HL |
544 | void *get_stream_limit_cb_arg, |
545 | QUIC_RXFC *max_streams_bidi_rxfc, | |
5915a900 HL |
546 | QUIC_RXFC *max_streams_uni_rxfc, |
547 | int is_server); | |
a73078b7 HL |
548 | |
549 | /* | |
550 | * Any streams still in the map will be released as though | |
551 | * ossl_quic_stream_map_release was called on them. | |
552 | */ | |
553 | void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm); | |
554 | ||
a73078b7 HL |
555 | /* |
556 | * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_* | |
557 | * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate | |
558 | * server-initiated streams as they will need to allocate a QUIC_STREAM | |
559 | * structure to track any stream created by the server, etc. | |
560 | * | |
561 | * stream_id must be a valid value. Returns NULL if a stream already exists | |
562 | * with the given ID. | |
563 | */ | |
564 | QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm, | |
565 | uint64_t stream_id, | |
566 | int type); | |
567 | ||
568 | /* | |
569 | * Releases a stream object. Note that this must only be done once the teardown | |
570 | * process is entirely complete and the object will never be referenced again. | |
571 | */ | |
572 | void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream); | |
573 | ||
574 | /* | |
575 | * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque | |
576 | * argument which is passed through. | |
577 | */ | |
578 | void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm, | |
579 | void (*visit_cb)(QUIC_STREAM *stream, void *arg), | |
580 | void *visit_cb_arg); | |
581 | ||
582 | /* | |
583 | * Retrieves a stream by stream ID. Returns NULL if it does not exist. | |
584 | */ | |
585 | QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm, | |
586 | uint64_t stream_id); | |
587 | ||
588 | /* | |
589 | * Marks the given stream as active or inactive based on its state. Idempotent. | |
590 | * | |
591 | * When a stream is marked active, it becomes available in the iteration list, | |
592 | * and when a stream is marked inactive, it no longer appears in the iteration | |
593 | * list. | |
594 | * | |
595 | * Calling this function invalidates any iterator currently pointing at the | |
596 | * given stream object, but iterators not currently pointing at the given stream | |
597 | * object are not invalidated. | |
598 | */ | |
599 | void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s); | |
600 | ||
601 | /* | |
602 | * Sets the RR stepping value, n. The RR rotation will be advanced every n | |
603 | * packets. The default value is 1. | |
604 | */ | |
605 | void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping); | |
606 | ||
2f018d14 HL |
607 | /* |
608 | * Stream Send Part | |
609 | * ================ | |
610 | */ | |
611 | ||
b89c81e4 | 612 | /* |
2f018d14 HL |
613 | * Ensures that the sending part has transitioned out of the READY state (i.e., |
614 | * to SEND, or a subsequent state). This function is named as it is because, | |
615 | * while on paper the distinction between READY and SEND is whether we have | |
616 | * started transmitting application data, in practice the meaningful distinction | |
617 | * between the two states is whether we have allocated a stream ID to the stream | |
618 | * or not. QUIC permits us to defer stream ID allocation until first STREAM (or | |
619 | * STREAM_DATA_BLOCKED) frame transmission for locally-initiated streams. | |
e8b9f632 | 620 | * |
2f018d14 | 621 | * Our implementation does not currently do this and we allocate stream IDs up |
96b7df60 HL |
622 | * front, however we may revisit this in the future. Calling this represents a |
623 | * demand for a stream ID by the caller and ensures one has been allocated to | |
624 | * the stream, and causes us to transition to SEND if we are still in the READY | |
625 | * state. | |
2f018d14 HL |
626 | * |
627 | * Returns 0 if there is no send part (caller error) and 1 otherwise. | |
628 | */ | |
629 | int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm, | |
630 | QUIC_STREAM *qs); | |
631 | ||
632 | /* | |
b3695154 HL |
633 | * Transitions from SEND to the DATA_SENT state. Note that this is NOT the same |
634 | * as the point in time at which the final size of the stream becomes known | |
635 | * (i.e., the time at which ossl_quic_sstream_fin()) is called as it occurs when | |
636 | * we have SENT all data on a given stream send part, not merely buffered it. | |
637 | * Note that this transition is NOT reversed in the event of some of that data | |
638 | * being lost. | |
2f018d14 HL |
639 | * |
640 | * Returns 1 if the state transition was successfully taken. Returns 0 if there | |
641 | * is no send part (caller error) or if the state transition cannot be taken | |
642 | * because the send part is not in the SEND state. | |
643 | */ | |
644 | int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm, | |
645 | QUIC_STREAM *qs); | |
646 | ||
647 | /* | |
648 | * Transitions from the DATA_SENT to DATA_RECVD state; should be called | |
649 | * when all transmitted stream data is ACKed by the peer. | |
650 | * | |
b3695154 HL |
651 | * Returns 1 if the state transition was successfully taken. Returns 0 if there |
652 | * is no send part (caller error) or the state transition cannot be taken | |
653 | * because the send part is not in the DATA_SENT state. Because | |
654 | * ossl_quic_stream_map_notify_all_data_sent() should always be called prior to | |
655 | * this function, the send state must already be in DATA_SENT in order for this | |
2f018d14 HL |
656 | * function to succeed. |
657 | */ | |
658 | int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm, | |
659 | QUIC_STREAM *qs); | |
660 | ||
661 | /* | |
662 | * Resets the sending part of a stream. This is a transition from the READY, | |
663 | * SEND or DATA_SENT send stream states to the RESET_SENT state. | |
664 | * | |
665 | * This function returns 1 if the transition is taken (i.e., if the send stream | |
666 | * part was in one of the states above), or if it is already in the RESET_SENT | |
667 | * state (idempotent operation), or if it has reached the RESET_RECVD state. | |
668 | * | |
669 | * It returns 0 if in the DATA_RECVD state, as a send stream cannot be reset | |
670 | * in this state. It also returns 0 if there is no send part (caller error). | |
e8b9f632 HL |
671 | */ |
672 | int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm, | |
673 | QUIC_STREAM *qs, | |
674 | uint64_t aec); | |
675 | ||
676 | /* | |
2f018d14 HL |
677 | * Transitions from the RESET_SENT to the RESET_RECVD state. This should be |
678 | * called when a sent RESET_STREAM frame has been acknowledged by the peer. | |
679 | * | |
680 | * This function returns 1 if the transition is taken (i.e., if the send stream | |
681 | * part was in one of the states above) or if it is already in the RESET_RECVD | |
682 | * state (idempotent operation). | |
683 | * | |
b3695154 HL |
684 | * It returns 0 if not in the RESET_SENT or RESET_RECVD states, as this function |
685 | * should only be called after we have already sent a RESET_STREAM frame and | |
686 | * entered the RESET_SENT state. It also returns 0 if there is no send part | |
687 | * (caller error). | |
2f018d14 HL |
688 | */ |
689 | int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm, | |
690 | QUIC_STREAM *qs); | |
691 | ||
692 | ||
693 | /* | |
694 | * Stream Receive Part | |
695 | * =================== | |
696 | */ | |
697 | ||
698 | /* | |
b3695154 HL |
699 | * Transitions from the RECV receive stream state to the SIZE_KNOWN state. This |
700 | * should be called once a STREAM frame is received for the stream with the FIN | |
701 | * bit set. final_size should be the final size of the stream in bytes. | |
e8b9f632 | 702 | * |
2f018d14 HL |
703 | * Returns 1 if the transition was taken. |
704 | */ | |
705 | int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm, | |
418e122c HL |
706 | QUIC_STREAM *qs, |
707 | uint64_t final_size); | |
2f018d14 | 708 | |
b3695154 HL |
709 | /* |
710 | * Transitions from the SIZE_KNOWN receive stream state to the DATA_RECVD state. | |
711 | * This should be called once all data for a receive stream is received. | |
712 | * | |
713 | * Returns 1 if the transition was taken. | |
714 | */ | |
2f018d14 HL |
715 | int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm, |
716 | QUIC_STREAM *qs); | |
717 | ||
b3695154 HL |
718 | /* |
719 | * Transitions from the DATA_RECVD receive stream state to the DATA_READ state. | |
1d547f8f | 720 | * This should be called once all data for a receive stream is read by the |
b3695154 HL |
721 | * application. |
722 | * | |
723 | * Returns 1 if the transition was taken. | |
724 | */ | |
2f018d14 HL |
725 | int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm, |
726 | QUIC_STREAM *qs); | |
727 | ||
b3695154 HL |
728 | /* |
729 | * Transitions from the RECV, SIZE_KNOWN or DATA_RECVD receive stream state to | |
730 | * the RESET_RECVD state. This should be called on RESET_STREAM. | |
731 | * | |
732 | * Returns 1 if the transition was taken. | |
733 | */ | |
2f018d14 HL |
734 | int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm, |
735 | QUIC_STREAM *qs, | |
2cc0e2dd HL |
736 | uint64_t app_error_code, |
737 | uint64_t final_size); | |
2f018d14 | 738 | |
b3695154 HL |
739 | /* |
740 | * Transitions from the RESET_RECVD receive stream state to the RESET_READ | |
741 | * receive stream state. This should be called when the application is notified | |
742 | * of a stream reset. | |
743 | */ | |
2f018d14 HL |
744 | int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm, |
745 | QUIC_STREAM *qs); | |
746 | ||
747 | /* | |
748 | * Marks the receiving part of a stream for STOP_SENDING. This is orthogonal to | |
749 | * receive stream state as it does not affect it directly. | |
750 | * | |
751 | * Returns 1 if the receiving part of a stream was not already marked for | |
e8b9f632 HL |
752 | * STOP_SENDING. |
753 | * Returns 0 otherwise, which need not be considered an error. | |
b89c81e4 | 754 | */ |
e8b9f632 HL |
755 | int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm, |
756 | QUIC_STREAM *qs, | |
757 | uint64_t aec); | |
b89c81e4 | 758 | |
418e122c HL |
759 | /* |
760 | * Marks the stream as wanting a STOP_SENDING frame transmitted. It is not valid | |
96b7df60 | 761 | * to call this if ossl_quic_stream_map_stop_sending_recv_part() has not been |
418e122c HL |
762 | * called. For TXP use. |
763 | */ | |
764 | int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, | |
765 | QUIC_STREAM *qs); | |
766 | ||
767 | ||
2f018d14 HL |
768 | /* |
769 | * Accept Queue Management | |
770 | * ======================= | |
771 | */ | |
772 | ||
f20fdd16 HL |
773 | /* |
774 | * Adds a stream to the accept queue. | |
775 | */ | |
776 | void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm, | |
777 | QUIC_STREAM *s); | |
778 | ||
779 | /* | |
780 | * Returns the next item to be popped from the accept queue, or NULL if it is | |
781 | * empty. | |
782 | */ | |
783 | QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm); | |
784 | ||
785 | /* | |
90cecc40 HL |
786 | * Removes a stream from the accept queue. rtt is the estimated connection RTT. |
787 | * The stream is retired for the purposes of MAX_STREAMS RXFC. | |
f20fdd16 HL |
788 | * |
789 | * Precondition: s is in the accept queue. | |
790 | */ | |
791 | void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm, | |
90cecc40 HL |
792 | QUIC_STREAM *s, |
793 | OSSL_TIME rtt); | |
f20fdd16 HL |
794 | |
795 | /* Returns the length of the accept queue. */ | |
796 | size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm); | |
797 | ||
0847e63e HL |
798 | /* |
799 | * Delete streams ready for GC. Pointers to those QUIC_STREAM objects become | |
800 | * invalid. | |
801 | */ | |
802 | void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm); | |
803 | ||
a73078b7 HL |
804 | /* |
805 | * QUIC Stream Iterator | |
806 | * ==================== | |
807 | * | |
808 | * Allows the current set of active streams to be walked using a RR-based | |
809 | * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm | |
810 | * is stepped. The RR algorithm rotates the iteration order such that the next | |
811 | * active stream is returned first after n calls to ossl_quic_stream_iter_init, | |
812 | * where n is the stepping value configured via | |
813 | * ossl_quic_stream_map_set_rr_stepping. | |
814 | * | |
815 | * Suppose there are three active streams and the configured stepping is n: | |
816 | * | |
817 | * Iteration 0n: [Stream 1] [Stream 2] [Stream 3] | |
818 | * Iteration 1n: [Stream 2] [Stream 3] [Stream 1] | |
819 | * Iteration 2n: [Stream 3] [Stream 1] [Stream 2] | |
820 | * | |
821 | */ | |
822 | typedef struct quic_stream_iter_st { | |
823 | QUIC_STREAM_MAP *qsm; | |
824 | QUIC_STREAM *first_stream, *stream; | |
825 | } QUIC_STREAM_ITER; | |
826 | ||
827 | /* | |
828 | * Initialise an iterator, advancing the RR algorithm as necessary (if | |
829 | * advance_rr is 1). After calling this, it->stream will be the first stream in | |
830 | * the iteration sequence, or NULL if there are no active streams. | |
831 | */ | |
832 | void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm, | |
833 | int advance_rr); | |
834 | ||
835 | /* | |
836 | * Advances to next stream in iteration sequence. You do not need to call this | |
837 | * immediately after calling ossl_quic_stream_iter_init(). If the end of the | |
838 | * list is reached, it->stream will be NULL after calling this. | |
839 | */ | |
840 | void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it); | |
841 | ||
cbe7f586 HL |
842 | # endif |
843 | ||
a73078b7 | 844 | #endif |