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