use crate::subscription::SubscriptionId;
use bytes::Bytes;
use std::net::{IpAddr, SocketAddr};
#[derive(Debug, Clone)]
pub struct Packet {
pub subscription_id: SubscriptionId,
pub source: SocketAddr,
pub group: IpAddr,
pub dst_port: u16,
pub payload: Bytes,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct ReceiveMetadata {
pub socket_local_addr: Option<SocketAddr>,
pub configured_interface: Option<IpAddr>,
pub configured_interface_index: Option<u32>,
pub destination_local_ip: Option<IpAddr>,
pub ingress_interface_index: Option<u32>,
}
impl ReceiveMetadata {
pub(crate) fn empty() -> Self {
Self {
socket_local_addr: None,
configured_interface: None,
configured_interface_index: None,
destination_local_ip: None,
ingress_interface_index: None,
}
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct PacketWithMetadata {
pub packet: Packet,
pub metadata: ReceiveMetadata,
}
impl Packet {
pub fn payload_len(&self) -> usize {
self.payload.len()
}
pub fn payload(&self) -> &[u8] {
&self.payload
}
}
impl PacketWithMetadata {
pub fn packet(&self) -> &Packet {
&self.packet
}
pub fn metadata(&self) -> &ReceiveMetadata {
&self.metadata
}
pub fn into_packet(self) -> Packet {
self.packet
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
#[test]
fn packet_payload_len_returns_correct_length() {
let packet = Packet {
subscription_id: SubscriptionId(1),
source: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 12345)),
group: IpAddr::V4(Ipv4Addr::new(239, 1, 2, 3)),
dst_port: 5000,
payload: Bytes::from_static(&[1, 2, 3]),
};
assert_eq!(packet.payload_len(), 3);
}
#[test]
fn subscription_id_equality_works() {
let a = SubscriptionId(7);
let b = SubscriptionId(7);
let c = SubscriptionId(8);
assert_eq!(a, b);
assert_ne!(a, c);
}
#[test]
fn packet_with_metadata_into_packet_discards_metadata() {
let packet = Packet {
subscription_id: SubscriptionId(1),
source: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 12345)),
group: IpAddr::V4(Ipv4Addr::new(239, 1, 2, 3)),
dst_port: 5000,
payload: Bytes::from_static(&[1, 2, 3]),
};
let detailed = PacketWithMetadata {
packet: packet.clone(),
metadata: ReceiveMetadata {
socket_local_addr: Some(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::UNSPECIFIED,
5000,
))),
configured_interface: None,
configured_interface_index: None,
destination_local_ip: None,
ingress_interface_index: None,
},
};
let stripped = detailed.into_packet();
assert_eq!(stripped.subscription_id, packet.subscription_id);
assert_eq!(stripped.source, packet.source);
assert_eq!(stripped.group, packet.group);
assert_eq!(stripped.dst_port, packet.dst_port);
assert_eq!(stripped.payload, packet.payload);
}
}