1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::Error;

use byteorder::{ByteOrder, WriteBytesExt};
use futures::AsyncWriteExt;
use std::io::Cursor;

#[derive(Clone, Debug)]
pub struct Packet {
    timestamp: std::time::SystemTime,
    actual_length: u32,
    original_length: u32,
    data: Vec<u8>,
}

impl Packet {
    pub fn into_data(self) -> Vec<u8> {
        self.data
    }
    pub fn into_pcap_record<T: ByteOrder>(self) -> Result<Vec<u8>, Error> {
        let dur = self
            .timestamp
            .duration_since(std::time::UNIX_EPOCH)
            .map_err(Error::Time)?;
        let data = Vec::with_capacity(self.data.len() + 4 * std::mem::size_of::<u32>());
        let mut cursor = Cursor::new(data);
        cursor
            .write_u32::<T>(dur.as_secs() as _)
            .map_err(Error::Io)?;
        cursor
            .write_u32::<T>(dur.subsec_micros())
            .map_err(Error::Io)?;
        cursor
            .write_u32::<T>(self.actual_length)
            .map_err(Error::Io)?;
        cursor
            .write_u32::<T>(self.original_length)
            .map_err(Error::Io)?;
        let mut res = cursor.into_inner();
        res.extend(self.data);
        Ok(res)
    }
    pub fn timestamp(&self) -> &std::time::SystemTime {
        &self.timestamp
    }
    pub fn data(&self) -> &Vec<u8> {
        &self.data
    }
    pub fn actual_length(&self) -> u32 {
        self.actual_length
    }
    pub fn original_length(&self) -> u32 {
        self.original_length
    }

    pub fn new(
        timestamp: std::time::SystemTime,
        actual_length: u32,
        original_length: u32,
        data: Vec<u8>,
    ) -> Packet {
        Packet {
            timestamp: timestamp,
            actual_length: actual_length,
            original_length: original_length,
            data,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use byteorder::ReadBytesExt;
    use std::io::Read;
    use std::time::SystemTime;

    #[test]
    fn converts_to_record() {
        let ts = SystemTime::now();
        let data = vec![0u8; 100];
        let packet = Packet {
            timestamp: ts,
            actual_length: 100,
            original_length: 200,
            data: data.clone(),
        };
        let bytes = packet
            .into_pcap_record::<byteorder::LittleEndian>()
            .expect("Failed to convert to record");

        let dur = ts
            .duration_since(std::time::UNIX_EPOCH)
            .expect("Could not convert to dur");

        let mut cursor = Cursor::new(bytes);
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            dur.as_secs() as u32
        );
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            dur.subsec_micros()
        );
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            100
        );
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            200
        );
        let mut read_data = vec![];
        assert_eq!(
            cursor.read_to_end(&mut read_data).expect("Failed to read"),
            100
        );
        assert_eq!(read_data, data);
    }
}