项目介绍
- 这是一个名为NetFlow-Sentry的项目,项目实现了对网络流量的实时检测,特征抓取,内置了基于Pytorch的深度学习模型来进行流量分类。该项目除可以进行实时特征提取,还提供了网络流量数据的输入口,可以直接识别分类导入的网络流量文件。
- 项目启动除要运行gradlew,还需要运行app.py脚本,脚本创建了一个Flask应用,用于沟通我们的模型和java项目。
- 如有需要请私我
声明:本项目为本人本科毕设成果
1.NetFlow-Sentry的目录框架:
各部分具体代码
FlowMgr类:
package cic.cs.unb.ca.flow;
import cic.cs.unb.ca.Sys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDate;
public class FlowMgr {
protected static final Logger logger = LoggerFactory.getLogger(FlowMgr.class);
public static final String FLOW_SUFFIX = "_Flow.csv";
private static FlowMgr Instance = new FlowMgr();
private String mFlowSavePath;
private String mDataPath;
private FlowMgr() {
super();
}
public static FlowMgr getInstance() {
return Instance;
}
public FlowMgr init() {
String rootPath = System.getProperty("user.dir");
StringBuilder sb = new StringBuilder(rootPath);
sb.append(Sys.FILE_SEP).append("data").append(Sys.FILE_SEP);
mDataPath = sb.toString();
sb.append("daily").append(Sys.FILE_SEP);
mFlowSavePath = sb.toString();
return Instance;
}
public void destroy() {
}
public String getSavePath() {
return mFlowSavePath;
}
public String getmDataPath() {
return mDataPath;
}
public String getAutoSaveFile() {
String filename = LocalDate.now().toString()+FLOW_SUFFIX;
return mFlowSavePath+filename;
}
}
ChartContainer.java类:
package cic.cs.unb.ca.flow.ui;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.*;
public class ChartContainer extends JPanel{
protected static final Logger logger = LoggerFactory.getLogger(ChartContainer.class);
private static Dimension maxDim;
private static Dimension minDim;
private static double zoomPercentage;
private static Color boxDefaultColor;
private static Color focusColor;
Box parentBox;
Box chartBox;
ChartPanel chartPane;
static{
maxDim = new Dimension(ChartPanel.DEFAULT_MAXIMUM_DRAW_WIDTH*4, ChartPanel.DEFAULT_MAXIMUM_DRAW_HEIGHT*4);
minDim = new Dimension(ChartPanel.DEFAULT_MINIMUM_DRAW_WIDTH, ChartPanel.DEFAULT_MINIMUM_DRAW_HEIGHT);
zoomPercentage = 0.1;
boxDefaultColor = Box.createHorizontalBox().getBackground();
focusColor = UIManager.getColor("Tree.selectionBackground");
}
public ChartContainer(JFreeChart chart) {
setLayout(new BorderLayout(0,0));
chartPane = new ChartPanel(chart);
chartPane.setMaximumSize(maxDim);
chartPane.setMaximumDrawWidth(maxDim.width);
chartPane.setMaximumDrawHeight(maxDim.height);
chartPane.setMouseWheelEnabled(true);
chartPane.setMouseZoomable(true);
chartPane.setFillZoomRectangle(true);
add(initChartBox(chartPane), BorderLayout.CENTER);
}
private Box initChartBox(ChartPanel chart) {
parentBox = Box.createVerticalBox();
chartBox = Box.createHorizontalBox();
//Dimension d = new Dimension(500, 500);
chartBox.setPreferredSize(minDim);
chartBox.setMinimumSize(minDim);
chartBox.setMaximumSize(minDim);
//chartBox.add(Box.createHorizontalGlue());
chartBox.add(chart);
//chartBox.add(Box.createHorizontalGlue());
parentBox.add(chartBox);
parentBox.add(Box.createVerticalStrut(4));
parentBox.add(new JSeparator(SwingConstants.HORIZONTAL));
parentBox.add(Box.createVerticalStrut(4));
return parentBox;
}
private JPanel init_btnPane(ChartPanel chart) {
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane,BoxLayout.Y_AXIS));
JButton zoomIn = new JButton("Zoom In");
JButton zoomOut = new JButton("Zoom Out");
zoomIn.addActionListener(actionEvent -> {
int w = getWidth();
int h = getHeight();
Dimension d = new Dimension(w + 10, h + 10);
setPreferredSize(d);
setMinimumSize(d);
setMaximumSize(d);
repaint();
revalidate();
});
zoomOut.addActionListener(actionEvent -> chart.restoreAutoBounds());
pane.add(Box.createVerticalGlue());
pane.add(zoomIn);
pane.add(Box.createVerticalGlue());
pane.add(zoomOut);
pane.add(Box.createVerticalGlue());
return pane;
}
public void setFocus(boolean focus) {
parentBox.setOpaque(true);
if (focus) {
parentBox.setBackground(focusColor);
} else {
parentBox.setBackground(boxDefaultColor);
}
}
public void zoomIn() {
Dimension d = chartBox.getSize();
double w = d.width + d.width * zoomPercentage;
double h = (w * d.height)/d.width;
d.setSize(w, h);
d = clipDim(d);
chartBox.setPreferredSize(d);
chartBox.setMinimumSize(d);
chartBox.setMaximumSize(d);
parentBox.setMaximumSize(d);
chartBox.repaint();
chartBox.revalidate();
}
public void zoomOut() {
Dimension d = chartBox.getSize();
double w = d.width - d.width * zoomPercentage;
double h = (w * d.height)/d.width;
d.setSize(w, h);
chartBox.setPreferredSize(d);
chartBox.setMinimumSize(d);
chartBox.setMaximumSize(d);
chartBox.repaint();
chartBox.revalidate();
}
public void resetSize() {
chartBox.setPreferredSize(minDim);
chartBox.setMinimumSize(minDim);
chartBox.setMaximumSize(minDim);
chartBox.repaint();
chartBox.revalidate();
}
public void resetScale() {
chartPane.restoreAutoBounds();
}
private Dimension clipDim(Dimension dimension) {
if (dimension == null) {
return null;
}
if (dimension.width < minDim.width || dimension.height < minDim.height) {
return minDim;
} else if (dimension.width > maxDim.width || dimension.height > maxDim.height) {
return maxDim;
} else {
return dimension;
}
}
}
FlowChartInfo.java类:
package cic.cs.unb.ca.flow.ui;
public class FlowChartInfo {
private String name;
private ChartContainer cc;
public FlowChartInfo(String name, ChartContainer cc) {
this.name = name;
this.cc = cc;
}
public String getName() {
return name;
}
public ChartContainer getCc() {
return cc;
}
@Override
public String toString() {
return name;
}
}
FlowChartPane.java类:
package cic.cs.unb.ca.flow.ui;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
public class FlowChartPane extends JPanel{
protected static final Logger logger = LoggerFactory.getLogger(FlowChartPane.class);
private JPanel chartPane;
private List<ChartContainer> ccList = new ArrayList<>();
private ChartContainer focusCC = null;
public FlowChartPane() {
init();
setLayout(new BorderLayout(0,0));
setOpaque(true);
JScrollPane jScrollPane = new JScrollPane(initBoxPane());
jScrollPane.setPreferredSize(getPreferredSize());
jScrollPane.setOpaque(true);
add(jScrollPane, BorderLayout.CENTER);
}
private void init() {
}
private JPanel initBoxPane() {
chartPane = new JPanel();
chartPane.setLayout(new BoxLayout(chartPane,BoxLayout.Y_AXIS));
chartPane.setOpaque(true);
return chartPane;
}
public void addChartContainer(ChartContainer cc) {
if (cc == null) {
return;
}
cc.addMouseListener(mChartContainerMouseListener);
ccList.add(cc);
chartPane.add(cc);
chartPane.repaint();
chartPane.revalidate();
}
public void removeChart(){
chartPane.removeAll();
chartPane.revalidate();
chartPane.repaint();
}
public void zoomIn() {
if (focusCC != null) {
focusCC.zoomIn();
}
}
public void zoomOut() {
if (focusCC != null) {
focusCC.zoomOut();
}
}
public void resetSize() {
for (ChartContainer chartContainer : ccList) {
chartContainer.resetSize();
}
}
public void resetScale() {
for (ChartContainer chartContainer : ccList) {
chartContainer.resetScale();
}
}
private MouseAdapter mChartContainerMouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {
super.mouseClicked(mouseEvent);
ChartContainer cc = (ChartContainer) mouseEvent.getSource();
for (ChartContainer chartContainer : ccList) {
chartContainer.setFocus(false);
}
cc.setFocus(true);
focusCC = cc;
}
};
}
FlowChartWorkerFactory.java类:
package cic.cs.unb.ca.flow.ui;
import cic.cs.unb.ca.jnetpcap.FlowFeature;
import cic.cs.unb.ca.weka.WekaFactory;
import cic.cs.unb.ca.weka.WekaXMeans;
import com.google.common.collect.Multimap;
import org.apache.commons.lang3.math.NumberUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import weka.core.Attribute;
import weka.core.Instance;
import javax.swing.*;
public class FlowChartWorkerFactory {
protected static final Logger logger = LoggerFactory.getLogger(FlowChartWorkerFactory.class);
public static final int PIE_CHART = 1;
public static final int BAR_CHART = 2;
public static abstract class FlowChartSwingWorker<T, V> extends SwingWorker<T, V> {
protected FlowFileInfo flowFileInfo;
protected FlowFeature feature;
protected int chartType;
protected String title = "undefined";
public FlowFileInfo getFlowFileInfo() {
return flowFileInfo;
}
public FlowFeature getFeature() {
return feature;
}
public int getChartType() {
return chartType;
}
public String getChartTitle() {
return title;
}
}
public static class BuildProtocolChartWorker extends FlowChartSwingWorker<JFreeChart, String> {
WekaXMeans xMeans;
public BuildProtocolChartWorker(FlowFileInfo info, int type) {
flowFileInfo = info;
feature = FlowFeature.prot;
chartType = type;
xMeans = flowFileInfo.getxMeans();
}
@Override
protected JFreeChart doInBackground() {
if (xMeans ==null) {
throw new IllegalArgumentException("xMeans should not be null");
}
JFreeChart chart;
title = "Flows By " + feature.getName();
Attribute attribute = WekaFactory.feature2attr(feature.getName(),feature.isNumeric());
Multimap<String, Instance> protocol_multimap = xMeans.getMultiMap(attribute);
switch(chartType){
case PIE_CHART:
DefaultPieDataset pieDataset = new DefaultPieDataset();
for (String key : protocol_multimap.keySet()) {
pieDataset.setValue(FlowFeature.featureValue2String(feature,key),protocol_multimap.get(key).size());
}
chart = ChartFactory.createPieChart(
title, // chart title
pieDataset, // data
true, // include legend
true,
false);
break;
case BAR_CHART:
DefaultCategoryDataset barDataSet = new DefaultCategoryDataset();
for (String key : protocol_multimap.keySet()) {
barDataSet.setValue(protocol_multimap.get(key).size(),key,feature.getAbbr());
}
chart = ChartFactory.createBarChart(title,
"",
"num",
barDataSet, PlotOrientation.HORIZONTAL,
true,
true,
false);
break;
default:
return null;
}
return chart;
}
}
public static class BuildIPChartWorker extends FlowChartSwingWorker<JFreeChart, String> {
WekaXMeans xMeans;
public BuildIPChartWorker(FlowFileInfo info, FlowFeature f, int type) {
flowFileInfo = info;
feature = f;
chartType = type;
xMeans = flowFileInfo.getxMeans();
}
@Override
protected JFreeChart doInBackground() {
if (xMeans == null || feature ==null) {
throw new IllegalArgumentException("xMeans or feature should not be null");
}
JFreeChart chart;
title = "Flows By " + feature.getName();
Attribute attribute = WekaFactory.feature2attr(feature.getName(),feature.isNumeric());
Multimap<String, Instance> feature_value_map = xMeans.getMultiMap(attribute);
switch(chartType){
case PIE_CHART:
DefaultPieDataset pieDataset = new DefaultPieDataset();
for (String key : feature_value_map.keySet()) {
pieDataset.setValue(key,feature_value_map.get(key).size());
}
chart = ChartFactory.createPieChart(
title, // chart title
pieDataset, // data
true, // include legend
true,
false);
break;
case BAR_CHART:
DefaultCategoryDataset barDataSet = new DefaultCategoryDataset();
for (String key : feature_value_map.keySet()) {
double value = feature_value_map.get(key).size();
String rowKey = feature.getAbbr();
String colKey = key;
barDataSet.setValue(value,rowKey,colKey);
}
chart = ChartFactory.createBarChart(title,
null,
"Count",
barDataSet,
PlotOrientation.HORIZONTAL,
false,
true,
false);
break;
default:
return null;
}
return chart;
}
}
public static class BuildPortChartWorker extends FlowChartSwingWorker<JFreeChart, String> {
WekaXMeans xMeans;
public BuildPortChartWorker(FlowFileInfo info, FlowFeature f, int type) {
flowFileInfo = info;
feature = f;
chartType = type;
xMeans = flowFileInfo.getxMeans();
}
@Override
protected JFreeChart doInBackground() {
if (xMeans == null || feature ==null) {
throw new IllegalArgumentException("xMeans or feature should not be null");
}
JFreeChart chart;
title = "Flows By " + feature.getName();
Attribute attribute = WekaFactory.feature2attr(feature.getName(),feature.isNumeric());
Multimap<String, Instance> port_multimap = xMeans.getMultiMap(attribute);
switch(chartType){
case PIE_CHART:
DefaultPieDataset pieDataSet = new DefaultPieDataset();
for (String key : port_multimap.keySet()) {
Integer port = NumberUtils.createNumber(key).intValue();
pieDataSet.setValue(port,port_multimap.get(key).size());
}
chart = ChartFactory.createPieChart(
title, // chart title
pieDataSet, // data
true, // include legend
true,
false);
break;
case BAR_CHART:
DefaultCategoryDataset barDataSet = new DefaultCategoryDataset();
for (String key : port_multimap.keySet()) {
double value = port_multimap.get(key).size();
String rowKey = feature.getAbbr();
Integer colKey = NumberUtils.createNumber(key).intValue();
barDataSet.setValue(value,rowKey,colKey);
}
chart = ChartFactory.createBarChart(title,
"",
"Count",
barDataSet,PlotOrientation.HORIZONTAL,
false,
true,
false);
break;
default:
return null;
}
return chart;
}
}
}
FlowFileInfo.java类:
package cic.cs.unb.ca.flow.ui;
import cic.cs.unb.ca.weka.WekaXMeans;
import java.io.File;
public class FlowFileInfo {
private File filepath;
private WekaXMeans xMeans;
public FlowFileInfo(File filepath, WekaXMeans xMeans) {
this.filepath = filepath;
this.xMeans = xMeans;
}
@Override
public String toString() {
return filepath.getName();
}
public File getFilepath() {
return filepath;
}
public WekaXMeans getxMeans() {
return xMeans;
}
}
FlowMonitorPane.java类:
package cic.cs.unb.ca.flow.ui;
import cic.cs.unb.ca.Sys;
import cic.cs.unb.ca.flow.FlowMgr;
import cic.cs.unb.ca.guava.Event.FlowVisualEvent;
import cic.cs.unb.ca.guava.GuavaMgr;
import cic.cs.unb.ca.jnetpcap.BasicFlow;
import cic.cs.unb.ca.jnetpcap.FlowFeature;
import cic.cs.unb.ca.jnetpcap.PcapIfWrapper;
import cic.cs.unb.ca.jnetpcap.worker.LoadPcapInterfaceWorker;
import cic.cs.unb.ca.jnetpcap.worker.TrafficFlowWorker;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.jnetpcap.PcapIf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cic.cs.unb.ca.jnetpcap.worker.InsertCsvRow;
import swing.common.InsertTableRow;
import swing.common.JTable2CSVWorker;
import swing.common.TextFileFilter;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FlowMonitorPane extends JPanel {
protected static final Logger logger = LoggerFactory.getLogger(FlowMonitorPane.class);
private JTable flowTable;
private DefaultTableModel defaultTableModel;
private JList<PcapIfWrapper> list;
private DefaultListModel<PcapIfWrapper> listModel;
private JLabel lblStatus;
private JLabel lblFlowCnt;
private TrafficFlowWorker mWorker;
private JButton btnLoad;
private JToggleButton btnStart;
private JToggleButton btnStop;
private ButtonGroup btnGroup;
private JButton btnSave = new JButton();
private File lastSave;
private JButton btnGraph = new JButton();
private JFileChooser fileChooser;
private ExecutorService csvWriterThread;
public FlowMonitorPane() {
init();
setLayout(new BorderLayout(5, 5));
setBorder(new EmptyBorder(10, 10, 10, 10));
add(initCenterPane(), BorderLayout.CENTER);
}
private void init() {
csvWriterThread = Executors.newSingleThreadExecutor();
}
public void destory() {
csvWriterThread.shutdown();
}
private JPanel initCenterPane(){
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout(0, 0));
pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,initFlowPane(), initNWifsPane());
splitPane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(1.0);
pane.add(splitPane,BorderLayout.CENTER);
return pane;
}
private JPanel initFlowPane() {
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout(0, 5));
pane.setBorder(BorderFactory.createLineBorder(new Color(0x555555)));
//pane.add(initTableBtnPane(), BorderLayout.NORTH);
pane.add(initTablePane(), BorderLayout.CENTER);
pane.add(initStatusPane(), BorderLayout.SOUTH);
return pane;
}
private JPanel initTablePane() {
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout(0, 0));
pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
String[] arrayHeader = StringUtils.split(FlowFeature.getHeader(), ",");
defaultTableModel = new DefaultTableModel(arrayHeader,0);
flowTable = new JTable(defaultTableModel);
flowTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane scrollPane = new JScrollPane(flowTable);
scrollPane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
pane.add(scrollPane,BorderLayout.CENTER);
return pane;
}
private JPanel initTableBtnPane(){
JPanel btnPane = new JPanel();
btnPane.setLayout(new BoxLayout(btnPane, BoxLayout.X_AXIS));
btnSave = new JButton("Save as");
btnGraph = new JButton("Graphs");
btnSave.setFocusable(false);
btnSave.setEnabled(false);
btnGraph.setFocusable(false);
btnGraph.setEnabled(false);
fileChooser = new JFileChooser(new File(FlowMgr.getInstance().getmDataPath()));
TextFileFilter csvChooserFilter = new TextFileFilter("csv file (*.csv)", new String[]{"csv"});
fileChooser.setFileFilter(csvChooserFilter);
btnSave.addActionListener(actionEvent -> {
int action = fileChooser.showSaveDialog(FlowMonitorPane.this);
if (action == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
String filename = selectedFile.getName();
if (FilenameUtils.getExtension(filename).equalsIgnoreCase("csv")) {
//save name ok
} else {
selectedFile = new File(selectedFile.getParentFile(), FilenameUtils.getBaseName(filename) + ".csv");
}
String title = "file conflict";
String message = "Another file with the same name already exists,do you want to overwrite?";
if (selectedFile.exists()) {
int reply = JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION);
if (reply == JOptionPane.YES_OPTION) {
JTable2CSVWorker worker = new JTable2CSVWorker(flowTable, selectedFile);
worker.execute();
} else {
btnSave.doClick();
}
} else {
JTable2CSVWorker worker = new JTable2CSVWorker(flowTable, selectedFile);
worker.execute();
}
lastSave = selectedFile;
btnGraph.setEnabled(true);
}
});
btnGraph.addActionListener(actionEvent -> GuavaMgr.getInstance().getEventBus().post(new FlowVisualEvent(lastSave)));
btnPane.add(Box.createHorizontalGlue());
btnPane.add(btnSave);
btnPane.add(Box.createHorizontalGlue());
btnPane.add(btnGraph);
btnPane.add(Box.createHorizontalGlue());
btnPane.setBorder(BorderFactory.createRaisedSoftBevelBorder());
return btnPane;
}
private JPanel initStatusPane() {
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
lblStatus = new JLabel("Get ready");
lblStatus.setForeground(SystemColor.desktop);
lblFlowCnt = new JLabel("0");
pane.add(Box.createHorizontalStrut(5));
pane.add(lblStatus);
pane.add(Box.createHorizontalGlue());
pane.add(lblFlowCnt);
pane.add(Box.createHorizontalStrut(5));
return pane;
}
private JPanel initNWifsPane() {
JPanel pane = new JPanel(new BorderLayout(0, 0));
pane.setBorder(BorderFactory.createLineBorder(new Color(0x555555)));
pane.add(initNWifsButtonPane(), BorderLayout.WEST);
pane.add(initNWifsListPane(), BorderLayout.CENTER);
return pane;
}
private JPanel initNWifsButtonPane() {
JPanel pane = new JPanel();
pane.setBorder(BorderFactory.createEmptyBorder(10,15,10,15));
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
Dimension d = new Dimension(80,48);
btnLoad = new JButton("Load");
btnLoad.setMinimumSize(d);
btnLoad.setMaximumSize(d);
btnLoad.addActionListener(actionEvent -> loadPcapIfs());
btnStart = new JToggleButton("Start");
btnStart.setMinimumSize(d);
btnStart.setMaximumSize(d);
btnStart.setEnabled(false);
btnStart.addActionListener(actionEvent -> startTrafficFlow());
btnStop = new JToggleButton("Stop");
btnStop.setMinimumSize(d);
btnStop.setMaximumSize(d);
btnStop.setEnabled(false);
btnStop.addActionListener(actionEvent -> stopTrafficFlow());
btnGroup = new ButtonGroup();
btnGroup.add(btnStart);
btnGroup.add(btnStop);
pane.add(Box.createVerticalGlue());
pane.add(btnLoad);
pane.add(Box.createVerticalGlue());
pane.add(btnStart);
pane.add(Box.createVerticalGlue());
pane.add(btnStop);
pane.add(Box.createVerticalGlue());
return pane;
}
private JPanel initNWifsListPane() {
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout(0, 0));
pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
listModel = new DefaultListModel<>();
listModel.addElement(new PcapIfWrapper("Click Load button to load network interfaces"));
list = new JList<>(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
pane.add(scrollPane,BorderLayout.CENTER);
return pane;
}
private void loadPcapIfs() {
LoadPcapInterfaceWorker task = new LoadPcapInterfaceWorker();
task.addPropertyChangeListener(event -> {
if ("state".equals(event.getPropertyName())) {
LoadPcapInterfaceWorker task1 = (LoadPcapInterfaceWorker) event.getSource();
switch (task1.getState()) {
case STARTED:
break;
case DONE:
try {
java.util.List<PcapIf> ifs = task1.get();
List<PcapIfWrapper> pcapiflist = PcapIfWrapper.fromPcapIf(ifs);
listModel.removeAllElements();
for(PcapIfWrapper pcapif :pcapiflist) {
listModel.addElement(pcapif);
}
btnStart.setEnabled(true);
btnGroup.clearSelection();
lblStatus.setText("pick one network interface to listening");
lblStatus.validate();
} catch (InterruptedException | ExecutionException e) {
logger.debug(e.getMessage());
}
break;
}
}
});
task.execute();
}
private void startTrafficFlow() {
String ifName = list.getSelectedValue().name();
if (mWorker != null && !mWorker.isCancelled()) {
return;
}
mWorker = new TrafficFlowWorker(ifName);
mWorker.addPropertyChangeListener(event -> {
TrafficFlowWorker task = (TrafficFlowWorker) event.getSource();
if("progress".equals(event.getPropertyName())){
lblStatus.setText((String) event.getNewValue());
lblStatus.validate();
}else if (TrafficFlowWorker.PROPERTY_FLOW.equalsIgnoreCase(event.getPropertyName())) {
insertFlow((BasicFlow) event.getNewValue());
}else if ("state".equals(event.getPropertyName())) {
switch (task.getState()) {
case STARTED:
break;
case DONE:
try {
lblStatus.setText(task.get());
lblStatus.validate();
} catch(CancellationException e){
lblStatus.setText("stop listening");
lblStatus.setForeground(SystemColor.GRAY);
lblStatus.validate();
logger.info("Pcap stop listening");
}catch (InterruptedException | ExecutionException e) {
logger.debug(e.getMessage());
}
break;
}
}
});
mWorker.execute();
lblStatus.setForeground(SystemColor.desktop);
btnLoad.setEnabled(false);
btnStop.setEnabled(true);
}
private void stopTrafficFlow() {
if (mWorker != null) {
mWorker.cancel(true);
}
//FlowMgr.getInstance().stopFetchFlow();
btnLoad.setEnabled(true);
String path = FlowMgr.getInstance().getAutoSaveFile();
logger.info("path:{}", path);
if(defaultTableModel.getRowCount()>0 && new File(path).exists()) {
StringBuilder msg = new StringBuilder("The flow has been saved to :");
msg.append(Sys.LINE_SEP);
msg.append(path);
UIManager.put("OptionPane.minimumSize",new Dimension(0, 0));
JOptionPane.showMessageDialog(this.getParent(),msg.toString());
}
}
private void insertFlow(BasicFlow flow) {
List<String> flowStringList = new ArrayList<>();
List<String[]> flowDataList = new ArrayList<>();
String flowDump = flow.dumpFlowBasedFeaturesEx();
flowStringList.add(flowDump);
flowDataList.add(StringUtils.split(flowDump, ","));
//write flows to csv file
String header = FlowFeature.getHeader();
String path = FlowMgr.getInstance().getSavePath();
String filename = LocalDate.now().toString() + FlowMgr.FLOW_SUFFIX;
csvWriterThread.execute(new InsertCsvRow(header, flowStringList, path, filename));
//insert flows to JTable
SwingUtilities.invokeLater(new InsertTableRow(defaultTableModel,flowDataList,lblFlowCnt));
btnSave.setEnabled(true);
}
}
FlowOfflinePane.java类:
package cic.cs.unb.ca.flow.ui;
import cic.cs.unb.ca.flow.FlowMgr;
import cic.cs.unb.ca.jnetpcap.BasicFlow;
import cic.cs.unb.ca.jnetpcap.FlowFeature;
import cic.cs.unb.ca.jnetpcap.worker.ReadPcapFileWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cic.cs.unb.ca.jnetpcap.worker.InsertCsvRow;
import swing.common.PcapFileFilter;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FlowOfflinePane extends JPanel{
protected static final Logger logger = LoggerFactory.getLogger(FlowOfflinePane.class);
private static final Border PADDING = BorderFactory.createEmptyBorder(10,5,10,5);
private JFileChooser fileChooser;
private PcapFileFilter pcapChooserFilter;
private JTextArea textArea;
private JButton btnClr;
private JComboBox<File> cmbInput;
private JComboBox<File> cmbOutput;
private Vector<File> cmbInputEle;
private Vector<File> cmbOutputEle;
private JComboBox<Long> param1;
private JComboBox<Long> param2;
private Vector<Long> param1Ele;
private Vector<Long> param2Ele;
private Box progressBox;
private JProgressBar fileProgress;
private JProgressBar fileCntProgress;
private ExecutorService csvWriterThread;
public FlowOfflinePane() {
init();
setLayout(new BorderLayout(5, 5));
setBorder(new EmptyBorder(10, 10, 10, 10));
add(initOutPane(), BorderLayout.CENTER);
add(initCtrlPane(), BorderLayout.SOUTH);
}
private void init(){
fileChooser = new JFileChooser(new File("."));
pcapChooserFilter = new PcapFileFilter();
fileChooser.setFileFilter(pcapChooserFilter);
csvWriterThread = Executors.newSingleThreadExecutor();
}
public void destroy() {
csvWriterThread.shutdown();
}
private JPanel initOutPane(){
JPanel jPanel = new JPanel(new BorderLayout(5, 5));
JScrollPane scrollPane = new JScrollPane();
textArea = new JTextArea();
textArea.setRows(36);
textArea.setToolTipText("message");
scrollPane.setViewportView(textArea);
scrollPane.setBorder(BorderFactory.createLineBorder(new Color(0x555555)));
/*JPanel msgSettingPane = new JPanel();
msgSettingPane.setLayout(new BoxLayout(msgSettingPane, BoxLayout.X_AXIS));
btnClr = new JButton("Clear");
msgSettingPane.add(Box.createHorizontalGlue());
msgSettingPane.add(btnClr);
btnClr.addActionListener(actionEvent -> textArea.setText(""));*/
jPanel.add(scrollPane, BorderLayout.CENTER);
jPanel.add(initOutStatusPane(), BorderLayout.SOUTH);
return jPanel;
}
private JPanel initOutStatusPane() {
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
progressBox = Box.createVerticalBox();
fileProgress = new JProgressBar();
fileCntProgress = new JProgressBar();
fileProgress.setBorderPainted(true);
fileProgress.setStringPainted(true);
fileCntProgress.setBorderPainted(true);
fileCntProgress.setStringPainted(true);
progressBox.add(fileProgress);
progressBox.add(fileCntProgress);
btnClr = new JButton("Clear");
int height = fileProgress.getPreferredSize().height + fileCntProgress.getPreferredSize().height;
Dimension d = new Dimension(80,height);
btnClr.setPreferredSize(d);
btnClr.setMaximumSize(d);
btnClr.setMinimumSize(d);
btnClr.addActionListener(actionEvent -> textArea.setText(""));
progressBox.setVisible(false);
pane.add(btnClr);
pane.add(Box.createHorizontalStrut(18));
pane.add(progressBox);
return pane;
}
private JPanel initCtrlPane(){
JPanel jPanel = new JPanel(new BorderLayout(5, 5));
JPanel optPane = new JPanel();
optPane.setLayout(new BoxLayout(optPane,BoxLayout.Y_AXIS));
optPane.add(initFilePane());
optPane.add(initSettingPane());
optPane.add(initActionPane());
jPanel.add(optPane, BorderLayout.CENTER);
jPanel.setBorder(BorderFactory.createLineBorder(new Color(0x555555)));
return jPanel;
}
private JPanel initFilePane(){
JPanel jPanel = new JPanel();
jPanel.setLayout(new GridBagLayout());
jPanel.setBorder(PADDING);
GridBagConstraints gc = new GridBagConstraints();
gc.insets = new Insets(10, 0, 10, 0);
JLabel lblInputDir = new JLabel("Pcap dir:");
JButton btnInputBrowse = new JButton("Browse");
cmbInputEle = new Vector<>();
cmbInput = new JComboBox<>(cmbInputEle);
cmbInput.setEditable(true);
btnInputBrowse.addActionListener(actionEvent -> {
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
fileChooser.setFileFilter(pcapChooserFilter);
int action = fileChooser.showOpenDialog(FlowOfflinePane.this);
if (action == JFileChooser.APPROVE_OPTION) {
File inputFile = fileChooser.getSelectedFile();
logger.debug("offline select input {}", inputFile.getPath());
setComboBox(cmbInput, cmbInputEle, inputFile);
}
});
JLabel lblOutputDir = new JLabel("Output dir:");
JButton btnOutputBrowse = new JButton("Browse");
cmbOutputEle = new Vector<>();
cmbOutput = new JComboBox<>(cmbOutputEle);
cmbOutput.setEditable(true);
btnOutputBrowse.addActionListener(actionEvent -> {
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.removeChoosableFileFilter(pcapChooserFilter);
int action = fileChooser.showOpenDialog(FlowOfflinePane.this);
if (action == JFileChooser.APPROVE_OPTION) {
File outputFile = fileChooser.getSelectedFile();
logger.debug("offline select output {}", outputFile.getPath());
setComboBox(cmbOutput, cmbOutputEle, outputFile);
}
});
//first row
gc.gridx = 0;
gc.gridy = 0;
gc.weightx = 0;
gc.weighty = 0.1;
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.LINE_END;
//gc.insets = new Insets(10, 5, 10, 5);
jPanel.add(lblInputDir, gc);
gc.gridx = 1;
gc.gridy = 0;
gc.weightx = 1;
gc.weighty = 0.1;
gc.fill = GridBagConstraints.HORIZONTAL;
gc.anchor = GridBagConstraints.LINE_START;
//gc.insets = new Insets(0, 10, 0, 0);
gc.insets.left = gc.insets.right = 10;
jPanel.add(cmbInput, gc);
gc.gridx = 2;
gc.gridy = 0;
gc.weightx = 0;
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.LINE_END;
//gc.insets = new Insets(10, 5, 10, 0);
jPanel.add(btnInputBrowse, gc);
//second row
gc.gridx = 0;
gc.gridy = 1;
gc.weightx = 0;
gc.weighty = 0.1;
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.LINE_END;
//gc.insets = new Insets(10, 5, 10, 5);
jPanel.add(lblOutputDir, gc);
gc.gridx = 1;
gc.gridy = 1;
gc.weightx = 1;
gc.fill = GridBagConstraints.HORIZONTAL;
gc.anchor = GridBagConstraints.LINE_START;
//gc.insets = new Insets(0, 10, 0, 0);
gc.insets.left = gc.insets.right = 10;
jPanel.add(cmbOutput, gc);
gc.gridx = 2;
gc.gridy = 1;
gc.weightx = 0;
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.LINE_END;
//gc.insets = new Insets(10, 5, 10, 0);
jPanel.add(btnOutputBrowse, gc);
return jPanel;
}
private JPanel initSettingPane(){
JPanel jPanel = new JPanel();
jPanel.setLayout(new BoxLayout(jPanel,BoxLayout.X_AXIS));
jPanel.setBorder(PADDING);
JLabel lbl1 = new JLabel("Flow TimeOut:");
param1Ele = new Vector<>();
param1Ele.add(120000000L);
param1 = new JComboBox<>(param1Ele);
param1.setEditable(true);
JLabel lbl2 = new JLabel("Activity Timeout:");
param2Ele = new Vector<>();
param2Ele.add(5000000L);
param2 = new JComboBox<>(param2Ele);
param2.setEditable(true);
jPanel.add(lbl1);
jPanel.add(param1);
jPanel.add(Box.createHorizontalGlue());
jPanel.add(lbl2);
jPanel.add(param2);
return jPanel;
}
private JPanel initActionPane() {
JPanel jPanel = new JPanel();
jPanel.setLayout(new BoxLayout(jPanel,BoxLayout.X_AXIS));
jPanel.setBorder(PADDING);
JButton btnOK = new JButton("OK");
Dimension d = new Dimension(80,36);
btnOK.setPreferredSize(d);
btnOK.setMaximumSize(d);
btnOK.setMinimumSize(d);
jPanel.add(Box.createHorizontalGlue());
jPanel.add(btnOK);
jPanel.add(Box.createHorizontalGlue());
btnOK.addActionListener(actionEvent -> startReadPcap());
return jPanel;
}
private void setComboBox(JComboBox<File> combo, Vector<File> comboEle, File ele) {
if (comboEle.contains(ele)) {
combo.setSelectedItem(ele);
} else {
comboEle.addElement(ele);
combo.setSelectedItem(comboEle.lastElement());
}
}
private void updateOut(String str) {
textArea.append(str);
textArea.append(System.lineSeparator());
}
private long getComboParameter(JComboBox<Long> param,Vector<Long> paramEle) throws ClassCastException,NumberFormatException{
long ret;
int index = param.getSelectedIndex();
String input;
if (index < 0) {
Object o = param.getEditor().getItem();
if (o instanceof Long) {
ret = (long) o;
} else {
input = (String) param.getEditor().getItem();
ret = Long.valueOf(input);
}
paramEle.add(ret);
} else {
ret = paramEle.get(index);
}
return ret;
}
private void startReadPcap(){
final File in;
int cmbInIndex = cmbInput.getSelectedIndex();
if (cmbInIndex < 0) {
in = new File((String) cmbInput.getEditor().getItem());
}else{
in = cmbInputEle.get(cmbInIndex);
}
final File out;
int cmbOutIndex = cmbOutput.getSelectedIndex();
if (cmbOutIndex < 0) {
out = new File((String) cmbOutput.getEditor().getItem());
}else{
out = cmbOutputEle.get(cmbOutIndex);
}
updateOut("You select: " + in.toString());
updateOut("Out folder: " + out.toString());
updateOut("-------------------------------");
long flowTimeout;
long activityTimeout;
try {
flowTimeout = getComboParameter(param1, param1Ele);
activityTimeout = getComboParameter(param2, param2Ele);
Map<String, Long> flowCnt = new HashMap<>();
ReadPcapFileWorker worker = new ReadPcapFileWorker(in, out.getPath(), flowTimeout, activityTimeout);
worker.addPropertyChangeListener(evt -> {
ReadPcapFileWorker task = (ReadPcapFileWorker) evt.getSource();
if ("progress".equals(evt.getPropertyName())) {
//logger.info("progress -> {}", evt.getNewValue());
List<String> chunks = (List<String>) evt.getNewValue();
if (chunks != null) {
SwingUtilities.invokeLater(() -> {
for (String str : chunks) {
updateOut(str);
}
});
}
} else if ("state".equals(evt.getPropertyName())) {
switch (task.getState()) {
case STARTED:
progressBox.setVisible(true);
break;
case DONE:
progressBox.setVisible(false);
flowCnt.clear();
break;
}
} else if (ReadPcapFileWorker.PROPERTY_FILE_CNT.equalsIgnoreCase(evt.getPropertyName())) {
int max = (int) evt.getOldValue();
int cur = (int) evt.getNewValue()+1;
fileCntProgress.setIndeterminate(false);
fileCntProgress.setMaximum(max);
fileCntProgress.setValue(cur);
} else if (ReadPcapFileWorker.PROPERTY_CUR_FILE.equalsIgnoreCase(evt.getPropertyName())) {
fileProgress.setIndeterminate(true);
String curFile = (String) evt.getNewValue();
fileProgress.setString(curFile);
flowCnt.put(curFile, 0L);
} else if (ReadPcapFileWorker.PROPERTY_FLOW.equalsIgnoreCase(evt.getPropertyName())) {
String fileName = (String) evt.getOldValue();
BasicFlow flow = (BasicFlow) evt.getNewValue();
flowCnt.put(fileName, flowCnt.get(fileName) + 1);
String msg = String.format("%d flows on Reading %s",flowCnt.get(fileName),fileName);
fileProgress.setString(msg);
//write flows to csv file
String header = FlowFeature.getHeader();
csvWriterThread.execute(new InsertCsvRow(header, flow.dumpFlowBasedFeaturesEx(), out.getPath(), fileName+FlowMgr.FLOW_SUFFIX));
}
});
worker.execute();
} catch(ClassCastException | NumberFormatException e){
logger.info("startRead: {}",e.getMessage());
JOptionPane.showMessageDialog(FlowOfflinePane.this, "The parameter is not a number,please check and try again.", "Parameter error", JOptionPane.ERROR_MESSAGE);
}
}
}
FlowVisualPane.java类:
package cic.cs.unb.ca.flow.ui;
import cic.cs.unb.ca.weka.WekaFactory;
import cic.cs.unb.ca.weka.WekaXMeans;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import swing.common.CsvPickerPane;
import swing.common.SwingUtils;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.concurrent.ExecutionException;
import static cic.cs.unb.ca.jnetpcap.FlowFeature.*;
/**
* Created by yzhang29 on 03/01/18.
*/
public class FlowVisualPane extends JDesktopPane implements CsvPickerPane.CsvSelect{
protected static final Logger logger = LoggerFactory.getLogger(FlowVisualPane.class);
private CsvPickerPane pickerPane;
private FlowChartPane flowChartPane;
private JProgressBar progressBar;
private JTree graphTree;
private Multimap<FlowFileInfo,FlowChartInfo> treeNodeData;
public FlowVisualPane() {
init();
setLayout(new BorderLayout(0, 3));
//setBorder(Constants.LINEBORDER);
pickerPane = new CsvPickerPane(this);
pickerPane.setFilter("Flow");
pickerPane.setSelectListener(this);
flowChartPane = new FlowChartPane();
add(pickerPane, BorderLayout.NORTH);
add(flowChartPane,BorderLayout.CENTER);
add(initOptionPane(), BorderLayout.WEST);
}
public FlowVisualPane(File file) {
this();
visualFile(file);
}
private void init() {
progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
treeNodeData = ArrayListMultimap.create();
}
public void visualFile(File file) {
logger.info("visualFile {}",file.getPath());
if (isFlowFileInfoExist(file)) {
return;
} else {
flowChartPane.removeChart();
final CreateXMeansWorker xMeansWorker = new CreateXMeansWorker(file);
SwingUtils.setBorderLayoutPane(FlowVisualPane.this,progressBar,BorderLayout.SOUTH);
xMeansWorker.execute();
}
}
@Override
public void onSelected(File file) {
visualFile(file);
}
private JPanel initOptionPane() {
JPanel pane = new JPanel(new BorderLayout());
pane.add(initGraphTreePane(), BorderLayout.CENTER);
pane.add(initGraphButtonPane(), BorderLayout.SOUTH);
return pane;
}
private JScrollPane initGraphTreePane() {
graphTree = new JTree(createTree());
JScrollPane treeView = new JScrollPane(graphTree);
return treeView;
}
private JPanel initGraphButtonPane() {
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane,BoxLayout.Y_AXIS));
Box sizeBox = Box.createHorizontalBox();
JLabel wlbl = new JLabel("Width: ");
JSpinner widthSpinner;
JSpinner heightSpinner;
JLabel hlbl = new JLabel("Height: ");
SpinnerNumberModel widthSpinnerModel;
SpinnerNumberModel heightSpinnerModel;
widthSpinnerModel = new SpinnerNumberModel(300,ChartPanel.DEFAULT_MINIMUM_DRAW_WIDTH,ChartPanel.DEFAULT_MAXIMUM_DRAW_WIDTH,12);
heightSpinnerModel = new SpinnerNumberModel(200,ChartPanel.DEFAULT_MINIMUM_DRAW_HEIGHT,ChartPanel.DEFAULT_MAXIMUM_DRAW_HEIGHT,12);
widthSpinner = new JSpinner(widthSpinnerModel);
heightSpinner = new JSpinner(heightSpinnerModel);
widthSpinner.setPreferredSize(heightSpinner.getPreferredSize());
sizeBox.add(Box.createHorizontalStrut(16));
sizeBox.add(wlbl);
sizeBox.add(widthSpinner);
sizeBox.add(Box.createHorizontalStrut(16));
sizeBox.add(hlbl);
sizeBox.add(heightSpinner);
sizeBox.add(Box.createHorizontalStrut(16));
sizeBox.setVisible(false);
Dimension btnDim = new Dimension(116, 64);
JButton zoomIn = new JButton("Zoom In");
zoomIn.setPreferredSize(btnDim);
zoomIn.addActionListener(actionEvent -> flowChartPane.zoomIn());
JButton zoomOut = new JButton("Zoom Out");
zoomOut.setPreferredSize(btnDim);
zoomOut.addActionListener(actionEvent -> flowChartPane.zoomOut());
JButton reset_size = new JButton("Reset size");
reset_size.setPreferredSize(btnDim);
reset_size.setMinimumSize(btnDim);
reset_size.addActionListener(actionEvent -> flowChartPane.resetSize());
JButton reset_scale = new JButton("Reset scale");
reset_scale.setPreferredSize(btnDim);
reset_scale.setMinimumSize(btnDim);
reset_scale.addActionListener(actionEvent -> flowChartPane.resetScale());
Box zoomBox = Box.createHorizontalBox();
zoomBox.add(Box.createHorizontalStrut(16));
zoomBox.add(zoomIn);
zoomBox.add(Box.createHorizontalGlue());
zoomBox.add(zoomOut);
zoomBox.add(Box.createHorizontalStrut(16));
Box resetBox = Box.createHorizontalBox();
resetBox.add(Box.createHorizontalStrut(16));
resetBox.add(reset_scale);
resetBox.add(Box.createHorizontalGlue());
resetBox.add(reset_size);
resetBox.add(Box.createHorizontalStrut(16));
pane.add(sizeBox);
pane.add(Box.createVerticalStrut(24));
pane.add(zoomBox);
pane.add(Box.createVerticalStrut(24));
pane.add(resetBox);
pane.add(Box.createVerticalStrut(16));
return pane;
}
private DefaultMutableTreeNode createTree() {
DefaultMutableTreeNode top = new DefaultMutableTreeNode("Flow Chart");
// DefaultMutableTreeNode branch1 = new DefaultMutableTreeNode("File Name");
// DefaultMutableTreeNode graph1 = new DefaultMutableTreeNode(new FlowChartInfo("Flows By Protocol"));
// DefaultMutableTreeNode graph2 = new DefaultMutableTreeNode(new FlowChartInfo("Flows By Src IP"));
// DefaultMutableTreeNode graph3 = new DefaultMutableTreeNode(new FlowChartInfo("Flows By Dst IP"));
// DefaultMutableTreeNode graph4 = new DefaultMutableTreeNode(new FlowChartInfo("Flows By Src Port"));
// DefaultMutableTreeNode graph5 = new DefaultMutableTreeNode(new FlowChartInfo("Flows By Dst Port"));
// branch1.add(graph1);
// branch1.add(graph2);
// branch1.add(graph3);
// branch1.add(graph4);
// branch1.add(graph5);
//top.add(branch1);
return top;
}
private void addChart2Tree(FlowFileInfo flowFileInfo, FlowChartInfo flowChartInfo) {
DefaultTreeModel model = (DefaultTreeModel) graphTree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
DefaultMutableTreeNode fileInfoNode=null;
for(int i=0;i<root.getChildCount();i++) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) root.getChildAt(i);
FlowFileInfo fileInfoInNode = (FlowFileInfo) treeNode.getUserObject();
if (fileInfoInNode == flowFileInfo) {
logger.debug("tree node -> {} exist",flowFileInfo.getFilepath().getPath());
fileInfoNode = treeNode;
break;
}
}
if (fileInfoNode == null) {
fileInfoNode = new DefaultMutableTreeNode(flowFileInfo);
}
fileInfoNode.add(new DefaultMutableTreeNode(flowChartInfo));
root.add(fileInfoNode);
model.reload();
treeNodeData.put(flowFileInfo, flowChartInfo);
}
private boolean isFlowFileInfoExist(File file) {
if (file == null) {
return false;
}
for (FlowFileInfo info : treeNodeData.keySet()) {
if (info.getFilepath().getPath().equalsIgnoreCase(file.getPath())) {
return true;
}
}
return false;
}
private class CreateXMeansWorker extends SwingWorker<FlowFileInfo, String> {
File csv;
CreateXMeansWorker(File csv) {
this.csv = csv;
}
@Override
protected FlowFileInfo doInBackground() {
if (csv == null) {
throw new IllegalArgumentException("csv cannot be null");
}
WekaXMeans xMeans = new WekaXMeans(WekaFactory.loadFlowCsv(csv));
FlowFileInfo flowFileInfo = new FlowFileInfo(csv, xMeans);
return flowFileInfo;
}
@Override
protected void done() {
super.done();
try {
FlowFileInfo flowFileInfo = get();
buildChart(flowFileInfo);
SwingUtils.setBorderLayoutPane(FlowVisualPane.this,null,BorderLayout.SOUTH);
} catch (InterruptedException | ExecutionException e) {
logger.debug(e.getMessage());
}
}
}
public void buildChart(FlowFileInfo info) {
logger.info("buildChart");
FlowChartWorkerFactory.BuildProtocolChartWorker protocol_worker = new FlowChartWorkerFactory.BuildProtocolChartWorker(info,FlowChartWorkerFactory.PIE_CHART);
protocol_worker.addPropertyChangeListener(event -> {
//logger.info("build Protocol chart");
ChartWorkerPropertyChange(event, protocol_worker);
});
protocol_worker.execute();
FlowChartWorkerFactory.BuildIPChartWorker sip_worker = new FlowChartWorkerFactory.BuildIPChartWorker(info,src_ip,FlowChartWorkerFactory.BAR_CHART);
sip_worker.addPropertyChangeListener(event -> {
//logger.info("build src ip chart");
ChartWorkerPropertyChange(event, sip_worker);
});
sip_worker.execute();
FlowChartWorkerFactory.BuildIPChartWorker dip_worker = new FlowChartWorkerFactory.BuildIPChartWorker(info,dst_ip,FlowChartWorkerFactory.BAR_CHART);
dip_worker.addPropertyChangeListener(event -> {
//logger.info("build dst ip chart");
ChartWorkerPropertyChange(event, dip_worker);
});
dip_worker.execute();
FlowChartWorkerFactory.BuildPortChartWorker spt_worker = new FlowChartWorkerFactory.BuildPortChartWorker(info, src_port, FlowChartWorkerFactory.BAR_CHART);
spt_worker.addPropertyChangeListener(event -> {
//logger.info("build src port chart");
ChartWorkerPropertyChange(event, spt_worker);
});
spt_worker.execute();
FlowChartWorkerFactory.BuildPortChartWorker dpt_worker = new FlowChartWorkerFactory.BuildPortChartWorker(info, dst_pot, FlowChartWorkerFactory.BAR_CHART);
dpt_worker.addPropertyChangeListener(event -> {
//logger.info("build dst port chart");
ChartWorkerPropertyChange(event, dpt_worker);
});
dpt_worker.execute();
}
private void ChartWorkerPropertyChange(PropertyChangeEvent event, FlowChartWorkerFactory.FlowChartSwingWorker<JFreeChart, String> task) {
if ("state".equalsIgnoreCase(event.getPropertyName())) {
SwingWorker.StateValue sv = (SwingWorker.StateValue) event.getNewValue();
switch (sv) {
case STARTED:
SwingUtils.setBorderLayoutPane(FlowVisualPane.this,progressBar,BorderLayout.SOUTH);
break;
case DONE:
try {
JFreeChart chart = task.get();
FlowFileInfo fileInfo = task.getFlowFileInfo();
ChartContainer cc = new ChartContainer(chart);
FlowChartInfo chartInfo = new FlowChartInfo(task.getChartTitle(),cc);
flowChartPane.addChartContainer(cc);
addChart2Tree(fileInfo, chartInfo);
SwingUtils.setBorderLayoutPane(FlowVisualPane.this,null,BorderLayout.SOUTH);
} catch (InterruptedException | ExecutionException e) {
logger.debug(e.getMessage());
}
break;
}
}
}
}
FlowVisualEvent.java类:
package cic.cs.unb.ca.guava.Event;
import java.io.File;
public class FlowVisualEvent {
private File csv_file;
public FlowVisualEvent(File csv_file) {
this.csv_file = csv_file;
}
public File getCsv_file() {
return csv_file;
}
}
GuavaMgr.java类:
package cic.cs.unb.ca.guava;
import com.google.common.eventbus.EventBus;
public class GuavaMgr {
private static GuavaMgr Instance = new GuavaMgr();
private EventBus mEventBus;
public GuavaMgr() {
}
public static GuavaMgr getInstance() {
return Instance;
}
public void init(){
mEventBus = new EventBus("CICFlowMeter");
}
public EventBus getEventBus() {
return mEventBus;
}
}
FlowGenListener.java类:
package cic.cs.unb.ca.jnetpcap.worker;
import cic.cs.unb.ca.jnetpcap.BasicFlow;
public interface FlowGenListener {
void onFlowGenerated(BasicFlow flow);
}
InsertCsvRow.java类:
package cic.cs.unb.ca.jnetpcap.worker;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static cic.cs.unb.ca.jnetpcap.Utils.FILE_SEP;
import static cic.cs.unb.ca.jnetpcap.Utils.LINE_SEP;
public class InsertCsvRow implements Runnable {
public static final Logger logger = LoggerFactory.getLogger(InsertCsvRow.class);
private String header;
private List<String> rows;
private String savepath = null;
private String filename = null;
public InsertCsvRow(String header, List<String> rows, String savepath, String filename) {
this.header = header;
this.rows = rows;
this.savepath = savepath;
this.filename = filename;
}
public InsertCsvRow(String header, String row, String savepath, String filename) {
this.header = header;
this.rows = new ArrayList<>();
this.savepath = savepath;
this.filename = filename;
rows.add(row);
}
@Override
public void run() {
insert(header,rows,savepath,filename);
}
public static void insert(String header,List<String> rows,String savepath, String filename) {
if (savepath == null || filename == null || rows == null || rows.size() <= 0) {
String ex = String.format("savepath=%s,filename=%s", savepath, filename);
throw new IllegalArgumentException(ex);
}
File fileSavPath = new File(savepath);
if(!fileSavPath.exists()) {
fileSavPath.mkdirs();
}
if(!savepath.endsWith(FILE_SEP)){
savepath += FILE_SEP;
}
File file = new File(savepath+filename);
FileOutputStream output = null;
try {
if (file.exists()) {
output = new FileOutputStream(file, true);
}else{
if (file.createNewFile()) {
output = new FileOutputStream(file);
}
if (header != null) {
output.write((header+LINE_SEP).getBytes());
}
}
for (String row : rows) {
output.write((row+LINE_SEP).getBytes());
}
} catch (IOException e) {
logger.debug(e.getMessage());
} finally {
try {
if (output != null) {
output.flush();
output.close();
}
} catch (IOException e) {
logger.debug(e.getMessage());
}
}
}
}
LoadPcapInterfaceWorker.java类:
package cic.cs.unb.ca.jnetpcap.worker;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingWorker;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoadPcapInterfaceWorker extends SwingWorker<List<PcapIf>,String>{
public static final Logger logger = LoggerFactory.getLogger(LoadPcapInterfaceWorker.class);
public LoadPcapInterfaceWorker() {
super();
}
@Override
protected List<PcapIf> doInBackground() throws Exception {
StringBuilder errbuf = new StringBuilder();
List<PcapIf> ifs = new ArrayList<>();
if(Pcap.findAllDevs(ifs, errbuf)!=Pcap.OK) {
logger.error("Error occured: " + errbuf.toString());
throw new Exception(errbuf.toString());
}
return ifs;
}
@Override
protected void done() {
super.done();
}
}
PcapReader.java类:
package cic.cs.unb.ca.jnetpcap.worker;
import cic.cs.unb.ca.jnetpcap.*;
import org.jnetpcap.PcapClosedException;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static cic.cs.unb.ca.jnetpcap.Utils.FILE_SEP;
import static cic.cs.unb.ca.jnetpcap.Utils.FLOW_SUFFIX;
import static cic.cs.unb.ca.jnetpcap.Utils.countLines;
public class PcapReader {
public static void readFile(String inputFile, String outPath, long flowTimeout, long activityTimeout) {
if(inputFile==null ||outPath==null ) {
return;
}
//String fileName = FilenameUtils.getName(inputFile);
Path p = Paths.get(inputFile);
String fileName = p.getFileName().toString();
if(!outPath.endsWith(FILE_SEP)){
outPath += FILE_SEP;
}
File saveFileFullPath = new File(outPath+fileName+FLOW_SUFFIX);
if (saveFileFullPath.exists()) {
if (!saveFileFullPath.delete()) {
System.out.println("Saved file full path cannot be deleted");
}
}
FlowGenerator flowGen = new FlowGenerator(true, flowTimeout, activityTimeout);
flowGen.addFlowListener(new FlowListener(fileName,outPath));
boolean readIP6 = false;
boolean readIP4 = true;
PacketReader packetReader = new PacketReader(inputFile, readIP4, readIP6);
System.out.println(String.format("Working on... %s",fileName));
int nValid=0;
int nTotal=0;
int nDiscarded = 0;
long start = System.currentTimeMillis();
while(true) {
try{
BasicPacketInfo basicPacket = packetReader.nextPacket();
nTotal++;
if(basicPacket !=null){
flowGen.addPacket(basicPacket);
nValid++;
}else{
nDiscarded++;
}
}catch(PcapClosedException e){
break;
}
}
flowGen.dumpLabeledCurrentFlow(saveFileFullPath.getPath(), FlowFeature.getHeader());
long lines = countLines(saveFileFullPath.getPath());
System.out.println(String.format("%s is done. total %d flows ",fileName,lines));
System.out.println(String.format("Packet stats: Total=%d,Valid=%d,Discarded=%d",nTotal,nValid,nDiscarded));
System.out.println("-----------------------------------------------------------------------------------------");
}
static class FlowListener implements FlowGenListener {
private String fileName;
private String outPath;
private long cnt;
public FlowListener(String fileName, String outPath) {
this.fileName = fileName;
this.outPath = outPath;
}
@Override
public void onFlowGenerated(BasicFlow flow) {
String flowDump = flow.dumpFlowBasedFeaturesEx();
List<String> flowStringList = new ArrayList<>();
flowStringList.add(flowDump);
InsertCsvRow.insert(FlowFeature.getHeader(),flowStringList,outPath,fileName+ FLOW_SUFFIX);
cnt++;
String console = String.format("%s -> %d flows \r", fileName,cnt);
System.out.print(console);
}
}
}
ReadPcapFileWorker.java类:
package cic.cs.unb.ca.jnetpcap.worker;
import cic.cs.unb.ca.jnetpcap.*;
import org.jnetpcap.PcapClosedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static cic.cs.unb.ca.jnetpcap.Utils.*;
public class ReadPcapFileWorker extends SwingWorker<List<String>,String> {
public static final Logger logger = LoggerFactory.getLogger(ReadPcapFileWorker.class);
public static final String PROPERTY_FILE_CNT = "file_count";
public static final String PROPERTY_CUR_FILE = "file_current";
public static final String PROPERTY_FLOW = "file_flow";
private static final String DividingLine = "---------------------------------------------------------------------------------------------------------------";
private long flowTimeout;
private long activityTimeout;
private int totalFlows = 0;
private File pcapPath;
private String outPutDirectory;
private List<String> chunks;
public ReadPcapFileWorker(File inputFile, String outPutDir) {
super();
pcapPath = inputFile;
outPutDirectory = outPutDir;
chunks = new ArrayList<>();
if(!outPutDirectory.endsWith(FILE_SEP)) {
outPutDirectory = outPutDirectory + FILE_SEP;
}
flowTimeout = 120000000L;
activityTimeout = 5000000L;
}
public ReadPcapFileWorker(File inputFile, String outPutDir,long param1,long param2) {
super();
pcapPath = inputFile;
outPutDirectory = outPutDir;
chunks = new ArrayList<>();
if(!outPutDirectory.endsWith(FILE_SEP)) {
outPutDirectory = outPutDirectory + FILE_SEP;
}
flowTimeout = param1;
activityTimeout = param2;
}
@Override
protected List<String> doInBackground() {
if (pcapPath.isDirectory()) {
readPcapDir(pcapPath,outPutDirectory);
} else {
if (!isPcapFile(pcapPath)) {
publish("Please select pcap file!");
publish("");
} else {
publish("CICFlowMeter received 1 pcap file");
publish("");
publish("");
firePropertyChange(PROPERTY_CUR_FILE,"",pcapPath.getName());
firePropertyChange(PROPERTY_FILE_CNT,1,1);//begin with 1
readPcapFile(pcapPath.getPath(), outPutDirectory);
}
}
/*chunks.clear();
chunks.add("");
chunks.add(DividingLine);
chunks.add(String.format("TOTAL FLOWS GENERATED :%s", totalFlows));
chunks.add(DividingLine);
publish(chunks.toArray( new String[chunks.size()]));*/
return chunks;
}
@Override
protected void done() {
super.done();
}
@Override
protected void process(List<String> chunks) {
super.process(chunks);
firePropertyChange("progress","",chunks);
}
private void readPcapDir(File inputPath, String outPath) {
if(inputPath==null||outPath==null) {
return;
}
//File[] pcapFiles = inputPath.listFiles(file -> file.getName().toLowerCase().endsWith("pcap"));
File[] pcapFiles = inputPath.listFiles(file -> isPcapFile(file));
int file_cnt = pcapFiles.length;
logger.debug("CICFlowMeter found :{} pcap files", file_cnt);
publish(String.format("CICFlowMeter found :%s pcap files", file_cnt));
publish("");
publish("");
for(int i=0;i<file_cnt;i++) {
File file = pcapFiles[i];
if (file.isDirectory()) {
continue;
}
firePropertyChange(PROPERTY_CUR_FILE,"",file.getName());
firePropertyChange(PROPERTY_FILE_CNT,file_cnt,i+1);//begin with 1
readPcapFile(file.getPath(),outPath);
}
}
private void readPcapFile(String inputFile, String outPath) {
if(inputFile==null ||outPath==null ) {
return;
}
Path p = Paths.get(inputFile);
String fileName = p.getFileName().toString();//FilenameUtils.getName(inputFile);
if(!outPath.endsWith(FILE_SEP)){
outPath += FILE_SEP;
}
File saveFileFullPath = new File(outPath+fileName+Utils.FLOW_SUFFIX);
if (saveFileFullPath.exists()) {
if (!saveFileFullPath.delete()) {
System.out.println("Saved file full path cannot be deleted");
}
}
FlowGenerator flowGen = new FlowGenerator(true, flowTimeout, activityTimeout);
flowGen.addFlowListener(new FlowListener(fileName));
boolean readIP6 = false;
boolean readIP4 = true;
PacketReader packetReader = new PacketReader(inputFile, readIP4, readIP6);
publish(String.format("Working on... %s",inputFile));
logger.debug("Working on... {}",inputFile);
int nValid=0;
int nTotal=0;
int nDiscarded = 0;
long start = System.currentTimeMillis();
while(true) {
try{
BasicPacketInfo basicPacket = packetReader.nextPacket();
nTotal++;
if(basicPacket !=null){
flowGen.addPacket(basicPacket);
nValid++;
}else{
nDiscarded++;
}
}catch(PcapClosedException e){
break;
}
}
flowGen.dumpLabeledCurrentFlow(saveFileFullPath.getPath(), FlowFeature.getHeader());
long lines = countLines(saveFileFullPath.getPath());
long end = System.currentTimeMillis();
chunks.clear();
chunks.add(String.format("Done! Total %d flows",lines));
chunks.add(String.format("Packets stats: Total=%d,Valid=%d,Discarded=%d",nTotal,nValid,nDiscarded));
chunks.add(DividingLine);
publish(chunks.toArray( new String[chunks.size()]));
/*chunks.add(String.format("\t Total packets: %d",nTotal));
chunks.add(String.format("\t Valid packets: %d",nValid));
chunks.add(String.format("\t Ignored packets:%d %d ", nDiscarded,(nTotal-nValid)));
chunks.add(String.format("PCAP duration %d seconds",((packetReader.getLastPacket()- packetReader.getFirstPacket())/1000)));
chunks.add(DividingLine);
int singleTotal = flowGen.dumpLabeledFlowBasedFeatures(outPath, fullname+ FlowMgr.FLOW_SUFFIX, FlowFeature.getHeader());
chunks.add(String.format("Number of Flows: %d",singleTotal));
chunks.add("");
publish(chunks.toArray( new String[chunks.size()]));
totalFlows += singleTotal;
logger.debug("{} is done,Total {}",inputFile,singleTotal);*/
}
class FlowListener implements FlowGenListener {
private String fileName;
FlowListener(String fileName) {
this.fileName = fileName;
}
@Override
public void onFlowGenerated(BasicFlow flow) {
firePropertyChange(PROPERTY_FLOW,fileName,flow);
}
}
}
TrafficFlowWorker.java类:
package cic.cs.unb.ca.jnetpcap.worker;
import cic.cs.unb.ca.jnetpcap.BasicFlow;
import cic.cs.unb.ca.jnetpcap.FlowGenerator;
import cic.cs.unb.ca.jnetpcap.PacketReader;
import org.jnetpcap.Pcap;
import org.jnetpcap.nio.JMemory.Type;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.util.List;
public class TrafficFlowWorker extends SwingWorker<String,String> implements FlowGenListener{
public static final Logger logger = LoggerFactory.getLogger(TrafficFlowWorker.class);
public static final String PROPERTY_FLOW = "flow";
private String device;
public TrafficFlowWorker(String device) {
super();
this.device = device;
}
@Override
protected String doInBackground() {
FlowGenerator flowGen = new FlowGenerator(true,120000000L, 5000000L);
flowGen.addFlowListener(this);
int snaplen = 64 * 1024;//2048; // Truncate packet at this size
int promiscous = Pcap.MODE_PROMISCUOUS;
int timeout = 60 * 1000; // In milliseconds
StringBuilder errbuf = new StringBuilder();
Pcap pcap = Pcap.openLive(device, snaplen, promiscous, timeout, errbuf);
if (pcap == null) {
logger.info("open {} fail -> {}",device,errbuf.toString());
return String.format("open %s fail ->",device)+errbuf.toString();
}
PcapPacketHandler<String> jpacketHandler = (packet, user) -> {
/*
* BufferUnderflowException while decoding header
* that is because:
* 1.PCAP library is not multi-threaded
* 2.jNetPcap library is not multi-threaded
* 3.Care must be taken how packets or the data they referenced is used in multi-threaded environment
*
* typical rule:
* make new packet objects and perform deep copies of the data in PCAP buffers they point to
*
* but it seems not work
*/
PcapPacket permanent = new PcapPacket(Type.POINTER);
packet.transferStateAndDataTo(permanent);
flowGen.addPacket(PacketReader.getBasicPacketInfo(permanent, true, false));
if(isCancelled()) {
pcap.breakloop();
logger.debug("break Packet loop");
}
};
//FlowMgr.getInstance().setListenFlag(true);
logger.info("Pcap is listening...");
firePropertyChange("progress","open successfully","listening: "+device);
int ret = pcap.loop(Pcap.DISPATCH_BUFFER_FULL, jpacketHandler, device);
String str;
switch (ret) {
case 0:
str = "listening: " + device + " finished";
break;
case -1:
str = "listening: " + device + " error";
break;
case -2:
str = "stop listening: " + device;
break;
default:
str = String.valueOf(ret);
}
return str;
}
@Override
protected void process(List<String> chunks) {
super.process(chunks);
}
@Override
protected void done() {
super.done();
}
@Override
public void onFlowGenerated(BasicFlow flow) {
firePropertyChange(PROPERTY_FLOW,null,flow);
}
}