File: quic_rcidm.h

package info (click to toggle)
openssl 3.6.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 147,036 kB
  • sloc: ansic: 652,495; perl: 247,867; asm: 6,332; sh: 1,681; pascal: 997; python: 648; makefile: 551; lisp: 35; ruby: 16; cpp: 10; sed: 6
file content (185 lines) | stat: -rw-r--r-- 6,557 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#ifndef OSSL_INTERNAL_QUIC_RCIDM_H
#define OSSL_INTERNAL_QUIC_RCIDM_H
#pragma once

#include "internal/e_os.h"
#include "internal/time.h"
#include "internal/quic_types.h"
#include "internal/quic_wire.h"

#ifndef OPENSSL_NO_QUIC

/*
 * QUIC Remote Connection ID Manager
 * =================================
 *
 * This manages connection IDs for the TX side. The RCIDM tracks remote CIDs
 * (RCIDs) which a peer has issued to us and which we can use as the DCID of
 * packets we transmit. It is entirely separate from the LCIDM, which handles
 * routing received packets by their DCIDs.
 *
 * RCIDs fall into four categories:
 *
 *   1. A client's Initial ODCID                        (0..1)
 *   2. A peer's Initial SCID                           (1)
 *   3. A server's Retry SCID                           (0..1)
 *   4. A CID issued via a NEW_CONNECTION_ID frame      (n)
 *
 * Unlike a LCIDM, which is per port, a RCIDM is per connection, as there is no
 * need for routing of outgoing packets.
 */
typedef struct quic_rcidm_st QUIC_RCIDM;

/*
 * Creates a new RCIDM. Returns NULL on failure.
 *
 * For a client, initial_odcid is the client's Initial ODCID.
 * For a server, initial_odcid is NULL.
 */
QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);

/* Frees a RCIDM. */
void ossl_quic_rcidm_free(QUIC_RCIDM *rcidm);

/*
 * CID Events
 * ==========
 */

/*
 * To be called by a client when a server responds to the first Initial packet
 * sent with its own Initial packet with its own SCID; or to be called by a
 * server when we first get an Initial packet from a client with the client's
 * supplied SCID. The added RCID implicitly has a sequence number of 0.
 *
 * We immediately switch to using this SCID as our preferred RCID. This SCID
 * must be enrolled using this function. May only be called once.
 */
int ossl_quic_rcidm_add_from_initial(QUIC_RCIDM *rcidm,
    const QUIC_CONN_ID *rcid);

/*
 * To be called by a client when a server responds to the first Initial packet
 * sent with a Retry packet with its own SCID (the "Retry ODCID"). We
 * immediately switch to using this SCID as our preferred RCID when conducting
 * the retry. This SCID must be enrolled using this function. May only be called
 * once. The added RCID has no sequence number associated with it as it is
 * essentially a new ODCID (hereafter a Retry ODCID).
 *
 * Not for server use.
 */
int ossl_quic_rcidm_add_from_server_retry(QUIC_RCIDM *rcidm,
    const QUIC_CONN_ID *retry_odcid);

/*
 * Processes an incoming NEW_CONN_ID frame, recording the new CID as a potential
 * RCID. The RCIDM retirement mechanism is ratcheted according to the
 * ncid->retire_prior_to field. The stateless_reset field is ignored; the caller
 * is responsible for handling it separately.
 */
int ossl_quic_rcidm_add_from_ncid(QUIC_RCIDM *rcidm,
    const OSSL_QUIC_FRAME_NEW_CONN_ID *ncid);

/*
 * Other Events
 * ============
 */

/*
 * Notifies the RCIDM that the handshake for a connection is complete.
 * Should only be called once; further calls are ignored.
 *
 * This may influence the RCIDM's RCID change policy.
 */
void ossl_quic_rcidm_on_handshake_complete(QUIC_RCIDM *rcidm);

/*
 * Notifies the RCIDM that one or more packets have been sent.
 *
 * This may influence the RCIDM's RCID change policy.
 */
void ossl_quic_rcidm_on_packet_sent(QUIC_RCIDM *rcidm, uint64_t num_packets);

/*
 * Manually request switching to a new RCID as soon as possible.
 */
void ossl_quic_rcidm_request_roll(QUIC_RCIDM *rcidm);

/*
 * Queries
 * =======
 */

/*
 * The RCIDM decides when it will never use a given RCID again. When it does
 * this, it outputs the sequence number of that RCID using this function, which
 * pops from a logical queue of retired RCIDs. The caller is responsible
 * for polling this function and generating Retire CID frames from the result.
 *
 * If nothing needs doing and the queue is empty, this function returns 0. If
 * there is an RCID which needs retiring, the sequence number of that RCID is
 * written to *seq_num (if seq_num is non-NULL) and this function returns 1. The
 * queue entry is popped (and the caller is thus assumed to have taken
 * responsibility for transmitting the necessary Retire CID frame).
 *
 * Note that the caller should not transmit a Retire CID frame immediately as
 * packets using the RCID may still be in flight. The caller must determine an
 * appropriate delay using knowledge of network conditions (RTT, etc.) which is
 * outside the scope of the RCIDM. The caller is responsible for implementing
 * this delay based on the last time a packet was transmitted using the RCID
 * being retired.
 */
int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);

/*
 * Like ossl_quic_rcidm_pop_retire_seq_num, but does not pop the item from the
 * queue. If this call succeeds, the next call to
 * ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
 * number.
 */
int ossl_quic_rcidm_peek_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);

/*
 * Writes the DCID preferred for a newly transmitted packet at this time to
 * *tx_dcid. This function should be called to determine what DCID to use when
 * transmitting a packet to the peer. The RCIDM may implement arbitrary policy
 * to decide when to change the preferred RCID.
 *
 * Returns 1 on success and 0 on failure.
 */
int ossl_quic_rcidm_get_preferred_tx_dcid(QUIC_RCIDM *rcidm,
    QUIC_CONN_ID *tx_dcid);

/*
 * Returns 1 if the value output by ossl_quic_rcidm_get_preferred_tx_dcid() has
 * changed since the last call to this function with clear set. If clear is set,
 * clears the changed flag. Returns the old value of the changed flag.
 */
int ossl_quic_rcidm_get_preferred_tx_dcid_changed(QUIC_RCIDM *rcidm,
    int clear);

/*
 * Returns the number of active numbered RCIDs we have. Note that this includes
 * RCIDs on the retir*ing* queue accessed via
 * ossl_quic_rcidm_pop_retire_seq_num() as these are still active until actually
 * retired.
 */
size_t ossl_quic_rcidm_get_num_active(const QUIC_RCIDM *rcidm);

/*
 * Returns the number of retir*ing* numbered RCIDs we have.
 */
size_t ossl_quic_rcidm_get_num_retiring(const QUIC_RCIDM *rcidm);

#endif

#endif