1mod container;
2mod future;
3
4pub use container::Container as Packets;
5pub use future::PacketFuture;
6
7use crate::Error;
8
9use byteorder::{ByteOrder, WriteBytesExt};
10use futures::AsyncWriteExt;
11use std::io::Cursor;
12
13#[derive(Clone, Debug)]
14pub struct Packet {
15 pub(crate) timestamp: std::time::SystemTime,
16 pub(crate) actual_length: u32,
17 pub(crate) original_length: u32,
18 pub(crate) data: Vec<u8>,
19}
20
21impl Packet {
22 pub fn into_data(self) -> Vec<u8> {
23 self.data
24 }
25
26 pub fn into_pcap_record<T: ByteOrder>(self) -> Result<Vec<u8>, Error> {
27 self.as_pcap_record::<T>()
28 }
29
30 pub fn as_pcap_record<T: ByteOrder>(&self) -> Result<Vec<u8>, Error> {
31 let data = Vec::with_capacity(self.data.len() + 4 * std::mem::size_of::<u32>());
32 let mut cursor = Cursor::new(data);
33 self.write_pcap_record::<T, Cursor<Vec<u8>>>(&mut cursor)?;
34 Ok(cursor.into_inner())
35 }
36
37 pub fn write_pcap_record<B: ByteOrder, C: WriteBytesExt>(
38 &self,
39 cursor: &mut C,
40 ) -> Result<(), Error> {
41 let dur = self
42 .timestamp
43 .duration_since(std::time::UNIX_EPOCH)
44 .map_err(Error::Time)?;
45
46 cursor
47 .write_u32::<B>(dur.as_secs() as _)
48 .map_err(Error::Io)?;
49 cursor
50 .write_u32::<B>(dur.subsec_micros())
51 .map_err(Error::Io)?;
52 cursor
53 .write_u32::<B>(self.actual_length)
54 .map_err(Error::Io)?;
55 cursor
56 .write_u32::<B>(self.original_length)
57 .map_err(Error::Io)?;
58 cursor.write(self.data.as_slice()).map_err(Error::Io)?;
59 Ok(())
60 }
61
62 pub fn timestamp(&self) -> &std::time::SystemTime {
63 &self.timestamp
64 }
65 pub fn data(&self) -> &[u8] {
66 self.data.as_slice()
67 }
68 pub fn actual_length(&self) -> u32 {
69 self.actual_length
70 }
71 pub fn original_length(&self) -> u32 {
72 self.original_length
73 }
74
75 pub fn new(
76 timestamp: std::time::SystemTime,
77 actual_length: u32,
78 original_length: u32,
79 data: Vec<u8>,
80 ) -> Packet {
81 Packet {
82 timestamp: timestamp,
83 actual_length: actual_length,
84 original_length: original_length,
85 data,
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use byteorder::ReadBytesExt;
94 use std::io::Read;
95 use std::time::SystemTime;
96
97 #[test]
98 fn converts_to_record() {
99 let ts = SystemTime::now();
100 let packet = Packet {
101 timestamp: ts,
102 actual_length: 100,
103 original_length: 200,
104 data: vec![0u8; 100],
105 };
106 let bytes = packet
107 .as_pcap_record::<byteorder::LittleEndian>()
108 .expect("Failed to convert to record");
109
110 let dur = ts
111 .duration_since(std::time::UNIX_EPOCH)
112 .expect("Could not convert to dur");
113
114 let mut cursor = Cursor::new(bytes);
115 assert_eq!(
116 cursor
117 .read_u32::<byteorder::LittleEndian>()
118 .expect("Failed to read"),
119 dur.as_secs() as u32
120 );
121 assert_eq!(
122 cursor
123 .read_u32::<byteorder::LittleEndian>()
124 .expect("Failed to read"),
125 dur.subsec_micros()
126 );
127 assert_eq!(
128 cursor
129 .read_u32::<byteorder::LittleEndian>()
130 .expect("Failed to read"),
131 100
132 );
133 assert_eq!(
134 cursor
135 .read_u32::<byteorder::LittleEndian>()
136 .expect("Failed to read"),
137 200
138 );
139 let mut read_data = vec![];
140 assert_eq!(
141 cursor.read_to_end(&mut read_data).expect("Failed to read"),
142 100
143 );
144 assert_eq!(read_data, packet.data);
145 }
146}