From 1b524a7b2071d6e660164e9f1d61cb80b70ca696 Mon Sep 17 00:00:00 2001 From: Janus Varmarken Date: Sat, 12 Jan 2019 21:03:30 -0800 Subject: [PATCH] Make original ClusterMatcher inherit from AbstractClusterMatcher. Reorganize code by adding subpackages for layer2 and layer3 detection. --- .../detection/AbstractClusterMatcher.java | 20 ++++++-- .../detection/Layer2FlowObserver.java | 15 ------ .../layer2/Layer2ClusterMatcher.java | 2 +- .../layer2/Layer2SequenceMatcher.java | 17 ++++++- .../Layer3ClusterMatcher.java} | 47 ++++++++----------- .../{ => layer3}/SignatureDetector.java | 32 ++++++------- .../trafficreassembly/layer2/Layer2Flow.java | 42 ++++++++++++----- .../layer2/Layer2FlowObserver.java | 20 ++++++++ 8 files changed, 115 insertions(+), 80 deletions(-) delete mode 100644 Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/Layer2FlowObserver.java rename Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/{ClusterMatcher.java => layer3/Layer3ClusterMatcher.java} (92%) rename Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/{ => layer3}/SignatureDetector.java (97%) create mode 100644 Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2FlowObserver.java diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/AbstractClusterMatcher.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/AbstractClusterMatcher.java index 3815acd..bda6493 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/AbstractClusterMatcher.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/AbstractClusterMatcher.java @@ -6,26 +6,38 @@ import java.util.List; import java.util.Objects; /** - * TODO add class documentation. + * Base class for classes that search a traffic trace for sequences of packets that "belong to" a given cluster (in + * other words, classes that attempt to classify traffic as pertaining to a given cluster). * - * @author Janus Varmarken + * @author Janus Varmarken {@literal } + * @author Rahmadi Trimananda {@literal } */ abstract public class AbstractClusterMatcher { + /** + * The cluster that describes the sequence of packets that this {@link AbstractClusterMatcher} is trying to detect + * in the observed traffic. + */ protected final List> mCluster; - protected AbstractClusterMatcher(List> cluster) { // ===================== PRECONDITION SECTION ===================== cluster = Objects.requireNonNull(cluster, "cluster cannot be null"); if (cluster.isEmpty() || cluster.stream().anyMatch(inner -> inner.isEmpty())) { throw new IllegalArgumentException("cluster is empty (or contains an empty inner List)"); } + for (List clusterMember : cluster) { + if (clusterMember.size() != cluster.get(0).size()) { + throw new IllegalArgumentException("All sequences in cluster must contain the same number of packets"); + } + } + // ================================================================ + // Let the subclass prune the provided cluster mCluster = pruneCluster(cluster); } /** - * Allows subclasses to specify how to prune input cluster provided to the constructor. + * Allows subclasses to specify how to prune the input cluster provided to the constructor. * @param cluster The input cluster provided to the constructor. * @return The pruned cluster to use in place of the input cluster. */ diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/Layer2FlowObserver.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/Layer2FlowObserver.java deleted file mode 100644 index 26823de..0000000 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/Layer2FlowObserver.java +++ /dev/null @@ -1,15 +0,0 @@ -package edu.uci.iotproject.detection; - -import edu.uci.iotproject.trafficreassembly.layer2.Layer2Flow; -import org.pcap4j.core.PcapPacket; - -/** - * TODO add class documentation. - * - * @author Janus Varmarken - */ -public interface Layer2FlowObserver { - - void onNewPacket(Layer2Flow flow, PcapPacket newPacket); - -} diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java index d50a517..b3a88b0 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java @@ -4,7 +4,7 @@ import edu.uci.iotproject.trafficreassembly.layer2.Layer2FlowReassembler; import edu.uci.iotproject.trafficreassembly.layer2.Layer2Flow; import edu.uci.iotproject.trafficreassembly.layer2.Layer2FlowReassemblerObserver; import edu.uci.iotproject.detection.AbstractClusterMatcher; -import edu.uci.iotproject.detection.Layer2FlowObserver; +import edu.uci.iotproject.trafficreassembly.layer2.Layer2FlowObserver; import edu.uci.iotproject.io.PcapHandleReader; import edu.uci.iotproject.util.PrintUtils; import org.pcap4j.core.*; diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2SequenceMatcher.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2SequenceMatcher.java index de5c14a..db7295d 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2SequenceMatcher.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer2/Layer2SequenceMatcher.java @@ -7,9 +7,11 @@ import java.util.ArrayList; import java.util.List; /** - * TODO add class documentation. + * Attempts to detect the presence of a specific packet sequence in the set of packets provided through multiple calls + * to {@link #matchPacket(PcapPacket)}, considering only layer 2 information. * - * @author Janus Varmarken + * @author Janus Varmarken {@literal } + * @author Rahmadi Trimananda {@literal } */ public class Layer2SequenceMatcher { @@ -24,10 +26,21 @@ public class Layer2SequenceMatcher { */ private final List mMatchedPackets = new ArrayList<>(); + /** + * Create a {@code Layer2SequenceMatcher}. + * @param sequence The sequence to match against (search for). + */ public Layer2SequenceMatcher(List sequence) { mSequence = sequence; } + /** + * Attempt to advance this {@code Layer2SequenceMatcher} by matching {@code packet} against the packet that this + * {@code Layer2SequenceMatcher} expects as the next packet of the sequence it is searching for. + * @param packet + * @return {@code true} if this {@code Layer2SequenceMatcher} could advance by adding {@code packet} to its set of + * matched packets, {@code false} otherwise. + */ public boolean matchPacket(PcapPacket packet) { // The packet we want to match next. PcapPacket expected = mSequence.get(mMatchedPackets.size()); diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/ClusterMatcher.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer3/Layer3ClusterMatcher.java similarity index 92% rename from Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/ClusterMatcher.java rename to Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer3/Layer3ClusterMatcher.java index 1ff2c02..b5e3077 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/ClusterMatcher.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer3/Layer3ClusterMatcher.java @@ -1,5 +1,6 @@ -package edu.uci.iotproject.detection; +package edu.uci.iotproject.detection.layer3; +import edu.uci.iotproject.detection.AbstractClusterMatcher; import edu.uci.iotproject.trafficreassembly.layer3.Conversation; import edu.uci.iotproject.trafficreassembly.layer3.TcpReassembler; import edu.uci.iotproject.analysis.TcpConversationUtils; @@ -20,7 +21,7 @@ import static edu.uci.iotproject.util.PcapPacketUtils.*; * @author Janus Varmarken {@literal } * @author Rahmadi Trimananda {@literal } */ -public class ClusterMatcher implements PacketListener { +public class Layer3ClusterMatcher extends AbstractClusterMatcher implements PacketListener { // Test client public static void main(String[] args) throws PcapNativeException, NotOpenException { @@ -31,7 +32,7 @@ public class ClusterMatcher implements PacketListener { final String signatureFile = path + "/2018-07/dlink/offSignature1.sig"; List> signature = PrintUtils.deserializeClustersFromFile(signatureFile); - ClusterMatcher clusterMatcher = new ClusterMatcher(signature, null, + Layer3ClusterMatcher clusterMatcher = new Layer3ClusterMatcher(signature, null, (sig, match) -> System.out.println( String.format("[ !!! SIGNATURE DETECTED AT %s !!! ]", match.get(0).getTimestamp().atZone(ZoneId.of("America/Los_Angeles"))) @@ -49,12 +50,6 @@ public class ClusterMatcher implements PacketListener { clusterMatcher.performDetection(); } - /** - * The cluster that describes the sequence of packets that this {@link ClusterMatcher} is trying to detect in the - * observed traffic. - */ - private final List> mCluster; - /** * The ordered directions of packets in the sequences that make up {@link #mCluster}. */ @@ -73,21 +68,18 @@ public class ClusterMatcher implements PacketListener { private final ClusterMatchObserver[] mObservers; /** - * Create a {@link ClusterMatcher}. + * Create a {@link Layer3ClusterMatcher}. * @param cluster The cluster that traffic is matched against. * @param routerWanIp The router's WAN IP if examining traffic captured at the ISP's point of view (used for * determining the direction of packets). - * @param detectionObservers Client code that wants to get notified whenever the {@link ClusterMatcher} detects that + * @param detectionObservers Client code that wants to get notified whenever the {@link Layer3ClusterMatcher} detects that * (a subset of) the examined traffic is similar to the traffic that makes up * {@code cluster}, i.e., when the examined traffic is classified as pertaining to * {@code cluster}. */ - public ClusterMatcher(List> cluster, String routerWanIp, ClusterMatchObserver... detectionObservers) { + public Layer3ClusterMatcher(List> cluster, String routerWanIp, ClusterMatchObserver... detectionObservers) { + super(cluster); // ===================== PRECONDITION SECTION ===================== - cluster = Objects.requireNonNull(cluster, "cluster cannot be null"); - if (cluster.isEmpty() || cluster.stream().anyMatch(inner -> inner.isEmpty())) { - throw new IllegalArgumentException("cluster is empty (or contains an empty inner List)"); - } mObservers = Objects.requireNonNull(detectionObservers, "detectionObservers cannot be null"); if (mObservers.length == 0) { throw new IllegalArgumentException("no detectionObservers provided"); @@ -101,7 +93,7 @@ public class ClusterMatcher implements PacketListener { * on in favor of performance. However, it is only run once (at instantiation), so the overhead may be warranted * in order to ensure correctness, especially during the development/debugging phase. */ - if (cluster.stream(). + if (mCluster.stream(). anyMatch(inner -> !Arrays.equals(mClusterMemberDirections, getPacketDirections(inner, null)))) { throw new IllegalArgumentException( "cluster members must contain the same number of packets and exhibit the same packet direction " + @@ -109,8 +101,6 @@ public class ClusterMatcher implements PacketListener { ); } // ================================================================ - // Prune the provided cluster. - mCluster = pruneCluster(cluster); mRouterWanIp = routerWanIp; } @@ -121,8 +111,8 @@ public class ClusterMatcher implements PacketListener { } /** - * Get the cluster that describes the packet sequence that this {@link ClusterMatcher} is searching for. - * @return the cluster that describes the packet sequence that this {@link ClusterMatcher} is searching for. + * Get the cluster that describes the packet sequence that this {@link Layer3ClusterMatcher} is searching for. + * @return the cluster that describes the packet sequence that this {@link Layer3ClusterMatcher} is searching for. */ public List> getCluster() { return mCluster; @@ -158,7 +148,7 @@ public class ClusterMatcher implements PacketListener { isPresent()) { List matchSeq = match.get(); // Notify observers about the match. - Arrays.stream(mObservers).forEach(o -> o.onMatch(ClusterMatcher.this, matchSeq)); + Arrays.stream(mObservers).forEach(o -> o.onMatch(Layer3ClusterMatcher.this, matchSeq)); /* * Get the index in cPkts of the last packet in the sequence of packets that matches the searched * signature sequence. @@ -293,7 +283,8 @@ public class ClusterMatcher implements PacketListener { * @param cluster A cluster to prune. * @return The resulting pruned cluster. */ - private final List> pruneCluster(List> cluster) { + @Override + protected List> pruneCluster(List> cluster) { List> prunedCluster = new ArrayList<>(); for (List originalClusterSeq : cluster) { boolean alreadyPresent = false; @@ -343,20 +334,20 @@ public class ClusterMatcher implements PacketListener { } /** - * Interface used by client code to register for receiving a notification whenever the {@link ClusterMatcher} + * Interface used by client code to register for receiving a notification whenever the {@link Layer3ClusterMatcher} * detects traffic that is similar to the traffic that makes up the cluster returned by - * {@link ClusterMatcher#getCluster()}. + * {@link Layer3ClusterMatcher#getCluster()}. */ interface ClusterMatchObserver { /** * Callback that is invoked whenever a sequence that is similar to a sequence associated with the cluster (i.e., - * a sequence is a member of the cluster) is detected in the traffic that the associated {@link ClusterMatcher} + * a sequence is a member of the cluster) is detected in the traffic that the associated {@link Layer3ClusterMatcher} * observes. - * @param clusterMatcher The {@link ClusterMatcher} that detected a match (classified traffic as pertaining to + * @param clusterMatcher The {@link Layer3ClusterMatcher} that detected a match (classified traffic as pertaining to * its associated cluster). * @param match The traffic that was deemed to match the cluster associated with {@code clusterMatcher}. */ - void onMatch(ClusterMatcher clusterMatcher, List match); + void onMatch(Layer3ClusterMatcher clusterMatcher, List match); } } diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/SignatureDetector.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer3/SignatureDetector.java similarity index 97% rename from Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/SignatureDetector.java rename to Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer3/SignatureDetector.java index fb3e67e..ad47106 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/SignatureDetector.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/detection/layer3/SignatureDetector.java @@ -1,4 +1,4 @@ -package edu.uci.iotproject.detection; +package edu.uci.iotproject.detection.layer3; import edu.uci.iotproject.analysis.TriggerTrafficExtractor; import edu.uci.iotproject.analysis.UserAction; @@ -11,13 +11,11 @@ import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.pcap4j.core.*; import java.time.Duration; -import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.*; import java.util.function.Consumer; -import java.util.stream.Collectors; /** * Detects an event signature that spans one or multiple TCP connections. @@ -25,7 +23,7 @@ import java.util.stream.Collectors; * @author Janus Varmarken {@literal } * @author Rahmadi Trimananda {@literal } */ -public class SignatureDetector implements PacketListener, ClusterMatcher.ClusterMatchObserver { +public class SignatureDetector implements PacketListener, Layer3ClusterMatcher.ClusterMatchObserver { // Test client public static void main(String[] args) throws PcapNativeException, NotOpenException { @@ -440,23 +438,23 @@ public class SignatureDetector implements PacketListener, ClusterMatcher.Cluster private final List>> mSignature; /** - * The {@link ClusterMatcher}s in charge of detecting each individual sequence of packets that together make up the + * The {@link Layer3ClusterMatcher}s in charge of detecting each individual sequence of packets that together make up the * the signature. */ - private final List mClusterMatchers; + private final List mClusterMatchers; /** * For each {@code i} ({@code i >= 0 && i < pendingMatches.length}), {@code pendingMatches[i]} holds the matches - * found by the {@link ClusterMatcher} at {@code mClusterMatchers.get(i)} that have yet to be "consumed", i.e., + * found by the {@link Layer3ClusterMatcher} at {@code mClusterMatchers.get(i)} that have yet to be "consumed", i.e., * have yet to be included in a signature detected by this {@link SignatureDetector} (a signature can be encompassed * of multiple packet sequences occurring shortly after one another on multiple connections). */ private final List>[] pendingMatches; /** - * Maps a {@link ClusterMatcher} to its corresponding index in {@link #pendingMatches}. + * Maps a {@link Layer3ClusterMatcher} to its corresponding index in {@link #pendingMatches}. */ - private final Map mClusterMatcherIds; + private final Map mClusterMatcherIds; private final List mObservers = new ArrayList<>(); @@ -489,9 +487,9 @@ public class SignatureDetector implements PacketListener, ClusterMatcher.Cluster // note: doesn't protect inner lists from changes :'( mSignature = Collections.unmodifiableList(searchedSignature); // Generate corresponding/appropriate ClusterMatchers based on the provided signature - List clusterMatchers = new ArrayList<>(); + List clusterMatchers = new ArrayList<>(); for (List> cluster : mSignature) { - clusterMatchers.add(new ClusterMatcher(cluster, routerWanIp, this)); + clusterMatchers.add(new Layer3ClusterMatcher(cluster, routerWanIp, this)); } mClusterMatchers = Collections.unmodifiableList(clusterMatchers); @@ -500,7 +498,7 @@ public class SignatureDetector implements PacketListener, ClusterMatcher.Cluster for (int i = 0; i < pendingMatches.length; i++) { pendingMatches[i] = new ArrayList<>(); } - Map clusterMatcherIds = new HashMap<>(); + Map clusterMatcherIds = new HashMap<>(); for (int i = 0; i < mClusterMatchers.size(); i++) { clusterMatcherIds.put(mClusterMatchers.get(i), i); } @@ -522,7 +520,7 @@ public class SignatureDetector implements PacketListener, ClusterMatcher.Cluster } @Override - public void onMatch(ClusterMatcher clusterMatcher, List match) { + public void onMatch(Layer3ClusterMatcher clusterMatcher, List match) { // Add the match at the corresponding index pendingMatches[mClusterMatcherIds.get(clusterMatcher)].add(match); checkSignatureMatch(); @@ -532,7 +530,7 @@ public class SignatureDetector implements PacketListener, ClusterMatcher.Cluster // << Graph-based approach using Balint's idea. >> // This implementation assumes that the packets in the inner lists (the sequences) are ordered by asc timestamp. - // There cannot be a signature match until each ClusterMatcher has found a match of its respective sequence. + // There cannot be a signature match until each Layer3ClusterMatcher has found a match of its respective sequence. if (Arrays.stream(pendingMatches).noneMatch(l -> l.isEmpty())) { // Construct the DAG final SimpleDirectedWeightedGraph graph = @@ -553,19 +551,19 @@ public class SignatureDetector implements PacketListener, ClusterMatcher.Cluster final Vertex sink = new Vertex(null); graph.addVertex(source); graph.addVertex(sink); - // The source is connected to all vertices that wrap the sequences detected by ClusterMatcher at index 0. + // The source is connected to all vertices that wrap the sequences detected by Layer3ClusterMatcher at index 0. // Note: zero cost edges as this is just a dummy link to facilitate search from a common start node. for (Vertex v : vertices[0]) { DefaultWeightedEdge edge = graph.addEdge(source, v); graph.setEdgeWeight(edge, 0.0); } - // Similarly, all vertices that wrap the sequences detected by the last ClusterMatcher of the signature + // Similarly, all vertices that wrap the sequences detected by the last Layer3ClusterMatcher of the signature // are connected to the sink node. for (Vertex v : vertices[vertices.length-1]) { DefaultWeightedEdge edge = graph.addEdge(v, sink); graph.setEdgeWeight(edge, 0.0); } - // Now link sequences detected by ClusterMatcher at index i to sequences detected by ClusterMatcher at index + // Now link sequences detected by Layer3ClusterMatcher at index i to sequences detected by Layer3ClusterMatcher at index // i+1 if they obey the timestamp constraint (i.e., that the latter is later in time than the former). for (int i = 0; i < vertices.length; i++) { int j = i + 1; diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2Flow.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2Flow.java index f1b7190..2d804bd 100644 --- a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2Flow.java +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2Flow.java @@ -1,6 +1,5 @@ package edu.uci.iotproject.trafficreassembly.layer2; -import edu.uci.iotproject.detection.Layer2FlowObserver; import org.pcap4j.core.PcapPacket; import org.pcap4j.packet.EthernetPacket; import org.pcap4j.util.MacAddress; @@ -10,15 +9,26 @@ import java.util.Collections; import java.util.List; /** - * The packets exchanged between two endpoints (MAC addresses). + * Models a layer 2 flow: groups packets exchanged between two specific endpoints (MAC addresses). * - * @author Janus Varmarken + * @author Janus Varmarken {@literal } + * @author Rahmadi Trimananda {@literal } */ public class Layer2Flow { + /** + * The first endpoint of this layer 2 flow. + */ private final MacAddress mEndpoint1; + + /** + * The second endpoint of this layer 2 flow. + */ private final MacAddress mEndpoint2; + /** + * Clients observing for changes to this layer 2 flow. + */ private final List mFlowObservers = new ArrayList<>(); public Layer2Flow(MacAddress endpoint1, MacAddress endpoint2) { @@ -26,10 +36,18 @@ public class Layer2Flow { mEndpoint2 = endpoint2; } + /** + * Register as an observer of this flow. + * @param observer The client that is to be notified whenever this flow changes (has new packets added). + */ public void addFlowObserver(Layer2FlowObserver observer) { mFlowObservers.add(observer); } + /** + * Deregister as an observer of this flow. + * @param observer The client that no longer wishes to be notified whenever this flow changes. + */ public void removeFlowObserver(Layer2FlowObserver observer) { mFlowObservers.remove(observer); } @@ -50,10 +68,18 @@ public class Layer2Flow { mFlowObservers.forEach(o -> o.onNewPacket(this, packet)); } + /** + * Get the packets pertaining to this flow. + * @return The packets pertaining to this flow. + */ public List getPackets() { return Collections.unmodifiableList(mPackets); } + /** + * Verify that a packet pertains to this flow. + * @param packet The packet that is to be verified. + */ private void verifyAddresses(PcapPacket packet) { EthernetPacket ethPkt = packet.get(EthernetPacket.class); MacAddress srcAddr = ethPkt.getHeader().getSrcAddr(); @@ -67,13 +93,3 @@ public class Layer2Flow { } } - - - -/* - - - Packet stream -> flow reassembler -> flow1, flow2, flow3... -> for each flow, keep a sequence matcher for each sequence of cluster - - - */ \ No newline at end of file diff --git a/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2FlowObserver.java b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2FlowObserver.java new file mode 100644 index 0000000..e1648ba --- /dev/null +++ b/Code/Projects/SmartPlugDetector/src/main/java/edu/uci/iotproject/trafficreassembly/layer2/Layer2FlowObserver.java @@ -0,0 +1,20 @@ +package edu.uci.iotproject.trafficreassembly.layer2; + +import org.pcap4j.core.PcapPacket; + +/** + * Interface for observing a {@link Layer2Flow}. + * + * @author Janus Varmarken {@literal } + * @author Rahmadi Trimananda {@literal } + */ +public interface Layer2FlowObserver { + + /** + * Invoked when a new packet is added to the observed flow. + * @param flow The observed flow. + * @param newPacket The packet that was added to the flow. + */ + void onNewPacket(Layer2Flow flow, PcapPacket newPacket); + +} -- 2.34.1