Renaming root project name.
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / analysis / TriggerTrafficExtractor.java
index aa01f974d7a28fd915710c2a611fd07ee5cc97c7..0a22d63f09714e4323d2ea3a829a9cf0ed7a97d9 100644 (file)
@@ -1,5 +1,6 @@
 package edu.uci.iotproject.analysis;
 
+import edu.uci.iotproject.io.PcapHandleReader;
 import org.pcap4j.core.*;
 
 import java.time.Instant;
@@ -20,8 +21,12 @@ public class TriggerTrafficExtractor implements PcapPacketFilter {
 
     private int mTriggerIndex = 0;
 
+    /**
+     * The total number of packets marked for inclusion during one run of {@link #performExtraction(PacketListener...)}.
+     */
+    private long mIncludedPackets = 0;
 
-    private static final int INCLUSION_WINDOW_MILLIS = 3_000;
+    public static final int INCLUSION_WINDOW_MILLIS = 15_000;
 
     public TriggerTrafficExtractor(String pcapFilePath, List<Instant> triggerTimes, String deviceIp) throws PcapNativeException, NotOpenException {
         mPcapFilePath = pcapFilePath;
@@ -38,6 +43,9 @@ public class TriggerTrafficExtractor implements PcapPacketFilter {
 
 
     public void performExtraction(PacketListener... extractedPacketsConsumers) throws PcapNativeException, NotOpenException, TimeoutException {
+        // Reset trigger index and packet counter in case client code chooses to rerun the extraction.
+        mTriggerIndex = 0;
+        mIncludedPackets = 0;
         PcapHandle handle;
         try {
             handle = Pcaps.openOffline(mPcapFilePath, PcapHandle.TimestampPrecision.NANO);
@@ -48,48 +56,40 @@ public class TriggerTrafficExtractor implements PcapPacketFilter {
         handle.setFilter("ip host " + mDeviceIp, BpfProgram.BpfCompileMode.OPTIMIZE);
         PcapHandleReader pcapReader = new PcapHandleReader(handle, this, extractedPacketsConsumers);
         pcapReader.readFromHandle();
-        // Reset trigger index (in case client code chooses to rerun the extraction)
-        mTriggerIndex = 0;
+
     }
 
-//    public TriggerTrafficExtractor(String deviceIp, PcapHandle handle, List<Instant> triggerTimes) throws PcapNativeException, NotOpenException {
-//        mDeviceIp = deviceIp;
-//        mHandle = handle;
-//        mHandle.setFilter("ip host " + deviceIp, BpfProgram.BpfCompileMode.OPTIMIZE);
-//        // Sort in ascending order.
-//        Collections.sort(triggerTimes, (i1, i2) -> {
-//            if (i1.isBefore(i2)) return -1;
-//            else if (i2.isBefore(i1)) return 1;
-//            else return 0;
-//        });
-//        mTriggerTimes = Collections.unmodifiableList(triggerTimes);
-//    }
-
-
-
-    //    private void process() {
-//        try {
-//            PcapPacket prevPacket = null;
-//            PcapPacket packet;
-//            while ((packet = mHandle.getNextPacketEx()) != null) {
-//                if (prevPacket != null && packet.getTimestamp().isBefore(prevPacket.getTimestamp())) {
-//                    // Fail early if assumption doesn't hold.
-//                    throw new RuntimeException("Packets not in ascending temporal order");
-//                }
-//                if (shouldIncludePacket(packet)) {
-//                    // TODO output packet
-//                }
-//                prevPacket = packet;
-//            }
-//        } catch (PcapNativeException | TimeoutException | NotOpenException e) {
-//            e.printStackTrace();
-//        } catch (EOFException e) {
-//            System.out.println("Reached end of pcap file");
-//        }
-//    }
+    /**
+     * Return the number of extracted packets (i.e., packets selected for inclusion) as a result of the most recent call
+     * to {@link #performExtraction(PacketListener...)}.
+     *
+     * @return the number of extracted packets (i.e., packets selected for inclusion) as a result of the most recent
+     *         call to {@link #performExtraction(PacketListener...)}.
+     */
+    public long getPacketsIncludedCount() {
+        return mIncludedPackets;
+    }
 
     @Override
     public boolean shouldIncludePacket(PcapPacket packet) {
+        // New version. Simpler, but slower: the later a packet arrives, the more elements of mTriggerTimes will need to
+        // be traversed.
+        boolean include = mTriggerTimes.stream().anyMatch(
+                trigger -> trigger.isBefore(packet.getTimestamp()) &&
+                        packet.getTimestamp().isBefore(trigger.plusMillis(INCLUSION_WINDOW_MILLIS))
+        );
+        if (include) {
+            mIncludedPackets++;
+        }
+        return include;
+
+        /*
+        // Old version. Faster, but more complex - is it correct?
+        if (mTriggerIndex >= mTriggerTimes.size()) {
+            // Don't include packet if we've exhausted the list of trigger times.
+            return false;
+        }
+
         // TODO hmm, is this correct?
         Instant trigger = mTriggerTimes.get(mTriggerIndex);
         if (trigger.isBefore(packet.getTimestamp()) &&
@@ -108,62 +108,7 @@ public class TriggerTrafficExtractor implements PcapPacketFilter {
                 return shouldIncludePacket(packet);
             }
         }
-
-
-
-
-
-
-        /*
-        if (mTriggerIndex >= mTriggerTimes.size()) {
-            // Don't include packet if we've exhausted the list of trigger timestamps.
-            return false;
-        }
-        Instant trigger = mTriggerTimes.get(mTriggerIndex);
-        if (trigger.isBefore(packet.getTimestamp()) &&
-                packet.getTimestamp().isBefore(trigger.plusMillis(INCLUSION_WINDOW_MILLIS))) {
-            // Packet lies within INCLUSION_WINDOW_MILLIS after currently considered trigger, include it.
-            return true;
-        }
-        if (mTriggerIndex >= mTriggerTimes.size()-1) {
-            // No additional triggers left to be considered.
-            return false;
-        }
-        trigger = mTriggerTimes.get(mTriggerIndex + 1);
-        if (packet.getTimestamp().isBefore(trigger)) {
-            return false;
-        } else {
-            mTriggerIndex++;
-            return includePacket(packet);
-        }
         */
-
-
-//        else if (trigger.isBefore(packet.getTimestamp()) &&
-//                !packet.getTimestamp().isBefore(trigger.plusMillis(INCLUSION_WINDOW_MILLIS)) {
-//
-//        }
     }
 
-
-    private Instant findTriggerTime(PcapPacket packet) {
-        mTriggerTimes.stream().filter(i ->
-                i.isBefore(packet.getTimestamp()) && packet.getTimestamp().isBefore(i.plusMillis(3000)));
-
-        while (mTriggerIndex < mTriggerTimes.size() &&
-                !(mTriggerTimes.get(mTriggerIndex).isBefore(packet.getTimestamp()) &&
-                        packet.getTimestamp().isBefore(mTriggerTimes.get(mTriggerIndex).plusMillis(3_000)))
-                ) {
-            mTriggerIndex++;
-        }
-        return mTriggerIndex < mTriggerTimes.size() ? mTriggerTimes.get(mTriggerIndex) : null;
-        /*
-        // Trigger time must logically be BEFORE packet timestamp, so advance
-        while (mTriggerIndex < mTriggerTimes.size() &&
-                mTriggerTimes.get(mTriggerIndex).isAfter(packet.getTimestamp())) {
-            mTriggerIndex++;
-        }
-        return mTriggerIndex < mTriggerTimes.size() ? mTriggerTimes.get(mTriggerIndex) : null;
-        */
-    }
 }