1 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4 // option. This file may not be copied, modified, or distributed
5 // except according to those terms.
6 
7 // Representation and management of connection IDs.
8 
9 use crate::frame::FRAME_TYPE_NEW_CONNECTION_ID;
10 use crate::packet::PacketBuilder;
11 use crate::recovery::RecoveryToken;
12 use crate::stats::FrameStats;
13 use crate::{Error, Res};
14 
15 use neqo_common::{hex, hex_with_len, qinfo, Decoder, Encoder};
16 use neqo_crypto::random;
17 
18 use smallvec::SmallVec;
19 use std::borrow::Borrow;
20 use std::cell::{Ref, RefCell};
21 use std::cmp::max;
22 use std::cmp::min;
23 use std::convert::AsRef;
24 use std::convert::TryFrom;
25 use std::ops::Deref;
26 use std::rc::Rc;
27 
28 pub const MAX_CONNECTION_ID_LEN: usize = 20;
29 pub const LOCAL_ACTIVE_CID_LIMIT: usize = 8;
30 pub const CONNECTION_ID_SEQNO_INITIAL: u64 = 0;
31 pub const CONNECTION_ID_SEQNO_PREFERRED: u64 = 1;
32 /// A special value.  See `ConnectionIdManager::add_odcid`.
33 const CONNECTION_ID_SEQNO_ODCID: u64 = u64::MAX;
34 /// A special value.  See `ConnectionIdEntry::empty_remote`.
35 const CONNECTION_ID_SEQNO_EMPTY: u64 = u64::MAX - 1;
36 
37 #[derive(Clone, Default, Eq, Hash, PartialEq)]
38 pub struct ConnectionId {
39     pub(crate) cid: SmallVec<[u8; MAX_CONNECTION_ID_LEN]>,
40 }
41 
42 impl ConnectionId {
generate(len: usize) -> Self43     pub fn generate(len: usize) -> Self {
44         assert!(matches!(len, 0..=MAX_CONNECTION_ID_LEN));
45         Self::from(random(len))
46     }
47 
48     // Apply a wee bit of greasing here in picking a length between 8 and 20 bytes long.
generate_initial() -> Self49     pub fn generate_initial() -> Self {
50         let v = random(1);
51         // Bias selection toward picking 8 (>50% of the time).
52         let len: usize = max(8, 5 + (v[0] & (v[0] >> 4))).into();
53         Self::generate(len)
54     }
55 
as_cid_ref(&self) -> ConnectionIdRef56     pub fn as_cid_ref(&self) -> ConnectionIdRef {
57         ConnectionIdRef::from(&self.cid[..])
58     }
59 }
60 
61 impl AsRef<[u8]> for ConnectionId {
as_ref(&self) -> &[u8]62     fn as_ref(&self) -> &[u8] {
63         self.borrow()
64     }
65 }
66 
67 impl Borrow<[u8]> for ConnectionId {
borrow(&self) -> &[u8]68     fn borrow(&self) -> &[u8] {
69         &self.cid
70     }
71 }
72 
73 impl From<SmallVec<[u8; MAX_CONNECTION_ID_LEN]>> for ConnectionId {
from(cid: SmallVec<[u8; MAX_CONNECTION_ID_LEN]>) -> Self74     fn from(cid: SmallVec<[u8; MAX_CONNECTION_ID_LEN]>) -> Self {
75         Self { cid }
76     }
77 }
78 
79 impl From<Vec<u8>> for ConnectionId {
from(cid: Vec<u8>) -> Self80     fn from(cid: Vec<u8>) -> Self {
81         Self::from(SmallVec::from(cid))
82     }
83 }
84 
85 impl<T: AsRef<[u8]> + ?Sized> From<&T> for ConnectionId {
from(buf: &T) -> Self86     fn from(buf: &T) -> Self {
87         Self::from(SmallVec::from(buf.as_ref()))
88     }
89 }
90 
91 impl<'a> From<&ConnectionIdRef<'a>> for ConnectionId {
from(cidref: &ConnectionIdRef<'a>) -> Self92     fn from(cidref: &ConnectionIdRef<'a>) -> Self {
93         Self::from(SmallVec::from(cidref.cid))
94     }
95 }
96 
97 impl std::ops::Deref for ConnectionId {
98     type Target = [u8];
99 
deref(&self) -> &Self::Target100     fn deref(&self) -> &Self::Target {
101         &self.cid
102     }
103 }
104 
105 impl ::std::fmt::Debug for ConnectionId {
fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result106     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
107         write!(f, "CID {}", hex_with_len(&self.cid))
108     }
109 }
110 
111 impl ::std::fmt::Display for ConnectionId {
fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result112     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
113         write!(f, "{}", hex(&self.cid))
114     }
115 }
116 
117 impl<'a> PartialEq<ConnectionIdRef<'a>> for ConnectionId {
eq(&self, other: &ConnectionIdRef<'a>) -> bool118     fn eq(&self, other: &ConnectionIdRef<'a>) -> bool {
119         &self.cid[..] == other.cid
120     }
121 }
122 
123 #[derive(Hash, Eq, PartialEq)]
124 pub struct ConnectionIdRef<'a> {
125     cid: &'a [u8],
126 }
127 
128 impl<'a> ::std::fmt::Debug for ConnectionIdRef<'a> {
fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result129     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
130         write!(f, "CID {}", hex_with_len(&self.cid))
131     }
132 }
133 
134 impl<'a> ::std::fmt::Display for ConnectionIdRef<'a> {
fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result135     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
136         write!(f, "{}", hex(&self.cid))
137     }
138 }
139 
140 impl<'a, T: AsRef<[u8]> + ?Sized> From<&'a T> for ConnectionIdRef<'a> {
from(cid: &'a T) -> Self141     fn from(cid: &'a T) -> Self {
142         Self { cid: cid.as_ref() }
143     }
144 }
145 
146 impl<'a> std::ops::Deref for ConnectionIdRef<'a> {
147     type Target = [u8];
148 
deref(&self) -> &Self::Target149     fn deref(&self) -> &Self::Target {
150         &self.cid
151     }
152 }
153 
154 impl<'a> PartialEq<ConnectionId> for ConnectionIdRef<'a> {
eq(&self, other: &ConnectionId) -> bool155     fn eq(&self, other: &ConnectionId) -> bool {
156         self.cid == &other.cid[..]
157     }
158 }
159 
160 pub trait ConnectionIdDecoder {
161     /// Decodes a connection ID from the provided decoder.
decode_cid<'a>(&self, dec: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>>162     fn decode_cid<'a>(&self, dec: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>>;
163 }
164 
165 pub trait ConnectionIdGenerator: ConnectionIdDecoder {
166     /// Generates a connection ID.  This can return `None` if the generator
167     /// is exhausted.
generate_cid(&mut self) -> Option<ConnectionId>168     fn generate_cid(&mut self) -> Option<ConnectionId>;
169     /// Indicates whether the connection IDs are zero-length.
170     /// If this returns true, `generate_cid` must always produce an empty value
171     /// and never `None`.
172     /// If this returns false, `generate_cid` must never produce an empty value,
173     /// though it can return `None`.
174     ///
175     /// You should not need to implement this: if you want zero-length connection IDs,
176     /// use `EmptyConnectionIdGenerator` instead.
generates_empty_cids(&self) -> bool177     fn generates_empty_cids(&self) -> bool {
178         false
179     }
as_decoder(&self) -> &dyn ConnectionIdDecoder180     fn as_decoder(&self) -> &dyn ConnectionIdDecoder;
181 }
182 
183 /// An `EmptyConnectionIdGenerator` generates empty connection IDs.
184 #[derive(Default)]
185 pub struct EmptyConnectionIdGenerator {}
186 
187 impl ConnectionIdDecoder for EmptyConnectionIdGenerator {
decode_cid<'a>(&self, _: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>>188     fn decode_cid<'a>(&self, _: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>> {
189         Some(ConnectionIdRef::from(&[]))
190     }
191 }
192 
193 impl ConnectionIdGenerator for EmptyConnectionIdGenerator {
generate_cid(&mut self) -> Option<ConnectionId>194     fn generate_cid(&mut self) -> Option<ConnectionId> {
195         Some(ConnectionId::from(&[]))
196     }
as_decoder(&self) -> &dyn ConnectionIdDecoder197     fn as_decoder(&self) -> &dyn ConnectionIdDecoder {
198         self
199     }
generates_empty_cids(&self) -> bool200     fn generates_empty_cids(&self) -> bool {
201         true
202     }
203 }
204 
205 /// An RandomConnectionIdGenerator produces connection IDs of
206 /// a fixed length and random content.  No effort is made to
207 /// prevent collisions.
208 pub struct RandomConnectionIdGenerator {
209     len: usize,
210 }
211 
212 impl RandomConnectionIdGenerator {
new(len: usize) -> Self213     pub fn new(len: usize) -> Self {
214         Self { len }
215     }
216 }
217 
218 impl ConnectionIdDecoder for RandomConnectionIdGenerator {
decode_cid<'a>(&self, dec: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>>219     fn decode_cid<'a>(&self, dec: &mut Decoder<'a>) -> Option<ConnectionIdRef<'a>> {
220         dec.decode(self.len).map(ConnectionIdRef::from)
221     }
222 }
223 
224 impl ConnectionIdGenerator for RandomConnectionIdGenerator {
generate_cid(&mut self) -> Option<ConnectionId>225     fn generate_cid(&mut self) -> Option<ConnectionId> {
226         Some(ConnectionId::from(&random(self.len)))
227     }
228 
as_decoder(&self) -> &dyn ConnectionIdDecoder229     fn as_decoder(&self) -> &dyn ConnectionIdDecoder {
230         self
231     }
232 
generates_empty_cids(&self) -> bool233     fn generates_empty_cids(&self) -> bool {
234         self.len == 0
235     }
236 }
237 
238 /// A single connection ID, as saved from NEW_CONNECTION_ID.
239 /// This is templated so that the connection ID entries from a peer can be
240 /// saved with a stateless reset token.  Local entries don't need that.
241 #[derive(Debug, PartialEq, Eq, Clone)]
242 pub struct ConnectionIdEntry<SRT: Clone + PartialEq> {
243     /// The sequence number.
244     seqno: u64,
245     /// The connection ID.
246     cid: ConnectionId,
247     /// The corresponding stateless reset token.
248     srt: SRT,
249 }
250 
251 impl ConnectionIdEntry<[u8; 16]> {
252     /// Create a random stateless reset token so that it is hard to guess the correct
253     /// value and reset the connection.
random_srt() -> [u8; 16]254     fn random_srt() -> [u8; 16] {
255         <[u8; 16]>::try_from(&random(16)[..]).unwrap()
256     }
257 
258     /// Create the first entry, which won't have a stateless reset token.
initial_remote(cid: ConnectionId) -> Self259     pub fn initial_remote(cid: ConnectionId) -> Self {
260         Self::new(CONNECTION_ID_SEQNO_INITIAL, cid, Self::random_srt())
261     }
262 
263     /// Create an empty for when the peer chooses empty connection IDs.
264     /// This uses a special sequence number just because it can.
empty_remote() -> Self265     pub fn empty_remote() -> Self {
266         Self::new(
267             CONNECTION_ID_SEQNO_EMPTY,
268             ConnectionId::from(&[]),
269             Self::random_srt(),
270         )
271     }
272 
token_equal(a: &[u8; 16], b: &[u8; 16]) -> bool273     fn token_equal(a: &[u8; 16], b: &[u8; 16]) -> bool {
274         // rustc might decide to optimize this and make this non-constant-time
275         // with respect to `t`, but it doesn't appear to currently.
276         let mut c = 0;
277         for (&a, &b) in a.iter().zip(b) {
278             c |= a ^ b;
279         }
280         c == 0
281     }
282 
283     /// Determine whether this is a valid stateless reset.
is_stateless_reset(&self, token: &[u8; 16]) -> bool284     pub fn is_stateless_reset(&self, token: &[u8; 16]) -> bool {
285         // A sequence number of 2^62 or more has no corresponding stateless reset token.
286         (self.seqno < (1 << 62)) && Self::token_equal(&self.srt, token)
287     }
288 
289     /// Return true if the two contain any equal parts.
any_part_equal(&self, other: &Self) -> bool290     fn any_part_equal(&self, other: &Self) -> bool {
291         self.seqno == other.seqno || self.cid == other.cid || self.srt == other.srt
292     }
293 
294     /// The sequence number of this entry.
sequence_number(&self) -> u64295     pub fn sequence_number(&self) -> u64 {
296         self.seqno
297     }
298 }
299 
300 impl ConnectionIdEntry<()> {
301     /// Create an initial entry.
initial_local(cid: ConnectionId) -> Self302     pub fn initial_local(cid: ConnectionId) -> Self {
303         Self::new(0, cid, ())
304     }
305 }
306 
307 impl<SRT: Clone + PartialEq> ConnectionIdEntry<SRT> {
new(seqno: u64, cid: ConnectionId, srt: SRT) -> Self308     pub fn new(seqno: u64, cid: ConnectionId, srt: SRT) -> Self {
309         Self { seqno, cid, srt }
310     }
311 
312     /// Update the stateless reset token.  This panics if the sequence number is non-zero.
set_stateless_reset_token(&mut self, srt: SRT)313     pub fn set_stateless_reset_token(&mut self, srt: SRT) {
314         assert_eq!(self.seqno, CONNECTION_ID_SEQNO_INITIAL);
315         self.srt = srt;
316     }
317 
318     /// Replace the connection ID.  This panics if the sequence number is non-zero.
update_cid(&mut self, cid: ConnectionId)319     pub fn update_cid(&mut self, cid: ConnectionId) {
320         assert_eq!(self.seqno, CONNECTION_ID_SEQNO_INITIAL);
321         self.cid = cid;
322     }
323 
connection_id(&self) -> &ConnectionId324     pub fn connection_id(&self) -> &ConnectionId {
325         &self.cid
326     }
327 }
328 
329 pub type RemoteConnectionIdEntry = ConnectionIdEntry<[u8; 16]>;
330 
331 /// A collection of connection IDs that are indexed by a sequence number.
332 /// Used to store connection IDs that are provided by a peer.
333 #[derive(Debug, Default)]
334 pub struct ConnectionIdStore<SRT: Clone + PartialEq> {
335     cids: SmallVec<[ConnectionIdEntry<SRT>; 8]>,
336     retired: Vec<[ConnectionIdEntry<SRT>; 8]>,
337 }
338 
339 impl<SRT: Clone + PartialEq> ConnectionIdStore<SRT> {
retire(&mut self, seqno: u64)340     pub fn retire(&mut self, seqno: u64) {
341         self.cids.retain(|c| c.seqno != seqno);
342     }
343 
contains(&self, cid: &ConnectionIdRef) -> bool344     pub fn contains(&self, cid: &ConnectionIdRef) -> bool {
345         self.cids.iter().any(|c| &c.cid == cid)
346     }
347 
next(&mut self) -> Option<ConnectionIdEntry<SRT>>348     pub fn next(&mut self) -> Option<ConnectionIdEntry<SRT>> {
349         if self.cids.is_empty() {
350             None
351         } else {
352             Some(self.cids.remove(0))
353         }
354     }
355 
len(&self) -> usize356     pub fn len(&self) -> usize {
357         self.cids.len()
358     }
359 }
360 
361 impl ConnectionIdStore<[u8; 16]> {
add_remote(&mut self, entry: ConnectionIdEntry<[u8; 16]>) -> Res<()>362     pub fn add_remote(&mut self, entry: ConnectionIdEntry<[u8; 16]>) -> Res<()> {
363         // It's OK if this perfectly matches an existing entry.
364         if self.cids.iter().any(|c| c == &entry) {
365             return Ok(());
366         }
367         // It's not OK if any individual piece matches though.
368         if self.cids.iter().any(|c| c.any_part_equal(&entry)) {
369             qinfo!("ConnectionIdStore found reused part in NEW_CONNECTION_ID");
370             return Err(Error::ProtocolViolation);
371         }
372 
373         // Insert in order so that we use them in order where possible.
374         if let Err(idx) = self.cids.binary_search_by_key(&entry.seqno, |e| e.seqno) {
375             self.cids.insert(idx, entry);
376             Ok(())
377         } else {
378             Err(Error::ProtocolViolation)
379         }
380     }
381 
382     // Retire connection IDs and return the sequence numbers of those that were retired.
retire_prior_to(&mut self, retire_prior: u64) -> Vec<u64>383     pub fn retire_prior_to(&mut self, retire_prior: u64) -> Vec<u64> {
384         let mut retired = Vec::new();
385         self.cids.retain(|e| {
386             if e.seqno < retire_prior {
387                 retired.push(e.seqno);
388                 false
389             } else {
390                 true
391             }
392         });
393         retired
394     }
395 }
396 
397 impl ConnectionIdStore<()> {
add_local(&mut self, entry: ConnectionIdEntry<()>)398     fn add_local(&mut self, entry: ConnectionIdEntry<()>) {
399         self.cids.push(entry);
400     }
401 }
402 
403 pub struct ConnectionIdDecoderRef<'a> {
404     generator: Ref<'a, dyn ConnectionIdGenerator>,
405 }
406 
407 // Ideally this would be an implementation of `Deref`, but it doesn't
408 // seem to be possible to convince the compiler to build anything useful.
409 impl<'a: 'b, 'b> ConnectionIdDecoderRef<'a> {
as_ref(&'a self) -> &'b dyn ConnectionIdDecoder410     pub fn as_ref(&'a self) -> &'b dyn ConnectionIdDecoder {
411         self.generator.as_decoder()
412     }
413 }
414 
415 /// A connection ID manager looks after the generation of connection IDs,
416 /// the set of connection IDs that are valid for the connection, and the
417 /// generation of `NEW_CONNECTION_ID` frames.
418 pub struct ConnectionIdManager {
419     /// The `ConnectionIdGenerator` instance that is used to create connection IDs.
420     generator: Rc<RefCell<dyn ConnectionIdGenerator>>,
421     /// The connection IDs that we will accept.
422     /// This includes any we advertise in `NEW_CONNECTION_ID` that haven't been bound to a path yet.
423     /// During the handshake at the server, it also includes the randomized DCID pick by the client.
424     connection_ids: ConnectionIdStore<()>,
425     /// The maximum number of connection IDs this will accept.  This is at least 2 and won't
426     /// be more than `LOCAL_ACTIVE_CID_LIMIT`.
427     limit: usize,
428     /// The next sequence number that will be used for sending `NEW_CONNECTION_ID` frames.
429     next_seqno: u64,
430     /// Outstanding, but lost NEW_CONNECTION_ID frames will be stored here.
431     lost_new_connection_id: Vec<ConnectionIdEntry<[u8; 16]>>,
432 }
433 
434 impl ConnectionIdManager {
new(generator: Rc<RefCell<dyn ConnectionIdGenerator>>, initial: ConnectionId) -> Self435     pub fn new(generator: Rc<RefCell<dyn ConnectionIdGenerator>>, initial: ConnectionId) -> Self {
436         let mut connection_ids = ConnectionIdStore::default();
437         connection_ids.add_local(ConnectionIdEntry::initial_local(initial));
438         Self {
439             generator,
440             connection_ids,
441             // A note about initializing the limit to 2.
442             // For a server, the number of connection IDs that are tracked at the point that
443             // it is first possible to send `NEW_CONNECTION_ID` is 2.  One is the client-generated
444             // destination connection (stored with a sequence number of `HANDSHAKE_SEQNO`); the
445             // other being the handshake value (seqno 0).  As a result, `NEW_CONNECTION_ID`
446             // won't be sent until until after the handshake completes, because this initial
447             // value remains until the connection completes and transport parameters are handled.
448             limit: 2,
449             next_seqno: 2, // A different value.
450             lost_new_connection_id: Vec::new(),
451         }
452     }
453 
decoder(&self) -> ConnectionIdDecoderRef454     pub fn decoder(&self) -> ConnectionIdDecoderRef {
455         ConnectionIdDecoderRef {
456             generator: self.generator.deref().borrow(),
457         }
458     }
459 
460     /// Generate a connection ID and stateless reset token for a preferred address.
preferred_address_cid(&mut self) -> Res<(ConnectionId, [u8; 16])>461     pub fn preferred_address_cid(&mut self) -> Res<(ConnectionId, [u8; 16])> {
462         if self.generator.deref().borrow().generates_empty_cids() {
463             return Err(Error::ConnectionIdsExhausted);
464         }
465         if let Some(cid) = self.generator.borrow_mut().generate_cid() {
466             assert_ne!(cid.len(), 0);
467             self.connection_ids.add_local(ConnectionIdEntry::new(
468                 CONNECTION_ID_SEQNO_PREFERRED,
469                 cid.clone(),
470                 (),
471             ));
472 
473             let srt = <[u8; 16]>::try_from(&random(16)[..]).unwrap();
474             Ok((cid, srt))
475         } else {
476             Err(Error::ConnectionIdsExhausted)
477         }
478     }
479 
is_valid(&self, cid: &ConnectionIdRef) -> bool480     pub fn is_valid(&self, cid: &ConnectionIdRef) -> bool {
481         self.connection_ids.contains(cid)
482     }
483 
retire(&mut self, seqno: u64)484     pub fn retire(&mut self, seqno: u64) {
485         // TODO(mt) - consider keeping connection IDs around for a short while.
486 
487         self.connection_ids.retire(seqno);
488         self.lost_new_connection_id.retain(|cid| cid.seqno != seqno);
489     }
490 
491     /// During the handshake, a server needs to regard the client's choice of destination
492     /// connection ID as valid.  This function saves it in the store in a special place.
add_odcid(&mut self, cid: ConnectionId)493     pub fn add_odcid(&mut self, cid: ConnectionId) {
494         let entry = ConnectionIdEntry::new(CONNECTION_ID_SEQNO_ODCID, cid, ());
495         self.connection_ids.add_local(entry);
496     }
497 
498     /// Stop treating the original destination connection ID as valid.
remove_odcid(&mut self)499     pub fn remove_odcid(&mut self) {
500         self.connection_ids.retire(CONNECTION_ID_SEQNO_ODCID);
501     }
502 
set_limit(&mut self, limit: u64)503     pub fn set_limit(&mut self, limit: u64) {
504         debug_assert!(limit >= 2);
505         self.limit = min(
506             LOCAL_ACTIVE_CID_LIMIT,
507             usize::try_from(limit).unwrap_or(LOCAL_ACTIVE_CID_LIMIT),
508         );
509     }
510 
write_entry( &mut self, entry: &ConnectionIdEntry<[u8; 16]>, builder: &mut PacketBuilder, stats: &mut FrameStats, ) -> Res<bool>511     fn write_entry(
512         &mut self,
513         entry: &ConnectionIdEntry<[u8; 16]>,
514         builder: &mut PacketBuilder,
515         stats: &mut FrameStats,
516     ) -> Res<bool> {
517         let len = 1 + Encoder::varint_len(entry.seqno) + 1 + 1 + entry.cid.len() + 16;
518         if builder.remaining() < len {
519             return Ok(false);
520         }
521 
522         builder.encode_varint(FRAME_TYPE_NEW_CONNECTION_ID);
523         builder.encode_varint(entry.seqno);
524         builder.encode_varint(0u64);
525         builder.encode_vec(1, &entry.cid);
526         builder.encode(&entry.srt);
527         if builder.len() > builder.limit() {
528             return Err(Error::InternalError(8));
529         }
530 
531         stats.new_connection_id += 1;
532         Ok(true)
533     }
534 
write_frames( &mut self, builder: &mut PacketBuilder, tokens: &mut Vec<RecoveryToken>, stats: &mut FrameStats, ) -> Res<()>535     pub fn write_frames(
536         &mut self,
537         builder: &mut PacketBuilder,
538         tokens: &mut Vec<RecoveryToken>,
539         stats: &mut FrameStats,
540     ) -> Res<()> {
541         if self.generator.deref().borrow().generates_empty_cids() {
542             debug_assert_eq!(self.generator.borrow_mut().generate_cid().unwrap().len(), 0);
543             return Ok(());
544         }
545 
546         while let Some(entry) = self.lost_new_connection_id.pop() {
547             if self.write_entry(&entry, builder, stats)? {
548                 tokens.push(RecoveryToken::NewConnectionId(entry));
549             } else {
550                 // This shouldn't happen often.
551                 self.lost_new_connection_id.push(entry);
552                 break;
553             }
554         }
555 
556         // Keep writing while we have fewer than the limit of active connection IDs
557         // and while there is room for more.  This uses the longest connection ID
558         // length to simplify (assuming Retire Prior To is just 1 byte).
559         while self.connection_ids.len() < self.limit && builder.remaining() >= 47 {
560             let maybe_cid = self.generator.borrow_mut().generate_cid();
561             if let Some(cid) = maybe_cid {
562                 assert_ne!(cid.len(), 0);
563                 // TODO: generate the stateless reset tokens from the connection ID and a key.
564                 let srt = <[u8; 16]>::try_from(&random(16)[..]).unwrap();
565 
566                 let seqno = self.next_seqno;
567                 self.next_seqno += 1;
568                 self.connection_ids
569                     .add_local(ConnectionIdEntry::new(seqno, cid.clone(), ()));
570 
571                 let entry = ConnectionIdEntry::new(seqno, cid, srt);
572                 debug_assert!(self.write_entry(&entry, builder, stats)?);
573                 tokens.push(RecoveryToken::NewConnectionId(entry));
574             }
575         }
576         Ok(())
577     }
578 
lost(&mut self, entry: &ConnectionIdEntry<[u8; 16]>)579     pub fn lost(&mut self, entry: &ConnectionIdEntry<[u8; 16]>) {
580         self.lost_new_connection_id.push(entry.clone());
581     }
582 
acked(&mut self, entry: &ConnectionIdEntry<[u8; 16]>)583     pub fn acked(&mut self, entry: &ConnectionIdEntry<[u8; 16]>) {
584         self.lost_new_connection_id
585             .retain(|e| e.seqno != entry.seqno);
586     }
587 }
588 
589 #[cfg(test)]
590 mod tests {
591     use super::*;
592     use test_fixture::fixture_init;
593 
594     #[test]
generate_initial_cid()595     fn generate_initial_cid() {
596         fixture_init();
597         for _ in 0..100 {
598             let cid = ConnectionId::generate_initial();
599             if !matches!(cid.len(), 8..=MAX_CONNECTION_ID_LEN) {
600                 panic!("connection ID {:?}", cid);
601             }
602         }
603     }
604 }
605