added claude-gen python tooling
This commit is contained in:
104
chapter10_packet.py
Normal file
104
chapter10_packet.py
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Chapter 10 Packet class for IRIG106 Chapter 10 frame parsing
|
||||
"""
|
||||
|
||||
import struct
|
||||
from typing import Dict, Optional
|
||||
|
||||
try:
|
||||
from scapy.layers.inet import IP, UDP
|
||||
except ImportError:
|
||||
print("Error: scapy library not found. Install with: pip install scapy")
|
||||
exit(1)
|
||||
|
||||
|
||||
class Chapter10Packet:
|
||||
"""Represents an IRIG106 Chapter 10 packet"""
|
||||
|
||||
def __init__(self, packet, original_frame_num: Optional[int] = None):
|
||||
"""
|
||||
Initialize Chapter 10 packet from raw scapy packet
|
||||
|
||||
Args:
|
||||
packet: Raw scapy packet
|
||||
original_frame_num: Original frame number in PCAP file
|
||||
"""
|
||||
self.raw_packet = packet
|
||||
self.original_frame_num: Optional[int] = original_frame_num
|
||||
|
||||
# Extract basic packet info
|
||||
self.timestamp = float(packet.time)
|
||||
self.packet_size = len(packet)
|
||||
|
||||
# Extract IP/UDP info if available
|
||||
if packet.haslayer(IP) and packet.haslayer(UDP):
|
||||
ip_layer = packet[IP]
|
||||
udp_layer = packet[UDP]
|
||||
|
||||
self.src_ip = ip_layer.src
|
||||
self.dst_ip = ip_layer.dst
|
||||
self.src_port = udp_layer.sport
|
||||
self.dst_port = udp_layer.dport
|
||||
self.payload = bytes(udp_layer.payload)
|
||||
else:
|
||||
self.src_ip = ""
|
||||
self.dst_ip = ""
|
||||
self.src_port = 0
|
||||
self.dst_port = 0
|
||||
self.payload = bytes()
|
||||
|
||||
# Parse Chapter 10 header
|
||||
self.ch10_header = self._parse_ch10_header()
|
||||
|
||||
def _parse_ch10_header(self) -> Optional[Dict]:
|
||||
"""Parse Chapter 10 header from payload"""
|
||||
if len(self.payload) < 28: # Minimum payload size (4-byte prefix + 24-byte Ch10 header)
|
||||
return None
|
||||
|
||||
try:
|
||||
# Look for Ch10 sync pattern in first several bytes
|
||||
ch10_offset = None
|
||||
for offset in range(min(8, len(self.payload) - 24)):
|
||||
sync_pattern = struct.unpack('<H', self.payload[offset:offset+2])[0]
|
||||
if sync_pattern == 0xEB25: # Ch10 sync pattern
|
||||
ch10_offset = offset
|
||||
break
|
||||
|
||||
if ch10_offset is None:
|
||||
return None
|
||||
|
||||
# Parse Chapter 10 header starting at found offset
|
||||
base = ch10_offset
|
||||
sync_pattern = struct.unpack('<H', self.payload[base:base+2])[0]
|
||||
channel_id = struct.unpack('<H', self.payload[base+2:base+4])[0]
|
||||
packet_length = struct.unpack('<I', self.payload[base+4:base+8])[0]
|
||||
data_length = struct.unpack('<I', self.payload[base+8:base+12])[0]
|
||||
header_version = self.payload[base+12]
|
||||
sequence_number = self.payload[base+13]
|
||||
packet_flags = self.payload[base+14]
|
||||
data_type = self.payload[base+15]
|
||||
rtc_low = struct.unpack('<I', self.payload[base+16:base+20])[0]
|
||||
rtc_high = struct.unpack('<H', self.payload[base+20:base+22])[0]
|
||||
checksum = struct.unpack('<H', self.payload[base+22:base+24])[0]
|
||||
|
||||
# Store the offset for reference
|
||||
self.ch10_offset = ch10_offset
|
||||
|
||||
return {
|
||||
'sync_pattern': f'0x{sync_pattern:04X}',
|
||||
'channel_id': channel_id,
|
||||
'packet_length': packet_length,
|
||||
'data_length': data_length,
|
||||
'header_version': header_version,
|
||||
'sequence_number': sequence_number,
|
||||
'packet_flags': f'0x{packet_flags:02X}',
|
||||
'data_type': f'0x{data_type:02X}',
|
||||
'rtc_low': rtc_low,
|
||||
'rtc_high': rtc_high,
|
||||
'checksum': f'0x{checksum:04X}',
|
||||
'rtc_timestamp': (rtc_high << 32) | rtc_low,
|
||||
'ch10_offset': ch10_offset
|
||||
}
|
||||
except (struct.error, IndexError):
|
||||
return None
|
||||
Reference in New Issue
Block a user