1use super::{
24 kx_pair::KxPair, packet_queues::AuthoredPacketQueue, replay_filter::ReplayFilter,
25 topology::Topology,
26};
27use std::{
28 fmt,
29 ops::{Add, Index, IndexMut},
30 time::Duration,
31};
32
33pub struct Session<X> {
34 pub kx_pair: KxPair,
36 pub topology: Topology<X>,
38 pub authored_packet_queue: AuthoredPacketQueue,
40 pub mean_authored_packet_period: Duration,
42 pub replay_filter: ReplayFilter,
47}
48
49pub type SessionIndex = u32;
51
52#[derive(Clone, Copy, PartialEq, Eq)]
54pub enum RelSessionIndex {
55 Current,
57 Prev,
59}
60
61impl RelSessionIndex {
62 pub fn from_session_index(
65 session_index: SessionIndex,
66 current_session_index: SessionIndex,
67 ) -> Option<Self> {
68 match current_session_index.checked_sub(session_index) {
69 Some(0) => Some(Self::Current),
70 Some(1) => Some(Self::Prev),
71 _ => None,
72 }
73 }
74}
75
76impl Add<SessionIndex> for RelSessionIndex {
77 type Output = SessionIndex;
78
79 fn add(self, other: SessionIndex) -> Self::Output {
80 match self {
81 Self::Current => other,
82 Self::Prev => other.checked_sub(1).expect("Session index underflow"),
83 }
84 }
85}
86
87pub enum SessionSlot<X> {
88 Empty,
89 KxPair(KxPair),
90 Disabled,
92 Full(Session<X>),
93}
94
95impl<X> SessionSlot<X> {
96 pub fn is_empty(&self) -> bool {
97 matches!(self, Self::Empty)
98 }
99
100 pub fn as_option(&self) -> Option<&Session<X>> {
101 match self {
102 Self::Full(session) => Some(session),
103 _ => None,
104 }
105 }
106
107 pub fn as_mut_option(&mut self) -> Option<&mut Session<X>> {
108 match self {
109 Self::Full(session) => Some(session),
110 _ => None,
111 }
112 }
113}
114
115pub struct Sessions<X> {
116 pub current: SessionSlot<X>,
117 pub prev: SessionSlot<X>,
118}
119
120impl<X> Sessions<X> {
121 pub fn is_empty(&self) -> bool {
122 self.current.is_empty() && self.prev.is_empty()
123 }
124
125 pub fn iter(&self) -> impl Iterator<Item = &Session<X>> {
126 [&self.current, &self.prev]
127 .into_iter()
128 .filter_map(|session| session.as_option())
129 }
130
131 pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (RelSessionIndex, &mut Session<X>)> {
133 [(RelSessionIndex::Current, &mut self.current), (RelSessionIndex::Prev, &mut self.prev)]
134 .into_iter()
135 .filter_map(|(index, session)| session.as_mut_option().map(|session| (index, session)))
136 }
137}
138
139impl<X> Index<RelSessionIndex> for Sessions<X> {
140 type Output = SessionSlot<X>;
141
142 fn index(&self, index: RelSessionIndex) -> &Self::Output {
143 match index {
144 RelSessionIndex::Current => &self.current,
145 RelSessionIndex::Prev => &self.prev,
146 }
147 }
148}
149
150impl<X> IndexMut<RelSessionIndex> for Sessions<X> {
151 fn index_mut(&mut self, index: RelSessionIndex) -> &mut Self::Output {
152 match index {
153 RelSessionIndex::Current => &mut self.current,
154 RelSessionIndex::Prev => &mut self.prev,
155 }
156 }
157}
158
159#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
161pub enum SessionPhase {
162 CoverToCurrent,
164 RequestsToCurrent,
167 CoverToPrev,
171 DisconnectFromPrev,
173}
174
175impl SessionPhase {
176 pub fn need_prev(self) -> bool {
178 self < Self::DisconnectFromPrev
179 }
180
181 pub fn allow_requests_and_replies(self, rel_session_index: RelSessionIndex) -> bool {
184 match rel_session_index {
185 RelSessionIndex::Prev => self < Self::CoverToPrev,
186 RelSessionIndex::Current => self >= Self::RequestsToCurrent,
187 }
188 }
189
190 pub fn default_request_session(self) -> RelSessionIndex {
192 if self >= Self::RequestsToCurrent {
193 RelSessionIndex::Current
194 } else {
195 RelSessionIndex::Prev
196 }
197 }
198}
199
200impl fmt::Display for SessionPhase {
201 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
202 match self {
203 Self::CoverToCurrent => write!(fmt, "Generating cover traffic to current mixnode set"),
204 Self::RequestsToCurrent => write!(fmt, "Building requests using current mixnode set"),
205 Self::CoverToPrev => write!(fmt, "Only sending cover traffic to previous mixnode set"),
206 Self::DisconnectFromPrev => write!(fmt, "Only using current mixnode set"),
207 }
208 }
209}
210
211#[derive(Clone, Copy, PartialEq, Eq)]
213pub struct SessionStatus {
214 pub current_index: SessionIndex,
216 pub phase: SessionPhase,
218}
219
220impl fmt::Display for SessionStatus {
221 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
222 write!(fmt, "Current index {}, phase: {}", self.current_index, self.phase)
223 }
224}