Implementing relaxed matching for layer 2 and layer 3.
[pingpong.git] / Code / Projects / PacketLevelSignatureExtractor / src / main / java / edu / uci / iotproject / detection / AbstractSignatureDetector.java
1 package edu.uci.iotproject.detection;
2
3 import org.pcap4j.core.PcapPacket;
4
5 import java.util.*;
6
7 /**
8  * TODO add class documentation.
9  *
10  * @author Janus Varmarken
11  */
12 public abstract class AbstractSignatureDetector implements ClusterMatcherObserver {
13
14
15     /**
16      * The signature that this {@link AbstractSignatureDetector} is searching for.
17      */
18     private final List<List<List<PcapPacket>>> mSignature;
19
20     /**
21      * The {@link AbstractClusterMatcher}s in charge of detecting each individual sequence of packets that together make
22      * up the the signature.
23      */
24     private final List<AbstractClusterMatcher> mClusterMatchers;
25
26     /**
27      * For each {@code i} ({@code i >= 0 && i < pendingMatches.length}), {@code pendingMatches[i]} holds the matches
28      * found by the {@link AbstractClusterMatcher} at {@code mClusterMatchers.get(i)} that have yet to be "consumed",
29      * i.e., have yet to be included in a signature detected by this {@link AbstractSignatureDetector} (a signature can
30      * be encompassed of multiple packet sequences occurring shortly after one another on multiple connections).
31      */
32     private final List<List<PcapPacket>>[] pendingMatches;
33
34     /**
35      * Maps an {@link AbstractClusterMatcher} to its corresponding index in {@link #pendingMatches}.
36      */
37     private final Map<AbstractClusterMatcher, Integer> mClusterMatcherIds;
38
39     public AbstractSignatureDetector(List<List<List<PcapPacket>>> searchedSignature) {
40         mSignature = Collections.unmodifiableList(searchedSignature);
41         List<AbstractClusterMatcher> clusterMatchers = new ArrayList<>();
42         for (List<List<PcapPacket>> cluster : mSignature) {
43             AbstractClusterMatcher clusterMatcher = constructClusterMatcher(cluster);
44             clusterMatcher.addObserver(this);
45             clusterMatchers.add(clusterMatcher);
46         }
47         mClusterMatchers = Collections.unmodifiableList(clusterMatchers);
48         pendingMatches = new List[mClusterMatchers.size()];
49         for (int i = 0; i < pendingMatches.length; i++) {
50             pendingMatches[i] = new ArrayList<>();
51         }
52         Map<AbstractClusterMatcher, Integer> clusterMatcherIds = new HashMap<>();
53         for (int i = 0; i < mClusterMatchers.size(); i++) {
54             clusterMatcherIds.put(mClusterMatchers.get(i), i);
55         }
56         mClusterMatcherIds = Collections.unmodifiableMap(clusterMatcherIds);
57     }
58
59     abstract protected AbstractClusterMatcher constructClusterMatcher(List<List<PcapPacket>> cluster);
60
61     /**
62      * Encapsulates a {@code List<PcapPacket>} so as to allow the list to be used as a vertex in a graph while avoiding
63      * the expensive {@link AbstractList#equals(Object)} calls when adding vertices to the graph.
64      * Using this wrapper makes the incurred {@code equals(Object)} calls delegate to {@link Object#equals(Object)}
65      * instead of {@link AbstractList#equals(Object)}. The net effect is a faster implementation, but the graph will not
66      * recognize two lists that contain the same items--from a value and not reference point of view--as the same
67      * vertex. However, this is fine for our purposes -- in fact restricting it to reference equality seems more
68      * appropriate.
69      */
70     private static class Vertex {
71         private final List<PcapPacket> sequence;
72         private Vertex(List<PcapPacket> wrappedSequence) {
73             sequence = wrappedSequence;
74         }
75     }
76
77 }