Skip to main content

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}