1 | /*
|
---|
2 | * Copyright 2023-2024 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_RCIDM_H
|
---|
11 | # define OSSL_INTERNAL_QUIC_RCIDM_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_wire.h"
|
---|
18 |
|
---|
19 | # ifndef OPENSSL_NO_QUIC
|
---|
20 |
|
---|
21 | /*
|
---|
22 | * QUIC Remote Connection ID Manager
|
---|
23 | * =================================
|
---|
24 | *
|
---|
25 | * This manages connection IDs for the TX side. The RCIDM tracks remote CIDs
|
---|
26 | * (RCIDs) which a peer has issued to us and which we can use as the DCID of
|
---|
27 | * packets we transmit. It is entirely separate from the LCIDM, which handles
|
---|
28 | * routing received packets by their DCIDs.
|
---|
29 | *
|
---|
30 | * RCIDs fall into four categories:
|
---|
31 | *
|
---|
32 | * 1. A client's Initial ODCID (0..1)
|
---|
33 | * 2. A peer's Initial SCID (1)
|
---|
34 | * 3. A server's Retry SCID (0..1)
|
---|
35 | * 4. A CID issued via a NEW_CONNECTION_ID frame (n)
|
---|
36 | *
|
---|
37 | * Unlike a LCIDM, which is per port, a RCIDM is per connection, as there is no
|
---|
38 | * need for routing of outgoing packets.
|
---|
39 | */
|
---|
40 | typedef struct quic_rcidm_st QUIC_RCIDM;
|
---|
41 |
|
---|
42 | /*
|
---|
43 | * Creates a new RCIDM. Returns NULL on failure.
|
---|
44 | *
|
---|
45 | * For a client, initial_odcid is the client's Initial ODCID.
|
---|
46 | * For a server, initial_odcid is NULL.
|
---|
47 | */
|
---|
48 | QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);
|
---|
49 |
|
---|
50 | /* Frees a RCIDM. */
|
---|
51 | void ossl_quic_rcidm_free(QUIC_RCIDM *rcidm);
|
---|
52 |
|
---|
53 | /*
|
---|
54 | * CID Events
|
---|
55 | * ==========
|
---|
56 | */
|
---|
57 |
|
---|
58 | /*
|
---|
59 | * To be called by a client when a server responds to the first Initial packet
|
---|
60 | * sent with its own Initial packet with its own SCID; or to be called by a
|
---|
61 | * server when we first get an Initial packet from a client with the client's
|
---|
62 | * supplied SCID. The added RCID implicitly has a sequence number of 0.
|
---|
63 | *
|
---|
64 | * We immediately switch to using this SCID as our preferred RCID. This SCID
|
---|
65 | * must be enrolled using this function. May only be called once.
|
---|
66 | */
|
---|
67 | int ossl_quic_rcidm_add_from_initial(QUIC_RCIDM *rcidm,
|
---|
68 | const QUIC_CONN_ID *rcid);
|
---|
69 |
|
---|
70 | /*
|
---|
71 | * To be called by a client when a server responds to the first Initial packet
|
---|
72 | * sent with a Retry packet with its own SCID (the "Retry ODCID"). We
|
---|
73 | * immediately switch to using this SCID as our preferred RCID when conducting
|
---|
74 | * the retry. This SCID must be enrolled using this function. May only be called
|
---|
75 | * once. The added RCID has no sequence number associated with it as it is
|
---|
76 | * essentially a new ODCID (hereafter a Retry ODCID).
|
---|
77 | *
|
---|
78 | * Not for server use.
|
---|
79 | */
|
---|
80 | int ossl_quic_rcidm_add_from_server_retry(QUIC_RCIDM *rcidm,
|
---|
81 | const QUIC_CONN_ID *retry_odcid);
|
---|
82 |
|
---|
83 | /*
|
---|
84 | * Processes an incoming NEW_CONN_ID frame, recording the new CID as a potential
|
---|
85 | * RCID. The RCIDM retirement mechanism is ratcheted according to the
|
---|
86 | * ncid->retire_prior_to field. The stateless_reset field is ignored; the caller
|
---|
87 | * is responsible for handling it separately.
|
---|
88 | */
|
---|
89 | int ossl_quic_rcidm_add_from_ncid(QUIC_RCIDM *rcidm,
|
---|
90 | const OSSL_QUIC_FRAME_NEW_CONN_ID *ncid);
|
---|
91 |
|
---|
92 | /*
|
---|
93 | * Other Events
|
---|
94 | * ============
|
---|
95 | */
|
---|
96 |
|
---|
97 | /*
|
---|
98 | * Notifies the RCIDM that the handshake for a connection is complete.
|
---|
99 | * Should only be called once; further calls are ignored.
|
---|
100 | *
|
---|
101 | * This may influence the RCIDM's RCID change policy.
|
---|
102 | */
|
---|
103 | void ossl_quic_rcidm_on_handshake_complete(QUIC_RCIDM *rcidm);
|
---|
104 |
|
---|
105 | /*
|
---|
106 | * Notifies the RCIDM that one or more packets have been sent.
|
---|
107 | *
|
---|
108 | * This may influence the RCIDM's RCID change policy.
|
---|
109 | */
|
---|
110 | void ossl_quic_rcidm_on_packet_sent(QUIC_RCIDM *rcidm, uint64_t num_packets);
|
---|
111 |
|
---|
112 | /*
|
---|
113 | * Manually request switching to a new RCID as soon as possible.
|
---|
114 | */
|
---|
115 | void ossl_quic_rcidm_request_roll(QUIC_RCIDM *rcidm);
|
---|
116 |
|
---|
117 | /*
|
---|
118 | * Queries
|
---|
119 | * =======
|
---|
120 | */
|
---|
121 |
|
---|
122 | /*
|
---|
123 | * The RCIDM decides when it will never use a given RCID again. When it does
|
---|
124 | * this, it outputs the sequence number of that RCID using this function, which
|
---|
125 | * pops from a logical queue of retired RCIDs. The caller is responsible
|
---|
126 | * for polling this function and generating Retire CID frames from the result.
|
---|
127 | *
|
---|
128 | * If nothing needs doing and the queue is empty, this function returns 0. If
|
---|
129 | * there is an RCID which needs retiring, the sequence number of that RCID is
|
---|
130 | * written to *seq_num (if seq_num is non-NULL) and this function returns 1. The
|
---|
131 | * queue entry is popped (and the caller is thus assumed to have taken
|
---|
132 | * responsibility for transmitting the necessary Retire CID frame).
|
---|
133 | *
|
---|
134 | * Note that the caller should not transmit a Retire CID frame immediately as
|
---|
135 | * packets using the RCID may still be in flight. The caller must determine an
|
---|
136 | * appropriate delay using knowledge of network conditions (RTT, etc.) which is
|
---|
137 | * outside the scope of the RCIDM. The caller is responsible for implementing
|
---|
138 | * this delay based on the last time a packet was transmitted using the RCID
|
---|
139 | * being retired.
|
---|
140 | */
|
---|
141 | int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
|
---|
142 |
|
---|
143 | /*
|
---|
144 | * Like ossl_quic_rcidm_pop_retire_seq_num, but does not pop the item from the
|
---|
145 | * queue. If this call succeeds, the next call to
|
---|
146 | * ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
|
---|
147 | * number.
|
---|
148 | */
|
---|
149 | int ossl_quic_rcidm_peek_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
|
---|
150 |
|
---|
151 | /*
|
---|
152 | * Writes the DCID preferred for a newly transmitted packet at this time to
|
---|
153 | * *tx_dcid. This function should be called to determine what DCID to use when
|
---|
154 | * transmitting a packet to the peer. The RCIDM may implement arbitrary policy
|
---|
155 | * to decide when to change the preferred RCID.
|
---|
156 | *
|
---|
157 | * Returns 1 on success and 0 on failure.
|
---|
158 | */
|
---|
159 | int ossl_quic_rcidm_get_preferred_tx_dcid(QUIC_RCIDM *rcidm,
|
---|
160 | QUIC_CONN_ID *tx_dcid);
|
---|
161 |
|
---|
162 | /*
|
---|
163 | * Returns 1 if the value output by ossl_quic_rcidm_get_preferred_tx_dcid() has
|
---|
164 | * changed since the last call to this function with clear set. If clear is set,
|
---|
165 | * clears the changed flag. Returns the old value of the changed flag.
|
---|
166 | */
|
---|
167 | int ossl_quic_rcidm_get_preferred_tx_dcid_changed(QUIC_RCIDM *rcidm,
|
---|
168 | int clear);
|
---|
169 |
|
---|
170 | /*
|
---|
171 | * Returns the number of active numbered RCIDs we have. Note that this includes
|
---|
172 | * RCIDs on the retir*ing* queue accessed via
|
---|
173 | * ossl_quic_rcidm_pop_retire_seq_num() as these are still active until actually
|
---|
174 | * retired.
|
---|
175 | */
|
---|
176 | size_t ossl_quic_rcidm_get_num_active(const QUIC_RCIDM *rcidm);
|
---|
177 |
|
---|
178 | /*
|
---|
179 | * Returns the number of retir*ing* numbered RCIDs we have.
|
---|
180 | */
|
---|
181 | size_t ossl_quic_rcidm_get_num_retiring(const QUIC_RCIDM *rcidm);
|
---|
182 |
|
---|
183 | # endif
|
---|
184 |
|
---|
185 | #endif
|
---|