package com.netifera.platform.net.internal.daemon.probe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import com.netifera.platform.api.dispatcher.IProbeMessage;
import com.netifera.platform.api.dispatcher.MessengerException;
import com.netifera.platform.api.events.EventListenerManager;
import com.netifera.platform.api.events.IEvent;
import com.netifera.platform.api.events.IEventHandler;
import com.netifera.platform.api.log.ILogger;
import com.netifera.platform.api.probe.IProbe;
import com.netifera.platform.dispatcher.StatusMessage;
import com.netifera.platform.net.daemon.sniffing.ISniffingDaemon;
import com.netifera.platform.net.daemon.sniffing.ISniffingModule;
import com.netifera.platform.net.pcap.ICaptureInterface;
import com.netifera.platform.net.sniffing.ICaptureFileInterface;
import com.netifera.platform.net.sniffing.util.ICaptureFileProgress;
public class RemoteSniffingDaemon implements ISniffingDaemon {
private final IProbe probe;
private final ILogger logger;
private String messengerError;
private final BlockingQueue<IProbeMessage> sendQueue;
private final Thread sendThread;
private ICaptureFileProgress progress;
private List<InterfaceRecord> interfaceRecords;
private List<ModuleRecord> moduleRecords;
private Object lock = new Object();
private final EventListenerManager stateChangeListeners;
private boolean isRunning;
public RemoteSniffingDaemon(IProbe probe, ILogger logger, IEventHandler changeHandler) {
this.probe = probe;
this.logger = logger;
stateChangeListeners = new EventListenerManager();
stateChangeListeners.addListener(changeHandler);
sendQueue = new ArrayBlockingQueue<IProbeMessage>(10);
sendThread = new Thread(createSendMessageRunnable());
sendThread.start();
refreshInterfaceInformation();
refreshModuleInformation();
refreshStatus();
}
public ICaptureFileInterface createCaptureFileInterface(String path) {
final CaptureFileValid valid = (CaptureFileValid) exchangeMessage(new CaptureFileValid(path));
if(valid == null) {
logger.warning("CaptureFileValid failed");
return null;
}
return new CaptureFileStub(path, valid.isValid(), valid.getErrorMessage());
}
public void enableInterfaces(Collection<ICaptureInterface> interfaces) {
final List<InterfaceRecord> interfaceRecords = new ArrayList<InterfaceRecord>();
for(ICaptureInterface iface : interfaces) {
interfaceRecords.add(new InterfaceRecord(iface.getName(), true, true));
}
sendQueue.add(new SetInterfaceEnableState(interfaceRecords));
// if(!sendMessage(new SetInterfaceEnableState(interfaceRecords))) {
// logger.warning("Failed to set interface states: " + getLastError());
// }
}
public void enableModules(Set<ISniffingModule> enabledModuleSet) {
final List<ModuleRecord> moduleRecords = new ArrayList<ModuleRecord>();
for(ISniffingModule module : enabledModuleSet) {
moduleRecords.add(new ModuleRecord(module.getName(), true));
}
sendQueue.add(new SetModuleEnableState(moduleRecords));
// if(!sendMessage(new SetModuleEnableState(moduleRecords))) {
// logger.warning("Failed to set module enable states: " + getLastError());
// }
}
public Collection<ICaptureInterface> getInterfaces() {
synchronized(lock) {
while(interfaceRecords == null) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Collections.emptyList();
}
}
return new ArrayList<ICaptureInterface>(interfaceRecords);
}
}
private List<InterfaceRecord> getInterfaceRecords() {
final RequestInterfaceInformation response = (RequestInterfaceInformation) exchangeMessage(new RequestInterfaceInformation());
if(response == null) {
logger.warning("Failed to get capture interface information: " + getLastError());
return null;
}
return response.getInterfaceRecords();
}
public Set<ISniffingModule> getModules() {
synchronized (lock) {
while(moduleRecords == null) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Collections.emptySet();
}
}
return new HashSet<ISniffingModule>(moduleRecords);
}
}
private List<ModuleRecord> getModuleRecords() {
final RequestModuleInformation response = (RequestModuleInformation) exchangeMessage(new RequestModuleInformation());
if(response == null) {
logger.warning("Failed to get module information: " + getLastError());
return null;
}
return response.getModuleRecords();
}
public boolean isEnabled(ICaptureInterface iface) {
synchronized(lock) {
while(interfaceRecords == null) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
for(InterfaceRecord record : interfaceRecords) {
if(record.getName().equals(iface.getName()))
return record.isEnabled();
}
logger.warning("Interface not found for name " + iface.getName());
return false;
}
}
public boolean isEnabled(ISniffingModule module) {
synchronized(lock) {
while(moduleRecords == null) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
for(ModuleRecord record : moduleRecords) {
if(record.getName().equals(module.getName())) {
return record.isEnabled();
}
}
logger.warning("Module not found for name " + module.getName());
return false;
}
}
public void runCaptureFile(long spaceId, ICaptureFileInterface iface,
ICaptureFileProgress progress) {
this.progress = progress;
if(!sendMessage(new RunCaptureFile(spaceId, iface.getPath()))) {
logger.warning("Error running capture file " + getLastError());
}
}
public void cancelCaptureFile() {
if(!sendMessage(new CancelCaptureFile())) {
logger.warning("Error cancelling capture file " + getLastError());
}
}
public void setEnabled(ICaptureInterface iface, boolean enable) {
final InterfaceRecord interfaceRecord = new InterfaceRecord(iface.getName(), iface.captureAvailable(), enable);
sendQueue.add(new SetInterfaceEnableState(interfaceRecord));
refreshInterfaceInformation();
//if(!sendMessage(new SetInterfaceEnableState(interfaceRecord))) {
// logger.warning("Failed to enable interface " + getLastError());
// }
}
public void setEnabled(ISniffingModule module, boolean enable) {
final ModuleRecord moduleRecord = new ModuleRecord(module.getName(), enable);
sendQueue.add(new SetModuleEnableState(moduleRecord));
refreshModuleInformation();
// if(!sendMessage(new SetModuleEnableState(moduleRecord))) {
// logger.warning("Failed to enable sniffing module " + getLastError());
// }
}
public boolean isRunning() {
return isRunning;
// SniffingDaemonStatus status = (SniffingDaemonStatus) exchangeMessage(new SniffingDaemonStatus());
// if(status == null) {
// logger.warning("Failed to get SniffingDaemonStatus");
// return false;
// }
// return status.isRunning;
}
public void start(long spaceId) {
sendQueue.add(new StartSniffingDaemon(spaceId));
isRunning = true;
refreshStatus();
// if(!sendMessage(new StartSniffingDaemon(spaceId))) {
// logger.warning("Failed to start sniffing daemon " + getLastError());
// }
}
public void stop() {
sendQueue.add(new StopSniffingDaemon());
isRunning = false;
refreshStatus();
// if(!sendMessage(new StopSniffingDaemon())) {
// logger.warning("Failed to stop sniffing daemon " + getLastError());
// }
}
public void captureFileProgress(CaptureFileProgress progressUpdate) {
if(progressUpdate.isUpdate()) {
progress.updateProgress(progressUpdate.getPercent(), progressUpdate.getCount());
} else if(progressUpdate.isError()) {
progress.error(progressUpdate.getErrorMessage(), null);
} else {
progress.finished();
}
}
public void sniffingModuleOutput(String output) {
logger.getManager().logRaw(output);
}
private String getLastError() {
return messengerError;
}
private boolean sendMessage(IProbeMessage message) {
try {
probe.getMessenger().sendMessage(message);
return true;
} catch (MessengerException e) {
messengerError = e.getMessage();
return false;
}
}
private IProbeMessage exchangeMessage(IProbeMessage message) {
try {
IProbeMessage response = probe.getMessenger().exchangeMessage(message);
if(response instanceof StatusMessage) {
return null;
} else {
return response;
}
} catch (MessengerException e) {
messengerError = e.getMessage();
return null;
}
}
private Runnable createSendMessageRunnable() {
return new Runnable() {
public void run() {
while(!Thread.interrupted()) {
try {
IProbeMessage message = sendQueue.take();
if(!sendMessage(message)) {
logger.error("failed to send message : " + messengerError);
}
synchronized (sendQueue) {
sendQueue.notifyAll();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
};
}
private void waitForEmptySendQueue() {
synchronized (sendQueue) {
while(!sendQueue.isEmpty()) {
try {
sendQueue.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
}
private void refreshInterfaceInformation() {
Thread t = new Thread(new Runnable() {
public void run() {
waitForEmptySendQueue();
synchronized(lock) {
interfaceRecords = getInterfaceRecords();
lock.notifyAll();
}
}
});
t.start();
}
private void refreshModuleInformation() {
Thread t = new Thread(new Runnable() {
public void run() {
waitForEmptySendQueue();
synchronized(lock) {
moduleRecords = getModuleRecords();
lock.notifyAll();
}
}
});
t.start();
}
private void refreshStatus() {
Thread t = new Thread(new Runnable() {
public void run() {
waitForEmptySendQueue();
SniffingDaemonStatus status = (SniffingDaemonStatus) exchangeMessage(new SniffingDaemonStatus());
if(status == null) {
logger.warning("Failed to receive status message");
return;
}
if(status.isRunning != isRunning) {
isRunning = status.isRunning;
stateChangeListeners.fireEvent(new IEvent() {});
}
}
});
t.start();
}
}