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 pub(crate) fn empty() -> Self {
41 Self {
42 socket_local_addr: None,
43 configured_interface: None,
44 configured_interface_index: None,
45 destination_local_ip: None,
46 ingress_interface_index: None,
47 }
48 }
49}
50
51#[derive(Debug, Clone)]
53#[non_exhaustive]
54pub struct PacketWithMetadata {
55 pub packet: Packet,
57 pub metadata: ReceiveMetadata,
59}
60
61impl Packet {
62 pub fn payload_len(&self) -> usize {
64 self.payload.len()
65 }
66
67 pub fn payload(&self) -> &[u8] {
68 &self.payload
69 }
70}
71
72impl PacketWithMetadata {
73 pub fn packet(&self) -> &Packet {
75 &self.packet
76 }
77
78 pub fn metadata(&self) -> &ReceiveMetadata {
80 &self.metadata
81 }
82
83 pub fn into_packet(self) -> Packet {
85 self.packet
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
93
94 #[test]
95 fn packet_payload_len_returns_correct_length() {
96 let packet = Packet {
97 subscription_id: SubscriptionId(1),
98 source: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 12345)),
99 group: IpAddr::V4(Ipv4Addr::new(239, 1, 2, 3)),
100 dst_port: 5000,
101 payload: Bytes::from_static(&[1, 2, 3]),
102 };
103
104 assert_eq!(packet.payload_len(), 3);
105 }
106
107 #[test]
108 fn subscription_id_equality_works() {
109 let a = SubscriptionId(7);
110 let b = SubscriptionId(7);
111 let c = SubscriptionId(8);
112
113 assert_eq!(a, b);
114 assert_ne!(a, c);
115 }
116
117 #[test]
118 fn packet_with_metadata_into_packet_discards_metadata() {
119 let packet = Packet {
120 subscription_id: SubscriptionId(1),
121 source: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 12345)),
122 group: IpAddr::V4(Ipv4Addr::new(239, 1, 2, 3)),
123 dst_port: 5000,
124 payload: Bytes::from_static(&[1, 2, 3]),
125 };
126
127 let detailed = PacketWithMetadata {
128 packet: packet.clone(),
129 metadata: ReceiveMetadata {
130 socket_local_addr: Some(SocketAddr::V4(SocketAddrV4::new(
131 Ipv4Addr::UNSPECIFIED,
132 5000,
133 ))),
134 configured_interface: None,
135 configured_interface_index: None,
136 destination_local_ip: None,
137 ingress_interface_index: None,
138 },
139 };
140
141 let stripped = detailed.into_packet();
142
143 assert_eq!(stripped.subscription_id, packet.subscription_id);
144 assert_eq!(stripped.source, packet.source);
145 assert_eq!(stripped.group, packet.group);
146 assert_eq!(stripped.dst_port, packet.dst_port);
147 assert_eq!(stripped.payload, packet.payload);
148 }
149}