push_packet/events/
copy.rs1use std::mem::offset_of;
3
4use aya::maps::ring_buf::RingBufItem;
5use push_packet_common::CopyArgs;
6
7use crate::{cast, rules::RuleId};
8
9#[derive(Debug)]
14pub struct CopyEvent<'a>(RingBufItem<'a>);
15
16impl AsRef<[u8]> for CopyEvent<'_> {
17 fn as_ref(&self) -> &[u8] {
18 self.data()
19 }
20}
21
22impl<'a> From<RingBufItem<'a>> for CopyEvent<'a> {
23 fn from(value: RingBufItem<'a>) -> Self {
24 Self(value)
25 }
26}
27
28fn read_u32(data: &[u8], offset: usize) -> u32 {
29 u32::from_ne_bytes(data[offset..offset + 4].try_into().expect("4 bytes"))
30}
31
32fn parse_take(data: &[u8]) -> Option<u32> {
33 match read_u32(data, offset_of!(CopyArgs, take)) {
34 0 => None,
35 n => Some(n),
36 }
37}
38
39fn parse_rule_id(data: &[u8]) -> RuleId {
40 let rule_id = read_u32(data, offset_of!(CopyArgs, rule_id));
41 RuleId(rule_id)
42}
43
44fn parse_packet_len(data: &[u8]) -> u32 {
45 read_u32(data, offset_of!(CopyArgs, packet_len))
46}
47
48fn parse_data_len(data: &[u8]) -> u32 {
49 parse_take(data).unwrap_or(parse_packet_len(data))
50}
51
52fn parse_data(data: &[u8]) -> &[u8] {
53 let header_len = core::mem::size_of::<CopyArgs>();
54 &data[header_len..(header_len + cast::packet_len_to_usize(parse_data_len(data)))]
55}
56
57impl CopyEvent<'_> {
58 #[must_use]
61 pub fn take(&self) -> Option<u32> {
62 parse_take(&self.0)
63 }
64
65 #[must_use]
67 pub fn rule_id(&self) -> RuleId {
68 parse_rule_id(&self.0)
69 }
70
71 #[must_use]
73 pub fn packet_len(&self) -> u32 {
74 parse_packet_len(&self.0)
75 }
76
77 #[must_use]
79 pub fn data_len(&self) -> u32 {
80 parse_data_len(&self.0)
81 }
82
83 #[must_use]
85 pub fn data(&self) -> &[u8] {
86 parse_data(&self.0)
87 }
88
89 #[must_use]
92 pub fn into_owned(self) -> OwnedCopyEvent {
93 let take = self.take();
94 let rule_id = self.rule_id();
95 let packet_len = self.packet_len();
96 let data = self.data().into();
97 OwnedCopyEvent {
98 take,
99 rule_id,
100 packet_len,
101 data,
102 }
103 }
104}
105
106#[derive(Debug, Clone)]
109pub struct OwnedCopyEvent {
110 take: Option<u32>,
111 rule_id: RuleId,
112 packet_len: u32,
113 data: Box<[u8]>,
114}
115
116impl AsRef<[u8]> for OwnedCopyEvent {
117 fn as_ref(&self) -> &[u8] {
118 self.data()
119 }
120}
121
122impl OwnedCopyEvent {
123 #[must_use]
126 pub fn take(&self) -> Option<u32> {
127 self.take
128 }
129
130 #[must_use]
132 pub fn rule_id(&self) -> RuleId {
133 self.rule_id
134 }
135
136 #[must_use]
138 pub fn packet_len(&self) -> u32 {
139 self.packet_len
140 }
141
142 #[must_use]
144 pub fn data_len(&self) -> u32 {
145 self.take.unwrap_or(self.packet_len)
146 }
147
148 #[must_use]
150 pub fn data(&self) -> &[u8] {
151 &self.data
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use crate::{
158 events::copy::{parse_packet_len, parse_rule_id, parse_take},
159 rules::RuleId,
160 };
161
162 fn make_packet(take: u32, rule_id: u32, packet_len: u32, data: &[u8]) -> Vec<u8> {
163 let mut packet = vec![];
164 packet.extend_from_slice(&take.to_ne_bytes());
165 packet.extend_from_slice(&rule_id.to_ne_bytes());
166 packet.extend_from_slice(&packet_len.to_ne_bytes());
167 packet.extend_from_slice(data);
168 packet
169 }
170
171 #[test]
172 fn zero_take_is_none() {
173 let packet = make_packet(0, 0, 100, &[0]);
174 assert_eq!(parse_take(&packet), None);
175 }
176
177 #[test]
178 fn nonzero_take_is_some() {
179 let packet = make_packet(10, 0, 100, &[0]);
180 assert_eq!(parse_take(&packet), Some(10));
181 }
182
183 #[test]
184 fn rule_id_parses() {
185 let packet = make_packet(0, 4, 100, &[0]);
186 assert_eq!(parse_rule_id(&packet), RuleId(4));
187 }
188
189 #[test]
190 fn packet_len_parses() {
191 let packet = make_packet(0, 0, 100, &[0]);
192 assert_eq!(parse_packet_len(&packet), 100);
193 }
194}