1#[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
17pub 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 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 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 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 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}