2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
10 #ifndef OSSL_INTERNAL_QUIC_STREAM_MAP_H
11 # define OSSL_INTERNAL_QUIC_STREAM_MAP_H
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>
21 # ifndef OPENSSL_NO_QUIC
27 * Logical QUIC stream composing all relevant send and receive components.
29 typedef struct quic_stream_st QUIC_STREAM;
31 typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE;
33 struct quic_stream_list_node_st {
34 QUIC_STREAM_LIST_NODE *prev, *next;
37 struct quic_stream_st {
38 QUIC_STREAM_LIST_NODE active_node; /* for use by QUIC_STREAM_MAP */
40 /* Temporary link used by TXP. */
41 QUIC_STREAM *txp_next;
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,
51 * Application Error Code (AEC) used for STOP_SENDING frame.
52 * This is only valid if stop_sending is 1.
54 uint64_t stop_sending_aec;
57 * Application Error Code (AEC) used for RESET_STREAM frame.
58 * This is only valid if reset_stream is 1.
60 uint64_t reset_stream_aec;
62 /* Temporary value used by TXP. */
63 uint64_t txp_txfc_new_credit_consumed;
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;
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.
77 unsigned int stop_sending : 1;
80 * Has RESET_STREAM been requested (by us)? Works identically to
81 * STOP_SENDING for transmission purposes.
83 unsigned int reset_stream : 1;
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;
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;
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 */
102 /* A FIN has been retired from the rstream buffer. */
103 unsigned int recv_fin_retired : 1;
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.
110 int ossl_quic_stream_stop_sending(QUIC_STREAM *s, uint64_t aec);
113 * Marks a stream for reset. aec is the application error code (AEC).
114 * This can only fail if it has already been called.
116 int ossl_quic_stream_reset(QUIC_STREAM *s, uint64_t aec);
122 * The QUIC stream map:
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.
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;
134 uint64_t (*get_stream_limit_cb)(int uni, void *arg);
135 void *get_stream_limit_cb_arg;
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.
144 * If uni is 1, get the limit for locally-initiated unidirectional streams, else
145 * get the limit for locally-initiated bidirectional streams.
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
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);
156 * Any streams still in the map will be released as though
157 * ossl_quic_stream_map_release was called on them.
159 void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
161 #define QUIC_STREAM_INITIATOR_CLIENT 0
162 #define QUIC_STREAM_INITIATOR_SERVER 1
163 #define QUIC_STREAM_INITIATOR_MASK 1
165 #define QUIC_STREAM_DIR_BIDI 0
166 #define QUIC_STREAM_DIR_UNI 2
167 #define QUIC_STREAM_DIR_MASK 2
169 static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(QUIC_STREAM *s)
171 return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
174 static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(QUIC_STREAM *s)
176 return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
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.
185 * stream_id must be a valid value. Returns NULL if a stream already exists
188 QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
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.
196 void ossl_quic_stream_map_release(QUIC_STREAM_MAP *qsm, QUIC_STREAM *stream);
199 * Calls visit_cb() for each stream in the map. visit_cb_arg is an opaque
200 * argument which is passed through.
202 void ossl_quic_stream_map_visit(QUIC_STREAM_MAP *qsm,
203 void (*visit_cb)(QUIC_STREAM *stream, void *arg),
207 * Retrieves a stream by stream ID. Returns NULL if it does not exist.
209 QUIC_STREAM *ossl_quic_stream_map_get_by_id(QUIC_STREAM_MAP *qsm,
213 * Marks the given stream as active or inactive based on its state. Idempotent.
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
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.
223 void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
226 * Sets the RR stepping value, n. The RR rotation will be advanced every n
227 * packets. The default value is 1.
229 void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
232 * QUIC Stream Iterator
233 * ====================
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.
242 * Suppose there are three active streams and the configured stepping is n:
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]
249 typedef struct quic_stream_iter_st {
250 QUIC_STREAM_MAP *qsm;
251 QUIC_STREAM *first_stream, *stream;
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.
259 void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm,
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.
267 void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it);