""" Core analysis engine for the Ethernet Traffic Analyzer """ import sys import threading from typing import List, Dict try: from scapy.all import rdpcap, sniff, Packet except ImportError: print("Error: scapy library required. Install with: pip install scapy") sys.exit(1) from .flow_manager import FlowManager from .statistics import StatisticsEngine from ..models import AnalysisResult class EthernetAnalyzer: """Main analyzer class for ethernet traffic analysis""" def __init__(self, enable_realtime: bool = False, outlier_threshold_sigma: float = 3.0): self.statistics_engine = StatisticsEngine(outlier_threshold_sigma=outlier_threshold_sigma, enable_realtime=enable_realtime) self.flow_manager = FlowManager(self.statistics_engine) self.all_packets: List[Packet] = [] self.is_live = False self.stop_capture = False # Expose flows for backward compatibility self.flows = self.flow_manager.flows # Create a simple dissector for backward compatibility self.dissector = SimpleFrameDissector(self.flow_manager) def analyze_pcap(self, pcap_file: str) -> None: """Analyze a pcap file""" print(f"Loading pcap file: {pcap_file}") try: packets = rdpcap(pcap_file) self.all_packets = packets print(f"Loaded {len(packets)} packets") self._process_packets(packets) except Exception as e: print(f"Error loading pcap file: {e}") sys.exit(1) def start_live_capture(self, interface: str = None, filter_str: str = None) -> None: """Start live packet capture""" self.is_live = True print(f"Starting live capture on interface: {interface or 'default'}") def packet_handler(packet): if self.stop_capture: return self.all_packets.append(packet) self._process_single_packet(packet, len(self.all_packets)) try: sniff(iface=interface, filter=filter_str, prn=packet_handler, stop_filter=lambda x: self.stop_capture) except Exception as e: print(f"Error during live capture: {e}") def _process_packets(self, packets: List[Packet]) -> None: """Process a list of packets""" for i, packet in enumerate(packets, 1): self._process_single_packet(packet, i) def _process_single_packet(self, packet: Packet, frame_num: int) -> None: """Process a single packet""" self.flow_manager.process_packet(packet, frame_num) def calculate_statistics(self) -> None: """Calculate timing statistics and detect outliers""" self.statistics_engine.calculate_flow_statistics(self.flows) def get_summary(self) -> Dict: """Get analysis summary""" flow_summary = self.flow_manager.get_flows_summary() return { 'total_packets': len(self.all_packets), 'unique_flows': flow_summary['total_flows'], 'unique_ips': flow_summary['unique_ips'], 'flows': flow_summary['flows'] } def get_analysis_result(self) -> AnalysisResult: """Get structured analysis result""" summary = self.get_summary() return AnalysisResult( total_packets=summary['total_packets'], unique_flows=summary['unique_flows'], unique_ips=summary['unique_ips'], flows=summary['flows'] ) def get_high_jitter_flows(self, threshold: float = 0.1): """Get flows with high timing jitter""" return self.statistics_engine.identify_high_jitter_flows(self.flows, threshold) def get_summary_statistics(self) -> Dict: """Get summary statistics across all flows""" return self.statistics_engine.get_flow_summary_statistics(self.flows) class SimpleFrameDissector: """Simple frame dissector for backward compatibility""" def __init__(self, flow_manager: FlowManager): self.flow_manager = flow_manager def dissect_frame(self, packet: Packet, frame_num: int) -> Dict: """Dissect a frame using the flow manager's dissection system""" return self.flow_manager._dissect_packet(packet, frame_num)