Skip to main content

srt/packet/
data.rs

1use bitflags::bitflags;
2use bytes::{Buf, BufMut, Bytes};
3
4use std::cmp::min;
5use std::fmt;
6
7use super::PacketParseError;
8use crate::protocol::TimeStamp;
9use crate::{MsgNumber, SeqNumber, SocketID};
10
11/// A UDT packet carrying data
12///
13/// ```ignore,
14///  0                   1                   2                   3
15///  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
16///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17///  |0|                     Packet Sequence Number                  |
18///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19///  |FF |O|                     Message Number                      |
20///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21///  |                          Time Stamp                           |
22///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23///  |                    Destination Socket ID                      |
24///  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25/// ```
26/// (from <https://tools.ietf.org/html/draft-gg-udt-03>)
27#[derive(Clone, PartialEq, Eq)]
28pub struct DataPacket {
29    /// The sequence number is packet based, so if packet n has
30    /// sequence number `i`, the next would have `i + 1`
31
32    /// Represented by a 31 bit unsigned integer, so
33    /// Sequence number is wrapped after it recahed 2^31 - 1
34    pub seq_number: SeqNumber,
35
36    /// Message location and delivery order
37    /// Represented by the first two bits in the second row of 4 bytes
38    pub message_loc: PacketLocation,
39
40    /// In order delivery, the third bit in the second row of 4 bytes
41    pub in_order_delivery: bool,
42
43    /// The message number, is the ID of the message being passed
44    /// Represented by the final 29 bits of the third row
45    /// It's only 29 bits long, so it's wrapped after 2^29 - 1
46    pub message_number: MsgNumber,
47
48    /// The timestamp, relative to when the connection was created.
49    pub timestamp: TimeStamp,
50
51    /// The dest socket id, used for UDP multiplexing
52    pub dest_sockid: SocketID,
53
54    /// The rest of the packet, the payload
55    pub payload: Bytes,
56}
57
58bitflags! {
59    /// Signifies the packet location in a message for a data packet
60    /// The bitflag just represents the first byte in the second line
61    /// FIRST | LAST means it's the only one
62    /// FIRST means it's the beginning of a longer message
63    /// 0 means it's the middle of a longer message
64    pub struct PacketLocation: u8 {
65        const MIDDLE   = 0b0000_0000;
66        const FIRST    = 0b1000_0000;
67        const LAST     = 0b0100_0000;
68        const ONLY = Self::FIRST.bits | Self::LAST.bits;
69    }
70}
71
72impl DataPacket {
73    pub fn parse(buf: &mut impl Buf) -> Result<DataPacket, PacketParseError> {
74        // get the sequence number, which is the last 31 bits of the header
75        let seq_number = SeqNumber::new_truncate(buf.get_u32());
76
77        // the first two bits of the second line (second_line >> 24) is the location
78        let message_loc = PacketLocation::from_bits_truncate(buf.bytes()[0]);
79
80        // in order delivery is the third bit
81        let in_order_delivery = (buf.bytes()[0] & 0b0010_0000) != 0;
82
83        let message_number = MsgNumber::new_truncate(buf.get_u32());
84        let timestamp = TimeStamp::from_micros(buf.get_u32());
85        let dest_sockid = SocketID(buf.get_u32());
86
87        Ok(DataPacket {
88            seq_number,
89            message_loc,
90            in_order_delivery,
91            message_number,
92            timestamp,
93            dest_sockid,
94            payload: buf.to_bytes(),
95        })
96    }
97
98    pub fn serialize(&self, into: &mut impl BufMut) {
99        assert!(self.seq_number.as_raw() & (1 << 31) == 0);
100
101        into.put_u32(self.seq_number.as_raw());
102
103        // the format is first two bits are the message location, third is in order delivery, and the rest is message number
104        // message number is garunteed have it's first three bits as zero
105        into.put_u32(
106            self.message_number.as_raw()
107                | ((u32::from(self.message_loc.bits() | (self.in_order_delivery as u8) << 5))
108                    << 24),
109        );
110        into.put_u32(self.timestamp.as_micros());
111        into.put_u32(self.dest_sockid.0);
112        into.put(&self.payload[..]);
113    }
114}
115
116impl fmt::Debug for DataPacket {
117    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
118        write!(
119            f,
120            "{{DATA sn={} loc={:?} msgno={} ts={:.4} dst={:?} payload=[len={}, start={:?}]}}",
121            self.seq_number.0,
122            self.message_loc,
123            self.message_number.0,
124            self.timestamp.as_secs_f64(),
125            self.dest_sockid,
126            self.payload.len(),
127            self.payload.slice(..min(8, self.payload.len())),
128        )
129    }
130}