use crate::packet::cookie_echo_chunk::CookieEchoChunk;
use crate::socket::transmission_control_block::TransmissionControlBlock;
use crate::timer::Timer;
use crate::types::Tsn;
pub(crate) struct CookieWaitState {
pub t1_init: Timer,
pub initial_tsn: Tsn,
pub verification_tag: u32,
}
pub(crate) struct CookieEchoState {
pub t1_cookie: Timer,
pub cookie_echo_chunk: CookieEchoChunk,
pub initial_tsn: Tsn,
pub verification_tag: u32,
pub tcb: TransmissionControlBlock,
}
pub(crate) struct ShutdownState {
pub t2_shutdown: Timer,
pub tcb: TransmissionControlBlock,
}
pub(crate) enum State {
Closed,
CookieWait(CookieWaitState),
CookieEchoed(CookieEchoState),
Established(TransmissionControlBlock),
ShutdownPending(TransmissionControlBlock),
ShutdownSent(ShutdownState),
ShutdownReceived(TransmissionControlBlock),
ShutdownAckSent(ShutdownState),
}
impl State {
pub fn tcb_mut(&mut self) -> Option<&mut TransmissionControlBlock> {
match self {
State::CookieEchoed(CookieEchoState { tcb, .. })
| State::Established(tcb)
| State::ShutdownPending(tcb)
| State::ShutdownSent(ShutdownState { tcb, .. })
| State::ShutdownReceived(tcb)
| State::ShutdownAckSent(ShutdownState { tcb, .. }) => Some(tcb),
_ => None,
}
}
pub fn tcb(&self) -> Option<&TransmissionControlBlock> {
match self {
State::CookieEchoed(CookieEchoState { tcb, .. })
| State::Established(tcb)
| State::ShutdownPending(tcb)
| State::ShutdownSent(ShutdownState { tcb, .. })
| State::ShutdownReceived(tcb)
| State::ShutdownAckSent(ShutdownState { tcb, .. }) => Some(tcb),
_ => None,
}
}
}
#[macro_export]
macro_rules! transition_between {
($state:expr, $($from_pat:pat),+ => $to_expr:expr) => {
$state = match std::mem::replace(&mut $state, State::Closed) {
$($from_pat => $to_expr,)+
_ => unreachable!(),
};
};
}