use super::{Error, Result, SEQ_NUMBER_MASK, SRT_HEADER_LEN, be32, put_be32};
const MESSAGE_NUMBER_BITS: u32 = 26;
const MESSAGE_NUMBER_MASK: u32 = (1 << MESSAGE_NUMBER_BITS) - 1;
const PP_MIDDLE: u8 = 0b00;
const PP_LAST: u8 = 0b01;
const PP_FIRST: u8 = 0b10;
const PP_SOLO: u8 = 0b11;
const KK_NOT_ENCRYPTED: u8 = 0b00;
const KK_EVEN: u8 = 0b01;
const KK_ODD: u8 = 0b10;
#[cfg(test)]
const KK_CONTROL_ONLY: u8 = 0b11;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum PacketPosition {
First,
Middle,
Last,
Solo,
}
impl PacketPosition {
pub fn from_bits(v: u8) -> Self {
match v & 0b11 {
PP_FIRST => PacketPosition::First,
PP_LAST => PacketPosition::Last,
PP_SOLO => PacketPosition::Solo,
_ => PacketPosition::Middle, }
}
pub fn to_bits(self) -> u8 {
match self {
PacketPosition::First => PP_FIRST,
PacketPosition::Middle => PP_MIDDLE,
PacketPosition::Last => PP_LAST,
PacketPosition::Solo => PP_SOLO,
}
}
pub fn name(&self) -> &'static str {
match self {
PacketPosition::First => "first",
PacketPosition::Middle => "middle",
PacketPosition::Last => "last",
PacketPosition::Solo => "solo",
}
}
}
broadcast_common::impl_spec_display!(PacketPosition);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub enum EncryptionKeyField {
NotEncrypted,
Even,
Odd,
Reserved(u8),
}
impl EncryptionKeyField {
pub fn from_bits(v: u8) -> Self {
match v & 0b11 {
KK_NOT_ENCRYPTED => EncryptionKeyField::NotEncrypted,
KK_EVEN => EncryptionKeyField::Even,
KK_ODD => EncryptionKeyField::Odd,
other => EncryptionKeyField::Reserved(other),
}
}
pub fn to_bits(self) -> u8 {
match self {
EncryptionKeyField::NotEncrypted => KK_NOT_ENCRYPTED,
EncryptionKeyField::Even => KK_EVEN,
EncryptionKeyField::Odd => KK_ODD,
EncryptionKeyField::Reserved(v) => v & 0b11,
}
}
pub fn name(&self) -> &'static str {
match self {
EncryptionKeyField::NotEncrypted => "not encrypted",
EncryptionKeyField::Even => "even key",
EncryptionKeyField::Odd => "odd key",
EncryptionKeyField::Reserved(_) => "reserved",
}
}
}
broadcast_common::impl_spec_display!(EncryptionKeyField, Reserved);
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct DataPacket<'a> {
pub seq_number: u32,
pub position: PacketPosition,
pub in_order: bool,
pub key_flag: EncryptionKeyField,
pub retransmitted: bool,
pub message_number: u32,
pub timestamp: u32,
pub dest_socket_id: u32,
pub data: &'a [u8],
}
const KK_SHIFT: u32 = 27;
const PP_SHIFT: u32 = 30;
const O_SHIFT: u32 = 29;
const R_SHIFT: u32 = 26;
impl<'a> DataPacket<'a> {
pub fn parse(bytes: &'a [u8]) -> Result<Self> {
if bytes.len() < SRT_HEADER_LEN {
return Err(Error::BufferTooShort {
need: SRT_HEADER_LEN,
have: bytes.len(),
what: "SRT data packet header",
});
}
let word0 = be32(bytes, 0);
if word0 & super::F_BIT != 0 {
return Err(Error::WrongPacketKind {
expected: "data packet (F=0)",
});
}
let word1 = be32(bytes, 4);
let seq_number = word0 & SEQ_NUMBER_MASK;
let position = PacketPosition::from_bits((word1 >> PP_SHIFT) as u8);
let in_order = (word1 >> O_SHIFT) & 1 != 0;
let key_flag = EncryptionKeyField::from_bits((word1 >> KK_SHIFT) as u8);
let retransmitted = (word1 >> R_SHIFT) & 1 != 0;
let message_number = word1 & MESSAGE_NUMBER_MASK;
let timestamp = be32(bytes, 8);
let dest_socket_id = be32(bytes, 12);
let data = &bytes[SRT_HEADER_LEN..];
Ok(DataPacket {
seq_number,
position,
in_order,
key_flag,
retransmitted,
message_number,
timestamp,
dest_socket_id,
data,
})
}
pub fn serialized_len(&self) -> usize {
SRT_HEADER_LEN + self.data.len()
}
pub fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
let len = self.serialized_len();
if buf.len() < len {
return Err(Error::OutputBufferTooSmall {
need: len,
have: buf.len(),
});
}
if self.seq_number > SEQ_NUMBER_MASK {
return Err(Error::FieldTooWide {
what: "Packet Sequence Number",
value: u64::from(self.seq_number),
bits: 31,
});
}
if self.message_number > MESSAGE_NUMBER_MASK {
return Err(Error::FieldTooWide {
what: "Message Number",
value: u64::from(self.message_number),
bits: MESSAGE_NUMBER_BITS,
});
}
let word0 = self.seq_number; let word1 = (u32::from(self.position.to_bits()) << PP_SHIFT)
| (u32::from(self.in_order) << O_SHIFT)
| (u32::from(self.key_flag.to_bits()) << KK_SHIFT)
| (u32::from(self.retransmitted) << R_SHIFT)
| self.message_number;
put_be32(buf, 0, word0);
put_be32(buf, 4, word1);
put_be32(buf, 8, self.timestamp);
put_be32(buf, 12, self.dest_socket_id);
buf[SRT_HEADER_LEN..len].copy_from_slice(self.data);
Ok(len)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample() -> DataPacket<'static> {
DataPacket {
seq_number: 0x0123_4567,
position: PacketPosition::Solo,
in_order: true,
key_flag: EncryptionKeyField::Even,
retransmitted: false,
message_number: 0x0155_5555, timestamp: 0xAABB_CCDD,
dest_socket_id: 0x1122_3344,
data: &[0x47, 0x00, 0x01, 0x02],
}
}
#[test]
fn round_trip_bytes_are_hand_computed() {
let pkt = sample();
let mut buf = [0u8; 20];
let n = pkt.serialize_into(&mut buf).unwrap();
assert_eq!(n, 20);
assert_eq!(&buf[0..4], &0x0123_4567u32.to_be_bytes());
let expected_word1 = (0b11u32 << 30) | (1u32 << 29) | (0b01u32 << 27) | 0x0155_5555;
assert_eq!(&buf[4..8], &expected_word1.to_be_bytes());
assert_eq!(&buf[8..12], &0xAABB_CCDDu32.to_be_bytes());
assert_eq!(&buf[12..16], &0x1122_3344u32.to_be_bytes());
assert_eq!(&buf[16..20], &[0x47, 0x00, 0x01, 0x02]);
let parsed = DataPacket::parse(&buf).unwrap();
assert_eq!(parsed, pkt);
}
#[test]
fn mutate_field_changes_bytes() {
let mut pkt = sample();
let mut buf1 = [0u8; 20];
pkt.serialize_into(&mut buf1).unwrap();
pkt.retransmitted = true;
let mut buf2 = [0u8; 20];
pkt.serialize_into(&mut buf2).unwrap();
assert_ne!(buf1, buf2);
}
#[test]
fn rejects_control_packet_bytes() {
let mut buf = [0u8; 16];
buf[0] = 0x80; assert_eq!(
DataPacket::parse(&buf).unwrap_err(),
Error::WrongPacketKind {
expected: "data packet (F=0)"
}
);
}
#[test]
fn all_packet_positions_round_trip() {
for p in [
PacketPosition::First,
PacketPosition::Middle,
PacketPosition::Last,
PacketPosition::Solo,
] {
assert_eq!(PacketPosition::from_bits(p.to_bits()), p);
}
}
#[test]
fn all_key_flags_round_trip() {
for k in [
EncryptionKeyField::NotEncrypted,
EncryptionKeyField::Even,
EncryptionKeyField::Odd,
] {
assert_eq!(EncryptionKeyField::from_bits(k.to_bits()), k);
}
assert_eq!(
EncryptionKeyField::from_bits(KK_CONTROL_ONLY),
EncryptionKeyField::Reserved(KK_CONTROL_ONLY)
);
}
#[test]
fn overwide_seq_number_errs() {
let mut pkt = sample();
pkt.seq_number = 0x8000_0000;
let mut buf = [0u8; 20];
assert!(matches!(
pkt.serialize_into(&mut buf),
Err(Error::FieldTooWide { .. })
));
}
}