<content url="file://$MODULE_DIR$/../..">
<excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
<excludeFolder url="file://$MODULE_DIR$/../../build" />
+ <excludeFolder url="file://$MODULE_DIR$/../../out" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="SmartPlugDetector:main" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="edu.uci.iotproject" external.system.module.type="sourceSet" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
- <output url="file://$MODULE_DIR$/../../build/classes/main" />
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+ <output url="file://$MODULE_DIR$/../../out/production/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../src/main">
<sourceFolder url="file://$MODULE_DIR$/../../src/main/java" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/../../src/main/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="SmartPlugDetector:test" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="edu.uci.iotproject" external.system.module.type="sourceSet" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
- <output-test url="file://$MODULE_DIR$/../../build/classes/test" />
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+ <output-test url="file://$MODULE_DIR$/../../out/test/classes" />
<exclude-output />
- <content url="file://$MODULE_DIR$/../../src/test">
- <sourceFolder url="file://$MODULE_DIR$/../../src/test/java" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/../../src/test/resources" type="java-test-resource" />
- </content>
+ <content url="file://$MODULE_DIR$/../../src/test" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="SmartPlugDetector_main" />
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+package edu.uci.iotproject;
+
+import org.pcap4j.core.PcapHandle;
+import org.pcap4j.core.PcapPacket;
+
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Models a (TCP) conversation/connection/session/flow (packet's belonging to the same session between a client and a
+ * server).
+ * Holds a pair of packet lengths from {@link PcapPacket}s identified as pertaining to the flow.
+ * Here we consider pairs of packet lengths, e.g., from device to cloud and cloud to device.
+ * We collect these pairs of data points as signatures that we can plot on a graph.
+ *
+ * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
+ * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
+ */
+public class ConversationPair {
+
+ /* Begin instance properties */
+ /**
+ * The PrintWriter object that writes data points into file
+ */
+ private PrintWriter pw;
+
+ /**
+ * The direction of conversation
+ * true = device to server to device
+ */
+ private Direction direction;
+
+ /**
+ * If this is the first packet processed then the value is true (it is false otherwise).
+ */
+ private boolean firstPacket;
+
+ /**
+ * Four possible directions of conversations.
+ * E.g., DEVICE_TO_SERVER means the conversation is started from
+ * a device-server packet and then a server-device as a response.
+ * SERVER_TO_DEVICE means the conversation is started from a
+ * server-device packet and then a device-server packet as a response.
+ * The same pattern applies to PHONE_TO_SERVER and SERVER_TO_PHONE
+ * directions.
+ */
+ public enum Direction {
+ DEVICE_TO_SERVER,
+ SERVER_TO_DEVICE,
+ PHONE_TO_SERVER,
+ SERVER_TO_PHONE
+ }
+
+ /**
+ * Constructs a ConversationPair object.
+ * @param fileName The file name to write data points into.
+ * @param direction The direction of the first packet of the pair.
+ */
+ public ConversationPair(String fileName, Direction direction) {
+ try {
+ this.pw = new PrintWriter(fileName, "UTF-8");
+ this.direction = direction;
+ this.firstPacket = true;
+ } catch(UnsupportedEncodingException |
+ FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Writes conversation pair's packet lengths.
+ * @param packet The {@link PcapPacket} object that has packet information.
+ * @param fromClient If true then this packet comes from client, e.g., device.
+ * @param fromServer If true then this packet comes from server.
+ */
+ public void writeConversationPair(PcapPacket packet, boolean fromClient, boolean fromServer) {
+
+ // Write device data point first and then server
+ if (direction == Direction.DEVICE_TO_SERVER || direction == Direction.PHONE_TO_SERVER) {
+ if (fromClient && firstPacket) { // first packet
+ pw.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
+ System.out.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
+ firstPacket = false;
+ } else if (fromServer && !firstPacket) { // second packet
+ pw.println(packet.getPayload().length());
+ System.out.println(packet.getPayload().length());
+ firstPacket = true;
+ }
+ // Write server data point first and then device
+ } else if (direction == Direction.SERVER_TO_DEVICE || direction == Direction.SERVER_TO_PHONE) {
+ if (fromServer && firstPacket) { // first packet
+ pw.print(packet.getTimestamp() + ", " + packet.getPayload().length() + ", ");
+ firstPacket = false;
+ } else if (fromClient && !firstPacket) { // second packet
+ pw.println(packet.getPayload().length());
+ firstPacket = true;
+ }
+ }
+ }
+
+ /**
+ * Close the PrintWriter object.
+ */
+ public void close() {
+ pw.close();
+ }
+}
\ No newline at end of file
private final DnsMap mDnsMap;
private final PcapHandle mPcap;
private final FlowPattern mPattern;
+ private final ConversationPair mConvPair;
+ private final String FILE = "./datapoints.csv";
private final List<Future<CompleteMatchPatternComparisonResult>> mPendingComparisons = new ArrayList<>();
/* End instance properties */
String.format("Argument of type '%s' cannot be null", PcapHandle.class.getSimpleName()));
this.mPattern = Objects.requireNonNull(pattern,
String.format("Argument of type '%s' cannot be null", FlowPattern.class.getSimpleName()));
+ this.mConvPair = new ConversationPair(FILE, ConversationPair.Direction.DEVICE_TO_SERVER);
}
/**
}
// Note: does not make sense to call attemptAcknowledgementOfFin here as the new packet has no FINs
// in its list, so if this packet is an ACK, it would not be added anyway.
-
+ // Record the conversation pairs
+ if (tcpPacket.getPayload() != null) {
+ mConvPair.writeConversationPair(packet, fromClient, fromServer);
+ }
// Need to retain a final reference to get access to the packet in the lambda below.
final PcapPacket finalPacket = packet;
// Add the new conversation to the map if an equal entry is not already present.
new PatternComparisonTask<>(conversation, mPattern, ComparisonFunctions.SUB_SEQUENCE_COMPLETE_MATCH);
mPendingComparisons.add(EXECUTOR_SERVICE.submit(comparisonTask));
// Increment hostIndex to find the next
-
+
}
}
} catch (EOFException eofe) {
+ mConvPair.close();
+ System.out.println("[ findFlowPattern ] ConversationPair writer closed!");
// TODO should check for leftover conversations in map here and fire tasks for those.
// TODO [cont'd] such tasks may be present if connections did not terminate gracefully or if there are longlived connections.
System.out.println("[ findFlowPattern ] Finished processing entire PCAP stream!");
public static void main(String[] args) throws PcapNativeException, NotOpenException, EOFException, TimeoutException, UnknownHostException {
// -------------------------------------------------------------------------------------------------------------
// Example/debug code for searching for a pattern at the MAC layer.
- String fileName = "./pcap/mac-tplink.local.pcapng";
- PcapHandle handle;
- try {
- handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
- } catch (PcapNativeException pne) {
- handle = Pcaps.openOffline(fileName);
- }
-// Arrays.asList(1590, 1590, 1590, 1001, 337, 197, 636, 1311, 177) // Full pattern (all non-zero payload packets).
- MacLayerFlowPattern pattern = new MacLayerFlowPattern("TP_LINK_LOCAL_OFF_MAC", "50:c7:bf:33:1f:09", Arrays.asList(637, 1312));
- MacLayerFlowPatternFinder finder = new MacLayerFlowPatternFinder(handle, pattern);
- finder.findFlowPattern();
- // -------------------------------------------------------------------------------------------------------------
-
-// final String fileName = args.length > 0 ? args[0] : "/home/rtrimana/pcap_processing/smart_home_traffic/Code/Projects/SmartPlugDetector/pcap/wlan1.local.remote.dns.pcap";
-// final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON_SUBSET.pcap";
-// //final String trainingFileName = "./pcap/TP_LINK_REMOTE_ON.pcap";
-//
-// // ====== Debug code ======
+// String fileName = "./pcap/mac-tplink.local.pcapng";
// PcapHandle handle;
-// PcapHandle trainingPcap;
// try {
// handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
-// trainingPcap = Pcaps.openOffline(trainingFileName, PcapHandle.TimestampPrecision.NANO);
// } catch (PcapNativeException pne) {
// handle = Pcaps.openOffline(fileName);
-// trainingPcap = Pcaps.openOffline(trainingFileName);
// }
+// Arrays.asList(1590, 1590, 1590, 1001, 337, 197, 636, 1311, 177) // Full pattern (all non-zero payload packets).
+// MacLayerFlowPattern pattern = new MacLayerFlowPattern("TP_LINK_LOCAL_OFF_MAC", "50:c7:bf:33:1f:09", Arrays.asList(637, 1312));
+// MacLayerFlowPatternFinder finder = new MacLayerFlowPatternFinder(handle, pattern);
+// finder.findFlowPattern();
+ // -------------------------------------------------------------------------------------------------------------
+
+ final String fileName = args.length > 0 ? args[0] : "/home/rtrimana/pcap_processing/smart_home_traffic/Code/Projects/SmartPlugDetector/pcap/wlan1.local.dns.pcap";
+ final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON_SUBSET.pcap";
+// final String trainingFileName = "./pcap/TP_LINK_LOCAL_ON.pcap";
+//
+// // ====== Debug code ======
+ PcapHandle handle;
+ PcapHandle trainingPcap;
+ try {
+ handle = Pcaps.openOffline(fileName, PcapHandle.TimestampPrecision.NANO);
+ trainingPcap = Pcaps.openOffline(trainingFileName, PcapHandle.TimestampPrecision.NANO);
+ } catch (PcapNativeException pne) {
+ handle = Pcaps.openOffline(fileName);
+ trainingPcap = Pcaps.openOffline(trainingFileName);
+ }
//
// // TODO: The followings are the way to extract multiple hostnames and their associated packet lengths lists
// //List<String> list = new ArrayList<>();
// //list2.add("events.tplinkra.com");
// //FlowPattern fp3 = new FlowPattern("TP_LINK_REMOTE_ON", list2, trainingPcap);
//
-// FlowPattern fp = new FlowPattern("TP_LINK_LOCAL_ON", "events.tplinkra.com", trainingPcap);
-// FlowPatternFinder fpf = new FlowPatternFinder(handle, fp);
-// fpf.start();
+ FlowPattern fp = new FlowPattern("TP_LINK_LOCAL_ON", "events.tplinkra.com", trainingPcap);
+ FlowPatternFinder fpf = new FlowPatternFinder(handle, fp);
+ fpf.start();
//
// // ========================
}