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 }
337 
338 impl<SRT: Clone + PartialEq> ConnectionIdStore<SRT> {
retire(&mut self, seqno: u64)339     pub fn retire(&mut self, seqno: u64) {
340         self.cids.retain(|c| c.seqno != seqno);
341     }
342 
contains(&self, cid: &ConnectionIdRef) -> bool343     pub fn contains(&self, cid: &ConnectionIdRef) -> bool {
344         self.cids.iter().any(|c| &c.cid == cid)
345     }
346 
next(&mut self) -> Option<ConnectionIdEntry<SRT>>347     pub fn next(&mut self) -> Option<ConnectionIdEntry<SRT>> {
348         if self.cids.is_empty() {
349             None
350         } else {
351             Some(self.cids.remove(0))
352         }
353     }
354 
len(&self) -> usize355     pub fn len(&self) -> usize {
356         self.cids.len()
357     }
358 }
359 
360 impl ConnectionIdStore<[u8; 16]> {
add_remote(&mut self, entry: ConnectionIdEntry<[u8; 16]>) -> Res<()>361     pub fn add_remote(&mut self, entry: ConnectionIdEntry<[u8; 16]>) -> Res<()> {
362         // It's OK if this perfectly matches an existing entry.
363         if self.cids.iter().any(|c| c == &entry) {
364             return Ok(());
365         }
366         // It's not OK if any individual piece matches though.
367         if self.cids.iter().any(|c| c.any_part_equal(&entry)) {
368             qinfo!("ConnectionIdStore found reused part in NEW_CONNECTION_ID");
369             return Err(Error::ProtocolViolation);
370         }
371 
372         // Insert in order so that we use them in order where possible.
373         if let Err(idx) = self.cids.binary_search_by_key(&entry.seqno, |e| e.seqno) {
374             self.cids.insert(idx, entry);
375             Ok(())
376         } else {
377             Err(Error::ProtocolViolation)
378         }
379     }
380 
381     // Retire connection IDs and return the sequence numbers of those that were retired.
retire_prior_to(&mut self, retire_prior: u64) -> Vec<u64>382     pub fn retire_prior_to(&mut self, retire_prior: u64) -> Vec<u64> {
383         let mut retired = Vec::new();
384         self.cids.retain(|e| {
385             if e.seqno < retire_prior {
386                 retired.push(e.seqno);
387                 false
388             } else {
389                 true
390             }
391         });
392         retired
393     }
394 }
395 
396 impl ConnectionIdStore<()> {
add_local(&mut self, entry: ConnectionIdEntry<()>)397     fn add_local(&mut self, entry: ConnectionIdEntry<()>) {
398         self.cids.push(entry);
399     }
400 }
401 
402 pub struct ConnectionIdDecoderRef<'a> {
403     generator: Ref<'a, dyn ConnectionIdGenerator>,
404 }
405 
406 // Ideally this would be an implementation of `Deref`, but it doesn't
407 // seem to be possible to convince the compiler to build anything useful.
408 impl<'a: 'b, 'b> ConnectionIdDecoderRef<'a> {
as_ref(&'a self) -> &'b dyn ConnectionIdDecoder409     pub fn as_ref(&'a self) -> &'b dyn ConnectionIdDecoder {
410         self.generator.as_decoder()
411     }
412 }
413 
414 /// A connection ID manager looks after the generation of connection IDs,
415 /// the set of connection IDs that are valid for the connection, and the
416 /// generation of `NEW_CONNECTION_ID` frames.
417 pub struct ConnectionIdManager {
418     /// The `ConnectionIdGenerator` instance that is used to create connection IDs.
419     generator: Rc<RefCell<dyn ConnectionIdGenerator>>,
420     /// The connection IDs that we will accept.
421     /// This includes any we advertise in `NEW_CONNECTION_ID` that haven't been bound to a path yet.
422     /// During the handshake at the server, it also includes the randomized DCID pick by the client.
423     connection_ids: ConnectionIdStore<()>,
424     /// The maximum number of connection IDs this will accept.  This is at least 2 and won't
425     /// be more than `LOCAL_ACTIVE_CID_LIMIT`.
426     limit: usize,
427     /// The next sequence number that will be used for sending `NEW_CONNECTION_ID` frames.
428     next_seqno: u64,
429     /// Outstanding, but lost NEW_CONNECTION_ID frames will be stored here.
430     lost_new_connection_id: Vec<ConnectionIdEntry<[u8; 16]>>,
431 }
432 
433 impl ConnectionIdManager {
new(generator: Rc<RefCell<dyn ConnectionIdGenerator>>, initial: ConnectionId) -> Self434     pub fn new(generator: Rc<RefCell<dyn ConnectionIdGenerator>>, initial: ConnectionId) -> Self {
435         let mut connection_ids = ConnectionIdStore::default();
436         connection_ids.add_local(ConnectionIdEntry::initial_local(initial));
437         Self {
438             generator,
439             connection_ids,
440             // A note about initializing the limit to 2.
441             // For a server, the number of connection IDs that are tracked at the point that
442             // it is first possible to send `NEW_CONNECTION_ID` is 2.  One is the client-generated
443             // destination connection (stored with a sequence number of `HANDSHAKE_SEQNO`); the
444             // other being the handshake value (seqno 0).  As a result, `NEW_CONNECTION_ID`
445             // won't be sent until until after the handshake completes, because this initial
446             // value remains until the connection completes and transport parameters are handled.
447             limit: 2,
448             next_seqno: 1,
449             lost_new_connection_id: Vec::new(),
450         }
451     }
452 
decoder(&self) -> ConnectionIdDecoderRef453     pub fn decoder(&self) -> ConnectionIdDecoderRef {
454         ConnectionIdDecoderRef {
455             generator: self.generator.deref().borrow(),
456         }
457     }
458 
459     /// Generate a connection ID and stateless reset token for a preferred address.
preferred_address_cid(&mut self) -> Res<(ConnectionId, [u8; 16])>460     pub fn preferred_address_cid(&mut self) -> Res<(ConnectionId, [u8; 16])> {
461         if self.generator.deref().borrow().generates_empty_cids() {
462             return Err(Error::ConnectionIdsExhausted);
463         }
464         if let Some(cid) = self.generator.borrow_mut().generate_cid() {
465             assert_ne!(cid.len(), 0);
466             debug_assert_eq!(self.next_seqno, CONNECTION_ID_SEQNO_PREFERRED);
467             self.connection_ids
468                 .add_local(ConnectionIdEntry::new(self.next_seqno, cid.clone(), ()));
469             self.next_seqno += 1;
470 
471             let srt = <[u8; 16]>::try_from(&random(16)[..]).unwrap();
472             Ok((cid, srt))
473         } else {
474             Err(Error::ConnectionIdsExhausted)
475         }
476     }
477 
is_valid(&self, cid: &ConnectionIdRef) -> bool478     pub fn is_valid(&self, cid: &ConnectionIdRef) -> bool {
479         self.connection_ids.contains(cid)
480     }
481 
retire(&mut self, seqno: u64)482     pub fn retire(&mut self, seqno: u64) {
483         // TODO(mt) - consider keeping connection IDs around for a short while.
484 
485         self.connection_ids.retire(seqno);
486         self.lost_new_connection_id.retain(|cid| cid.seqno != seqno);
487     }
488 
489     /// During the handshake, a server needs to regard the client's choice of destination
490     /// connection ID as valid.  This function saves it in the store in a special place.
add_odcid(&mut self, cid: ConnectionId)491     pub fn add_odcid(&mut self, cid: ConnectionId) {
492         let entry = ConnectionIdEntry::new(CONNECTION_ID_SEQNO_ODCID, cid, ());
493         self.connection_ids.add_local(entry);
494     }
495 
496     /// Stop treating the original destination connection ID as valid.
remove_odcid(&mut self)497     pub fn remove_odcid(&mut self) {
498         self.connection_ids.retire(CONNECTION_ID_SEQNO_ODCID);
499     }
500 
set_limit(&mut self, limit: u64)501     pub fn set_limit(&mut self, limit: u64) {
502         debug_assert!(limit >= 2);
503         self.limit = min(
504             LOCAL_ACTIVE_CID_LIMIT,
505             usize::try_from(limit).unwrap_or(LOCAL_ACTIVE_CID_LIMIT),
506         );
507     }
508 
write_entry( &mut self, entry: &ConnectionIdEntry<[u8; 16]>, builder: &mut PacketBuilder, stats: &mut FrameStats, ) -> Res<bool>509     fn write_entry(
510         &mut self,
511         entry: &ConnectionIdEntry<[u8; 16]>,
512         builder: &mut PacketBuilder,
513         stats: &mut FrameStats,
514     ) -> Res<bool> {
515         let len = 1 + Encoder::varint_len(entry.seqno) + 1 + 1 + entry.cid.len() + 16;
516         if builder.remaining() < len {
517             return Ok(false);
518         }
519 
520         builder.encode_varint(FRAME_TYPE_NEW_CONNECTION_ID);
521         builder.encode_varint(entry.seqno);
522         builder.encode_varint(0u64);
523         builder.encode_vec(1, &entry.cid);
524         builder.encode(&entry.srt);
525         if builder.len() > builder.limit() {
526             return Err(Error::InternalError(8));
527         }
528 
529         stats.new_connection_id += 1;
530         Ok(true)
531     }
532 
write_frames( &mut self, builder: &mut PacketBuilder, tokens: &mut Vec<RecoveryToken>, stats: &mut FrameStats, ) -> Res<()>533     pub fn write_frames(
534         &mut self,
535         builder: &mut PacketBuilder,
536         tokens: &mut Vec<RecoveryToken>,
537         stats: &mut FrameStats,
538     ) -> Res<()> {
539         if self.generator.deref().borrow().generates_empty_cids() {
540             debug_assert_eq!(self.generator.borrow_mut().generate_cid().unwrap().len(), 0);
541             return Ok(());
542         }
543 
544         while let Some(entry) = self.lost_new_connection_id.pop() {
545             if self.write_entry(&entry, builder, stats)? {
546                 tokens.push(RecoveryToken::NewConnectionId(entry));
547             } else {
548                 // This shouldn't happen often.
549                 self.lost_new_connection_id.push(entry);
550                 break;
551             }
552         }
553 
554         // Keep writing while we have fewer than the limit of active connection IDs
555         // and while there is room for more.  This uses the longest connection ID
556         // length to simplify (assuming Retire Prior To is just 1 byte).
557         while self.connection_ids.len() < self.limit && builder.remaining() >= 47 {
558             let maybe_cid = self.generator.borrow_mut().generate_cid();
559             if let Some(cid) = maybe_cid {
560                 assert_ne!(cid.len(), 0);
561                 // TODO: generate the stateless reset tokens from the connection ID and a key.
562                 let srt = <[u8; 16]>::try_from(&random(16)[..]).unwrap();
563 
564                 let seqno = self.next_seqno;
565                 self.next_seqno += 1;
566                 self.connection_ids
567                     .add_local(ConnectionIdEntry::new(seqno, cid.clone(), ()));
568 
569                 let entry = ConnectionIdEntry::new(seqno, cid, srt);
570                 debug_assert!(self.write_entry(&entry, builder, stats)?);
571                 tokens.push(RecoveryToken::NewConnectionId(entry));
572             }
573         }
574         Ok(())
575     }
576 
lost(&mut self, entry: &ConnectionIdEntry<[u8; 16]>)577     pub fn lost(&mut self, entry: &ConnectionIdEntry<[u8; 16]>) {
578         self.lost_new_connection_id.push(entry.clone());
579     }
580 
acked(&mut self, entry: &ConnectionIdEntry<[u8; 16]>)581     pub fn acked(&mut self, entry: &ConnectionIdEntry<[u8; 16]>) {
582         self.lost_new_connection_id
583             .retain(|e| e.seqno != entry.seqno);
584     }
585 }
586 
587 #[cfg(test)]
588 mod tests {
589     use super::*;
590     use test_fixture::fixture_init;
591 
592     #[test]
generate_initial_cid()593     fn generate_initial_cid() {
594         fixture_init();
595         for _ in 0..100 {
596             let cid = ConnectionId::generate_initial();
597             if !matches!(cid.len(), 8..=MAX_CONNECTION_ID_LEN) {
598                 panic!("connection ID {:?}", cid);
599             }
600         }
601     }
602 }
603