srt_protocol/packet/
mod.rs

1// Packet structures
2// see https://tools.ietf.org/html/draft-gg-udt-03#page-5
3
4mod control;
5mod data;
6mod error;
7mod modular_num;
8mod msg_number;
9mod seq_number;
10mod socket_id;
11mod time;
12
13pub use control::*;
14pub use data::*;
15pub use error::*;
16pub use msg_number::*;
17pub use seq_number::*;
18pub use socket_id::*;
19pub use time::*;
20
21use std::{
22    fmt::{self, Debug, Formatter},
23    io,
24    net::SocketAddr,
25};
26
27use bytes::{Buf, BufMut};
28
29use super::options::PacketSize;
30
31/// Represents A UDT/SRT packet
32#[derive(Clone, PartialEq, Eq)]
33#[allow(clippy::large_enum_variant)]
34pub enum Packet {
35    Data(DataPacket),
36    Control(ControlPacket),
37}
38
39impl Packet {
40    const IPV4_HEADER_SIZE: u64 = 20;
41    const UDP_HEADER_SIZE: u64 = 8;
42    const SRT_HEADER_SIZE: u64 = 16;
43
44    pub const HEADER_SIZE: PacketSize =
45        PacketSize(Self::IPV4_HEADER_SIZE + Self::UDP_HEADER_SIZE + Self::SRT_HEADER_SIZE);
46
47    pub fn timestamp(&self) -> TimeStamp {
48        match *self {
49            Packet::Data(DataPacket { timestamp, .. })
50            | Packet::Control(ControlPacket { timestamp, .. }) => timestamp,
51        }
52    }
53
54    pub fn dest_sockid(&self) -> SocketId {
55        match *self {
56            Packet::Data(DataPacket { dest_sockid, .. })
57            | Packet::Control(ControlPacket { dest_sockid, .. }) => dest_sockid,
58        }
59    }
60
61    pub fn data(&self) -> Option<&DataPacket> {
62        if let Packet::Data(d) = self {
63            Some(d)
64        } else {
65            None
66        }
67    }
68
69    pub fn control(&self) -> Option<&ControlPacket> {
70        if let Packet::Control(c) = self {
71            Some(c)
72        } else {
73            None
74        }
75    }
76
77    pub fn is_handshake(&self) -> bool {
78        matches!(
79            self,
80            Packet::Control(ControlPacket {
81                control_type: ControlTypes::Handshake(_),
82                ..
83            })
84        )
85    }
86
87    /// Wire size of the packet, including IP+UDP+SRT headers
88    pub fn wire_size(&self) -> usize {
89        match self {
90            Packet::Data(d) => d.wire_size(),
91            Packet::Control(c) => c.wire_size(),
92        }
93    }
94
95    pub fn parse<T: Buf>(buf: &mut T, is_ipv6: bool) -> Result<Packet, PacketParseError> {
96        // Buffer must be at least 16 bytes,
97        // the length of a header packet
98        if buf.remaining() < 16 {
99            return Err(PacketParseError::NotEnoughData);
100        }
101
102        // peek at the first byte to check if it's data or control
103        let first = buf.chunk()[0];
104
105        // Check if the first bit is one or zero;
106        // if it's one it's a cotnrol packet,
107        // if zero it's a data packet
108        Ok(if (first & 0x80) == 0 {
109            Packet::Data(DataPacket::parse(buf)?)
110        } else {
111            Packet::Control(ControlPacket::parse(buf, is_ipv6)?)
112        })
113    }
114
115    pub fn serialize<T: BufMut>(&self, into: &mut T) {
116        match *self {
117            Packet::Control(ref control) => {
118                control.serialize(into);
119            }
120            Packet::Data(ref data) => {
121                data.serialize(into);
122            }
123        }
124    }
125}
126
127impl From<DataPacket> for Packet {
128    fn from(dp: DataPacket) -> Self {
129        Packet::Data(dp)
130    }
131}
132
133impl From<ControlPacket> for Packet {
134    fn from(cp: ControlPacket) -> Self {
135        Packet::Control(cp)
136    }
137}
138
139impl Debug for Packet {
140    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
141        match self {
142            Packet::Data(dp) => write!(f, "{dp:?}"),
143            Packet::Control(cp) => write!(f, "{cp:?}"),
144        }
145    }
146}
147
148#[derive(Debug)]
149pub enum ReceivePacketError {
150    Parse(PacketParseError),
151    Io(io::Error),
152}
153
154impl From<io::Error> for ReceivePacketError {
155    fn from(error: io::Error) -> Self {
156        ReceivePacketError::Io(error)
157    }
158}
159
160impl From<PacketParseError> for ReceivePacketError {
161    fn from(error: PacketParseError) -> Self {
162        ReceivePacketError::Parse(error)
163    }
164}
165
166impl fmt::Display for ReceivePacketError {
167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168        use ReceivePacketError::*;
169        match self {
170            Parse(e) => <PacketParseError as fmt::Display>::fmt(e, f),
171            Io(e) => <io::Error as fmt::Display>::fmt(e, f),
172        }
173    }
174}
175
176impl std::error::Error for ReceivePacketError {
177    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
178        use ReceivePacketError::*;
179        match self {
180            Parse(e) => Some(e),
181            Io(e) => Some(e),
182        }
183    }
184}
185
186// NOTE: Eq, PartialEq are only here to accommodate structural comparison in tests without losing
187//  the ability to surface network errors for logging purposes, improve on this as needed, but don't
188//  remove.
189impl Eq for ReceivePacketError {}
190impl PartialEq for ReceivePacketError {
191    fn eq(&self, other: &Self) -> bool {
192        use ReceivePacketError::*;
193        match (self, other) {
194            (Parse(s), Parse(o)) => s.eq(o),
195            (Io(s), Io(o)) => s.kind().eq(&o.kind()) && s.raw_os_error().eq(&o.raw_os_error()),
196            _ => false,
197        }
198    }
199}
200
201pub type ReceivePacketResult = Result<(Packet, SocketAddr), ReceivePacketError>;