Skip to main content

typhoon/tailer/
flags.rs

1#[cfg(test)]
2#[path = "../../tests/tailer/flags.rs"]
3mod tests;
4
5use bitflags::bitflags;
6
7bitflags! {
8    /// Packet type flags for the tailer FG field.
9    /// Normally only one flag should be set, but a health check packet can be embedded into a data packet (shadowride).
10    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11    pub struct PacketFlags: u8 {
12        /// Handshake packet (128).
13        const HANDSHAKE = 0b1000_0000;
14        /// Health check packet (64).
15        const HEALTH_CHECK = 0b0100_0000;
16        /// Data packet (32).
17        const DATA = 0b0010_0000;
18        /// Decoy packet (16).
19        const DECOY = 0b0001_0000;
20        /// Termination packet (8).
21        const TERMINATION = 0b0000_1000;
22    }
23}
24
25impl PacketFlags {
26    /// Check if this is a shadowride packet (data + health check).
27    #[inline]
28    pub fn is_shadowride(&self) -> bool {
29        self.contains(Self::DATA | Self::HEALTH_CHECK)
30    }
31
32    /// Check if this packet carries payload data.
33    #[inline]
34    pub fn has_payload(&self) -> bool {
35        self.contains(Self::DATA)
36    }
37
38    /// Check if this packet should be discarded by flow manager (decoy).
39    #[inline]
40    pub fn is_discardable(&self) -> bool {
41        self.contains(Self::DECOY)
42    }
43
44    /// Check if this is a termination packet.
45    #[inline]
46    pub fn is_termination(&self) -> bool {
47        self.contains(Self::TERMINATION)
48    }
49}
50
51/// Return codes for handshake and termination packets (CD field).
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53#[repr(u8)]
54pub enum ReturnCode {
55    /// No error (successful handshake or graceful termination).
56    Success = 0,
57    /// Client and server major version numbers are incompatible.
58    VersionMismatch = 1,
59    /// Connection decayed: health check exchange timed out after all retries.
60    ConnectionDecayed = 2,
61    /// Unknown error.
62    UnknownError = 101,
63}
64
65impl From<u8> for ReturnCode {
66    fn from(value: u8) -> Self {
67        match value {
68            0 => ReturnCode::Success,
69            1 => ReturnCode::VersionMismatch,
70            2 => ReturnCode::ConnectionDecayed,
71            _ => ReturnCode::UnknownError,
72        }
73    }
74}
75
76impl From<ReturnCode> for u8 {
77    fn from(code: ReturnCode) -> Self {
78        code as u8
79    }
80}