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