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