Skip to main content

dcp/multiplex/
header.rs

1//! Stream header for multiplexing.
2//!
3//! Defines the header format for multiplexed streams.
4
5use bytes::{Buf, BufMut, Bytes, BytesMut};
6
7/// Stream header size in bytes
8pub const STREAM_HEADER_SIZE: usize = 8;
9
10/// Stream flags for control
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
12pub struct StreamFlags(u8);
13
14impl StreamFlags {
15    const KNOWN_MASK: u8 = Self::FIN.0 | Self::RST.0 | Self::ACK.0 | Self::SYN.0;
16
17    /// No flags set
18    pub const NONE: StreamFlags = StreamFlags(0);
19    /// FIN - stream is closing
20    pub const FIN: StreamFlags = StreamFlags(1);
21    /// RST - stream reset/error
22    pub const RST: StreamFlags = StreamFlags(2);
23    /// ACK - acknowledgment
24    pub const ACK: StreamFlags = StreamFlags(4);
25    /// SYN - stream open request
26    pub const SYN: StreamFlags = StreamFlags(8);
27
28    /// Create flags from raw byte
29    pub fn from_byte(b: u8) -> Self {
30        StreamFlags(b)
31    }
32
33    /// Get raw byte value
34    pub fn as_byte(self) -> u8 {
35        self.0
36    }
37
38    /// Check if no flags are set.
39    pub fn is_empty(self) -> bool {
40        self.0 == 0
41    }
42
43    /// Check if any currently undefined flag bits are set.
44    pub fn has_unknown_bits(self) -> bool {
45        self.0 & !Self::KNOWN_MASK != 0
46    }
47
48    /// Check if FIN flag is set
49    pub fn is_fin(self) -> bool {
50        self.0 & Self::FIN.0 != 0
51    }
52
53    /// Check if RST flag is set
54    pub fn is_rst(self) -> bool {
55        self.0 & Self::RST.0 != 0
56    }
57
58    /// Check if ACK flag is set
59    pub fn is_ack(self) -> bool {
60        self.0 & Self::ACK.0 != 0
61    }
62
63    /// Check if SYN flag is set
64    pub fn is_syn(self) -> bool {
65        self.0 & Self::SYN.0 != 0
66    }
67
68    /// Combine flags
69    pub fn with(self, other: StreamFlags) -> StreamFlags {
70        StreamFlags(self.0 | other.0)
71    }
72}
73
74impl std::ops::BitOr for StreamFlags {
75    type Output = Self;
76
77    fn bitor(self, rhs: Self) -> Self::Output {
78        StreamFlags(self.0 | rhs.0)
79    }
80}
81
82/// Stream header for multiplexing
83///
84/// Format (8 bytes):
85/// - stream_id: u16 (0 = control, 1-65535 = data streams)
86/// - flags: u8 (FIN=1, RST=2, ACK=4, SYN=8)
87/// - reserved: u8
88/// - length: u32 (payload length, big-endian)
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub struct StreamHeader {
91    /// Stream ID (0 = control, 1-65535 = data streams)
92    pub stream_id: u16,
93    /// Flags: FIN=1, RST=2, ACK=4, SYN=8
94    pub flags: StreamFlags,
95    /// Reserved for future use
96    pub reserved: u8,
97    /// Payload length
98    pub length: u32,
99}
100
101impl StreamHeader {
102    /// Control stream ID
103    pub const CONTROL_STREAM: u16 = 0;
104
105    /// Maximum stream ID
106    pub const MAX_STREAM_ID: u16 = 65535;
107
108    /// Create a new stream header
109    pub fn new(stream_id: u16, flags: StreamFlags, length: u32) -> Self {
110        Self {
111            stream_id,
112            flags,
113            reserved: 0,
114            length,
115        }
116    }
117
118    /// Create a data header
119    pub fn data(stream_id: u16, length: u32) -> Self {
120        Self::new(stream_id, StreamFlags::NONE, length)
121    }
122
123    /// Create a SYN header (open stream)
124    pub fn syn(stream_id: u16) -> Self {
125        Self::new(stream_id, StreamFlags::SYN, 0)
126    }
127
128    /// Create a FIN header (close stream)
129    pub fn fin(stream_id: u16) -> Self {
130        Self::new(stream_id, StreamFlags::FIN, 0)
131    }
132
133    /// Create a RST header (reset stream)
134    pub fn rst(stream_id: u16) -> Self {
135        Self::new(stream_id, StreamFlags::RST, 0)
136    }
137
138    /// Create an ACK header
139    pub fn ack(stream_id: u16) -> Self {
140        Self::new(stream_id, StreamFlags::ACK, 0)
141    }
142
143    /// Check if this is a control stream message
144    pub fn is_control(&self) -> bool {
145        self.stream_id == Self::CONTROL_STREAM
146    }
147
148    /// Encode header to bytes
149    pub fn encode(&self, dst: &mut BytesMut) {
150        dst.put_u16(self.stream_id);
151        dst.put_u8(self.flags.as_byte());
152        dst.put_u8(self.reserved);
153        dst.put_u32(self.length);
154    }
155
156    /// Encode header to a new BytesMut
157    pub fn to_bytes(&self) -> Bytes {
158        let mut buf = BytesMut::with_capacity(STREAM_HEADER_SIZE);
159        self.encode(&mut buf);
160        buf.freeze()
161    }
162
163    /// Decode header from bytes
164    pub fn decode(src: &[u8]) -> Option<Self> {
165        if src.len() < STREAM_HEADER_SIZE {
166            return None;
167        }
168
169        Some(Self {
170            stream_id: u16::from_be_bytes([src[0], src[1]]),
171            flags: StreamFlags::from_byte(src[2]),
172            reserved: src[3],
173            length: u32::from_be_bytes([src[4], src[5], src[6], src[7]]),
174        })
175    }
176
177    /// Decode header from BytesMut, advancing the buffer
178    pub fn decode_from(src: &mut BytesMut) -> Option<Self> {
179        if src.len() < STREAM_HEADER_SIZE {
180            return None;
181        }
182
183        let header = Self::decode(src)?;
184        src.advance(STREAM_HEADER_SIZE);
185        Some(header)
186    }
187
188    /// Total frame size (header + payload)
189    pub fn frame_size(&self) -> usize {
190        STREAM_HEADER_SIZE + self.length as usize
191    }
192}
193
194#[cfg(test)]
195mod tests {
196    use super::*;
197
198    #[test]
199    fn test_stream_flags() {
200        let flags = StreamFlags::FIN | StreamFlags::ACK;
201        assert!(flags.is_fin());
202        assert!(flags.is_ack());
203        assert!(!flags.is_rst());
204        assert!(!flags.is_syn());
205    }
206
207    #[test]
208    fn test_stream_header_encode_decode() {
209        let header = StreamHeader::new(42, StreamFlags::FIN, 1234);
210        let mut buf = BytesMut::new();
211        header.encode(&mut buf);
212
213        assert_eq!(buf.len(), STREAM_HEADER_SIZE);
214
215        let decoded = StreamHeader::decode(&buf).unwrap();
216        assert_eq!(decoded.stream_id, 42);
217        assert!(decoded.flags.is_fin());
218        assert_eq!(decoded.length, 1234);
219    }
220
221    #[test]
222    fn test_stream_header_helpers() {
223        let syn = StreamHeader::syn(1);
224        assert!(syn.flags.is_syn());
225        assert_eq!(syn.stream_id, 1);
226
227        let fin = StreamHeader::fin(2);
228        assert!(fin.flags.is_fin());
229        assert_eq!(fin.stream_id, 2);
230
231        let rst = StreamHeader::rst(3);
232        assert!(rst.flags.is_rst());
233        assert_eq!(rst.stream_id, 3);
234    }
235
236    #[test]
237    fn test_control_stream() {
238        let header = StreamHeader::data(StreamHeader::CONTROL_STREAM, 100);
239        assert!(header.is_control());
240
241        let header = StreamHeader::data(1, 100);
242        assert!(!header.is_control());
243    }
244
245    #[test]
246    fn test_frame_size() {
247        let header = StreamHeader::data(1, 100);
248        assert_eq!(header.frame_size(), STREAM_HEADER_SIZE + 100);
249    }
250}