1use crate::Error;
28use crate::Result;
29use std::cmp;
30
31use crate::frame;
32
33use crate::packet::ConnectionId;
34
35use std::collections::HashSet;
36use std::collections::VecDeque;
37
38use smallvec::SmallVec;
39
40const RETIRED_CONN_ID_LIMIT_MULTIPLIER: u64 = 3;
44
45#[derive(Default)]
46struct BoundedConnectionIdSeqSet {
47 inner: HashSet<u64>,
49
50 capacity: usize,
52}
53
54impl BoundedConnectionIdSeqSet {
55 fn new(capacity: usize) -> Self {
57 Self {
58 inner: HashSet::new(),
59 capacity,
60 }
61 }
62
63 fn insert(&mut self, e: u64) -> Result<bool> {
64 if self.inner.len() >= self.capacity {
65 return Err(Error::IdLimit);
66 }
67
68 Ok(self.inner.insert(e))
69 }
70
71 fn remove(&mut self, e: &u64) -> bool {
72 self.inner.remove(e)
73 }
74
75 fn is_empty(&self) -> bool {
76 self.inner.is_empty()
77 }
78}
79
80#[derive(Debug, Default)]
82pub struct ConnectionIdEntry {
83 pub cid: ConnectionId<'static>,
85
86 pub seq: u64,
88
89 pub reset_token: Option<u128>,
91
92 pub path_id: Option<usize>,
94}
95
96#[derive(Default)]
97struct BoundedNonEmptyConnectionIdVecDeque {
98 inner: VecDeque<ConnectionIdEntry>,
100
101 capacity: usize,
103}
104
105impl BoundedNonEmptyConnectionIdVecDeque {
106 fn new(capacity: usize, initial_entry: ConnectionIdEntry) -> Self {
109 let mut inner = VecDeque::with_capacity(1);
110 inner.push_back(initial_entry);
111 Self { inner, capacity }
112 }
113
114 fn resize(&mut self, new_capacity: usize) {
118 if new_capacity > self.capacity {
119 self.capacity = new_capacity;
120 }
121 }
122
123 fn get_oldest(&self) -> &ConnectionIdEntry {
125 self.inner.front().expect("vecdeque is empty")
126 }
127
128 fn get(&self, seq: u64) -> Option<&ConnectionIdEntry> {
130 self.inner.iter().find(|e| e.seq == seq)
132 }
133
134 fn get_mut(&mut self, seq: u64) -> Option<&mut ConnectionIdEntry> {
136 self.inner.iter_mut().find(|e| e.seq == seq)
138 }
139
140 fn iter(&self) -> impl Iterator<Item = &ConnectionIdEntry> {
142 self.inner.iter()
143 }
144
145 fn len(&self) -> usize {
147 self.inner.len()
148 }
149
150 fn insert(&mut self, e: ConnectionIdEntry) -> Result<()> {
161 match self.get_mut(e.seq) {
163 Some(oe) => *oe = e,
164 None => {
165 if self.inner.len() >= self.capacity {
166 return Err(Error::IdLimit);
167 }
168 self.inner.push_back(e);
169 },
170 };
171 Ok(())
172 }
173
174 fn clear_and_insert(&mut self, e: ConnectionIdEntry) {
176 self.inner.clear();
177 self.inner.push_back(e);
178 }
179
180 fn remove(&mut self, seq: u64) -> Result<Option<ConnectionIdEntry>> {
190 let index = match self.inner.iter().position(|e| e.seq == seq) {
191 Some(i) => i,
192 None => return Ok(None),
193 };
194
195 if self.inner.len() <= 1 {
196 return Err(Error::OutOfIdentifiers);
197 }
198
199 Ok(self.inner.remove(index))
200 }
201
202 fn retire_prior_to<F>(&mut self, retire_prior_to: u64, mut inspect: F)
209 where
210 F: FnMut(&mut ConnectionIdEntry),
211 {
212 self.inner.retain_mut(|e| {
213 if e.seq < retire_prior_to {
214 inspect(e);
215 return false;
216 }
217 true
218 });
219 }
220}
221
222#[derive(Default)]
223pub struct ConnectionIdentifiers {
224 dcids: BoundedNonEmptyConnectionIdVecDeque,
226
227 scids: BoundedNonEmptyConnectionIdVecDeque,
229
230 advertise_new_scid_seqs: VecDeque<u64>,
232
233 retire_dcid_seqs: BoundedConnectionIdSeqSet,
235
236 retired_scids: VecDeque<ConnectionId<'static>>,
239
240 largest_peer_retire_prior_to: u64,
242
243 largest_destination_seq: u64,
245
246 next_scid_seq: u64,
248
249 retire_prior_to: u64,
251
252 source_conn_id_limit: usize,
254
255 zero_length_scid: bool,
257
258 zero_length_dcid: bool,
260}
261
262impl ConnectionIdentifiers {
263 pub fn new(
267 mut destination_conn_id_limit: usize, initial_scid: &ConnectionId,
268 initial_path_id: usize, reset_token: Option<u128>,
269 ) -> ConnectionIdentifiers {
270 if destination_conn_id_limit < 2 {
272 destination_conn_id_limit = 2;
273 }
274
275 let source_conn_id_limit = 2;
277
278 let zero_length_scid = initial_scid.is_empty();
280
281 let initial_scid =
282 ConnectionId::from_ref(initial_scid.as_ref()).into_owned();
283
284 let scids = BoundedNonEmptyConnectionIdVecDeque::new(
287 2 * source_conn_id_limit - 1,
288 ConnectionIdEntry {
289 cid: initial_scid,
290 seq: 0,
291 reset_token,
292 path_id: Some(initial_path_id),
293 },
294 );
295
296 let dcids = BoundedNonEmptyConnectionIdVecDeque::new(
297 destination_conn_id_limit,
298 ConnectionIdEntry {
299 cid: ConnectionId::default(),
300 seq: 0,
301 reset_token: None,
302 path_id: Some(initial_path_id),
303 },
304 );
305
306 let value =
308 (destination_conn_id_limit as u64) * RETIRED_CONN_ID_LIMIT_MULTIPLIER;
309 let size = cmp::min(usize::MAX as u64, value) as usize;
310 let next_scid_seq = 1;
312 ConnectionIdentifiers {
313 scids,
314 dcids,
315 retire_dcid_seqs: BoundedConnectionIdSeqSet::new(size),
316 next_scid_seq,
317 source_conn_id_limit,
318 zero_length_scid,
319 ..Default::default()
320 }
321 }
322
323 pub fn set_source_conn_id_limit(&mut self, v: u64) {
325 let v = cmp::min(v, (usize::MAX / 2) as u64) as usize;
327
328 if v >= 2 {
330 self.source_conn_id_limit = v;
331 self.scids.resize(2 * v - 1);
334 }
335 }
336
337 #[inline]
340 pub fn get_dcid(&self, seq_num: u64) -> Result<&ConnectionIdEntry> {
341 self.dcids.get(seq_num).ok_or(Error::InvalidState)
342 }
343
344 #[inline]
347 pub fn get_scid(&self, seq_num: u64) -> Result<&ConnectionIdEntry> {
348 self.scids.get(seq_num).ok_or(Error::InvalidState)
349 }
350
351 pub fn new_scid(
380 &mut self, cid: ConnectionId<'static>, reset_token: Option<u128>,
381 advertise: bool, path_id: Option<usize>, retire_if_needed: bool,
382 ) -> Result<u64> {
383 if self.zero_length_scid {
384 return Err(Error::InvalidState);
385 }
386
387 if self.scids.len() >= self.source_conn_id_limit {
392 if !retire_if_needed {
393 return Err(Error::IdLimit);
394 }
395
396 self.retire_prior_to = self.lowest_usable_scid_seq()? + 1;
398 }
399
400 let seq = self.next_scid_seq;
401
402 if reset_token.is_none() && seq != 0 {
403 return Err(Error::InvalidState);
404 }
405
406 if let Some(e) = self.scids.iter().find(|e| e.cid == cid) {
408 if e.reset_token != reset_token {
409 return Err(Error::InvalidState);
410 }
411 return Ok(e.seq);
412 }
413
414 self.scids.insert(ConnectionIdEntry {
415 cid,
416 seq,
417 reset_token,
418 path_id,
419 })?;
420 self.next_scid_seq += 1;
421
422 self.mark_advertise_new_scid_seq(seq, advertise);
423
424 Ok(seq)
425 }
426
427 pub fn set_initial_dcid(
429 &mut self, cid: ConnectionId<'static>, reset_token: Option<u128>,
430 path_id: Option<usize>,
431 ) {
432 self.zero_length_dcid = cid.is_empty();
434 self.dcids.clear_and_insert(ConnectionIdEntry {
435 cid,
436 seq: 0,
437 reset_token,
438 path_id,
439 });
440 }
441
442 pub fn new_dcid(
452 &mut self, cid: ConnectionId<'static>, seq: u64, reset_token: u128,
453 retire_prior_to: u64, retired_path_ids: &mut SmallVec<[(u64, usize); 1]>,
454 ) -> Result<()> {
455 if self.zero_length_dcid {
456 return Err(Error::InvalidState);
457 }
458
459 if let Some(e) = self.dcids.iter().find(|e| e.cid == cid || e.seq == seq)
466 {
467 if e.cid != cid || e.seq != seq || e.reset_token != Some(reset_token)
468 {
469 return Err(Error::InvalidFrame);
470 }
471 return Ok(());
473 }
474
475 if retire_prior_to > seq {
481 return Err(Error::InvalidFrame);
482 }
483
484 if seq < self.largest_peer_retire_prior_to {
490 self.mark_retire_dcid_seq(seq, true)?;
491 return Ok(());
492 }
493
494 if seq > self.largest_destination_seq {
495 self.largest_destination_seq = seq;
496 }
497
498 let new_entry = ConnectionIdEntry {
499 cid: cid.clone(),
500 seq,
501 reset_token: Some(reset_token),
502 path_id: None,
503 };
504
505 let mut retired_dcid_queue_err = None;
506
507 if retire_prior_to > self.largest_peer_retire_prior_to {
516 let retired = &mut self.retire_dcid_seqs;
517
518 if new_entry.seq < retire_prior_to {
521 return Err(Error::OutOfIdentifiers);
522 }
523
524 self.dcids.retire_prior_to(retire_prior_to, |e| {
527 if let Some(pid) = e.path_id {
528 retired_path_ids.push((e.seq, pid));
529 }
530
531 if let Err(e) = retired.insert(e.seq) {
532 retired_dcid_queue_err.get_or_insert(e);
536 }
537 });
538
539 self.largest_peer_retire_prior_to = retire_prior_to;
540 }
541
542 self.dcids.insert(new_entry)?;
545
546 if let Some(e) = retired_dcid_queue_err {
549 return Err(e);
550 }
551
552 Ok(())
553 }
554
555 pub fn retire_scid(
566 &mut self, seq: u64, pkt_dcid: &ConnectionId,
567 ) -> Result<Option<usize>> {
568 if seq >= self.next_scid_seq {
569 return Err(Error::InvalidState);
570 }
571
572 let pid = if let Some(e) = self.scids.remove(seq)? {
573 if e.cid == *pkt_dcid {
574 return Err(Error::InvalidState);
575 }
576
577 self.retired_scids.push_back(e.cid);
579
580 let lowest_scid_seq = self.lowest_usable_scid_seq()?;
582 self.retire_prior_to = lowest_scid_seq;
583
584 e.path_id
585 } else {
586 None
587 };
588
589 Ok(pid)
590 }
591
592 pub fn retire_dcid(&mut self, seq: u64) -> Result<Option<usize>> {
606 if self.zero_length_dcid {
607 return Err(Error::InvalidState);
608 }
609
610 let e = self.dcids.remove(seq)?.ok_or(Error::InvalidState)?;
611
612 self.mark_retire_dcid_seq(seq, true)?;
613
614 Ok(e.path_id)
615 }
616
617 pub fn scids_iter(&self) -> impl Iterator<Item = &ConnectionId<'_>> {
619 self.scids.iter().map(|e| &e.cid)
620 }
621
622 pub fn link_scid_to_path_id(
625 &mut self, dcid_seq: u64, path_id: usize,
626 ) -> Result<()> {
627 let e = self.scids.get_mut(dcid_seq).ok_or(Error::InvalidState)?;
628 e.path_id = Some(path_id);
629 Ok(())
630 }
631
632 pub fn link_dcid_to_path_id(
635 &mut self, dcid_seq: u64, path_id: usize,
636 ) -> Result<()> {
637 let e = self.dcids.get_mut(dcid_seq).ok_or(Error::InvalidState)?;
638 e.path_id = Some(path_id);
639 Ok(())
640 }
641
642 #[inline]
645 pub fn lowest_usable_scid_seq(&self) -> Result<u64> {
646 self.scids
647 .iter()
648 .filter_map(|e| {
649 if e.seq >= self.retire_prior_to {
650 Some(e.seq)
651 } else {
652 None
653 }
654 })
655 .min()
656 .ok_or(Error::InvalidState)
657 }
658
659 #[inline]
662 pub fn lowest_available_dcid_seq(&self) -> Option<u64> {
663 self.dcids
664 .iter()
665 .filter_map(|e| {
666 if e.path_id.is_none() {
667 Some(e.seq)
668 } else {
669 None
670 }
671 })
672 .min()
673 }
674
675 #[inline]
678 pub fn find_scid_seq(
679 &self, scid: &ConnectionId,
680 ) -> Option<(u64, Option<usize>)> {
681 self.scids.iter().find_map(|e| {
682 if e.cid == *scid {
683 Some((e.seq, e.path_id))
684 } else {
685 None
686 }
687 })
688 }
689
690 #[inline]
696 pub fn available_scids(&self) -> usize {
697 self.scids.iter().filter(|e| e.path_id.is_none()).count()
698 }
699
700 #[inline]
706 pub fn available_dcids(&self) -> usize {
707 if self.zero_length_dcid() {
708 return 0;
709 }
710 self.dcids.iter().filter(|e| e.path_id.is_none()).count()
711 }
712
713 #[inline]
715 pub fn oldest_scid(&self) -> &ConnectionIdEntry {
716 self.scids.get_oldest()
717 }
718
719 #[inline]
726 pub fn oldest_dcid(&self) -> &ConnectionIdEntry {
727 self.dcids.get_oldest()
728 }
729
730 #[inline]
734 pub fn mark_advertise_new_scid_seq(
735 &mut self, scid_seq: u64, advertise: bool,
736 ) {
737 if advertise {
738 self.advertise_new_scid_seqs.push_back(scid_seq);
739 } else if let Some(index) = self
740 .advertise_new_scid_seqs
741 .iter()
742 .position(|s| *s == scid_seq)
743 {
744 self.advertise_new_scid_seqs.remove(index);
745 }
746 }
747
748 #[inline]
752 pub fn mark_retire_dcid_seq(
753 &mut self, dcid_seq: u64, retire: bool,
754 ) -> Result<()> {
755 if retire {
756 self.retire_dcid_seqs.insert(dcid_seq)?;
757 } else {
758 self.retire_dcid_seqs.remove(&dcid_seq);
759 }
760
761 Ok(())
762 }
763
764 #[inline]
770 pub fn next_advertise_new_scid_seq(&self) -> Option<u64> {
771 self.advertise_new_scid_seqs.front().copied()
772 }
773
774 #[inline]
781 pub fn retire_dcid_seqs(&self) -> HashSet<u64> {
782 self.retire_dcid_seqs.inner.clone()
783 }
784
785 #[inline]
787 pub fn has_new_scids(&self) -> bool {
788 !self.advertise_new_scid_seqs.is_empty()
789 }
790
791 #[inline]
794 pub fn has_retire_dcids(&self) -> bool {
795 !self.retire_dcid_seqs.is_empty()
796 }
797
798 #[inline]
800 pub fn zero_length_scid(&self) -> bool {
801 self.zero_length_scid
802 }
803
804 #[inline]
806 pub fn zero_length_dcid(&self) -> bool {
807 self.zero_length_dcid
808 }
809
810 pub fn get_new_connection_id_frame_for(
813 &self, seq_num: u64,
814 ) -> Result<frame::Frame> {
815 let e = self.scids.get(seq_num).ok_or(Error::InvalidState)?;
816 Ok(frame::Frame::NewConnectionId {
817 seq_num,
818 retire_prior_to: self.retire_prior_to,
819 conn_id: e.cid.to_vec(),
820 reset_token: e.reset_token.ok_or(Error::InvalidState)?.to_be_bytes(),
821 })
822 }
823
824 #[inline]
827 pub fn active_source_cids(&self) -> usize {
828 self.scids.len()
829 }
830
831 #[inline]
834 pub fn retired_source_cids(&self) -> usize {
835 self.retired_scids.len()
836 }
837
838 pub fn pop_retired_scid(&mut self) -> Option<ConnectionId<'static>> {
839 self.retired_scids.pop_front()
840 }
841}
842
843#[cfg(test)]
844mod tests {
845 use super::*;
846 use crate::test_utils::create_cid_and_reset_token;
847
848 #[test]
849 fn ids_new_scids() {
850 let (scid, _) = create_cid_and_reset_token(16);
851 let (dcid, _) = create_cid_and_reset_token(16);
852
853 let mut ids = ConnectionIdentifiers::new(2, &scid, 0, None);
854 ids.set_source_conn_id_limit(3);
855 ids.set_initial_dcid(dcid, None, Some(0));
856
857 assert_eq!(ids.available_dcids(), 0);
858 assert_eq!(ids.available_scids(), 0);
859 assert!(!ids.has_new_scids());
860 assert_eq!(ids.next_advertise_new_scid_seq(), None);
861
862 let (scid2, rt2) = create_cid_and_reset_token(16);
863
864 assert_eq!(ids.new_scid(scid2, Some(rt2), true, None, false), Ok(1));
865 assert_eq!(ids.available_dcids(), 0);
866 assert_eq!(ids.available_scids(), 1);
867 assert!(ids.has_new_scids());
868 assert_eq!(ids.next_advertise_new_scid_seq(), Some(1));
869
870 let (scid3, rt3) = create_cid_and_reset_token(16);
871
872 assert_eq!(ids.new_scid(scid3, Some(rt3), true, None, false), Ok(2));
873 assert_eq!(ids.available_dcids(), 0);
874 assert_eq!(ids.available_scids(), 2);
875 assert!(ids.has_new_scids());
876 assert_eq!(ids.next_advertise_new_scid_seq(), Some(1));
877
878 let (scid4, rt4) = create_cid_and_reset_token(16);
881
882 assert_eq!(
883 ids.new_scid(scid4, Some(rt4), true, None, false),
884 Err(Error::IdLimit),
885 );
886 assert_eq!(ids.available_dcids(), 0);
887 assert_eq!(ids.available_scids(), 2);
888 assert!(ids.has_new_scids());
889 assert_eq!(ids.next_advertise_new_scid_seq(), Some(1));
890
891 ids.mark_advertise_new_scid_seq(1, false);
893 assert_eq!(ids.available_dcids(), 0);
894 assert_eq!(ids.available_scids(), 2);
895 assert!(ids.has_new_scids());
896 assert_eq!(ids.next_advertise_new_scid_seq(), Some(2));
897
898 ids.mark_advertise_new_scid_seq(2, false);
900
901 assert_eq!(ids.available_dcids(), 0);
902 assert_eq!(ids.available_scids(), 2);
903 assert!(!ids.has_new_scids());
904 assert_eq!(ids.next_advertise_new_scid_seq(), None);
905 }
906
907 #[test]
908 fn new_dcid_event() {
909 let (scid, _) = create_cid_and_reset_token(16);
910 let (dcid, _) = create_cid_and_reset_token(16);
911
912 let mut retired_path_ids = SmallVec::new();
913
914 let mut ids = ConnectionIdentifiers::new(2, &scid, 0, None);
915 ids.set_initial_dcid(dcid, None, Some(0));
916
917 assert_eq!(ids.available_dcids(), 0);
918 assert_eq!(ids.dcids.len(), 1);
919
920 let (dcid2, rt2) = create_cid_and_reset_token(16);
921
922 assert_eq!(
923 ids.new_dcid(dcid2, 1, rt2, 0, &mut retired_path_ids),
924 Ok(()),
925 );
926 assert_eq!(retired_path_ids, SmallVec::from_buf([]));
927 assert_eq!(ids.available_dcids(), 1);
928 assert_eq!(ids.dcids.len(), 2);
929
930 let (dcid3, rt3) = create_cid_and_reset_token(16);
935 assert_eq!(
936 ids.new_dcid(dcid3, 2, rt3, 1, &mut retired_path_ids),
937 Ok(())
938 );
939 assert_eq!(retired_path_ids, SmallVec::from_buf([(0, 0)]));
940 ids.link_dcid_to_path_id(1, 0).unwrap();
942 assert_eq!(ids.available_dcids(), 1);
943 assert_eq!(ids.dcids.len(), 2);
944 assert!(ids.has_retire_dcids());
945 assert_eq!(ids.retire_dcid_seqs().iter().next(), Some(&0));
946
947 let _ = ids.mark_retire_dcid_seq(0, false);
949 assert!(!ids.has_retire_dcids());
950 assert_eq!(ids.retire_dcid_seqs().iter().next(), None);
951
952 assert_eq!(ids.retire_dcid(0), Err(Error::InvalidState));
955 assert_eq!(ids.retire_dcid(3), Err(Error::InvalidState));
956 assert!(!ids.has_retire_dcids());
957 assert_eq!(ids.dcids.len(), 2);
958
959 assert_eq!(ids.retire_dcid(1), Ok(Some(0)));
961 ids.link_dcid_to_path_id(2, 0).unwrap();
963 assert_eq!(ids.available_dcids(), 0);
964 assert!(ids.has_retire_dcids());
965 assert_eq!(ids.retire_dcid_seqs().iter().next(), Some(&1));
966 assert_eq!(ids.dcids.len(), 1);
967
968 let _ = ids.mark_retire_dcid_seq(1, false);
970 assert!(!ids.has_retire_dcids());
971 assert_eq!(ids.retire_dcid_seqs().iter().next(), None);
972
973 assert_eq!(ids.retire_dcid(2), Err(Error::OutOfIdentifiers));
975 assert_eq!(ids.retire_dcid(0), Err(Error::InvalidState));
976 assert_eq!(ids.retire_dcid(1), Err(Error::InvalidState));
977 assert_eq!(ids.available_dcids(), 0);
978 assert!(!ids.has_retire_dcids());
979 assert_eq!(ids.dcids.len(), 1);
980 }
981
982 #[test]
983 fn new_dcid_reordered() {
984 let (scid, _) = create_cid_and_reset_token(16);
985 let (dcid, _) = create_cid_and_reset_token(16);
986
987 let mut retired_path_ids = SmallVec::new();
988
989 let mut ids = ConnectionIdentifiers::new(2, &scid, 0, None);
990 ids.set_initial_dcid(dcid, None, Some(0));
991
992 assert_eq!(ids.available_dcids(), 0);
993 assert_eq!(ids.dcids.len(), 1);
994
995 let (dcid, rt) = create_cid_and_reset_token(16);
997 assert!(ids.new_dcid(dcid, 2, rt, 1, &mut retired_path_ids).is_ok());
998 assert_eq!(ids.dcids.len(), 1);
999
1000 let (dcid, rt) = create_cid_and_reset_token(16);
1001 assert!(ids.new_dcid(dcid, 3, rt, 2, &mut retired_path_ids).is_ok());
1002 assert_eq!(ids.dcids.len(), 2);
1003
1004 let (dcid, rt) = create_cid_and_reset_token(16);
1005 assert!(ids.new_dcid(dcid, 4, rt, 3, &mut retired_path_ids).is_ok());
1006 assert_eq!(ids.dcids.len(), 2);
1007
1008 let (dcid, rt) = create_cid_and_reset_token(16);
1011 assert!(ids.new_dcid(dcid, 1, rt, 0, &mut retired_path_ids).is_ok());
1012 assert_eq!(ids.dcids.len(), 2);
1013 assert!(ids.get_dcid(1).is_err());
1014
1015 let (dcid, rt) = create_cid_and_reset_token(16);
1017 assert!(ids.new_dcid(dcid, 1, rt, 0, &mut retired_path_ids).is_ok());
1018 assert_eq!(ids.dcids.len(), 2);
1019 assert!(ids.get_dcid(1).is_err());
1020 }
1021
1022 #[test]
1023 fn new_dcid_partial_retire_prior_to() {
1024 let (scid, _) = create_cid_and_reset_token(16);
1025 let (dcid, _) = create_cid_and_reset_token(16);
1026
1027 let mut retired_path_ids = SmallVec::new();
1028
1029 let mut ids = ConnectionIdentifiers::new(5, &scid, 0, None);
1030 ids.set_initial_dcid(dcid, None, Some(0));
1031
1032 assert_eq!(ids.available_dcids(), 0);
1033 assert_eq!(ids.dcids.len(), 1);
1034
1035 let (dcid, rt) = create_cid_and_reset_token(16);
1036 assert!(ids.new_dcid(dcid, 1, rt, 0, &mut retired_path_ids).is_ok());
1037 assert_eq!(ids.dcids.len(), 2);
1038
1039 let (dcid, rt) = create_cid_and_reset_token(16);
1040 assert!(ids.new_dcid(dcid, 2, rt, 0, &mut retired_path_ids).is_ok());
1041 assert_eq!(ids.dcids.len(), 3);
1042
1043 let (dcid, rt) = create_cid_and_reset_token(16);
1044 assert!(ids.new_dcid(dcid, 3, rt, 0, &mut retired_path_ids).is_ok());
1045 assert_eq!(ids.dcids.len(), 4);
1046
1047 let (dcid, rt) = create_cid_and_reset_token(16);
1048 assert!(ids.new_dcid(dcid, 4, rt, 0, &mut retired_path_ids).is_ok());
1049 assert_eq!(ids.dcids.len(), 5);
1050
1051 assert!(ids.retire_dcid(3).is_ok());
1053
1054 let (dcid, rt) = create_cid_and_reset_token(16);
1059 assert!(ids.new_dcid(dcid, 5, rt, 3, &mut retired_path_ids).is_ok());
1060 assert_eq!(ids.dcids.len(), 2);
1061
1062 let (dcid, rt) = create_cid_and_reset_token(16);
1064 assert!(ids.new_dcid(dcid, 6, rt, 6, &mut retired_path_ids).is_ok());
1065 assert_eq!(ids.dcids.len(), 1);
1066 }
1067
1068 #[test]
1069 fn new_dcid_partial_retire_out_of_order() {
1070 let (scid, _) = create_cid_and_reset_token(16);
1071 let (dcid, _) = create_cid_and_reset_token(16);
1072
1073 let mut retired_path_ids = SmallVec::new();
1074
1075 let mut ids = ConnectionIdentifiers::new(5, &scid, 0, None);
1076 ids.set_initial_dcid(dcid, None, Some(0));
1077
1078 assert_eq!(ids.available_dcids(), 0);
1079 assert_eq!(ids.dcids.len(), 1);
1080
1081 let seq_nums = [5, 3, 2, 19, 8];
1083 for &seq in &seq_nums {
1084 let (dcid, rt) = create_cid_and_reset_token(16);
1085 assert!(ids
1086 .new_dcid(dcid, seq, rt, 1, &mut retired_path_ids)
1087 .is_ok());
1088 }
1089 assert_eq!(ids.dcids.len(), 5);
1090
1091 let (dcid, rt) = create_cid_and_reset_token(16);
1093 assert!(ids.new_dcid(dcid, 20, rt, 4, &mut retired_path_ids).is_ok());
1094 assert_eq!(ids.dcids.len(), 4);
1095 assert!(ids.get_dcid(20).is_ok());
1096
1097 for &seq in &seq_nums {
1098 let dcid = ids.get_dcid(seq);
1099 assert_eq!(dcid.is_ok(), seq >= 4);
1100 }
1101
1102 let seq_iter = ids.dcids.inner.iter().map(|e| e.seq);
1104 for (seq, expected) in seq_iter.zip([5, 19, 8, 20]) {
1105 assert_eq!(seq, expected);
1106 }
1107 }
1108
1109 #[test]
1110 fn retire_scids() {
1111 let (scid, _) = create_cid_and_reset_token(16);
1112 let (dcid, _) = create_cid_and_reset_token(16);
1113
1114 let mut ids = ConnectionIdentifiers::new(3, &scid, 0, None);
1115 ids.set_initial_dcid(dcid, None, Some(0));
1116 ids.set_source_conn_id_limit(3);
1117
1118 let (scid2, rt2) = create_cid_and_reset_token(16);
1119 let (scid3, rt3) = create_cid_and_reset_token(16);
1120
1121 assert_eq!(
1122 ids.new_scid(scid2.clone(), Some(rt2), true, None, false),
1123 Ok(1),
1124 );
1125 assert_eq!(ids.scids.len(), 2);
1126 assert_eq!(
1127 ids.new_scid(scid3.clone(), Some(rt3), true, None, false),
1128 Ok(2),
1129 );
1130 assert_eq!(ids.scids.len(), 3);
1131
1132 assert_eq!(ids.pop_retired_scid(), None);
1133
1134 assert_eq!(ids.retire_scid(0, &scid2), Ok(Some(0)));
1135
1136 assert_eq!(ids.pop_retired_scid(), Some(scid));
1137 assert_eq!(ids.pop_retired_scid(), None);
1138
1139 assert_eq!(ids.retire_scid(1, &scid3), Ok(None));
1140 assert_eq!(ids.scids.len(), 1);
1141
1142 assert_eq!(ids.retire_scid(1, &scid3), Ok(None));
1144 assert_eq!(ids.scids.len(), 1);
1145
1146 assert_eq!(ids.pop_retired_scid(), Some(scid2));
1147 assert_eq!(ids.pop_retired_scid(), None);
1148
1149 assert_eq!(ids.retire_scid(2, &scid3), Err(Error::OutOfIdentifiers));
1151 assert_eq!(ids.scids.len(), 1);
1152 }
1153}