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 #[inline]
17 pub fn new(packet: DataPacket, is_valid: bool) -> Self {
18 Self { packet, is_valid }
19 }
20
21 #[inline]
23 pub fn is_valid(&self) -> bool {
24 self.is_valid
25 }
26
27 #[inline]
29 pub fn is_invalid(&self) -> bool {
30 !self.is_valid
31 }
32
33 #[inline]
35 pub fn get_timestamp_ns(&self) -> u64 {
36 self.packet.get_timestamp_ns()
37 }
38
39 #[inline]
41 pub fn packet_length(&self) -> usize {
42 self.packet.packet_length()
43 }
44
45 #[inline]
47 pub fn capture_time(&self) -> DateTime<Utc> {
48 self.packet.capture_time()
49 }
50
51 #[inline]
53 pub fn checksum(&self) -> u32 {
54 self.packet.checksum()
55 }
56
57 #[inline]
59 pub fn total_size(&self) -> usize {
60 self.packet.total_size()
61 }
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct PcapFileHeader {
67 pub magic_number: u32,
69 pub major_version: u16,
71 pub minor_version: u16,
73 pub timezone_offset: i32,
75 pub timestamp_accuracy: u32,
77}
78
79impl PcapFileHeader {
80 pub const HEADER_SIZE: usize = 16; pub const DEFAULT_TIMESTAMP_ACCURACY: u32 = 1;
85
86 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 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 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 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#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct DataPacketHeader {
164 pub timestamp_seconds: u32,
166 pub timestamp_nanoseconds: u32,
168 pub packet_length: u32,
170 pub checksum: u32,
172}
173
174impl DataPacketHeader {
175 pub const HEADER_SIZE: usize = 16; 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 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 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 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 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 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 Utc::now()
287 })
288 }
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize)]
293pub struct DataPacket {
294 pub header: DataPacketHeader,
296 pub data: Vec<u8>,
298}
299
300impl DataPacket {
301 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 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 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 #[inline]
351 pub fn capture_time(&self) -> DateTime<Utc> {
352 self.header.capture_time()
353 }
354
355 #[inline]
357 pub fn packet_length(&self) -> usize {
358 self.data.len()
359 }
360
361 #[inline]
363 pub fn total_size(&self) -> usize {
364 DataPacketHeader::HEADER_SIZE + self.packet_length()
365 }
366
367 #[inline]
369 pub fn checksum(&self) -> u32 {
370 self.header.checksum
371 }
372
373 #[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 #[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 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#[derive(Debug, Clone, Serialize, Deserialize)]
420pub struct DatasetInfo {
421 pub name: String,
423 pub path: std::path::PathBuf,
425 pub file_count: usize,
427 pub total_packets: u64,
429 pub total_size: u64,
431 pub start_timestamp: Option<u64>,
433 pub end_timestamp: Option<u64>,
435 pub created_time: String,
437 pub modified_time: String,
439 pub has_index: bool,
441}
442
443impl DatasetInfo {
444 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 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 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 pub fn total_duration_seconds(&self) -> f64 {
483 self.total_duration_ns() as f64 / 1_000_000_000.0
484 }
485
486 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#[derive(Debug, Clone, Serialize, Deserialize)]
499pub struct FileInfo {
500 pub file_name: String,
502 pub file_path: std::path::PathBuf,
504 pub file_size: u64,
506 pub packet_count: u64,
508 pub start_timestamp: Option<u64>,
510 pub end_timestamp: Option<u64>,
512 pub created_time: String,
514 pub modified_time: String,
516 pub is_valid: bool,
518}
519
520impl FileInfo {
521 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 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 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 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 pub fn duration_seconds(&self) -> f64 {
605 self.duration_ns() as f64 / 1_000_000_000.0
606 }
607}