package edu.uci.iotproject.analysis;
+import edu.uci.iotproject.io.PcapHandleReader;
import org.pcap4j.core.*;
import java.time.Instant;
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;
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);
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()) &&
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;
- */
- }
}