1use crate::subscription::SubscriptionId;
2use bytes::Bytes;
3use std::net::{IpAddr, SocketAddr};
4
5#[derive(Debug, Clone)]
7pub struct Packet {
8 pub subscription_id: SubscriptionId,
10 pub source: SocketAddr,
12 pub group: IpAddr,
14 pub dst_port: u16,
16 pub payload: Bytes,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
23#[non_exhaustive]
24pub struct ReceiveMetadata {
25 pub socket_local_addr: Option<SocketAddr>,
27 pub configured_interface: Option<IpAddr>,
31 pub configured_interface_index: Option<u32>,
33 pub destination_local_ip: Option<IpAddr>,
35 pub ingress_interface_index: Option<u32>,
37}
38
39impl ReceiveMetadata {
40 #[cfg_attr(
41 any(
42 not(feature = "raw-packets"),
43 not(any(target_os = "linux", target_os = "macos", windows))
44 ),
45 allow(dead_code)
46 )]
47 pub(crate) fn empty() -> Self {
48 Self {
49 socket_local_addr: None,
50 configured_interface: None,
51 configured_interface_index: None,
52 destination_local_ip: None,
53 ingress_interface_index: None,
54 }
55 }
56}
57
58#[derive(Debug, Clone)]
60#[non_exhaustive]
61pub struct PacketWithMetadata {
62 pub packet: Packet,
64 pub metadata: ReceiveMetadata,
66}
67
68impl Packet {
69 pub fn payload_len(&self) -> usize {
71 self.payload.len()
72 }
73
74 pub fn payload(&self) -> &[u8] {
75 &self.payload
76 }
77}
78
79impl PacketWithMetadata {
80 pub fn packet(&self) -> &Packet {
82 &self.packet
83 }
84
85 pub fn metadata(&self) -> &ReceiveMetadata {
87 &self.metadata
88 }
89
90 pub fn into_packet(self) -> Packet {
92 self.packet
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
100
101 #[test]
102 fn packet_payload_len_returns_correct_length() {
103 let packet = Packet {
104 subscription_id: SubscriptionId(1),
105 source: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 12345)),
106 group: IpAddr::V4(Ipv4Addr::new(239, 1, 2, 3)),
107 dst_port: 5000,
108 payload: Bytes::from_static(&[1, 2, 3]),
109 };
110
111 assert_eq!(packet.payload_len(), 3);
112 }
113
114 #[test]
115 fn subscription_id_equality_works() {
116 let a = SubscriptionId(7);
117 let b = SubscriptionId(7);
118 let c = SubscriptionId(8);
119
120 assert_eq!(a, b);
121 assert_ne!(a, c);
122 }
123
124 #[test]
125 fn packet_with_metadata_into_packet_discards_metadata() {
126 let packet = Packet {
127 subscription_id: SubscriptionId(1),
128 source: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 12345)),
129 group: IpAddr::V4(Ipv4Addr::new(239, 1, 2, 3)),
130 dst_port: 5000,
131 payload: Bytes::from_static(&[1, 2, 3]),
132 };
133
134 let detailed = PacketWithMetadata {
135 packet: packet.clone(),
136 metadata: ReceiveMetadata {
137 socket_local_addr: Some(SocketAddr::V4(SocketAddrV4::new(
138 Ipv4Addr::UNSPECIFIED,
139 5000,
140 ))),
141 configured_interface: None,
142 configured_interface_index: None,
143 destination_local_ip: None,
144 ingress_interface_index: None,
145 },
146 };
147
148 let stripped = detailed.into_packet();
149
150 assert_eq!(stripped.subscription_id, packet.subscription_id);
151 assert_eq!(stripped.source, packet.source);
152 assert_eq!(stripped.group, packet.group);
153 assert_eq!(stripped.dst_port, packet.dst_port);
154 assert_eq!(stripped.payload, packet.payload);
155 }
156}