srt_protocol/packet/
data.rs

1use std::cmp::min;
2use std::{convert::TryFrom, fmt};
3
4use bitflags::bitflags;
5use bytes::{Buf, BufMut, Bytes};
6
7use super::{MsgNumber, PacketParseError, SeqNumber, SocketId, TimeStamp};
8
9/// A UDT packet carrying data
10///
11/// ```ignore,
12///  0                   1                   2                   3
13///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
14///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15///  |0|                     Packet Sequence Number                  |
16///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17///  |FF |O|K K|R|               Message Number                      |
18///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19///  |                          Time Stamp                           |
20///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21///  |                    Destination Socket ID                      |
22///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23/// ```
24/// (from <https://tools.ietf.org/html/draft-gg-udt-03>)
25#[derive(Clone, PartialEq, Eq)]
26pub struct DataPacket {
27    /// The sequence number is packet based, so if packet n has
28    /// sequence number `i`, the next would have `i + 1`
29
30    /// Represented by a 31 bit unsigned integer, so
31    /// Sequence number is wrapped after it recahed 2^31 - 1
32    pub seq_number: SeqNumber,
33
34    /// Message location and delivery order
35    /// Represented by the first two bits in the second row of 4 bytes
36    pub message_loc: PacketLocation,
37
38    /// In order delivery, the third bit in the second row of 4 bytes
39    pub in_order_delivery: bool,
40
41    /// row 2 bits 4+5, which key it's encrypted with, if it is
42    pub encryption: DataEncryption,
43
44    // row 2 bit 6, if the packet was retransmitteed
45    pub retransmitted: bool,
46
47    /// The message number, is the ID of the message being passed
48    /// Represented by the final 26 bits of the third row
49    /// It's only 26 bits long, so it's wrapped after 2^26 - 1
50    pub message_number: MsgNumber,
51
52    /// The timestamp, relative to when the connection was created.
53    pub timestamp: TimeStamp,
54
55    /// The dest socket id, used for UDP multiplexing
56    pub dest_sockid: SocketId,
57
58    /// The rest of the packet, the payload
59    pub payload: Bytes,
60}
61
62impl DataPacket {
63    pub const HEADER_SIZE: usize = super::Packet::HEADER_SIZE.0 as usize;
64}
65
66bitflags! {
67    /// Signifies the packet location in a message for a data packet
68    /// The bitflag just represents the first byte in the second line
69    /// FIRST | LAST means it's the only one
70    /// FIRST means it's the beginning of a longer message
71    /// 0 means it's the middle of a longer message
72    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
73    pub struct PacketLocation: u8 {
74        const MIDDLE   = 0b0000_0000;
75        const FIRST    = 0b1000_0000;
76        const LAST     = 0b0100_0000;
77        const ONLY = Self::FIRST.bits() | Self::LAST.bits();
78    }
79}
80
81#[derive(Copy, Debug, Clone, PartialEq, Eq)]
82pub enum DataEncryption {
83    None = 0b0000_0000,
84    Even = 0b0000_1000,
85    Odd = 0b0001_0000,
86}
87
88impl DataPacket {
89    pub fn parse(buf: &mut impl Buf) -> Result<DataPacket, PacketParseError> {
90        // get the sequence number, which is the last 31 bits of the header
91        let seq_number = SeqNumber::new_truncate(buf.get_u32());
92
93        let second_word_first_byte = buf.get_u32();
94        let [swb1, _, _, _] = second_word_first_byte.to_be_bytes();
95
96        // the first two bits of the second line (second_line >> 24) is the location
97        let message_loc = PacketLocation::from_bits_truncate(swb1);
98        let encryption = DataEncryption::try_from(swb1)?;
99        let retransmitted = (swb1 >> 2) & 1 == 1;
100
101        // in order delivery is the third bit
102        let in_order_delivery = (swb1 & 0b0010_0000) != 0;
103
104        let message_number = MsgNumber::new_truncate(second_word_first_byte);
105        let timestamp = TimeStamp::from_micros(buf.get_u32());
106        let dest_sockid = SocketId(buf.get_u32());
107
108        Ok(DataPacket {
109            seq_number,
110            message_loc,
111            in_order_delivery,
112            encryption,
113            retransmitted,
114            message_number,
115            timestamp,
116            dest_sockid,
117            payload: Buf::copy_to_bytes(buf, buf.remaining()),
118        })
119    }
120
121    pub fn serialize(&self, into: &mut impl BufMut) {
122        assert!(self.seq_number.as_raw() & (1 << 31) == 0);
123
124        into.put_u32(self.seq_number.as_raw());
125
126        // the format is first two bits are the message location, third is in order delivery, and the rest is message number
127        // message number is guaranteed to have it's first three bits as zero
128        into.put_u32(
129            self.message_number.as_raw()
130                | ((u32::from(
131                    self.message_loc.bits() // first 2 bits
132                        | (self.in_order_delivery as u8) << 5 // 3rd bit
133                        | self.encryption as u8 // 4th-5th bits
134                        | (self.retransmitted as u8) << 2, // 6th bit
135                )) << 24),
136        );
137        into.put_u32(self.timestamp.as_micros());
138        into.put_u32(self.dest_sockid.0);
139        into.put(&self.payload[..]);
140    }
141
142    pub fn wire_size(&self) -> usize {
143        // 20 bytes IPv4 + 8 bytes of UDP + 16 bytes SRT header.
144        Self::HEADER_SIZE + self.payload.len()
145    }
146}
147
148impl TryFrom<u8> for DataEncryption {
149    type Error = PacketParseError;
150    fn try_from(value: u8) -> Result<Self, Self::Error> {
151        Ok(match value & 0b0001_1000 {
152            0b0000_0000 => DataEncryption::None,
153            0b0000_1000 => DataEncryption::Even,
154            0b0001_0000 => DataEncryption::Odd,
155            e => return Err(PacketParseError::BadDataEncryption(e)),
156        })
157    }
158}
159
160impl fmt::Debug for DataPacket {
161    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
162        write!(
163            f,
164            "{{DATA sn={} loc={:?} enc={:?} re={:?} msgno={} ts={:?} dst={:?} payload=[len={}, start={:?}]}}",
165            self.seq_number.0,
166            self.message_loc,
167            self.encryption,
168            self.retransmitted,
169            self.message_number.0,
170            self.timestamp,
171            self.dest_sockid,
172            self.payload.len(),
173            self.payload.slice(..min(8, self.payload.len())),
174        )
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use super::*;
181    use proptest::prelude::*;
182    use std::io::Cursor;
183
184    proptest! {
185        #[test]
186        fn data_enc(i: u8) {
187            match DataEncryption::try_from(i) {
188                Err(PacketParseError::BadDataEncryption(e)) => {
189                    assert_eq!(i & 0b0001_1000, e);
190                    assert_eq!(e, 0b0001_1000);
191                }
192                Err(e) => panic!("{}", e),
193                Ok(de) => {
194                    assert_eq!(de as u8, i & 0b0001_1000);
195                }
196            }
197
198        }
199        #[test]
200        fn test_datapacket(message_loc: u8, enc in 0u8..3u8, retransmitted: bool, in_order_delivery: bool) {
201            let message_loc = PacketLocation::from_bits_truncate(message_loc);
202            let encryption = DataEncryption::try_from(enc << 3).unwrap();
203            let dp = DataPacket {
204                seq_number: SeqNumber::new_truncate(123),
205                message_loc,
206                in_order_delivery,
207                encryption,
208                retransmitted,
209                message_number: MsgNumber::new_truncate(123),
210                timestamp: TimeStamp::from_micros(0),
211                dest_sockid: SocketId(0),
212                payload: Bytes::new(),
213            };
214            let mut v = vec![];
215            dp.serialize(&mut v);
216            let dp2 = DataPacket::parse(&mut Cursor::new(&v)).unwrap();
217
218            assert_eq!(dp, dp2);
219
220            let mut v2 = vec![];
221            dp2.serialize(&mut v2);
222            assert_eq!(v, v2);
223        }
224    }
225}