package com.netifera.platform.net.sniffing.util; import com.netifera.platform.net.internal.sniffing.file.CaptureFileException; import com.netifera.platform.net.internal.sniffing.file.ICaptureFileRecord; import com.netifera.platform.net.internal.sniffing.file.IPcapCaptureFile; import com.netifera.platform.net.internal.sniffing.file.PcapCaptureFile; import com.netifera.platform.net.internal.sniffing.managers.PacketContext; import com.netifera.platform.net.packets.IPacketDecoder; import com.netifera.platform.net.packets.IPacketHeader; import com.netifera.platform.net.packets.decoders.EthernetDecoder; import com.netifera.platform.net.packets.decoders.GenericDecoder; import com.netifera.platform.net.packets.decoders.NullDecoder; import com.netifera.platform.net.sniffing.ICaptureFileInterface; import com.netifera.platform.net.sniffing.IPacketSniffer; public class CaptureFileInterface implements ICaptureFileInterface { private final static IPacketDecoder ethernetDecoder = new EthernetDecoder(); private final static IPacketDecoder nullDecoder = new NullDecoder(); private final IPcapCaptureFile captureFile; private final boolean isValid; private final ISniffingEngineEx sniffingEngine; private String errorMessage = ""; private IPacketDecoder decoder; private IPacketSniffer<IPacketHeader> sniffer; private boolean processing = false; private volatile boolean isCancelled = false; public CaptureFileInterface(String path, ISniffingEngineEx engine) { this.captureFile = new PcapCaptureFile(path); this.sniffingEngine = engine; isValid = tryOpen(); } public String getPath() { return captureFile.getPath(); } public boolean captureAvailable() { return isValid; } private boolean tryOpen() { try { captureFile.open(); } catch (CaptureFileException e) { errorMessage = e.getMessage(); return false; } switch(captureFile.getLinkType()) { case DLT_EN10MB: decoder = ethernetDecoder; return true; case DLT_NULL: decoder = nullDecoder; return true; } decoder = GenericDecoder.createForDatalink(captureFile.getLinkType().getConstant()); if(decoder != null) { return true; } else { errorMessage = "No suitable decoder found for link type: " + captureFile.getLinkType(); return false; } } public String getName() { return "Pcap Capture [" + captureFile.getPath() + "]"; } public boolean isValid() { return isValid; } public String getErrorMessage() { return errorMessage; } public void process() { process(null); } public void setSniffer(IPacketSniffer<IPacketHeader> sniffer) { this.sniffer = sniffer; } public void cancelProcessing() { isCancelled = true; } public synchronized void process(final ICaptureFileProgress progress) { if(processing) { throw new IllegalStateException("Multiple calls to process() are not allowed"); } processing = true; isCancelled = false; final Thread processThread = new Thread(new Runnable() { public void run() { try { runProcess(progress); } catch (CaptureFileException e) { if(progress != null) { progress.error(e.getMessage(), e.getCause()); } } finally { finish(); } } }); processThread.start(); } public void dispose() { sniffingEngine.removeCaptureFileInterface(this); } private void finish() { dispose(); } private void runProcess(ICaptureFileProgress progress) throws CaptureFileException { while(!isCancelled) { ICaptureFileRecord record = captureFile.readRecord(); if(record == null) { if(progress != null) { progress.finished(); } return; } IPacketHeader packet; try { packet = decoder.decode(record.getRecordBytes()); } catch (Exception e) { sniffingEngine.getLogger().error("Unexpected exception decoding packet from capture file: " + e.getMessage(), e); continue; } if(sniffer == null) { throw new CaptureFileException("No sniffer set to deliver packets to"); } try { sniffer.handlePacket(packet, new PacketContext(record)); } catch(Exception e) { sniffingEngine.getLogger().error("Exception processing capture file: " + e.getMessage(), e); } if(progress != null) { if(!progress.updateProgress(captureFile.getProgress(), captureFile.getPacketCount())) { progress.finished(); return; } } } if(isCancelled && progress != null) { progress.finished(); } } }