maybenot/event.rs
1//! Events for [`State`](crate::state) transitions.
2
3use serde::{Deserialize, Serialize};
4
5use self::Event::*;
6use crate::{MachineId, constants::EVENT_NUM};
7use enum_map::Enum;
8use std::fmt;
9use std::hash::Hash;
10use std::slice::Iter;
11
12/// An Event may trigger a [`State`](crate::state) transition.
13#[derive(Debug, Enum, Eq, Hash, PartialEq, Clone, Copy, Serialize, Deserialize)]
14pub enum Event {
15 /// NormalRecv is when we received a normal, non-padding packet.
16 NormalRecv,
17 /// PaddingRecv is when we received a padding packet.
18 PaddingRecv,
19 /// TunnelRecv is when we received a packet in the tunnel: because it is
20 /// encrypted, we do not know if it is a normal or padding packet yet.
21 TunnelRecv,
22 /// NormalSent is when we sent a normal, non-padding packet.
23 NormalSent,
24 /// PaddingSent is when we sent a padding packet.
25 PaddingSent,
26 /// TunnelSent is when we sent a packet in the tunnel: because it is now
27 /// encrypted, we do not know if it is a normal or padding packet anymore.
28 TunnelSent,
29 /// BlockingBegin is when blocking started.
30 BlockingBegin,
31 /// BlockingEnd is when blocking ended.
32 BlockingEnd,
33 /// LimitReached is when a limit in a state is reached (internal).
34 LimitReached,
35 /// CounterZero is when a machine's counter was decremented to zero.
36 CounterZero,
37 /// TimerBegin is when a machine's timer started.
38 TimerBegin,
39 /// TimerEnd is when a machine's timer expired.
40 TimerEnd,
41 /// Signal is when a machine transitioned to [`STATE_SIGNAL`](crate::constants).
42 Signal,
43}
44
45impl fmt::Display for Event {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "{self:?}")
48 }
49}
50
51impl Event {
52 pub fn iter() -> Iter<'static, Event> {
53 static EVENTS: [Event; EVENT_NUM] = [
54 NormalRecv,
55 PaddingRecv,
56 TunnelRecv,
57 NormalSent,
58 PaddingSent,
59 TunnelSent,
60 BlockingBegin,
61 BlockingEnd,
62 LimitReached,
63 CounterZero,
64 TimerBegin,
65 TimerEnd,
66 Signal,
67 ];
68 EVENTS.iter()
69 }
70
71 // to usize
72 pub const fn to_usize(&self) -> usize {
73 *self as usize
74 }
75}
76
77/// Represents an event to be triggered in the framework.
78#[derive(Debug, Clone, Hash, Eq, PartialEq)]
79pub enum TriggerEvent {
80 /// Received non-padding packet.
81 ///
82 /// This event should be triggered once for each incoming non-padding
83 /// packet, after `TunnelRecv`, as soon as we have identified the packet as
84 /// non-padding.
85 NormalRecv,
86 /// Received padding packet.
87 ///
88 /// This event should be triggered once for each incoming padding packet,
89 /// after `TunnelRecv`, as soon as we have identified the packet as padding.
90 PaddingRecv,
91 /// Received a complete packet in the tunnel.
92 ///
93 /// This event should be triggered once for each incoming packet of any
94 /// type, as soon as possible after the packet is received from the network,
95 /// before the packet is queued, processed, or decrypted.
96 ///
97 /// (No event should be generated for a partially read packet.)
98 TunnelRecv,
99 /// Sent non-padding packet.
100 ///
101 /// This event should be triggered once for each outgoing non-padding
102 /// packet, as soon as we have decided put it on any internal queue.
103 NormalSent,
104 /// Sent padding packet.
105 ///
106 /// This event should be triggered once for each outgoing padding packet, as
107 /// soon as we have decided put it on any internal queue.
108 PaddingSent { machine: MachineId },
109 /// Sent packet in the tunnel.
110 ///
111 /// This event should be triggered once for each outgoing packet of any
112 /// type, after that packet's `NormalSent` or `PaddingSent` event, as close
113 /// as possible to the time when it is actually written to the network.
114 TunnelSent,
115 /// Blocking of outgoing traffic started by the action from a machine.
116 ///
117 /// This event should be triggered whenever the action timer for a
118 /// [`crate::action::TriggerAction::BlockOutgoing`] action expires, whether
119 /// the blocking timer is adjusted or not.
120 BlockingBegin { machine: MachineId },
121 /// Blocking of outgoing traffic has stopped.
122 ///
123 /// This event should be triggered when the framework-scoped blocking timer
124 /// expires.
125 BlockingEnd,
126 /// A machine's internal timer started, or was changed.
127 ///
128 /// This event should be triggered any time a new internal timer is started,
129 /// or whenever the expiration time of an machine's internal timer changes.
130 TimerBegin { machine: MachineId },
131 /// A machine's internal timer expired.
132 ///
133 /// (This event _should not_ be sent in response to a timer being
134 /// cancelled.)
135 TimerEnd { machine: MachineId },
136}
137
138impl TriggerEvent {
139 /// Checks if the [`TriggerEvent`] is a particular [`Event`].
140 pub fn is_event(&self, e: Event) -> bool {
141 match self {
142 TriggerEvent::NormalRecv => e == Event::NormalRecv,
143 TriggerEvent::PaddingRecv => e == Event::PaddingRecv,
144 TriggerEvent::NormalSent => e == Event::NormalSent,
145 TriggerEvent::PaddingSent { .. } => e == Event::PaddingSent,
146 TriggerEvent::BlockingBegin { .. } => e == Event::BlockingBegin,
147 TriggerEvent::BlockingEnd => e == Event::BlockingEnd,
148 TriggerEvent::TimerBegin { .. } => e == Event::TimerBegin,
149 TriggerEvent::TimerEnd { .. } => e == Event::TimerEnd,
150 TriggerEvent::TunnelSent => e == Event::TunnelSent,
151 TriggerEvent::TunnelRecv => e == Event::TunnelRecv,
152 }
153 }
154}
155
156impl fmt::Display for TriggerEvent {
157 // note that we don't share the private MachineId
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 match self {
160 TriggerEvent::NormalRecv => write!(f, "rn"),
161 TriggerEvent::PaddingRecv => write!(f, "rp"),
162 TriggerEvent::TunnelRecv => write!(f, "rt"),
163 TriggerEvent::NormalSent => write!(f, "sn"),
164 TriggerEvent::PaddingSent { .. } => write!(f, "sp"),
165 TriggerEvent::TunnelSent => write!(f, "st"),
166 TriggerEvent::BlockingBegin { .. } => write!(f, "bb"),
167 TriggerEvent::BlockingEnd => write!(f, "be"),
168 TriggerEvent::TimerBegin { .. } => write!(f, "tb"),
169 TriggerEvent::TimerEnd { .. } => write!(f, "te"),
170 }
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use crate::event::*;
177 #[test]
178 fn v1_events() {
179 assert_eq!(Event::NormalRecv.to_string(), "NormalRecv");
180 assert_eq!(Event::PaddingRecv.to_string(), "PaddingRecv");
181 assert_eq!(Event::NormalSent.to_string(), "NormalSent");
182 assert_eq!(Event::PaddingSent.to_string(), "PaddingSent");
183 assert_eq!(Event::BlockingBegin.to_string(), "BlockingBegin");
184 assert_eq!(Event::BlockingEnd.to_string(), "BlockingEnd");
185 assert_eq!(Event::LimitReached.to_string(), "LimitReached");
186 }
187
188 #[test]
189 fn v2_events() {
190 assert_eq!(Event::CounterZero.to_string(), "CounterZero");
191 assert_eq!(Event::TimerBegin.to_string(), "TimerBegin");
192 assert_eq!(Event::TimerEnd.to_string(), "TimerEnd");
193 assert_eq!(Event::TunnelRecv.to_string(), "TunnelRecv");
194 assert_eq!(Event::TunnelSent.to_string(), "TunnelSent");
195 assert_eq!(Event::Signal.to_string(), "Signal");
196 }
197}