pcapfile_io/data/
models.rs

1use crate::foundation::types::constants;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4
5/// 带校验结果的数据包
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ValidatedPacket {
8    /// 数据包
9    pub packet: DataPacket,
10    /// 校验是否通过
11    pub is_valid: bool,
12}
13
14impl ValidatedPacket {
15    /// 创建带校验结果的数据包
16    pub fn new(packet: DataPacket, is_valid: bool) -> Self {
17        Self { packet, is_valid }
18    }
19
20    /// 检查是否有效
21    pub fn is_valid(&self) -> bool {
22        self.is_valid
23    }
24
25    /// 检查是否无效
26    pub fn is_invalid(&self) -> bool {
27        !self.is_valid
28    }
29
30    /// 获取时间戳(纳秒)- 委托给内部数据包
31    pub fn get_timestamp_ns(&self) -> u64 {
32        self.packet.get_timestamp_ns()
33    }
34
35    /// 获取数据包长度 - 委托给内部数据包
36    pub fn packet_length(&self) -> usize {
37        self.packet.packet_length()
38    }
39
40    /// 获取捕获时间 - 委托给内部数据包
41    pub fn capture_time(&self) -> DateTime<Utc> {
42        self.packet.capture_time()
43    }
44
45    /// 获取校验和 - 委托给内部数据包
46    pub fn checksum(&self) -> u32 {
47        self.packet.checksum()
48    }
49
50    /// 获取总大小 - 委托给内部数据包
51    pub fn total_size(&self) -> usize {
52        self.packet.total_size()
53    }
54}
55
56/// PCAP文件头结构
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct PcapFileHeader {
59    /// 魔术数,固定值 0xD4C3B2A1
60    pub magic_number: u32,
61    /// 主版本号,固定值 0x0002
62    pub major_version: u16,
63    /// 次版本号,固定值 0x0004
64    pub minor_version: u16,
65    /// 时区偏移量(秒)
66    pub timezone_offset: i32,
67    /// 时间戳精度(纳秒)
68    pub timestamp_accuracy: u32,
69}
70
71impl PcapFileHeader {
72    /// 头部大小(字节)
73    pub const HEADER_SIZE: usize = 16; // 4 + 2 + 2 + 4 + 4
74
75    /// 默认时间戳精度(纳秒)
76    pub const DEFAULT_TIMESTAMP_ACCURACY: u32 = 1;
77
78    /// 创建新的PCAP文件头
79    pub fn new(timezone_offset: i32) -> Self {
80        Self {
81            magic_number: constants::PCAP_MAGIC_NUMBER,
82            major_version: constants::MAJOR_VERSION,
83            minor_version: constants::MINOR_VERSION,
84            timezone_offset,
85            timestamp_accuracy:
86                Self::DEFAULT_TIMESTAMP_ACCURACY,
87        }
88    }
89
90    /// 从字节数组创建文件头
91    pub fn from_bytes(
92        bytes: &[u8],
93    ) -> Result<Self, String> {
94        if bytes.len() < Self::HEADER_SIZE {
95            return Err("字节数组长度不足".to_string());
96        }
97
98        let magic_number = u32::from_le_bytes([
99            bytes[0], bytes[1], bytes[2], bytes[3],
100        ]);
101        let major_version =
102            u16::from_le_bytes([bytes[4], bytes[5]]);
103        let minor_version =
104            u16::from_le_bytes([bytes[6], bytes[7]]);
105        let timezone_offset = i32::from_le_bytes([
106            bytes[8], bytes[9], bytes[10], bytes[11],
107        ]);
108        let timestamp_accuracy = u32::from_le_bytes([
109            bytes[12], bytes[13], bytes[14], bytes[15],
110        ]);
111
112        Ok(Self {
113            magic_number,
114            major_version,
115            minor_version,
116            timezone_offset,
117            timestamp_accuracy,
118        })
119    }
120
121    /// 转换为字节数组
122    pub fn to_bytes(&self) -> Vec<u8> {
123        let mut bytes =
124            Vec::with_capacity(Self::HEADER_SIZE);
125        bytes.extend_from_slice(
126            &self.magic_number.to_le_bytes(),
127        );
128        bytes.extend_from_slice(
129            &self.major_version.to_le_bytes(),
130        );
131        bytes.extend_from_slice(
132            &self.minor_version.to_le_bytes(),
133        );
134        bytes.extend_from_slice(
135            &self.timezone_offset.to_le_bytes(),
136        );
137        bytes.extend_from_slice(
138            &self.timestamp_accuracy.to_le_bytes(),
139        );
140        bytes
141    }
142
143    /// 验证文件头是否有效
144    pub fn is_valid(&self) -> bool {
145        self.magic_number == constants::PCAP_MAGIC_NUMBER
146            && self.major_version
147                == constants::MAJOR_VERSION
148            && self.minor_version
149                == constants::MINOR_VERSION
150    }
151}
152
153/// 数据包头部结构
154#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct DataPacketHeader {
156    /// 时间戳(秒)
157    pub timestamp_seconds: u32,
158    /// 时间戳(纳秒)
159    pub timestamp_nanoseconds: u32,
160    /// 数据包长度
161    pub packet_length: u32,
162    /// 校验和
163    pub checksum: u32,
164}
165
166impl DataPacketHeader {
167    /// 头部大小(字节)
168    pub const HEADER_SIZE: usize = 16; // 4 + 4 + 4 + 4
169
170    /// 创建新的数据包头部
171    pub fn new(
172        timestamp_seconds: u32,
173        timestamp_nanoseconds: u32,
174        packet_length: u32,
175        checksum: u32,
176    ) -> Result<Self, String> {
177        Ok(Self {
178            timestamp_seconds,
179            timestamp_nanoseconds,
180            packet_length,
181            checksum,
182        })
183    }
184
185    /// 从DateTime创建数据包头部
186    pub fn from_datetime(
187        capture_time: DateTime<Utc>,
188        packet_length: u32,
189        checksum: u32,
190    ) -> Result<Self, String> {
191        let timestamp_seconds =
192            capture_time.timestamp() as u32;
193        let timestamp_nanoseconds =
194            capture_time.timestamp_subsec_nanos();
195
196        Self::new(
197            timestamp_seconds,
198            timestamp_nanoseconds,
199            packet_length,
200            checksum,
201        )
202    }
203
204    /// 从数据包数据创建头部
205    pub fn from_packet_data(
206        capture_time: DateTime<Utc>,
207        packet_data: &[u8],
208    ) -> Result<Self, String> {
209        let checksum =
210            crate::foundation::utils::calculate_crc32(
211                packet_data,
212            );
213        let packet_length = packet_data.len() as u32;
214
215        Self::from_datetime(
216            capture_time,
217            packet_length,
218            checksum,
219        )
220    }
221
222    /// 从字节数组创建头部
223    pub fn from_bytes(
224        bytes: &[u8],
225    ) -> Result<Self, String> {
226        if bytes.len() < Self::HEADER_SIZE {
227            return Err("字节数组长度不足".to_string());
228        }
229
230        let timestamp_seconds = u32::from_le_bytes([
231            bytes[0], bytes[1], bytes[2], bytes[3],
232        ]);
233        let timestamp_nanoseconds = u32::from_le_bytes([
234            bytes[4], bytes[5], bytes[6], bytes[7],
235        ]);
236        let packet_length = u32::from_le_bytes([
237            bytes[8], bytes[9], bytes[10], bytes[11],
238        ]);
239        let checksum = u32::from_le_bytes([
240            bytes[12], bytes[13], bytes[14], bytes[15],
241        ]);
242
243        Self::new(
244            timestamp_seconds,
245            timestamp_nanoseconds,
246            packet_length,
247            checksum,
248        )
249    }
250
251    /// 转换为字节数组
252    pub fn to_bytes(&self) -> Vec<u8> {
253        let mut bytes =
254            Vec::with_capacity(Self::HEADER_SIZE);
255        bytes.extend_from_slice(
256            &self.timestamp_seconds.to_le_bytes(),
257        );
258        bytes.extend_from_slice(
259            &self.timestamp_nanoseconds.to_le_bytes(),
260        );
261        bytes.extend_from_slice(
262            &self.packet_length.to_le_bytes(),
263        );
264        bytes.extend_from_slice(
265            &self.checksum.to_le_bytes(),
266        );
267        bytes
268    }
269
270    /// 获取捕获时间
271    pub fn capture_time(&self) -> DateTime<Utc> {
272        DateTime::from_timestamp(
273            self.timestamp_seconds as i64,
274            self.timestamp_nanoseconds,
275        )
276        .unwrap_or_else(Utc::now)
277    }
278}
279
280/// 数据包结构
281#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct DataPacket {
283    /// 数据包头部
284    pub header: DataPacketHeader,
285    /// 数据包内容
286    pub data: Vec<u8>,
287}
288
289impl DataPacket {
290    /// 创建新的数据包
291    pub fn new(
292        header: DataPacketHeader,
293        data: Vec<u8>,
294    ) -> Result<Self, String> {
295        if data.len() != header.packet_length as usize {
296            return Err(
297                "数据长度与头部长度不匹配".to_string()
298            );
299        }
300
301        Ok(Self { header, data })
302    }
303
304    /// 从DateTime和数据创建数据包
305    pub fn from_datetime(
306        capture_time: DateTime<Utc>,
307        data: Vec<u8>,
308    ) -> Result<Self, String> {
309        let header = DataPacketHeader::from_packet_data(
310            capture_time,
311            &data,
312        )?;
313        Self::new(header, data)
314    }
315
316    /// 从时间戳和数据创建数据包
317    pub fn from_timestamp(
318        timestamp_seconds: u32,
319        timestamp_nanoseconds: u32,
320        data: Vec<u8>,
321    ) -> Result<Self, String> {
322        let checksum =
323            crate::foundation::utils::calculate_crc32(
324                &data,
325            );
326        let packet_length = data.len() as u32;
327
328        let header = DataPacketHeader::new(
329            timestamp_seconds,
330            timestamp_nanoseconds,
331            packet_length,
332            checksum,
333        )?;
334
335        Self::new(header, data)
336    }
337
338    /// 获取捕获时间
339    pub fn capture_time(&self) -> DateTime<Utc> {
340        self.header.capture_time()
341    }
342
343    /// 获取数据包长度
344    pub fn packet_length(&self) -> usize {
345        self.data.len()
346    }
347
348    /// 获取总大小(头部 + 数据)
349    pub fn total_size(&self) -> usize {
350        DataPacketHeader::HEADER_SIZE + self.packet_length()
351    }
352
353    /// 获取校验和
354    pub fn checksum(&self) -> u32 {
355        self.header.checksum
356    }
357
358    /// 获取时间戳(纳秒)
359    pub fn get_timestamp_ns(&self) -> u64 {
360        let capture_time = self.capture_time();
361        capture_time.timestamp() as u64 * 1_000_000_000
362            + capture_time.timestamp_subsec_nanos() as u64
363    }
364
365    /// 验证数据包是否有效
366    pub fn is_valid(&self) -> bool {
367        let calculated_checksum =
368            crate::foundation::utils::calculate_crc32(
369                &self.data,
370            );
371        calculated_checksum == self.header.checksum
372    }
373
374    /// 转换为字节数组(头部 + 数据)
375    pub fn to_bytes(&self) -> Vec<u8> {
376        let mut bytes =
377            Vec::with_capacity(self.total_size());
378        bytes.extend_from_slice(&self.header.to_bytes());
379        bytes.extend_from_slice(&self.data);
380        bytes
381    }
382}
383
384impl std::fmt::Display for DataPacket {
385    fn fmt(
386        &self,
387        f: &mut std::fmt::Formatter<'_>,
388    ) -> std::fmt::Result {
389        write!(
390            f,
391            "DataPacket {{ timestamp: {:?}, length: {}, checksum: 0x{:08X} }}",
392            self.capture_time(),
393            self.packet_length(),
394            self.checksum()
395        )
396    }
397}
398
399// PacketIndexEntry、PcapFileIndex、PidxIndex、PidxStats 及其 impl 移动到 src/index/types.rs
400
401/// 数据集信息结构
402#[derive(Debug, Clone, Serialize, Deserialize)]
403pub struct DatasetInfo {
404    /// 数据集名称
405    pub name: String,
406    /// 数据集路径
407    pub path: std::path::PathBuf,
408    /// 包含的文件数量
409    pub file_count: usize,
410    /// 数据包总数
411    pub total_packets: u64,
412    /// 数据集总大小(字节)
413    pub total_size: u64,
414    /// 开始时间戳(纳秒)
415    pub start_timestamp: Option<u64>,
416    /// 结束时间戳(纳秒)
417    pub end_timestamp: Option<u64>,
418    /// 创建时间
419    pub created_time: String,
420    /// 最后修改时间
421    pub modified_time: String,
422    /// 是否包含索引文件
423    pub has_index: bool,
424}
425
426impl DatasetInfo {
427    /// 创建新的数据集信息
428    pub fn new<P: AsRef<std::path::Path>>(
429        name: String,
430        path: P,
431    ) -> Self {
432        use chrono::Utc;
433
434        Self {
435            name,
436            path: path.as_ref().to_path_buf(),
437            file_count: 0,
438            total_packets: 0,
439            total_size: 0,
440            start_timestamp: None,
441            end_timestamp: None,
442            created_time: Utc::now().to_rfc3339(),
443            modified_time: Utc::now().to_rfc3339(),
444            has_index: false,
445        }
446    }
447
448    /// 获取时间范围
449    pub fn time_range(&self) -> Option<(u64, u64)> {
450        match (self.start_timestamp, self.end_timestamp) {
451            (Some(start), Some(end)) => Some((start, end)),
452            _ => None,
453        }
454    }
455
456    /// 获取总时长(纳秒)
457    pub fn total_duration_ns(&self) -> u64 {
458        match self.time_range() {
459            Some((start, end)) => end.saturating_sub(start),
460            None => 0,
461        }
462    }
463
464    /// 获取总时长(秒)
465    pub fn total_duration_seconds(&self) -> f64 {
466        self.total_duration_ns() as f64 / 1_000_000_000.0
467    }
468
469    /// 获取平均数据包速率(包/秒)
470    pub fn average_packet_rate(&self) -> f64 {
471        let duration = self.total_duration_seconds();
472        if duration > 0.0 {
473            self.total_packets as f64 / duration
474        } else {
475            0.0
476        }
477    }
478}
479
480/// 文件信息结构
481#[derive(Debug, Clone, Serialize, Deserialize)]
482pub struct FileInfo {
483    /// 文件名
484    pub file_name: String,
485    /// 文件路径
486    pub file_path: std::path::PathBuf,
487    /// 文件大小(字节)
488    pub file_size: u64,
489    /// 数据包数量
490    pub packet_count: u64,
491    /// 开始时间戳(纳秒)
492    pub start_timestamp: Option<u64>,
493    /// 结束时间戳(纳秒)
494    pub end_timestamp: Option<u64>,
495    /// 文件哈希值
496    pub file_hash: Option<String>,
497    /// 创建时间
498    pub created_time: String,
499    /// 最后修改时间
500    pub modified_time: String,
501    /// 是否有效
502    pub is_valid: bool,
503}
504
505impl FileInfo {
506    /// 创建新的文件信息
507    pub fn new<P: AsRef<std::path::Path>>(
508        file_path: P,
509    ) -> Self {
510        use chrono::Utc;
511
512        let path = file_path.as_ref();
513        let file_name = path
514            .file_name()
515            .and_then(|name| name.to_str())
516            .unwrap_or("")
517            .to_string();
518
519        Self {
520            file_name,
521            file_path: path.to_path_buf(),
522            file_size: 0,
523            packet_count: 0,
524            start_timestamp: None,
525            end_timestamp: None,
526            file_hash: None,
527            created_time: Utc::now().to_rfc3339(),
528            modified_time: Utc::now().to_rfc3339(),
529            is_valid: false,
530        }
531    }
532
533    /// 从文件系统获取基本信息
534    pub fn from_file<P: AsRef<std::path::Path>>(
535        file_path: P,
536    ) -> Result<Self, std::io::Error> {
537        let path = file_path.as_ref();
538        let metadata = std::fs::metadata(path)?;
539
540        let file_name = path
541            .file_name()
542            .and_then(|name| name.to_str())
543            .unwrap_or("")
544            .to_string();
545
546        let created_time = metadata
547            .created()
548            .map(|time| {
549                DateTime::<Utc>::from(time).to_rfc3339()
550            })
551            .unwrap_or_else(|_| Utc::now().to_rfc3339());
552
553        let modified_time = metadata
554            .modified()
555            .map(|time| {
556                DateTime::<Utc>::from(time).to_rfc3339()
557            })
558            .unwrap_or_else(|_| Utc::now().to_rfc3339());
559
560        Ok(Self {
561            file_name,
562            file_path: path.to_path_buf(),
563            file_size: metadata.len(),
564            packet_count: 0,
565            start_timestamp: None,
566            end_timestamp: None,
567            file_hash: None,
568            created_time,
569            modified_time,
570            is_valid: path.exists() && metadata.is_file(),
571        })
572    }
573
574    /// 获取时间范围
575    pub fn time_range(&self) -> Option<(u64, u64)> {
576        match (self.start_timestamp, self.end_timestamp) {
577            (Some(start), Some(end)) => Some((start, end)),
578            _ => None,
579        }
580    }
581
582    /// 获取文件时长(纳秒)
583    pub fn duration_ns(&self) -> u64 {
584        match self.time_range() {
585            Some((start, end)) => end.saturating_sub(start),
586            None => 0,
587        }
588    }
589
590    /// 获取文件时长(秒)
591    pub fn duration_seconds(&self) -> f64 {
592        self.duration_ns() as f64 / 1_000_000_000.0
593    }
594
595    /// 计算并设置文件哈希值
596    pub fn calculate_hash(
597        &mut self,
598    ) -> Result<(), std::io::Error> {
599        use sha2::{Digest, Sha256};
600        use std::io::Read;
601
602        let mut file =
603            std::fs::File::open(&self.file_path)?;
604        let mut hasher = Sha256::new();
605        let mut buffer = [0; 8192];
606
607        loop {
608            let bytes_read = file.read(&mut buffer)?;
609            if bytes_read == 0 {
610                break;
611            }
612            hasher.update(&buffer[..bytes_read]);
613        }
614
615        self.file_hash =
616            Some(format!("{:x}", hasher.finalize()));
617        Ok(())
618    }
619}