1use crate::foundation::types::constants;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ValidatedPacket {
8 pub packet: DataPacket,
10 pub is_valid: bool,
12}
13
14impl ValidatedPacket {
15 pub fn new(packet: DataPacket, is_valid: bool) -> Self {
17 Self { packet, is_valid }
18 }
19
20 pub fn is_valid(&self) -> bool {
22 self.is_valid
23 }
24
25 pub fn is_invalid(&self) -> bool {
27 !self.is_valid
28 }
29
30 pub fn get_timestamp_ns(&self) -> u64 {
32 self.packet.get_timestamp_ns()
33 }
34
35 pub fn packet_length(&self) -> usize {
37 self.packet.packet_length()
38 }
39
40 pub fn capture_time(&self) -> DateTime<Utc> {
42 self.packet.capture_time()
43 }
44
45 pub fn checksum(&self) -> u32 {
47 self.packet.checksum()
48 }
49
50 pub fn total_size(&self) -> usize {
52 self.packet.total_size()
53 }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct PcapFileHeader {
59 pub magic_number: u32,
61 pub major_version: u16,
63 pub minor_version: u16,
65 pub timezone_offset: i32,
67 pub timestamp_accuracy: u32,
69}
70
71impl PcapFileHeader {
72 pub const HEADER_SIZE: usize = 16; pub const DEFAULT_TIMESTAMP_ACCURACY: u32 = 1;
77
78 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 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 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 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#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct DataPacketHeader {
156 pub timestamp_seconds: u32,
158 pub timestamp_nanoseconds: u32,
160 pub packet_length: u32,
162 pub checksum: u32,
164}
165
166impl DataPacketHeader {
167 pub const HEADER_SIZE: usize = 16; 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 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 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 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 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 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#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct DataPacket {
283 pub header: DataPacketHeader,
285 pub data: Vec<u8>,
287}
288
289impl DataPacket {
290 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 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 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 pub fn capture_time(&self) -> DateTime<Utc> {
340 self.header.capture_time()
341 }
342
343 pub fn packet_length(&self) -> usize {
345 self.data.len()
346 }
347
348 pub fn total_size(&self) -> usize {
350 DataPacketHeader::HEADER_SIZE + self.packet_length()
351 }
352
353 pub fn checksum(&self) -> u32 {
355 self.header.checksum
356 }
357
358 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 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 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#[derive(Debug, Clone, Serialize, Deserialize)]
403pub struct DatasetInfo {
404 pub name: String,
406 pub path: std::path::PathBuf,
408 pub file_count: usize,
410 pub total_packets: u64,
412 pub total_size: u64,
414 pub start_timestamp: Option<u64>,
416 pub end_timestamp: Option<u64>,
418 pub created_time: String,
420 pub modified_time: String,
422 pub has_index: bool,
424}
425
426impl DatasetInfo {
427 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 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 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 pub fn total_duration_seconds(&self) -> f64 {
466 self.total_duration_ns() as f64 / 1_000_000_000.0
467 }
468
469 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#[derive(Debug, Clone, Serialize, Deserialize)]
482pub struct FileInfo {
483 pub file_name: String,
485 pub file_path: std::path::PathBuf,
487 pub file_size: u64,
489 pub packet_count: u64,
491 pub start_timestamp: Option<u64>,
493 pub end_timestamp: Option<u64>,
495 pub file_hash: Option<String>,
497 pub created_time: String,
499 pub modified_time: String,
501 pub is_valid: bool,
503}
504
505impl FileInfo {
506 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 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 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 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 pub fn duration_seconds(&self) -> f64 {
592 self.duration_ns() as f64 / 1_000_000_000.0
593 }
594
595 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}