/src/openssl/include/internal/quic_stream_map.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2022-2025 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 | | |
14 | | # include "internal/e_os.h" |
15 | | # include "internal/time.h" |
16 | | # include "internal/common.h" |
17 | | # include "internal/quic_types.h" |
18 | | # include "internal/quic_predef.h" |
19 | | # include "internal/quic_stream.h" |
20 | | # include "internal/quic_fc.h" |
21 | | # include <openssl/lhash.h> |
22 | | |
23 | | # ifndef OPENSSL_NO_QUIC |
24 | | |
25 | | /* |
26 | | * QUIC Stream |
27 | | * =========== |
28 | | * |
29 | | * Logical QUIC stream composing all relevant send and receive components. |
30 | | */ |
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 | | |
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 | 0 | #define QUIC_SSTREAM_STATE_NONE 0 /* --- sstream == NULL */ |
52 | 0 | #define QUIC_SSTREAM_STATE_READY 1 /* \ */ |
53 | 0 | #define QUIC_SSTREAM_STATE_SEND 2 /* |-- sstream != NULL */ |
54 | 0 | #define QUIC_SSTREAM_STATE_DATA_SENT 3 /* / */ |
55 | 0 | #define QUIC_SSTREAM_STATE_DATA_RECVD 4 /* \ */ |
56 | 0 | #define QUIC_SSTREAM_STATE_RESET_SENT 5 /* |-- sstream == NULL */ |
57 | 0 | #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 | 0 | #define QUIC_RSTREAM_STATE_NONE 0 /* --- rstream == NULL */ |
73 | 0 | #define QUIC_RSTREAM_STATE_RECV 1 /* \ */ |
74 | 0 | #define QUIC_RSTREAM_STATE_SIZE_KNOWN 2 /* |-- rstream != NULL */ |
75 | 0 | #define QUIC_RSTREAM_STATE_DATA_RECVD 3 /* / */ |
76 | 0 | #define QUIC_RSTREAM_STATE_DATA_READ 4 /* \ */ |
77 | 0 | #define QUIC_RSTREAM_STATE_RESET_RECVD 5 /* |-- rstream == NULL */ |
78 | 0 | #define QUIC_RSTREAM_STATE_RESET_READ 6 /* / */ |
79 | | |
80 | | struct quic_stream_st { |
81 | | QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */ |
82 | | QUIC_STREAM_LIST_NODE accept_node; /* accept queue of remotely-created streams */ |
83 | | QUIC_STREAM_LIST_NODE ready_for_gc_node; /* queue of streams now ready for GC */ |
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 | | |
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. |
115 | | * This is only valid if peer_reset_stream is 1. |
116 | | */ |
117 | | uint64_t peer_reset_stream_aec; |
118 | | |
119 | | /* Temporary value used by TXP. */ |
120 | | uint64_t txp_txfc_new_credit_consumed; |
121 | | |
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 | | |
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 | | */ |
151 | | QUIC_SSTREAM *sstream; /* NULL if RX-only */ |
152 | | QUIC_RSTREAM *rstream; /* NULL if TX only */ |
153 | | |
154 | | /* Stream-level flow control managers. */ |
155 | | QUIC_TXFC txfc; /* NULL if RX-only */ |
156 | | QUIC_RXFC rxfc; /* NULL if TX-only */ |
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). */ |
164 | | unsigned int active : 1; |
165 | | |
166 | | /* |
167 | | * This is a copy of the QUIC connection as_server value, indicating |
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 | | |
175 | | /* |
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 |
178 | | * sent and fully acknowledged. |
179 | | */ |
180 | | unsigned int stop_sending : 1; |
181 | | |
182 | | /* |
183 | | * Has RESET_STREAM been requested (by us)? Works identically to |
184 | | * STOP_SENDING for transmission purposes. |
185 | | */ |
186 | | /* Has our peer sent a STOP_SENDING frame? */ |
187 | | unsigned int peer_stop_sending : 1; |
188 | | |
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 */ |
200 | | |
201 | | /* Flags set when frames *we* sent were acknowledged. */ |
202 | | unsigned int acked_stop_sending : 1; |
203 | | |
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 | | * |
213 | | * - Once this is the case (i.e., no user-facing API object exposing the |
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 FUTURE): Implement the latter case (currently we |
301 | | just 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 | | */ |
312 | | unsigned int deleted : 1; |
313 | | /* Set to 1 once the above conditions are actually met. */ |
314 | | unsigned int ready_for_gc : 1; |
315 | | /* Set to 1 if this is currently counted in the shutdown flush stream count. */ |
316 | | unsigned int shutdown_flush : 1; |
317 | | }; |
318 | | |
319 | 0 | #define QUIC_STREAM_INITIATOR_CLIENT 0 |
320 | 0 | #define QUIC_STREAM_INITIATOR_SERVER 1 |
321 | 0 | #define QUIC_STREAM_INITIATOR_MASK 1 |
322 | | |
323 | 0 | #define QUIC_STREAM_DIR_BIDI 0 |
324 | 0 | #define QUIC_STREAM_DIR_UNI 2 |
325 | 0 | #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 | 0 | { |
335 | 0 | return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER; |
336 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_is_server_init Unexecuted instantiation: t1_lib.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_impl.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_method.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_obj.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_port.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_txp.c:ossl_quic_stream_is_server_init Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_channel.c:ossl_quic_stream_is_server_init Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_is_server_init |
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 | 0 | { |
343 | 0 | return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI; |
344 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_is_bidi Unexecuted instantiation: t1_lib.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_impl.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_method.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_obj.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_port.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_txp.c:ossl_quic_stream_is_bidi Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_channel.c:ossl_quic_stream_is_bidi Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_is_bidi |
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 | 0 | { |
349 | 0 | return ossl_quic_stream_is_server_init(s) == s->as_server; |
350 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_is_local_init Unexecuted instantiation: t1_lib.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_impl.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_method.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_obj.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_port.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_txp.c:ossl_quic_stream_is_local_init Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_channel.c:ossl_quic_stream_is_local_init Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_is_local_init |
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 | 0 | { |
361 | 0 | return s->send_state != QUIC_SSTREAM_STATE_NONE; |
362 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_has_send Unexecuted instantiation: t1_lib.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_impl.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_method.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_obj.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_port.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_txp.c:ossl_quic_stream_has_send Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_channel.c:ossl_quic_stream_has_send Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_has_send |
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 | 0 | { |
374 | 0 | return s->recv_state != QUIC_RSTREAM_STATE_NONE; |
375 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_has_recv Unexecuted instantiation: t1_lib.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_impl.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_method.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_obj.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_port.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_txp.c:ossl_quic_stream_has_recv Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_channel.c:ossl_quic_stream_has_recv Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_has_recv |
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 | 0 | { |
396 | 0 | switch (s->send_state) { |
397 | 0 | case QUIC_SSTREAM_STATE_READY: |
398 | 0 | case QUIC_SSTREAM_STATE_SEND: |
399 | 0 | case QUIC_SSTREAM_STATE_DATA_SENT: |
400 | 0 | return 1; |
401 | 0 | default: |
402 | 0 | return 0; |
403 | 0 | } |
404 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: t1_lib.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_impl.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_method.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_obj.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_port.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_txp.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_channel.c:ossl_quic_stream_has_send_buffer Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_has_send_buffer |
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 | 0 | { |
412 | 0 | return s->send_state == QUIC_SSTREAM_STATE_RESET_SENT |
413 | 0 | || s->send_state == QUIC_SSTREAM_STATE_RESET_RECVD; |
414 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: t1_lib.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_impl.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_method.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_obj.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_port.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_txp.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_channel.c:ossl_quic_stream_send_is_reset Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_send_is_reset |
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 | 0 | { |
429 | 0 | switch (s->recv_state) { |
430 | 0 | case QUIC_RSTREAM_STATE_RECV: |
431 | 0 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: |
432 | 0 | case QUIC_RSTREAM_STATE_DATA_RECVD: |
433 | 0 | return 1; |
434 | 0 | default: |
435 | 0 | return 0; |
436 | 0 | } |
437 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: t1_lib.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_impl.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_method.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_obj.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_port.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_txp.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_channel.c:ossl_quic_stream_has_recv_buffer Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_has_recv_buffer |
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 | 0 | { |
445 | 0 | return s->recv_state == QUIC_RSTREAM_STATE_RESET_RECVD |
446 | 0 | || s->recv_state == QUIC_RSTREAM_STATE_RESET_READ; |
447 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: t1_lib.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_impl.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_method.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_obj.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_port.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_txp.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_channel.c:ossl_quic_stream_recv_is_reset Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_recv_is_reset |
448 | | |
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 | 0 | { |
458 | 0 | switch (s->send_state) { |
459 | 0 | default: |
460 | 0 | case QUIC_SSTREAM_STATE_NONE: |
461 | 0 | return 0; |
462 | 0 | 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 | 0 | return ossl_quic_sstream_get_final_size(s->sstream, final_size); |
469 | 0 | case QUIC_SSTREAM_STATE_DATA_SENT: |
470 | 0 | case QUIC_SSTREAM_STATE_DATA_RECVD: |
471 | 0 | case QUIC_SSTREAM_STATE_RESET_SENT: |
472 | 0 | case QUIC_SSTREAM_STATE_RESET_RECVD: |
473 | 0 | if (final_size != NULL) |
474 | 0 | *final_size = s->send_final_size; |
475 | 0 | return 1; |
476 | 0 | } |
477 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: t1_lib.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_impl.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_method.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_obj.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_port.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_txp.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_channel.c:ossl_quic_stream_send_get_final_size Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_send_get_final_size |
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 | 0 | { |
488 | 0 | switch (s->recv_state) { |
489 | 0 | default: |
490 | 0 | assert(0); |
491 | 0 | case QUIC_RSTREAM_STATE_NONE: |
492 | 0 | case QUIC_RSTREAM_STATE_RECV: |
493 | 0 | return 0; |
494 | | |
495 | 0 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: |
496 | 0 | case QUIC_RSTREAM_STATE_DATA_RECVD: |
497 | 0 | case QUIC_RSTREAM_STATE_DATA_READ: |
498 | 0 | case QUIC_RSTREAM_STATE_RESET_RECVD: |
499 | 0 | case QUIC_RSTREAM_STATE_RESET_READ: |
500 | 0 | if (!ossl_assert(ossl_quic_rxfc_get_final_size(&s->rxfc, final_size))) |
501 | 0 | return 0; |
502 | | |
503 | 0 | return 1; |
504 | 0 | } |
505 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: t1_lib.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_impl.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_method.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_obj.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_port.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_txp.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_channel.c:ossl_quic_stream_recv_get_final_size Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_recv_get_final_size |
506 | | |
507 | | /* |
508 | | * Determines the number of bytes available still to be read, and (if |
509 | | * include_fin is 1) whether a FIN or reset has yet to be read. |
510 | | */ |
511 | | static ossl_inline ossl_unused int ossl_quic_stream_recv_pending(const QUIC_STREAM *s, |
512 | | int include_fin) |
513 | 0 | { |
514 | 0 | size_t avail; |
515 | 0 | int fin = 0; |
516 | |
|
517 | 0 | switch (s->recv_state) { |
518 | 0 | default: |
519 | 0 | assert(0); |
520 | 0 | case QUIC_RSTREAM_STATE_NONE: |
521 | 0 | return 0; |
522 | | |
523 | 0 | case QUIC_RSTREAM_STATE_RECV: |
524 | 0 | case QUIC_RSTREAM_STATE_SIZE_KNOWN: |
525 | 0 | case QUIC_RSTREAM_STATE_DATA_RECVD: |
526 | 0 | if (!ossl_quic_rstream_available(s->rstream, &avail, &fin)) |
527 | 0 | avail = 0; |
528 | |
|
529 | 0 | if (avail == 0 && include_fin && fin) |
530 | 0 | avail = 1; |
531 | |
|
532 | 0 | return avail; |
533 | | |
534 | 0 | case QUIC_RSTREAM_STATE_RESET_RECVD: |
535 | 0 | return include_fin; |
536 | | |
537 | 0 | case QUIC_RSTREAM_STATE_DATA_READ: |
538 | 0 | case QUIC_RSTREAM_STATE_RESET_READ: |
539 | 0 | return 0; |
540 | 0 | } |
541 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_stream_recv_pending Unexecuted instantiation: t1_lib.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_impl.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_method.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_obj.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_port.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_stream_map.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_thread_assist.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_txp.c:ossl_quic_stream_recv_pending Unexecuted instantiation: rec_layer_s3.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_channel.c:ossl_quic_stream_recv_pending Unexecuted instantiation: quic_rx_depack.c:ossl_quic_stream_recv_pending |
542 | | |
543 | | /* |
544 | | * QUIC Stream Map |
545 | | * =============== |
546 | | * |
547 | | * The QUIC stream map: |
548 | | * |
549 | | * - maps stream IDs to QUIC_STREAM objects; |
550 | | * - tracks which streams are 'active' (currently have data for transmission); |
551 | | * - allows iteration over the active streams only. |
552 | | * |
553 | | */ |
554 | | struct quic_stream_map_st { |
555 | | LHASH_OF(QUIC_STREAM) *map; |
556 | | QUIC_STREAM_LIST_NODE active_list; |
557 | | QUIC_STREAM_LIST_NODE accept_list; |
558 | | QUIC_STREAM_LIST_NODE ready_for_gc_list; |
559 | | size_t rr_stepping, rr_counter; |
560 | | size_t num_accept_bidi, num_accept_uni, num_shutdown_flush; |
561 | | QUIC_STREAM *rr_cur; |
562 | | uint64_t (*get_stream_limit_cb)(int uni, void *arg); |
563 | | void *get_stream_limit_cb_arg; |
564 | | QUIC_RXFC *max_streams_bidi_rxfc; |
565 | | QUIC_RXFC *max_streams_uni_rxfc; |
566 | | int is_server; |
567 | | }; |
568 | | |
569 | | /* |
570 | | * get_stream_limit is a callback which is called to retrieve the current stream |
571 | | * limit for streams created by us. This mechanism is not used for |
572 | | * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if |
573 | | * (x >> 2) < returned limit value; i.e., the returned value is exclusive. |
574 | | * |
575 | | * If uni is 1, get the limit for locally-initiated unidirectional streams, else |
576 | | * get the limit for locally-initiated bidirectional streams. |
577 | | * |
578 | | * If the callback is NULL, stream limiting is not applied. |
579 | | * Stream limiting is used to determine if frames can currently be produced for |
580 | | * a stream. |
581 | | */ |
582 | | int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm, |
583 | | uint64_t (*get_stream_limit_cb)(int uni, void *arg), |
584 | | void *get_stream_limit_cb_arg, |
585 | | QUIC_RXFC *max_streams_bidi_rxfc, |
586 | | QUIC_RXFC *max_streams_uni_rxfc, |
587 | | int is_server); |
588 | | |
589 | | /* |
590 | | * Any streams still in the map will be released as though |
591 | | * ossl_quic_stream_map_release was called on them. |
592 | | */ |
593 | | void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm); |
594 | | |
595 | | /* |
596 | | * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_* |
597 | | * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate |
598 | | * server-initiated streams as they will need to allocate a QUIC_STREAM |
599 | | * structure to track any stream created by the server, etc. |
600 | | * |
601 | | * stream_id must be a valid value. Returns NULL if a stream already exists |
602 | | * with the given ID. |
603 | | */ |
604 | | QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm, |
605 | | uint64_t stream_id, |
606 | | int type); |
607 | | |
608 | | /* |
609 | | * Releases a stream object. Note that this must only be done once the teardown |
610 | | * process is entirely complete and the object will never be referenced again. |
611 | | */ |
612 | | void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream); |
613 | | |
614 | | /* |
615 | | * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque |
616 | | * argument which is passed through. |
617 | | */ |
618 | | void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm, |
619 | | void (*visit_cb)(QUIC_STREAM *stream, void *arg), |
620 | | void *visit_cb_arg); |
621 | | |
622 | | /* |
623 | | * Retrieves a stream by stream ID. Returns NULL if it does not exist. |
624 | | */ |
625 | | QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm, |
626 | | uint64_t stream_id); |
627 | | |
628 | | /* |
629 | | * Marks the given stream as active or inactive based on its state. Idempotent. |
630 | | * |
631 | | * When a stream is marked active, it becomes available in the iteration list, |
632 | | * and when a stream is marked inactive, it no longer appears in the iteration |
633 | | * list. |
634 | | * |
635 | | * Calling this function invalidates any iterator currently pointing at the |
636 | | * given stream object, but iterators not currently pointing at the given stream |
637 | | * object are not invalidated. |
638 | | */ |
639 | | void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s); |
640 | | |
641 | | /* |
642 | | * Sets the RR stepping value, n. The RR rotation will be advanced every n |
643 | | * packets. The default value is 1. |
644 | | */ |
645 | | void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping); |
646 | | |
647 | | /* |
648 | | * Returns 1 if the stream ordinal given is allowed by the current stream count |
649 | | * flow control limit, assuming a locally initiated stream of a type described |
650 | | * by is_uni. |
651 | | * |
652 | | * Note that stream_ordinal is a stream ordinal, not a stream ID. |
653 | | */ |
654 | | int ossl_quic_stream_map_is_local_allowed_by_stream_limit(QUIC_STREAM_MAP *qsm, |
655 | | uint64_t stream_ordinal, |
656 | | int is_uni); |
657 | | |
658 | | /* |
659 | | * Stream Send Part |
660 | | * ================ |
661 | | */ |
662 | | |
663 | | /* |
664 | | * Ensures that the sending part has transitioned out of the READY state (i.e., |
665 | | * to SEND, or a subsequent state). This function is named as it is because, |
666 | | * while on paper the distinction between READY and SEND is whether we have |
667 | | * started transmitting application data, in practice the meaningful distinction |
668 | | * between the two states is whether we have allocated a stream ID to the stream |
669 | | * or not. QUIC permits us to defer stream ID allocation until first STREAM (or |
670 | | * STREAM_DATA_BLOCKED) frame transmission for locally-initiated streams. |
671 | | * |
672 | | * Our implementation does not currently do this and we allocate stream IDs up |
673 | | * front, however we may revisit this in the future. Calling this represents a |
674 | | * demand for a stream ID by the caller and ensures one has been allocated to |
675 | | * the stream, and causes us to transition to SEND if we are still in the READY |
676 | | * state. |
677 | | * |
678 | | * Returns 0 if there is no send part (caller error) and 1 otherwise. |
679 | | */ |
680 | | int ossl_quic_stream_map_ensure_send_part_id(QUIC_STREAM_MAP *qsm, |
681 | | QUIC_STREAM *qs); |
682 | | |
683 | | /* |
684 | | * Transitions from SEND to the DATA_SENT state. Note that this is NOT the same |
685 | | * as the point in time at which the final size of the stream becomes known |
686 | | * (i.e., the time at which ossl_quic_sstream_fin()) is called as it occurs when |
687 | | * we have SENT all data on a given stream send part, not merely buffered it. |
688 | | * Note that this transition is NOT reversed in the event of some of that data |
689 | | * being lost. |
690 | | * |
691 | | * Returns 1 if the state transition was successfully taken. Returns 0 if there |
692 | | * is no send part (caller error) or if the state transition cannot be taken |
693 | | * because the send part is not in the SEND state. |
694 | | */ |
695 | | int ossl_quic_stream_map_notify_all_data_sent(QUIC_STREAM_MAP *qsm, |
696 | | QUIC_STREAM *qs); |
697 | | |
698 | | /* |
699 | | * Transitions from the DATA_SENT to DATA_RECVD state; should be called |
700 | | * when all transmitted stream data is ACKed by the peer. |
701 | | * |
702 | | * Returns 1 if the state transition was successfully taken. Returns 0 if there |
703 | | * is no send part (caller error) or the state transition cannot be taken |
704 | | * because the send part is not in the DATA_SENT state. Because |
705 | | * ossl_quic_stream_map_notify_all_data_sent() should always be called prior to |
706 | | * this function, the send state must already be in DATA_SENT in order for this |
707 | | * function to succeed. |
708 | | */ |
709 | | int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm, |
710 | | QUIC_STREAM *qs); |
711 | | |
712 | | /* |
713 | | * Resets the sending part of a stream. This is a transition from the READY, |
714 | | * SEND or DATA_SENT send stream states to the RESET_SENT state. |
715 | | * |
716 | | * This function returns 1 if the transition is taken (i.e., if the send stream |
717 | | * part was in one of the states above), or if it is already in the RESET_SENT |
718 | | * state (idempotent operation), or if it has reached the RESET_RECVD state. |
719 | | * |
720 | | * It returns 0 if in the DATA_RECVD state, as a send stream cannot be reset |
721 | | * in this state. It also returns 0 if there is no send part (caller error). |
722 | | */ |
723 | | int ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm, |
724 | | QUIC_STREAM *qs, |
725 | | uint64_t aec); |
726 | | |
727 | | /* |
728 | | * Transitions from the RESET_SENT to the RESET_RECVD state. This should be |
729 | | * called when a sent RESET_STREAM frame has been acknowledged by the peer. |
730 | | * |
731 | | * This function returns 1 if the transition is taken (i.e., if the send stream |
732 | | * part was in one of the states above) or if it is already in the RESET_RECVD |
733 | | * state (idempotent operation). |
734 | | * |
735 | | * It returns 0 if not in the RESET_SENT or RESET_RECVD states, as this function |
736 | | * should only be called after we have already sent a RESET_STREAM frame and |
737 | | * entered the RESET_SENT state. It also returns 0 if there is no send part |
738 | | * (caller error). |
739 | | */ |
740 | | int ossl_quic_stream_map_notify_reset_stream_acked(QUIC_STREAM_MAP *qsm, |
741 | | QUIC_STREAM *qs); |
742 | | |
743 | | |
744 | | /* |
745 | | * Stream Receive Part |
746 | | * =================== |
747 | | */ |
748 | | |
749 | | /* |
750 | | * Transitions from the RECV receive stream state to the SIZE_KNOWN state. This |
751 | | * should be called once a STREAM frame is received for the stream with the FIN |
752 | | * bit set. final_size should be the final size of the stream in bytes. |
753 | | * |
754 | | * Returns 1 if the transition was taken. |
755 | | */ |
756 | | int ossl_quic_stream_map_notify_size_known_recv_part(QUIC_STREAM_MAP *qsm, |
757 | | QUIC_STREAM *qs, |
758 | | uint64_t final_size); |
759 | | |
760 | | /* |
761 | | * Transitions from the SIZE_KNOWN receive stream state to the DATA_RECVD state. |
762 | | * This should be called once all data for a receive stream is received. |
763 | | * |
764 | | * Returns 1 if the transition was taken. |
765 | | */ |
766 | | int ossl_quic_stream_map_notify_totally_received(QUIC_STREAM_MAP *qsm, |
767 | | QUIC_STREAM *qs); |
768 | | |
769 | | /* |
770 | | * Transitions from the DATA_RECVD receive stream state to the DATA_READ state. |
771 | | * This should be called once all data for a receive stream is read by the |
772 | | * application. |
773 | | * |
774 | | * Returns 1 if the transition was taken. |
775 | | */ |
776 | | int ossl_quic_stream_map_notify_totally_read(QUIC_STREAM_MAP *qsm, |
777 | | QUIC_STREAM *qs); |
778 | | |
779 | | /* |
780 | | * Transitions from the RECV, SIZE_KNOWN or DATA_RECVD receive stream state to |
781 | | * the RESET_RECVD state. This should be called on RESET_STREAM. |
782 | | * |
783 | | * Returns 1 if the transition was taken. |
784 | | */ |
785 | | int ossl_quic_stream_map_notify_reset_recv_part(QUIC_STREAM_MAP *qsm, |
786 | | QUIC_STREAM *qs, |
787 | | uint64_t app_error_code, |
788 | | uint64_t final_size); |
789 | | |
790 | | /* |
791 | | * Transitions from the RESET_RECVD receive stream state to the RESET_READ |
792 | | * receive stream state. This should be called when the application is notified |
793 | | * of a stream reset. |
794 | | */ |
795 | | int ossl_quic_stream_map_notify_app_read_reset_recv_part(QUIC_STREAM_MAP *qsm, |
796 | | QUIC_STREAM *qs); |
797 | | |
798 | | /* |
799 | | * Marks the receiving part of a stream for STOP_SENDING. This is orthogonal to |
800 | | * receive stream state as it does not affect it directly. |
801 | | * |
802 | | * Returns 1 if the receiving part of a stream was not already marked for |
803 | | * STOP_SENDING. |
804 | | * Returns 0 otherwise, which need not be considered an error. |
805 | | */ |
806 | | int ossl_quic_stream_map_stop_sending_recv_part(QUIC_STREAM_MAP *qsm, |
807 | | QUIC_STREAM *qs, |
808 | | uint64_t aec); |
809 | | |
810 | | /* |
811 | | * Marks the stream as wanting a STOP_SENDING frame transmitted. It is not valid |
812 | | * to call this if ossl_quic_stream_map_stop_sending_recv_part() has not been |
813 | | * called. For TXP use. |
814 | | */ |
815 | | int ossl_quic_stream_map_schedule_stop_sending(QUIC_STREAM_MAP *qsm, |
816 | | QUIC_STREAM *qs); |
817 | | |
818 | | |
819 | | /* |
820 | | * Accept Queue Management |
821 | | * ======================= |
822 | | */ |
823 | | |
824 | | /* |
825 | | * Adds a stream to the accept queue. |
826 | | */ |
827 | | void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm, |
828 | | QUIC_STREAM *s); |
829 | | |
830 | | /* |
831 | | * Returns the next item to be popped from the accept queue, or NULL if it is |
832 | | * empty. |
833 | | */ |
834 | | QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm); |
835 | | |
836 | | /* |
837 | | * Removes a stream from the accept queue. rtt is the estimated connection RTT. |
838 | | * The stream is retired for the purposes of MAX_STREAMS RXFC. |
839 | | * |
840 | | * Precondition: s is in the accept queue. |
841 | | */ |
842 | | void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm, |
843 | | QUIC_STREAM *s, |
844 | | OSSL_TIME rtt); |
845 | | |
846 | | /* Returns the length of the accept queue for the given stream type. */ |
847 | | size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm, int is_uni); |
848 | | |
849 | | /* Returns the total length of the accept queues for all stream types. */ |
850 | | size_t ossl_quic_stream_map_get_total_accept_queue_len(QUIC_STREAM_MAP *qsm); |
851 | | |
852 | | /* |
853 | | * Shutdown Flush and GC |
854 | | * ===================== |
855 | | */ |
856 | | |
857 | | /* |
858 | | * Delete streams ready for GC. Pointers to those QUIC_STREAM objects become |
859 | | * invalid. |
860 | | */ |
861 | | void ossl_quic_stream_map_gc(QUIC_STREAM_MAP *qsm); |
862 | | |
863 | | /* |
864 | | * Begins shutdown stream flush triage. Analyses all streams, including deleted |
865 | | * but not yet GC'd streams, to determine if we should wait for that stream to |
866 | | * be fully flushed before shutdown. After calling this, call |
867 | | * ossl_quic_stream_map_is_shutdown_flush_finished() to determine if all |
868 | | * shutdown flush eligible streams have been flushed. |
869 | | */ |
870 | | void ossl_quic_stream_map_begin_shutdown_flush(QUIC_STREAM_MAP *qsm); |
871 | | |
872 | | /* |
873 | | * Returns 1 if all shutdown flush eligible streams have finished flushing, |
874 | | * or if ossl_quic_stream_map_begin_shutdown_flush() has not been called. |
875 | | */ |
876 | | int ossl_quic_stream_map_is_shutdown_flush_finished(QUIC_STREAM_MAP *qsm); |
877 | | |
878 | | /* |
879 | | * QUIC Stream Iterator |
880 | | * ==================== |
881 | | * |
882 | | * Allows the current set of active streams to be walked using a RR-based |
883 | | * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm |
884 | | * is stepped. The RR algorithm rotates the iteration order such that the next |
885 | | * active stream is returned first after n calls to ossl_quic_stream_iter_init, |
886 | | * where n is the stepping value configured via |
887 | | * ossl_quic_stream_map_set_rr_stepping. |
888 | | * |
889 | | * Suppose there are three active streams and the configured stepping is n: |
890 | | * |
891 | | * Iteration 0n: [Stream 1] [Stream 2] [Stream 3] |
892 | | * Iteration 1n: [Stream 2] [Stream 3] [Stream 1] |
893 | | * Iteration 2n: [Stream 3] [Stream 1] [Stream 2] |
894 | | * |
895 | | */ |
896 | | typedef struct quic_stream_iter_st { |
897 | | QUIC_STREAM_MAP *qsm; |
898 | | QUIC_STREAM *first_stream, *stream; |
899 | | } QUIC_STREAM_ITER; |
900 | | |
901 | | /* |
902 | | * Initialise an iterator, advancing the RR algorithm as necessary (if |
903 | | * advance_rr is 1). After calling this, it->stream will be the first stream in |
904 | | * the iteration sequence, or NULL if there are no active streams. |
905 | | */ |
906 | | void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm, |
907 | | int advance_rr); |
908 | | |
909 | | /* |
910 | | * Advances to next stream in iteration sequence. You do not need to call this |
911 | | * immediately after calling ossl_quic_stream_iter_init(). If the end of the |
912 | | * list is reached, it->stream will be NULL after calling this. |
913 | | */ |
914 | | void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it); |
915 | | |
916 | | # endif |
917 | | |
918 | | #endif |