#!/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('