Skip to main content

moqtap_session/
state.rs

1/// Session lifecycle states.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum SessionState {
4    Connecting,
5    SetupExchange,
6    Active,
7    Draining,
8    Closed,
9}
10
11#[derive(Debug, thiserror::Error, PartialEq, Eq)]
12pub enum SessionError {
13    #[error("invalid state transition from {from:?} to {to:?}")]
14    InvalidTransition { from: SessionState, to: SessionState },
15}
16
17/// Pure state machine for MoQT session lifecycle.
18/// Transitions: Connecting → SetupExchange → Active → Draining → Closed.
19pub struct SessionStateMachine {
20    state: SessionState,
21}
22
23impl Default for SessionStateMachine {
24    fn default() -> Self {
25        Self::new()
26    }
27}
28
29impl SessionStateMachine {
30    pub fn new() -> Self {
31        Self { state: SessionState::Connecting }
32    }
33
34    pub fn state(&self) -> SessionState {
35        self.state
36    }
37
38    /// Transition: Connecting → SetupExchange.
39    pub fn on_connect(&mut self) -> Result<(), SessionError> {
40        if self.state == SessionState::Connecting {
41            self.state = SessionState::SetupExchange;
42            Ok(())
43        } else {
44            Err(SessionError::InvalidTransition {
45                from: self.state,
46                to: SessionState::SetupExchange,
47            })
48        }
49    }
50
51    /// Transition: SetupExchange → Active.
52    pub fn on_setup_complete(&mut self) -> Result<(), SessionError> {
53        if self.state == SessionState::SetupExchange {
54            self.state = SessionState::Active;
55            Ok(())
56        } else {
57            Err(SessionError::InvalidTransition { from: self.state, to: SessionState::Active })
58        }
59    }
60
61    /// Transition: Active → Draining (GOAWAY received).
62    pub fn on_goaway(&mut self) -> Result<(), SessionError> {
63        if self.state == SessionState::Active {
64            self.state = SessionState::Draining;
65            Ok(())
66        } else {
67            Err(SessionError::InvalidTransition { from: self.state, to: SessionState::Draining })
68        }
69    }
70
71    /// Transition: Active|Draining → Closed.
72    pub fn on_close(&mut self) -> Result<(), SessionError> {
73        if self.state == SessionState::Active || self.state == SessionState::Draining {
74            self.state = SessionState::Closed;
75            Ok(())
76        } else {
77            Err(SessionError::InvalidTransition { from: self.state, to: SessionState::Closed })
78        }
79    }
80}