1 package edu.uci.iotproject;
3 import org.jgrapht.Graphs;
4 import org.jgrapht.graph.DefaultEdge;
5 import org.jgrapht.graph.SimpleDirectedGraph;
6 import org.pcap4j.core.PcapPacket;
9 import java.util.Optional;
12 * TODO add class documentation.
14 * @author Janus Varmarken
16 public class StateMachine {
19 private final SimpleDirectedGraph<Vertex, DefaultEdge> mGraph = new SimpleDirectedGraph<>(DefaultEdge.class);
22 public StateMachine(List<List<PcapPacket>> subCluster) {
24 for (List<PcapPacket> seqVariation : subCluster) {
27 Vertex prevVtx = null;
29 for (int i = 0; i < seqVariation.size(); i++) {
30 // Create new vertex corresponding to this packet of the sequence
31 PcapPacket currPkt = seqVariation.get(i);
32 currVtx = new Vertex(currPkt.getOriginalLength(), i);
38 mGraph.addVertex(currVtx);
42 if (prevVtx != null) {
43 // Link vertex representing previous packet of sequence to this vertex.
44 mGraph.addEdge(prevVtx, currVtx);
48 // Current vertex becomes previous vertex for next iteration.
56 private Vertex mCurrentState;
59 // public void gotPacket(PcapPacket packet) {
60 // // Generate a vertex corresponding to the received packet.
61 // // We expect a packet at the layer that follows the current state's layer.
62 // Vertex pktVtx = new Vertex(packet.getOriginalLength(), mCurrentState.mLayer + 1);
63 // // Check if such a vertex is present as a successor of the current state
64 // Optional<Vertex> match = Graphs.successorListOf(mGraph, mCurrentState).stream().
65 // filter(v -> v.equals(pktVtx)).findFirst();
66 // // If yes, we move to that new state (new vertex).
67 // match.ifPresent(v -> mCurrentState = v);
68 // // TODO buffer the packets that got us here
69 // // TODO check if we've reached the final layer...
75 * Attempts to use {@code packet} to advance this state machine.
77 * @return {@code true} if this state machine could progress by consuming {@code packet}, {@code false} otherwise.
79 public boolean attemptAdvance(PcapPacket packet) {
80 // Generate a vertex corresponding to the received packet.
81 // We expect a packet at the layer that follows the current state's layer.
82 Vertex pktVtx = new Vertex(packet.getOriginalLength(), mCurrentState.mLayer + 1);
83 // Check if such a vertex is present as a successor of the current state
84 Optional<Vertex> match = Graphs.successorListOf(mGraph, mCurrentState).stream().
85 filter(v -> v.equals(pktVtx)).findFirst();
86 if (match.isPresent()) {
87 // If yes, we move to that new state (new vertex).
88 mCurrentState = match.get();
89 // TODO buffer the packet to keep track of what packets got us here (keep track of the match)
90 // TODO check if we've reached the final layer...
97 private static class Vertex {
99 // TODO how to include direction of packets here...
101 private final int mPktLength;
102 private final int mLayer;
105 private Vertex(int pktLength, int layer) {
106 mPktLength = pktLength;
112 public boolean equals(Object obj) {
113 if (!(obj instanceof Vertex)) return false;
114 Vertex that = (Vertex) obj;
115 return that.mPktLength == this.mPktLength && that.mLayer == this.mLayer;
119 public int hashCode() {
120 // return Integer.hashCode(mPktLength);
121 // Hack: use string's hashCode implementation.
122 return (Integer.toString(mPktLength) + " " + Integer.toString(mLayer)).hashCode();