QUIC CHANNEL: Handle any number of 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
40     /* Temporary link used by TXP. */
41     QUIC_STREAM    *txp_next;
42
43     /*
44      * QUIC Stream ID. Do not assume that this encodes a type as this is a
45      * version-specific property and may change between QUIC versions; instead,
46      * use the type field.
47      */
48     uint64_t        id;
49
50     /*
51      * Application Error Code (AEC) used for STOP_SENDING frame.
52      * This is only valid if stop_sending is 1.
53      */
54     uint64_t        stop_sending_aec;
55
56     /*
57      * Application Error Code (AEC) used for RESET_STREAM frame.
58      * This is only valid if reset_stream is 1.
59      */
60     uint64_t        reset_stream_aec;
61
62     /* Temporary value used by TXP. */
63     uint64_t        txp_txfc_new_credit_consumed;
64
65     QUIC_SSTREAM    *sstream;   /* NULL if RX-only */
66     QUIC_RSTREAM    *rstream;   /* NULL if TX only */
67     QUIC_TXFC       txfc;       /* NULL if RX-only */
68     QUIC_RXFC       rxfc;       /* NULL if TX-only */
69     unsigned int    type   : 8; /* QUIC_STREAM_INITIATOR_*, QUIC_STREAM_DIR_* */
70     unsigned int    active : 1;
71
72     /*
73      * Has STOP_SENDING been requested (by us)? Note that this is not the same
74      * as want_stop_sending below, as a STOP_SENDING frame may already have been
75      * sent and fully acknowledged.
76      */
77     unsigned int    stop_sending            : 1;
78
79     /*
80      * Has RESET_STREAM been requested (by us)? Works identically to
81      * STOP_SENDING for transmission purposes.
82      */
83     unsigned int    reset_stream            : 1;
84
85     /* Has our peer sent a STOP_SENDING frame? */
86     unsigned int    peer_stop_sending       : 1;
87     /* Has our peer sent a RESET_STREAM frame? */
88     unsigned int    peer_reset_stream       : 1;
89
90     /* Temporary flags used by TXP. */
91     unsigned int    txp_sent_fc             : 1;
92     unsigned int    txp_sent_stop_sending   : 1;
93     unsigned int    txp_sent_reset_stream   : 1;
94     unsigned int    txp_drained             : 1;
95     unsigned int    txp_blocked             : 1;
96
97     /* Frame regeneration flags. */
98     unsigned int    want_max_stream_data    : 1; /* used for regen only */
99     unsigned int    want_stop_sending       : 1; /* used for gen or regen */
100     unsigned int    want_reset_stream       : 1; /* used for gen or regen */
101
102     /* A FIN has been retired from the rstream buffer. */
103     unsigned int    recv_fin_retired        : 1;
104 };
105
106 /*
107  * Marks a stream for STOP_SENDING. aec is the application error code (AEC).
108  * This can only fail if it has already been called.
109  */
110 int ossl_quic_stream_stop_sending(QUIC_STREAM *s, uint64_t aec);
111
112 /*
113  * Marks a stream for reset. aec is the application error code (AEC).
114  * This can only fail if it has already been called.
115  */
116 int ossl_quic_stream_reset(QUIC_STREAM *s, uint64_t aec);
117
118 /* 
119  * QUIC Stream Map
120  * ===============
121  *
122  * The QUIC stream map:
123  *
124  *   - maps stream IDs to QUIC_STREAM objects;
125  *   - tracks which streams are 'active' (currently have data for transmission);
126  *   - allows iteration over the active streams only.
127  *
128  */
129 typedef struct quic_stream_map_st {
130     LHASH_OF(QUIC_STREAM)   *map;
131     QUIC_STREAM_LIST_NODE   active_list;
132     size_t                  rr_stepping, rr_counter;
133     QUIC_STREAM             *rr_cur;
134     uint64_t                (*get_stream_limit_cb)(int uni, void *arg);
135     void                    *get_stream_limit_cb_arg;
136 } QUIC_STREAM_MAP;
137
138 /*
139  * get_stream_limit is a callback which is called to retrieve the current stream
140  * limit for streams created by us. This mechanism is not used for
141  * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if
142  * (x >> 2) < returned limit value; i.e., the returned value is exclusive.
143  *
144  * If uni is 1, get the limit for locally-initiated unidirectional streams, else
145  * get the limit for locally-initiated bidirectional streams.
146  *
147  * If the callback is NULL, stream limiting is not applied.
148  * Stream limiting is used to determine if frames can currently be produced for
149  * a stream.
150  */
151 int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
152                               uint64_t (*get_stream_limit_cb)(int uni, void *arg),
153                               void *get_stream_limit_cb_arg);
154
155 /*
156  * Any streams still in the map will be released as though
157  * ossl_quic_stream_map_release was called on them.
158  */
159 void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
160
161 #define QUIC_STREAM_INITIATOR_CLIENT        0
162 #define QUIC_STREAM_INITIATOR_SERVER        1
163 #define QUIC_STREAM_INITIATOR_MASK          1
164
165 #define QUIC_STREAM_DIR_BIDI                0
166 #define QUIC_STREAM_DIR_UNI                 2
167 #define QUIC_STREAM_DIR_MASK                2
168
169 static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(QUIC_STREAM *s)
170 {
171     return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
172 }
173
174 static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(QUIC_STREAM *s)
175 {
176     return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
177 }
178
179 /*
180  * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_*
181  * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate
182  * server-initiated streams as they will need to allocate a QUIC_STREAM
183  * structure to track any stream created by the server, etc.
184  *
185  * stream_id must be a valid value. Returns NULL if a stream already exists
186  * with the given ID.
187  */
188 QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
189                                         uint64_t stream_id,
190                                         int type);
191
192 /*
193  * Releases a stream object. Note that this must only be done once the teardown
194  * process is entirely complete and the object will never be referenced again.
195  */
196 void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream);
197
198 /*
199  * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque
200  * argument which is passed through.
201  */
202 void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
203                                 void (*visit_cb)(QUIC_STREAM *stream, void *arg),
204                                 void *visit_cb_arg);
205
206 /*
207  * Retrieves a stream by stream ID. Returns NULL if it does not exist.
208  */
209 QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
210                                             uint64_t stream_id);
211
212 /*
213  * Marks the given stream as active or inactive based on its state. Idempotent.
214  *
215  * When a stream is marked active, it becomes available in the iteration list,
216  * and when a stream is marked inactive, it no longer appears in the iteration
217  * list.
218  *
219  * Calling this function invalidates any iterator currently pointing at the
220  * given stream object, but iterators not currently pointing at the given stream
221  * object are not invalidated.
222  */
223 void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
224
225 /*
226  * Sets the RR stepping value, n. The RR rotation will be advanced every n
227  * packets. The default value is 1.
228  */
229 void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
230
231 /*
232  * QUIC Stream Iterator
233  * ====================
234  *
235  * Allows the current set of active streams to be walked using a RR-based
236  * algorithm. Each time ossl_quic_stream_iter_init is called, the RR algorithm
237  * is stepped. The RR algorithm rotates the iteration order such that the next
238  * active stream is returned first after n calls to ossl_quic_stream_iter_init,
239  * where n is the stepping value configured via
240  * ossl_quic_stream_map_set_rr_stepping.
241  *
242  * Suppose there are three active streams and the configured stepping is n:
243  *
244  *   Iteration 0n:  [Stream 1] [Stream 2] [Stream 3]
245  *   Iteration 1n:  [Stream 2] [Stream 3] [Stream 1]
246  *   Iteration 2n:  [Stream 3] [Stream 1] [Stream 2]
247  *
248  */
249 typedef struct quic_stream_iter_st {
250     QUIC_STREAM_MAP     *qsm;
251     QUIC_STREAM         *first_stream, *stream;
252 } QUIC_STREAM_ITER;
253
254 /*
255  * Initialise an iterator, advancing the RR algorithm as necessary (if
256  * advance_rr is 1). After calling this, it->stream will be the first stream in
257  * the iteration sequence, or NULL if there are no active streams.
258  */
259 void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
260                                 int advance_rr);
261
262 /*
263  * Advances to next stream in iteration sequence. You do not need to call this
264  * immediately after calling ossl_quic_stream_iter_init(). If the end of the
265  * list is reached, it->stream will be NULL after calling this.
266  */
267 void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);
268
269 # endif
270
271 #endif