1use std::{
3 collections::{BTreeSet, HashMap, HashSet},
4 hash::Hash,
5 io::Write,
6 mem,
7 sync::Arc,
8};
9
10use anyhow::Result;
11use rand::{rand_core::UnwrapErr, rngs::SysRng, RngExt};
12use tokio::sync::OwnedMutexGuard;
13
14use super::{
15 session::{Builder, Session, SessionInfo},
16 types::{Message, SessionID},
17};
18use crate::common::{
19 crypto::signature,
20 namespace::Namespace,
21 sgx::{EnclaveIdentity, QuotePolicy},
22 time::insecure_posix_time,
23};
24
25pub type SharedSession<PeerID> = Arc<tokio::sync::Mutex<MultiplexedSession<PeerID>>>;
27
28pub type SessionByTimeKey<PeerID> = (i64, PeerID, SessionID);
30
31#[derive(Debug, thiserror::Error)]
33pub enum Error {
34 #[error("max concurrent sessions reached")]
35 MaxConcurrentSessions,
36}
37
38pub struct MultiplexedSession<PeerID> {
40 peer_id: PeerID,
42 session_id: SessionID,
44 inner: Session,
46}
47
48impl<PeerID> MultiplexedSession<PeerID> {
49 pub fn get_peer_id(&self) -> &PeerID {
51 &self.peer_id
52 }
53
54 pub fn set_peer_id(&mut self, peer_id: PeerID) {
56 self.peer_id = peer_id;
57 }
58
59 pub fn get_session_id(&self) -> &SessionID {
61 &self.session_id
62 }
63
64 pub fn info(&self) -> Option<Arc<SessionInfo>> {
66 self.inner.session_info()
67 }
68
69 pub fn is_closed(&self) -> bool {
71 self.inner.is_closed()
72 }
73
74 pub async fn process_data<W: Write>(
76 &mut self,
77 data: &[u8],
78 writer: W,
79 ) -> Result<Option<Message>> {
80 self.inner.process_data(data, writer).await
81 }
82
83 pub fn write_message<W: Write>(&mut self, msg: Message, mut writer: W) -> Result<()> {
85 self.inner.write_message(msg, &mut writer)
86 }
87
88 pub fn get_remote_node(&self) -> Result<signature::PublicKey> {
90 self.inner.get_remote_node()
91 }
92
93 pub fn set_remote_node(&mut self, node: signature::PublicKey) -> Result<()> {
95 self.inner.set_remote_node(node)
96 }
97
98 pub fn is_connected(&self) -> bool {
101 self.inner.is_connected()
102 }
103
104 pub fn is_unauthenticated(&self) -> bool {
107 self.inner.is_unauthenticated()
108 }
109
110 pub fn close(&mut self) {
115 self.inner.close()
116 }
117}
118
119pub struct SessionMeta<PeerID: Clone + Ord + Hash> {
121 peer_id: PeerID,
123 session_id: SessionID,
125 last_access_time: i64,
127 inner: SharedSession<PeerID>,
129}
130
131impl<PeerID> SessionMeta<PeerID>
132where
133 PeerID: Clone + Ord + Hash,
134{
135 fn by_time_key(&self) -> SessionByTimeKey<PeerID> {
137 (self.last_access_time, self.peer_id.clone(), self.session_id)
138 }
139}
140
141pub struct Sessions<PeerID: Clone + Ord + Hash> {
143 builder: Builder,
145 max_sessions: usize,
147 max_sessions_per_peer: usize,
149 stale_session_timeout: i64,
151
152 by_peer: HashMap<PeerID, HashMap<SessionID, SessionMeta<PeerID>>>,
154 by_idle_time: BTreeSet<SessionByTimeKey<PeerID>>,
156}
157
158impl<PeerID> Sessions<PeerID>
159where
160 PeerID: Clone + Ord + Hash,
161{
162 pub fn new(
164 builder: Builder,
165 max_sessions: usize,
166 max_sessions_per_peer: usize,
167 stale_session_timeout: i64,
168 ) -> Self {
169 Self {
170 builder,
171 max_sessions,
172 max_sessions_per_peer,
173 stale_session_timeout,
174 by_peer: HashMap::new(),
175 by_idle_time: BTreeSet::new(),
176 }
177 }
178
179 pub fn set_builder(&mut self, builder: Builder) {
181 self.builder = builder;
182 }
183
184 pub fn update_enclaves(
187 &mut self,
188 enclaves: Option<HashSet<EnclaveIdentity>>,
189 ) -> Vec<SharedSession<PeerID>> {
190 if self.builder.get_remote_enclaves() == &enclaves {
191 return vec![];
192 }
193
194 self.builder = mem::take(&mut self.builder).remote_enclaves(enclaves);
195 self.drain()
196 }
197
198 pub fn update_quote_policy(&mut self, policy: QuotePolicy) -> Vec<SharedSession<PeerID>> {
201 let policy = Some(Arc::new(policy));
202 if self.builder.get_quote_policy() == &policy {
203 return vec![];
204 }
205
206 self.builder = mem::take(&mut self.builder).quote_policy(policy);
207 self.drain()
208 }
209
210 pub fn update_runtime_id(&mut self, id: Option<Namespace>) -> Vec<SharedSession<PeerID>> {
213 if self.builder.get_remote_runtime_id() == &id {
214 return vec![];
215 }
216
217 self.builder = mem::take(&mut self.builder).remote_runtime_id(id);
218 self.drain()
219 }
220
221 pub fn create_responder(
223 &mut self,
224 peer_id: PeerID,
225 session_id: SessionID,
226 ) -> Result<MultiplexedSession<PeerID>> {
227 if self.builder.get_quote_policy().is_none() {
229 let policy = self
230 .builder
231 .get_local_identity()
232 .as_ref()
233 .and_then(|id| id.quote_policy());
234
235 self.builder = mem::take(&mut self.builder).quote_policy(policy);
236 }
237
238 Ok(MultiplexedSession {
239 peer_id: peer_id.clone(),
240 session_id,
241 inner: self.builder.clone().build_responder()?,
242 })
243 }
244
245 pub fn create_initiator(&self, peer_id: PeerID) -> Result<MultiplexedSession<PeerID>> {
247 let session_id = SessionID::random();
248
249 Ok(MultiplexedSession {
250 peer_id,
251 session_id,
252 inner: self.builder.clone().build_initiator()?,
253 })
254 }
255
256 pub fn get(
258 &mut self,
259 peer_id: &PeerID,
260 session_id: &SessionID,
261 ) -> Option<SharedSession<PeerID>> {
262 let sessions = self.by_peer.get_mut(peer_id)?;
264
265 let session = sessions.get_mut(session_id)?;
267
268 Self::update_access_time(session, &mut self.by_idle_time);
269
270 Some(session.inner.clone())
271 }
272
273 pub fn find(&mut self, peer_ids: &[PeerID]) -> Option<SharedSession<PeerID>> {
276 match peer_ids.is_empty() {
277 true => self.find_any(),
278 false => self.find_one(peer_ids),
279 }
280 }
281
282 pub fn find_any(&mut self) -> Option<SharedSession<PeerID>> {
284 if self.by_idle_time.is_empty() {
285 return None;
286 }
287
288 for (_, peer_id, session_id) in self.by_idle_time.iter() {
290 let session = self
291 .by_peer
292 .get_mut(peer_id)
293 .unwrap()
294 .get_mut(session_id)
295 .unwrap();
296
297 if session.inner.clone().try_lock_owned().is_ok() {
298 Self::update_access_time(session, &mut self.by_idle_time);
299 return Some(session.inner.clone());
300 }
301 }
302
303 let mut rng = UnwrapErr(SysRng);
305 let n = rng.random_range(0..self.by_idle_time.len());
306 let (_, peer_id, session_id) = self.by_idle_time.iter().nth(n).unwrap();
307 let session = self
308 .by_peer
309 .get_mut(peer_id)
310 .unwrap()
311 .get_mut(session_id)
312 .unwrap();
313
314 Self::update_access_time(session, &mut self.by_idle_time);
315
316 Some(session.inner.clone())
317 }
318
319 pub fn find_one(&mut self, peer_ids: &[PeerID]) -> Option<SharedSession<PeerID>> {
321 let mut all_sessions = vec![];
322
323 for peer_id in peer_ids.iter() {
324 let sessions = self.by_peer.get_mut(peer_id)?;
325
326 let session = sessions
328 .values_mut()
329 .filter(|s| s.inner.clone().try_lock_owned().is_ok())
330 .min_by_key(|s| s.last_access_time);
331
332 if let Some(session) = session {
333 Self::update_access_time(session, &mut self.by_idle_time);
334 return Some(session.inner.clone());
335 }
336
337 for session in sessions.values() {
338 all_sessions.push((session.peer_id.clone(), session.session_id));
339 }
340 }
341
342 if all_sessions.is_empty() {
343 return None;
344 }
345
346 let mut rng = UnwrapErr(SysRng);
348 let n = rng.random_range(0..all_sessions.len());
349 let (peer_id, session_id) = all_sessions.get(n).unwrap();
350 let session = self
351 .by_peer
352 .get_mut(peer_id)
353 .unwrap()
354 .get_mut(session_id)
355 .unwrap();
356
357 Self::update_access_time(session, &mut self.by_idle_time);
358
359 Some(session.inner.clone())
360 }
361
362 pub fn remove_for(
364 &mut self,
365 peer_id: &PeerID,
366 now: i64,
367 ) -> Result<Option<OwnedMutexGuard<MultiplexedSession<PeerID>>>, Error> {
368 if let Some(session) = self.remove_from(peer_id)? {
369 return Ok(Some(session));
370 }
371 self.remove_one(now)
372 }
373
374 pub fn remove_from(
378 &mut self,
379 peer_id: &PeerID,
380 ) -> Result<Option<OwnedMutexGuard<MultiplexedSession<PeerID>>>, Error> {
381 let sessions = match self.by_peer.get_mut(peer_id) {
383 Some(sessions) => sessions,
384 None => return Ok(None),
385 };
386
387 if sessions.len() < self.max_sessions_per_peer
390 && self.by_idle_time.len() < self.max_sessions
391 {
392 return Ok(None);
393 }
394
395 let remove_session = sessions
397 .iter()
398 .min_by_key(|(_, s)| {
399 if let Ok(_inner) = s.inner.try_lock() {
400 s.last_access_time
401 } else {
402 i64::MAX }
404 })
405 .map(|(_, s)| s.inner.clone())
406 .ok_or(Error::MaxConcurrentSessions)?;
407
408 let session = match remove_session.try_lock_owned() {
409 Ok(inner) => inner,
410 Err(_) => return Err(Error::MaxConcurrentSessions), };
412
413 self.remove(&session);
414
415 Ok(Some(session))
416 }
417
418 pub fn remove_one(
421 &mut self,
422 now: i64,
423 ) -> Result<Option<OwnedMutexGuard<MultiplexedSession<PeerID>>>, Error> {
424 if self.by_idle_time.len() < self.max_sessions {
426 return Ok(None);
427 }
428
429 let mut remove_session: Option<OwnedMutexGuard<MultiplexedSession<PeerID>>> = None;
431
432 for (last_process_frame_time, peer_id, session_id) in self.by_idle_time.iter() {
433 if now.saturating_sub(*last_process_frame_time) < self.stale_session_timeout {
434 return Err(Error::MaxConcurrentSessions);
436 }
437
438 if let Some(sessions) = self.by_peer.get(peer_id) {
440 if let Some(session) = sessions.get(session_id) {
441 if let Ok(session) = session.inner.clone().try_lock_owned() {
442 remove_session = Some(session);
443 break;
444 }
445 }
446 }
447 }
448
449 let session = match remove_session {
451 Some(session) => session,
452 None => return Err(Error::MaxConcurrentSessions), };
454
455 self.remove(&session);
456
457 Ok(Some(session))
458 }
459
460 pub fn add(
462 &mut self,
463 session: MultiplexedSession<PeerID>,
464 now: i64,
465 ) -> Result<SharedSession<PeerID>, Error> {
466 if self.by_idle_time.len() >= self.max_sessions {
467 return Err(Error::MaxConcurrentSessions);
468 }
469
470 let sessions = self.by_peer.entry(session.peer_id.clone()).or_default();
471 if sessions.len() >= self.max_sessions_per_peer {
472 return Err(Error::MaxConcurrentSessions);
473 }
474
475 let peer_id = session.peer_id.clone();
476 let session_id = session.session_id;
477
478 let session = SessionMeta {
479 inner: Arc::new(tokio::sync::Mutex::new(session)),
480 peer_id,
481 session_id,
482 last_access_time: now,
483 };
484 let inner = session.inner.clone();
485
486 self.by_idle_time.insert(session.by_time_key());
487 sessions.insert(session.session_id, session);
488
489 Ok(inner)
490 }
491
492 pub fn remove(&mut self, session: &OwnedMutexGuard<MultiplexedSession<PeerID>>) {
494 let sessions = match self.by_peer.get_mut(&session.peer_id) {
495 Some(sessions) => sessions,
496 None => return,
497 };
498 let session_meta = match sessions.get(&session.session_id) {
499 Some(session_meta) => session_meta,
500 None => return,
501 };
502 let key = session_meta.by_time_key();
503 sessions.remove(&session.session_id);
504 self.by_idle_time.remove(&key);
505
506 if sessions.is_empty() {
508 self.by_peer.remove(&session.peer_id);
509 }
510 }
511
512 pub fn drain(&mut self) -> Vec<SharedSession<PeerID>> {
514 self.by_idle_time.clear();
515
516 let mut all_sessions = vec![];
517 for (_, mut sessions) in self.by_peer.drain() {
518 for (_, session) in sessions.drain() {
519 all_sessions.push(session.inner);
520 }
521 }
522
523 all_sessions
524 }
525
526 fn update_access_time(
527 session: &mut SessionMeta<PeerID>,
528 by_idle_time: &mut BTreeSet<SessionByTimeKey<PeerID>>,
529 ) {
530 by_idle_time.remove(&session.by_time_key());
532
533 session.last_access_time = insecure_posix_time();
535 by_idle_time.insert(session.by_time_key());
536 }
537
538 #[cfg(test)]
540 fn session_count(&self) -> usize {
541 self.by_idle_time.len()
542 }
543
544 #[cfg(test)]
546 fn peer_count(&self) -> usize {
547 self.by_peer.len()
548 }
549}
550
551#[cfg(test)]
552mod test {
553 use crate::enclave_rpc::{session::Builder, types::SessionID};
554
555 use super::{Error, Sessions};
556
557 fn ids() -> (Vec<Vec<u8>>, Vec<SessionID>) {
558 let peer_ids: Vec<Vec<u8>> = (1..8).map(|x| vec![x]).collect();
559 let session_ids: Vec<SessionID> = (1..8).map(|_| SessionID::random()).collect();
560
561 (peer_ids, session_ids)
562 }
563
564 #[test]
565 fn test_add() {
566 let (peer_ids, session_ids) = ids();
567 let mut sessions = Sessions::new(Builder::default(), 4, 2, 60);
568
569 let test_vector = vec![
570 (&peer_ids[0], &session_ids[0], 1, 1, true),
571 (&peer_ids[0], &session_ids[1], 2, 1, true), (&peer_ids[0], &session_ids[2], 2, 1, false), (&peer_ids[1], &session_ids[0], 3, 2, true), (&peer_ids[2], &session_ids[2], 4, 3, true), (&peer_ids[3], &session_ids[3], 4, 3, false), ];
577
578 let now = 0;
579 for (peer_id, session_id, num_sessions, num_peers, created) in test_vector {
580 let session = sessions
581 .create_responder(peer_id.clone(), session_id.clone())
582 .unwrap();
583 let res = sessions.add(session, now);
584 match created {
585 true => {
586 assert!(res.is_ok(), "session should be created");
587 let s = res.unwrap();
588 let s_owned = s.try_lock().unwrap();
589 assert_eq!(&s_owned.peer_id, peer_id);
590 assert_eq!(&s_owned.session_id, session_id);
591 }
592 false => {
593 assert!(res.is_err(), "session should not be created");
594 assert!(matches!(res, Err(Error::MaxConcurrentSessions)));
595 }
596 };
597 assert_eq!(sessions.session_count(), num_sessions);
598 assert_eq!(sessions.peer_count(), num_peers);
599 }
600 }
601
602 #[test]
603 fn test_get() {
604 let (peer_ids, session_ids) = ids();
605 let mut sessions = Sessions::new(Builder::default(), 8, 2, 60);
606
607 let test_vector = vec![
608 (&peer_ids[0], &session_ids[0], true),
609 (&peer_ids[0], &session_ids[1], false), (&peer_ids[1], &session_ids[0], false), (&peer_ids[1], &session_ids[1], false), ];
613
614 let now = 0;
615 for (peer_id, session_id, create) in test_vector {
616 if create {
617 let session = sessions
618 .create_responder(peer_id.clone(), session_id.clone())
619 .unwrap();
620 let _ = sessions.add(session, now);
621 }
622
623 let maybe_s = sessions.get(peer_id, session_id);
624 match create {
625 true => {
626 assert!(maybe_s.is_some(), "session should exist");
627 let s = maybe_s.unwrap();
628 let s_owned = s.try_lock_owned().unwrap();
629 assert_eq!(&s_owned.peer_id, peer_id);
630 assert_eq!(&s_owned.session_id, session_id);
631 }
632 false => assert!(maybe_s.is_none(), "session should not exist"),
633 }
634 }
635 }
636
637 #[test]
638 fn test_find_any() {
639 let (peer_ids, session_ids) = ids();
640 let mut sessions = Sessions::new(Builder::default(), 8, 2, 60);
641
642 let test_vector = vec![
643 (&peer_ids[0], &session_ids[0]),
644 (&peer_ids[0], &session_ids[1]),
645 (&peer_ids[1], &session_ids[2]),
646 ];
647
648 let maybe_s = sessions.find_any();
650 assert!(maybe_s.is_none(), "session should not be found");
651
652 let mut now = 0;
653 for (peer_id, session_id) in test_vector {
654 let session = sessions
655 .create_responder(peer_id.clone(), session_id.clone())
656 .unwrap();
657 let _ = sessions.add(session, now);
658 now += 1
659 }
660
661 let maybe_s = sessions.find_any();
663 assert!(maybe_s.is_some(), "session should be found");
664 let s = maybe_s.unwrap();
665 let s1_owned = s.try_lock_owned().unwrap(); assert_eq!(&s1_owned.peer_id, &peer_ids[0]);
667 assert_eq!(&s1_owned.session_id, &session_ids[0]);
668
669 let maybe_s = sessions.find_any();
671 assert!(maybe_s.is_some(), "session should be found");
672 let s = maybe_s.unwrap();
673 let s2_owned = s.try_lock_owned().unwrap(); assert_eq!(&s2_owned.peer_id, &peer_ids[0]);
675 assert_eq!(&s2_owned.session_id, &session_ids[1]); let maybe_s = sessions.find_any();
679 assert!(maybe_s.is_some(), "session should be found");
680 let s = maybe_s.unwrap();
681 let s3_owned = s.try_lock_owned().unwrap(); assert_eq!(&s3_owned.peer_id, &peer_ids[1]);
683 assert_eq!(&s3_owned.session_id, &session_ids[2]); let maybe_s = sessions.find_any();
687 assert!(maybe_s.is_some(), "session should be found");
688 let s = maybe_s.unwrap();
689 let res = s.try_lock_owned(); assert!(res.is_err(), "session should be in use");
691
692 drop(s2_owned);
694
695 let maybe_s = sessions.find_any();
697 assert!(maybe_s.is_some(), "session should be found");
698 let s = maybe_s.unwrap();
699 let s_owned = s.try_lock_owned().unwrap(); assert_eq!(&s_owned.peer_id, &peer_ids[0]);
701 assert_eq!(&s_owned.session_id, &session_ids[1]);
702 }
703
704 #[test]
705 fn test_find_one() {
706 let (peer_ids, session_ids) = ids();
707 let mut sessions = Sessions::new(Builder::default(), 8, 2, 60);
708
709 let test_vector = vec![
710 (&peer_ids[2], &session_ids[0]), (&peer_ids[0], &session_ids[0]),
712 (&peer_ids[3], &session_ids[1]), (&peer_ids[0], &session_ids[1]),
714 (&peer_ids[3], &session_ids[2]), (&peer_ids[1], &session_ids[2]),
716 (&peer_ids[2], &session_ids[2]), ];
718
719 let maybe_s = sessions.find_one(&peer_ids[0..2]);
721 assert!(maybe_s.is_none(), "session should not be found");
722
723 let mut now = 0;
724 for (peer_id, session_id) in test_vector {
725 let session = sessions
726 .create_responder(peer_id.clone(), session_id.clone())
727 .unwrap();
728 let _ = sessions.add(session, now);
729 now += 1
730 }
731
732 let maybe_s = sessions.find_one(&peer_ids[4..]);
734 assert!(maybe_s.is_none(), "session should not be found");
735
736 let maybe_s = sessions.find_one(&peer_ids[0..2]);
738 assert!(maybe_s.is_some(), "session should be found");
739 let s = maybe_s.unwrap();
740 let s1_owned = s.try_lock_owned().unwrap(); assert_eq!(&s1_owned.peer_id, &peer_ids[0]);
742 assert_eq!(&s1_owned.session_id, &session_ids[0]);
743
744 let maybe_s = sessions.find_one(&peer_ids[0..2]);
746 assert!(maybe_s.is_some(), "session should be found");
747 let s = maybe_s.unwrap();
748 let s2_owned = s.try_lock_owned().unwrap(); assert_eq!(&s2_owned.peer_id, &peer_ids[0]);
750 assert_eq!(&s2_owned.session_id, &session_ids[1]); let maybe_s = sessions.find_one(&peer_ids[0..2]);
754 assert!(maybe_s.is_some(), "session should be found");
755 let s = maybe_s.unwrap();
756 let s3_owned = s.try_lock_owned().unwrap(); assert_eq!(&s3_owned.peer_id, &peer_ids[1]);
758 assert_eq!(&s3_owned.session_id, &session_ids[2]); let maybe_s = sessions.find_one(&peer_ids[0..2]);
762 assert!(maybe_s.is_some(), "session should be found");
763 let s = maybe_s.unwrap();
764 let res = s.try_lock_owned(); assert!(res.is_err(), "session should be in use");
766
767 drop(s2_owned);
769
770 let maybe_s = sessions.find_one(&peer_ids[0..2]);
772 assert!(maybe_s.is_some(), "session should be found");
773 let s = maybe_s.unwrap();
774 let s_owned = s.try_lock_owned().unwrap(); assert_eq!(&s_owned.peer_id, &peer_ids[0]);
776 assert_eq!(&s_owned.session_id, &session_ids[1]);
777 }
778
779 #[test]
780 fn test_remove_from() {
781 let (peer_ids, session_ids) = ids();
782 let mut sessions = Sessions::new(Builder::default(), 4, 2, 60);
783
784 let test_vector = vec![
785 (&peer_ids[0], &session_ids[0]),
786 (&peer_ids[1], &session_ids[1]),
787 (&peer_ids[2], &session_ids[2]),
788 (&peer_ids[2], &session_ids[3]), ];
791
792 let mut now = 0;
793 for (peer_id, session_id) in test_vector.clone() {
794 let session = sessions
795 .create_responder(peer_id.clone(), session_id.clone())
796 .unwrap();
797 let _ = sessions.add(session, now);
798 now += 1;
799 }
800
801 let res = sessions.remove_from(&peer_ids[3]);
804 assert!(res.is_ok(), "remove_from should succeed");
805 let maybe_s_owned = res.unwrap();
806 assert!(maybe_s_owned.is_none(), "no sessions should be removed");
807 assert_eq!(sessions.session_count(), 4);
808 assert_eq!(sessions.peer_count(), 3);
809
810 let res = sessions.remove_from(&peer_ids[0]);
816 assert!(res.is_ok(), "remove_from should succeed");
817 let maybe_s_owned = res.unwrap();
818 assert!(maybe_s_owned.is_some(), "one session should be removed");
819 let s_owned = maybe_s_owned.unwrap();
820 assert_eq!(&s_owned.peer_id, &peer_ids[0]);
821 assert_eq!(&s_owned.session_id, &session_ids[0]);
822 assert_eq!(sessions.session_count(), 3);
823 assert_eq!(sessions.peer_count(), 2);
824
825 for peer_id in vec![&peer_ids[0], &peer_ids[1]] {
828 let res = sessions.remove_from(peer_id);
829 assert!(res.is_ok(), "remove_from should succeed");
830 let maybe_s_owned = res.unwrap();
831 assert!(maybe_s_owned.is_none(), "no sessions should be removed");
832 assert_eq!(sessions.session_count(), 3);
833 assert_eq!(sessions.peer_count(), 2);
834 }
835
836 let res = sessions.remove_from(&peer_ids[2]);
839 assert!(res.is_ok(), "remove_from should succeed");
840 let maybe_s_owned = res.unwrap();
841 assert!(maybe_s_owned.is_some(), "one session should be removed");
842 let s_owned = maybe_s_owned.unwrap();
843 assert_eq!(&s_owned.peer_id, &peer_ids[2]);
844 assert_eq!(&s_owned.session_id, &session_ids[2]);
845 assert_eq!(sessions.session_count(), 2);
846 assert_eq!(sessions.peer_count(), 2);
847 }
848
849 #[test]
850 fn test_remove_one() {
851 let (peer_ids, session_ids) = ids();
852 let mut sessions = Sessions::new(Builder::default(), 4, 2, 60);
853
854 let test_vector = vec![
855 (&peer_ids[0], &session_ids[0]),
856 (&peer_ids[1], &session_ids[1]),
857 (&peer_ids[2], &session_ids[2]),
858 (&peer_ids[2], &session_ids[3]), ];
860
861 let mut now = 0;
862 for (peer_id, session_id) in test_vector.clone() {
863 let session = sessions
864 .create_responder(peer_id.clone(), session_id.clone())
865 .unwrap();
866 let _ = sessions.add(session, now);
867 now += 1;
868 }
869
870 now += 60 - 4 - 1;
872
873 let res = sessions.remove_one(now);
875 assert!(res.is_err(), "remove_one should fail");
876 assert!(matches!(res, Err(Error::MaxConcurrentSessions)));
877 assert_eq!(sessions.session_count(), 4);
878 assert_eq!(sessions.peer_count(), 3);
879
880 now += 1;
882
883 let res = sessions.remove_one(now);
886 assert!(res.is_ok(), "remove_one should succeed");
887 let maybe_s_owned = res.unwrap();
888 assert!(maybe_s_owned.is_some(), "one session should be removed");
889 let s_owned = maybe_s_owned.unwrap();
890 assert_eq!(&s_owned.peer_id, &peer_ids[0]);
891 assert_eq!(&s_owned.session_id, &session_ids[0]);
892 assert_eq!(sessions.session_count(), 3);
893 assert_eq!(sessions.peer_count(), 2);
894
895 now += 100;
897
898 let res = sessions.remove_one(now);
901 assert!(res.is_ok(), "remove_one should succeed");
902 let maybe_s_owned = res.unwrap();
903 assert!(maybe_s_owned.is_none(), "no sessions should be removed");
904 assert_eq!(sessions.session_count(), 3);
905 assert_eq!(sessions.peer_count(), 2);
906 }
907
908 #[test]
909 fn test_remove() {
910 let (peer_ids, session_ids) = ids();
911 let mut sessions = Sessions::new(Builder::default(), 8, 2, 60);
912
913 let test_vector = vec![
914 (&peer_ids[0], &session_ids[0], 3, 2),
915 (&peer_ids[1], &session_ids[1], 2, 1),
916 (&peer_ids[2], &session_ids[2], 1, 1),
917 (&peer_ids[2], &session_ids[3], 0, 0),
918 ];
919
920 let now = 0;
921 for (peer_id, session_id, _, _) in test_vector.clone() {
922 let session = sessions
923 .create_responder(peer_id.clone(), session_id.clone())
924 .unwrap();
925 let _ = sessions.add(session, now);
926 }
927
928 for (peer_id, session_id, num_sessions, num_peers) in test_vector {
929 let maybe_s = sessions.get(peer_id, session_id);
930 assert!(maybe_s.is_some(), "session should exist");
931 let s = maybe_s.unwrap();
932 let s_owned = s.try_lock_owned().unwrap();
933
934 sessions.remove(&s_owned);
935 assert_eq!(sessions.session_count(), num_sessions);
936 assert_eq!(sessions.peer_count(), num_peers);
937 }
938 }
939
940 #[test]
941 fn test_clear() {
942 let (peer_ids, session_ids) = ids();
943 let mut sessions = Sessions::new(Builder::default(), 8, 2, 60);
944
945 let test_vector = vec![
946 (&peer_ids[0], &session_ids[0]),
947 (&peer_ids[1], &session_ids[1]),
948 (&peer_ids[2], &session_ids[2]),
949 (&peer_ids[2], &session_ids[3]),
950 ];
951
952 let now = 0;
953 for (peer_id, session_id) in test_vector.clone() {
954 let session = sessions
955 .create_responder(peer_id.clone(), session_id.clone())
956 .unwrap();
957 let _ = sessions.add(session, now);
958 }
959
960 let removed_sessions = sessions.drain();
961 assert_eq!(removed_sessions.len(), 4);
962 assert_eq!(sessions.session_count(), 0);
963 assert_eq!(sessions.peer_count(), 0);
964 }
965}