QUIC RXDP/QSM: Enforce MAX_STREAMS
[openssl.git] / include / internal / quic_stream_map.h
1 /*
2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #ifndef OSSL_INTERNAL_QUIC_STREAM_MAP_H
11 # define OSSL_INTERNAL_QUIC_STREAM_MAP_H
12 # pragma once
13
14 # include "internal/e_os.h"
15 # include "internal/time.h"
16 # include "internal/quic_types.h"
17 # include "internal/quic_stream.h"
18 # include "internal/quic_fc.h"
19 # include <openssl/lhash.h>
20
21 # ifndef OPENSSL_NO_QUIC
22
23 /*
24  * QUIC Stream
25  * ===========
26  *
27  * Logical QUIC stream composing all relevant send and receive components.
28  */
29 typedef struct quic_stream_st QUIC_STREAM;
30
31 typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE;
32
33 struct quic_stream_list_node_st {
34     QUIC_STREAM_LIST_NODE *prev, *next;
35 };
36
37 struct quic_stream_st {
38     QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */
39     QUIC_STREAM_LIST_NODE accept_node; /* accept queue of remotely-created streams */
40
41     /* Temporary link used by TXP. */
42     QUIC_STREAM    *txp_next;
43
44     /*
45      * QUIC Stream ID. Do not assume that this encodes a type as this is a
46      * version-specific property and may change between QUIC versions; instead,
47      * use the type field.
48      */
49     uint64_t        id;
50
51     /*
52      * Application Error Code (AEC) used for STOP_SENDING frame.
53      * This is only valid if stop_sending is 1.
54      */
55     uint64_t        stop_sending_aec;
56
57     /*
58      * Application Error Code (AEC) used for RESET_STREAM frame.
59      * This is only valid if reset_stream is 1.
60      */
61     uint64_t        reset_stream_aec;
62
63     /* Temporary value used by TXP. */
64     uint64_t        txp_txfc_new_credit_consumed;
65
66     QUIC_SSTREAM    *sstream;   /* NULL if RX-only */
67     QUIC_RSTREAM    *rstream;   /* NULL if TX only */
68     QUIC_TXFC       txfc;       /* NULL if RX-only */
69     QUIC_RXFC       rxfc;       /* NULL if TX-only */
70     unsigned int    type   : 8; /* QUIC_STREAM_INITIATOR_*, QUIC_STREAM_DIR_* */
71     unsigned int    active : 1;
72
73     /*
74      * Has STOP_SENDING been requested (by us)? Note that this is not the same
75      * as want_stop_sending below, as a STOP_SENDING frame may already have been
76      * sent and fully acknowledged.
77      */
78     unsigned int    stop_sending            : 1;
79
80     /*
81      * Has RESET_STREAM been requested (by us)? Works identically to
82      * STOP_SENDING for transmission purposes.
83      */
84     unsigned int    reset_stream            : 1;
85
86     /* Has our peer sent a STOP_SENDING frame? */
87     unsigned int    peer_stop_sending       : 1;
88     /* Has our peer sent a RESET_STREAM frame? */
89     unsigned int    peer_reset_stream       : 1;
90
91     /* Temporary flags used by TXP. */
92     unsigned int    txp_sent_fc             : 1;
93     unsigned int    txp_sent_stop_sending   : 1;
94     unsigned int    txp_sent_reset_stream   : 1;
95     unsigned int    txp_drained             : 1;
96     unsigned int    txp_blocked             : 1;
97
98     /* Frame regeneration flags. */
99     unsigned int    want_max_stream_data    : 1; /* used for regen only */
100     unsigned int    want_stop_sending       : 1; /* used for gen or regen */
101     unsigned int    want_reset_stream       : 1; /* used for gen or regen */
102
103     /* A FIN has been retired from the rstream buffer. */
104     unsigned int    recv_fin_retired        : 1;
105
106     /* The stream's XSO has been deleted. Pending GC. */
107     unsigned int    deleted                 : 1;
108 };
109
110 /*
111  * Marks a stream for STOP_SENDING. aec is the application error code (AEC).
112  * This can only fail if it has already been called.
113  */
114 int ossl_quic_stream_stop_sending(QUIC_STREAM *s, uint64_t aec);
115
116 /*
117  * Marks a stream for reset. aec is the application error code (AEC).
118  * This can only fail if it has already been called.
119  */
120 int ossl_quic_stream_reset(QUIC_STREAM *s, uint64_t aec);
121
122 /* 
123  * QUIC Stream Map
124  * ===============
125  *
126  * The QUIC stream map:
127  *
128  *   - maps stream IDs to QUIC_STREAM objects;
129  *   - tracks which streams are 'active' (currently have data for transmission);
130  *   - allows iteration over the active streams only.
131  *
132  */
133 typedef struct quic_stream_map_st {
134     LHASH_OF(QUIC_STREAM)   *map;
135     QUIC_STREAM_LIST_NODE   active_list;
136     QUIC_STREAM_LIST_NODE   accept_list;
137     size_t                  rr_stepping, rr_counter, num_accept;
138     QUIC_STREAM             *rr_cur;
139     uint64_t                (*get_stream_limit_cb)(int uni, void *arg);
140     void                    *get_stream_limit_cb_arg;
141     QUIC_RXFC               *max_streams_bidi_rxfc;
142     QUIC_RXFC               *max_streams_uni_rxfc;
143 } QUIC_STREAM_MAP;
144
145 /*
146  * get_stream_limit is a callback which is called to retrieve the current stream
147  * limit for streams created by us. This mechanism is not used for
148  * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if
149  * (x >> 2) < returned limit value; i.e., the returned value is exclusive.
150  *
151  * If uni is 1, get the limit for locally-initiated unidirectional streams, else
152  * get the limit for locally-initiated bidirectional streams.
153  *
154  * If the callback is NULL, stream limiting is not applied.
155  * Stream limiting is used to determine if frames can currently be produced for
156  * a stream.
157  */
158 int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
159                               uint64_t (*get_stream_limit_cb)(int uni, void *arg),
160                               void *get_stream_limit_cb_arg,
161                               QUIC_RXFC *max_streams_bidi_rxfc,
162                               QUIC_RXFC *max_streams_uni_rxfc);
163
164 /*
165  * Any streams still in the map will be released as though
166  * ossl_quic_stream_map_release was called on them.
167  */
168 void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
169
170 #define QUIC_STREAM_INITIATOR_CLIENT        0
171 #define QUIC_STREAM_INITIATOR_SERVER        1
172 #define QUIC_STREAM_INITIATOR_MASK          1
173
174 #define QUIC_STREAM_DIR_BIDI                0
175 #define QUIC_STREAM_DIR_UNI                 2
176 #define QUIC_STREAM_DIR_MASK                2
177
178 static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(QUIC_STREAM *s)
179 {
180     return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
181 }
182
183 static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(QUIC_STREAM *s)
184 {
185     return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
186 }
187
188 /*
189  * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_*
190  * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate
191  * server-initiated streams as they will need to allocate a QUIC_STREAM
192  * structure to track any stream created by the server, etc.
193  *
194  * stream_id must be a valid value. Returns NULL if a stream already exists
195  * with the given ID.
196  */
197 QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
198                                         uint64_t stream_id,
199                                         int type);
200
201 /*
202  * Releases a stream object. Note that this must only be done once the teardown
203  * process is entirely complete and the object will never be referenced again.
204  */
205 void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream);
206
207 /*
208  * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque
209  * argument which is passed through.
210  */
211 void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
212                                 void (*visit_cb)(QUIC_STREAM *stream, void *arg),
213                                 void *visit_cb_arg);
214
215 /*
216  * Retrieves a stream by stream ID. Returns NULL if it does not exist.
217  */
218 QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
219                                             uint64_t stream_id);
220
221 /*
222  * Marks the given stream as active or inactive based on its state. Idempotent.
223  *
224  * When a stream is marked active, it becomes available in the iteration list,
225  * and when a stream is marked inactive, it no longer appears in the iteration
226  * list.
227  *
228  * Calling this function invalidates any iterator currently pointing at the
229  * given stream object, but iterators not currently pointing at the given stream
230  * object are not invalidated.
231  */
232 void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
233
234 /*
235  * Sets the RR stepping value, n. The RR rotation will be advanced every n
236  * packets. The default value is 1.
237  */
238 void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
239
240 /*
241  * Adds a stream to the accept queue.
242  */
243 void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
244                                             QUIC_STREAM *s);
245
246 /*
247  * Returns the next item to be popped from the accept queue, or NULL if it is
248  * empty.
249  */
250 QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm);
251
252 /*
253  * Removes a stream from the accept queue. rtt is the estimated connection RTT.
254  * The stream is retired for the purposes of MAX_STREAMS RXFC.
255  *
256  * Precondition: s is in the accept queue.
257  */
258 void ossl_quic_stream_map_remove_from_accept_queue(QUIC_STREAM_MAP *qsm,
259                                                    QUIC_STREAM *s,
260                                                    OSSL_TIME rtt);
261
262 /* Returns the length of the accept queue. */
263 size_t ossl_quic_stream_map_get_accept_queue_len(QUIC_STREAM_MAP *qsm);
264
265 /*
266  * QUIC Stream Iterator
267  * ====================
268  *
269  * Allows the current set of active streams to be walked using a RR-based
270  * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm
271  * is stepped. The RR algorithm rotates the iteration order such that the next
272  * active stream is returned first after n calls to ossl_quic_stream_iter_init,
273  * where n is the stepping value configured via
274  * ossl_quic_stream_map_set_rr_stepping.
275  *
276  * Suppose there are three active streams and the configured stepping is n:
277  *
278  *   Iteration 0n:  [Stream 1] [Stream 2] [Stream 3]
279  *   Iteration 1n:  [Stream 2] [Stream 3] [Stream 1]
280  *   Iteration 2n:  [Stream 3] [Stream 1] [Stream 2]
281  *
282  */
283 typedef struct quic_stream_iter_st {
284     QUIC_STREAM_MAP     *qsm;
285     QUIC_STREAM         *first_stream, *stream;
286 } QUIC_STREAM_ITER;
287
288 /*
289  * Initialise an iterator, advancing the RR algorithm as necessary (if
290  * advance_rr is 1). After calling this, it->stream will be the first stream in
291  * the iteration sequence, or NULL if there are no active streams.
292  */
293 void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
294                                 int advance_rr);
295
296 /*
297  * Advances to next stream in iteration sequence. You do not need to call this
298  * immediately after calling ossl_quic_stream_iter_init(). If the end of the
299  * list is reached, it->stream will be NULL after calling this.
300  */
301 void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);
302
303 # endif
304
305 #endif