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