1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
use std::cmp::min;
use std::{convert::TryFrom, fmt};

use bitflags::bitflags;
use bytes::{Buf, BufMut, Bytes};

use super::{MsgNumber, PacketParseError, SeqNumber, SocketId, TimeStamp};

/// A UDT packet carrying data
///
/// ```ignore,
///  0                   1                   2                   3
///  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
///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///  |0|                     Packet Sequence Number                  |
///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///  |FF |O|K K|R|               Message Number                      |
///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///  |                          Time Stamp                           |
///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///  |                    Destination Socket ID                      |
///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// ```
/// (from <https://tools.ietf.org/html/draft-gg-udt-03>)
#[derive(Clone, PartialEq, Eq)]
pub struct DataPacket {
    /// The sequence number is packet based, so if packet n has
    /// sequence number `i`, the next would have `i + 1`

    /// Represented by a 31 bit unsigned integer, so
    /// Sequence number is wrapped after it recahed 2^31 - 1
    pub seq_number: SeqNumber,

    /// Message location and delivery order
    /// Represented by the first two bits in the second row of 4 bytes
    pub message_loc: PacketLocation,

    /// In order delivery, the third bit in the second row of 4 bytes
    pub in_order_delivery: bool,

    /// row 2 bits 4+5, which key it's encrypted with, if it is
    pub encryption: DataEncryption,

    // row 2 bit 6, if the packet was retransmitteed
    pub retransmitted: bool,

    /// The message number, is the ID of the message being passed
    /// Represented by the final 26 bits of the third row
    /// It's only 26 bits long, so it's wrapped after 2^26 - 1
    pub message_number: MsgNumber,

    /// The timestamp, relative to when the connection was created.
    pub timestamp: TimeStamp,

    /// The dest socket id, used for UDP multiplexing
    pub dest_sockid: SocketId,

    /// The rest of the packet, the payload
    pub payload: Bytes,
}

impl DataPacket {
    pub const HEADER_SIZE: usize = super::Packet::HEADER_SIZE.0 as usize;
}

bitflags! {
    /// Signifies the packet location in a message for a data packet
    /// The bitflag just represents the first byte in the second line
    /// FIRST | LAST means it's the only one
    /// FIRST means it's the beginning of a longer message
    /// 0 means it's the middle of a longer message
    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
    pub struct PacketLocation: u8 {
        const MIDDLE   = 0b0000_0000;
        const FIRST    = 0b1000_0000;
        const LAST     = 0b0100_0000;
        const ONLY = Self::FIRST.bits() | Self::LAST.bits();
    }
}

#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub enum DataEncryption {
    None = 0b0000_0000,
    Even = 0b0000_1000,
    Odd = 0b0001_0000,
}

impl DataPacket {
    pub fn parse(buf: &mut impl Buf) -> Result<DataPacket, PacketParseError> {
        // get the sequence number, which is the last 31 bits of the header
        let seq_number = SeqNumber::new_truncate(buf.get_u32());

        let second_word_first_byte = buf.get_u32();
        let [swb1, _, _, _] = second_word_first_byte.to_be_bytes();

        // the first two bits of the second line (second_line >> 24) is the location
        let message_loc = PacketLocation::from_bits_truncate(swb1);
        let encryption = DataEncryption::try_from(swb1)?;
        let retransmitted = (swb1 >> 2) & 1 == 1;

        // in order delivery is the third bit
        let in_order_delivery = (swb1 & 0b0010_0000) != 0;

        let message_number = MsgNumber::new_truncate(second_word_first_byte);
        let timestamp = TimeStamp::from_micros(buf.get_u32());
        let dest_sockid = SocketId(buf.get_u32());

        Ok(DataPacket {
            seq_number,
            message_loc,
            in_order_delivery,
            encryption,
            retransmitted,
            message_number,
            timestamp,
            dest_sockid,
            payload: Buf::copy_to_bytes(buf, buf.remaining()),
        })
    }

    pub fn serialize(&self, into: &mut impl BufMut) {
        assert!(self.seq_number.as_raw() & (1 << 31) == 0);

        into.put_u32(self.seq_number.as_raw());

        // the format is first two bits are the message location, third is in order delivery, and the rest is message number
        // message number is guaranteed to have it's first three bits as zero
        into.put_u32(
            self.message_number.as_raw()
                | ((u32::from(
                    self.message_loc.bits() // first 2 bits
                        | (self.in_order_delivery as u8) << 5 // 3rd bit
                        | self.encryption as u8 // 4th-5th bits
                        | (self.retransmitted as u8) << 2, // 6th bit
                )) << 24),
        );
        into.put_u32(self.timestamp.as_micros());
        into.put_u32(self.dest_sockid.0);
        into.put(&self.payload[..]);
    }

    pub fn wire_size(&self) -> usize {
        // 20 bytes IPv4 + 8 bytes of UDP + 16 bytes SRT header.
        Self::HEADER_SIZE + self.payload.len()
    }
}

impl TryFrom<u8> for DataEncryption {
    type Error = PacketParseError;
    fn try_from(value: u8) -> Result<Self, Self::Error> {
        Ok(match value & 0b0001_1000 {
            0b0000_0000 => DataEncryption::None,
            0b0000_1000 => DataEncryption::Even,
            0b0001_0000 => DataEncryption::Odd,
            e => return Err(PacketParseError::BadDataEncryption(e)),
        })
    }
}

impl fmt::Debug for DataPacket {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            f,
            "{{DATA sn={} loc={:?} enc={:?} re={:?} msgno={} ts={:?} dst={:?} payload=[len={}, start={:?}]}}",
            self.seq_number.0,
            self.message_loc,
            self.encryption,
            self.retransmitted,
            self.message_number.0,
            self.timestamp,
            self.dest_sockid,
            self.payload.len(),
            self.payload.slice(..min(8, self.payload.len())),
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use proptest::prelude::*;
    use std::io::Cursor;

    proptest! {
        #[test]
        fn data_enc(i: u8) {
            match DataEncryption::try_from(i) {
                Err(PacketParseError::BadDataEncryption(e)) => {
                    assert_eq!(i & 0b0001_1000, e);
                    assert_eq!(e, 0b0001_1000);
                }
                Err(e) => panic!("{}", e),
                Ok(de) => {
                    assert_eq!(de as u8, i & 0b0001_1000);
                }
            }

        }
        #[test]
        fn test_datapacket(message_loc: u8, enc in 0u8..3u8, retransmitted: bool, in_order_delivery: bool) {
            let message_loc = PacketLocation::from_bits_truncate(message_loc);
            let encryption = DataEncryption::try_from(enc << 3).unwrap();
            let dp = DataPacket {
                seq_number: SeqNumber::new_truncate(123),
                message_loc,
                in_order_delivery,
                encryption,
                retransmitted,
                message_number: MsgNumber::new_truncate(123),
                timestamp: TimeStamp::from_micros(0),
                dest_sockid: SocketId(0),
                payload: Bytes::new(),
            };
            let mut v = vec![];
            dp.serialize(&mut v);
            let dp2 = DataPacket::parse(&mut Cursor::new(&v)).unwrap();

            assert_eq!(dp, dp2);

            let mut v2 = vec![];
            dp2.serialize(&mut v2);
            assert_eq!(v, v2);
        }
    }
}