项目介绍
- 这是一个名为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;}@Overridepublic 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() {@Overridepublic 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();}@Overrideprotected 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 titlepieDataset, // datatrue, // include legendtrue,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();}@Overrideprotected 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 titlepieDataset, // datatrue, // include legendtrue,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();}@Overrideprotected 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 titlepieDataSet, // datatrue, // include legendtrue,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;}@Overridepublic 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 fileString 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 JTableSwingUtilities.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 rowgc.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 rowgc.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 fileString 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();}}@Overridepublic 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;}@Overrideprotected 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;}@Overrideprotected 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);}@Overridepublic 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();}@Overrideprotected 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;}@Overrideprotected 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;}@Overridepublic 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;}@Overrideprotected 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 1readPcapFile(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;}@Overrideprotected void done() {super.done();}@Overrideprotected 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 1readPcapFile(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;}@Overridepublic 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;}@Overrideprotected String doInBackground() {FlowGenerator flowGen = new FlowGenerator(true,120000000L, 5000000L);flowGen.addFlowListener(this);int snaplen = 64 * 1024;//2048; // Truncate packet at this sizeint promiscous = Pcap.MODE_PROMISCUOUS;int timeout = 60 * 1000; // In millisecondsStringBuilder 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;}@Overrideprotected void process(List<String> chunks) {super.process(chunks);}@Overrideprotected void done() {super.done();}@Overridepublic void onFlowGenerated(BasicFlow flow) {firePropertyChange(PROPERTY_FLOW,null,flow);}
}