working to analyze timing issues
This commit is contained in:
8
analyzer/utils/__init__.py
Normal file
8
analyzer/utils/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""
|
||||
Utility modules for the Ethernet Traffic Analyzer
|
||||
"""
|
||||
|
||||
from .pcap_loader import PCAPLoader
|
||||
from .live_capture import LiveCapture
|
||||
|
||||
__all__ = ['PCAPLoader', 'LiveCapture']
|
||||
129
analyzer/utils/live_capture.py
Normal file
129
analyzer/utils/live_capture.py
Normal file
@@ -0,0 +1,129 @@
|
||||
"""
|
||||
Live network capture utilities
|
||||
"""
|
||||
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from typing import Callable, Optional, List
|
||||
|
||||
try:
|
||||
from scapy.all import sniff, Packet, get_if_list
|
||||
except ImportError:
|
||||
print("Error: scapy library required. Install with: pip install scapy")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class LiveCapture:
|
||||
"""Utility class for live network capture"""
|
||||
|
||||
def __init__(self, interface: Optional[str] = None, filter_str: Optional[str] = None):
|
||||
self.interface = interface
|
||||
self.filter_str = filter_str
|
||||
self.is_capturing = False
|
||||
self.stop_requested = False
|
||||
self.packet_count = 0
|
||||
self.capture_thread: Optional[threading.Thread] = None
|
||||
self.packet_handlers: List[Callable[[Packet, int], None]] = []
|
||||
|
||||
def add_packet_handler(self, handler: Callable[[Packet, int], None]) -> None:
|
||||
"""Add a packet handler function"""
|
||||
self.packet_handlers.append(handler)
|
||||
|
||||
def remove_packet_handler(self, handler: Callable[[Packet, int], None]) -> None:
|
||||
"""Remove a packet handler function"""
|
||||
if handler in self.packet_handlers:
|
||||
self.packet_handlers.remove(handler)
|
||||
|
||||
def start_capture(self, threaded: bool = True) -> None:
|
||||
"""Start packet capture"""
|
||||
if self.is_capturing:
|
||||
raise RuntimeError("Capture is already running")
|
||||
|
||||
self.stop_requested = False
|
||||
self.packet_count = 0
|
||||
|
||||
if threaded:
|
||||
self.capture_thread = threading.Thread(target=self._capture_loop, daemon=True)
|
||||
self.capture_thread.start()
|
||||
else:
|
||||
self._capture_loop()
|
||||
|
||||
def stop_capture(self) -> None:
|
||||
"""Stop packet capture"""
|
||||
self.stop_requested = True
|
||||
|
||||
if self.capture_thread and self.capture_thread.is_alive():
|
||||
self.capture_thread.join(timeout=5.0)
|
||||
if self.capture_thread.is_alive():
|
||||
print("Warning: Capture thread did not stop gracefully")
|
||||
|
||||
def _capture_loop(self) -> None:
|
||||
"""Main capture loop"""
|
||||
self.is_capturing = True
|
||||
|
||||
try:
|
||||
def packet_handler(packet: Packet) -> None:
|
||||
if self.stop_requested:
|
||||
return
|
||||
|
||||
self.packet_count += 1
|
||||
|
||||
# Call all registered handlers
|
||||
for handler in self.packet_handlers:
|
||||
try:
|
||||
handler(packet, self.packet_count)
|
||||
except Exception as e:
|
||||
print(f"Error in packet handler: {e}")
|
||||
|
||||
sniff(
|
||||
iface=self.interface,
|
||||
filter=self.filter_str,
|
||||
prn=packet_handler,
|
||||
stop_filter=lambda x: self.stop_requested
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during live capture: {e}")
|
||||
finally:
|
||||
self.is_capturing = False
|
||||
|
||||
def get_capture_stats(self) -> dict:
|
||||
"""Get capture statistics"""
|
||||
return {
|
||||
'is_capturing': self.is_capturing,
|
||||
'packet_count': self.packet_count,
|
||||
'interface': self.interface,
|
||||
'filter': self.filter_str
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def list_interfaces() -> List[str]:
|
||||
"""List available network interfaces"""
|
||||
try:
|
||||
return get_if_list()
|
||||
except Exception as e:
|
||||
print(f"Error listing interfaces: {e}")
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def validate_interface(interface: str) -> bool:
|
||||
"""Validate that an interface exists"""
|
||||
try:
|
||||
available_interfaces = LiveCapture.list_interfaces()
|
||||
return interface in available_interfaces
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def test_capture_permissions() -> bool:
|
||||
"""Test if we have permissions for packet capture"""
|
||||
try:
|
||||
# Try a very short capture to test permissions
|
||||
def dummy_handler(packet):
|
||||
pass
|
||||
|
||||
sniff(count=1, timeout=1, prn=dummy_handler)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
96
analyzer/utils/pcap_loader.py
Normal file
96
analyzer/utils/pcap_loader.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
PCAP file loading utilities
|
||||
"""
|
||||
|
||||
import sys
|
||||
from typing import List, Iterator, Optional
|
||||
|
||||
try:
|
||||
from scapy.all import rdpcap, PcapReader, Packet
|
||||
except ImportError:
|
||||
print("Error: scapy library required. Install with: pip install scapy")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class PCAPLoader:
|
||||
"""Utility class for loading PCAP files"""
|
||||
|
||||
def __init__(self, file_path: str):
|
||||
self.file_path = file_path
|
||||
self._packet_count: Optional[int] = None
|
||||
|
||||
def load_all(self) -> List[Packet]:
|
||||
"""Load all packets from the PCAP file"""
|
||||
try:
|
||||
packets = rdpcap(self.file_path)
|
||||
self._packet_count = len(packets)
|
||||
return packets
|
||||
except Exception as e:
|
||||
raise IOError(f"Error loading PCAP file {self.file_path}: {e}")
|
||||
|
||||
def load_streaming(self, chunk_size: int = 1000) -> Iterator[List[Packet]]:
|
||||
"""Load packets in chunks for memory efficiency"""
|
||||
try:
|
||||
with PcapReader(self.file_path) as pcap_reader:
|
||||
chunk = []
|
||||
for packet in pcap_reader:
|
||||
chunk.append(packet)
|
||||
if len(chunk) >= chunk_size:
|
||||
yield chunk
|
||||
chunk = []
|
||||
|
||||
# Yield remaining packets
|
||||
if chunk:
|
||||
yield chunk
|
||||
|
||||
except Exception as e:
|
||||
raise IOError(f"Error streaming PCAP file {self.file_path}: {e}")
|
||||
|
||||
def get_packet_count(self) -> Optional[int]:
|
||||
"""Get the total number of packets (if loaded)"""
|
||||
return self._packet_count
|
||||
|
||||
def validate_file(self) -> bool:
|
||||
"""Validate that the file exists and is a valid PCAP"""
|
||||
try:
|
||||
with PcapReader(self.file_path) as pcap_reader:
|
||||
# Try to read first packet
|
||||
next(iter(pcap_reader))
|
||||
return True
|
||||
except (IOError, StopIteration):
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_file_info(file_path: str) -> dict:
|
||||
"""Get basic information about a PCAP file"""
|
||||
try:
|
||||
packet_count = 0
|
||||
first_timestamp = None
|
||||
last_timestamp = None
|
||||
total_bytes = 0
|
||||
|
||||
with PcapReader(file_path) as pcap_reader:
|
||||
for packet in pcap_reader:
|
||||
packet_count += 1
|
||||
total_bytes += len(packet)
|
||||
|
||||
if first_timestamp is None:
|
||||
first_timestamp = float(packet.time)
|
||||
last_timestamp = float(packet.time)
|
||||
|
||||
duration = (last_timestamp - first_timestamp) if first_timestamp and last_timestamp else 0
|
||||
|
||||
return {
|
||||
'file_path': file_path,
|
||||
'packet_count': packet_count,
|
||||
'total_bytes': total_bytes,
|
||||
'duration_seconds': duration,
|
||||
'first_timestamp': first_timestamp,
|
||||
'last_timestamp': last_timestamp,
|
||||
'avg_packet_rate': packet_count / duration if duration > 0 else 0
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {'error': str(e)}
|
||||
Reference in New Issue
Block a user