First attempt at labeling traffic with user actions
[pingpong.git] / Code / Projects / SmartPlugDetector / src / main / java / edu / uci / iotproject / analysis / TrafficLabeler.java
1 package edu.uci.iotproject.analysis;
2
3 import org.pcap4j.core.PacketListener;
4 import org.pcap4j.core.PcapPacket;
5
6 import java.time.Instant;
7 import java.util.*;
8
9 /**
10  * A {@link PacketListener} that marks network traffic as (potentially) related to a user's actions by comparing the
11  * timestamp of each packet to the timestamps of the provided list of user actions.
12  *
13  * @author Janus Varmarken {@literal <jvarmark@uci.edu>}
14  * @author Rahmadi Trimananda {@literal <rtrimana@uci.edu>}
15  */
16 public class TrafficLabeler implements PacketListener {
17
18     private final Map<UserAction, List<PcapPacket>> mActionToTrafficMap;
19     private final List<UserAction> mActionsSorted;
20
21     public TrafficLabeler(List<UserAction> userActions) {
22         // Init map with empty lists (no packets have been mapped to UserActions at the onset).
23         mActionToTrafficMap = new HashMap<>();
24         userActions.forEach(ua -> mActionToTrafficMap.put(ua, new ArrayList<>()));
25         // Sort list of UserActions by timestamp in order to facilitate fast Packet-to-UserAction mapping.
26         // For safety reasons, we create an internal copy of the list to prevent external code from changing the list's
27         // contents as that would render our assumptions about order of elements invalid.
28         // In addition, this also ensures that we do not break assumptions made by external code as we avoid reordering
29         // the elements of the list passed from the external code.
30         // If performance is to be favored over safety, assign userActions to mActionsSorted directly.
31         mActionsSorted = new ArrayList<>();
32         mActionsSorted.addAll(userActions);
33         Collections.sort(mActionsSorted, (ua1, ua2) -> ua1.getTimestamp().compareTo(ua2.getTimestamp()));
34     }
35
36
37     @Override
38     public void gotPacket(PcapPacket packet) {
39         // Locate UserAction corresponding to packet, if any.
40         int index = Collections.binarySearch(mActionsSorted, new UserAction(null, packet.getTimestamp()), (listItem, key) -> {
41             // Start of inclusion interval is the time of the user action
42             Instant intervalStart = listItem.getTimestamp();
43             // End of inclusion interval is some arbitrary number of milliseconds after the user action.
44             Instant intervalEnd = intervalStart.plusMillis(TriggerTrafficExtractor.INCLUSION_WINDOW_MILLIS);
45             if (key.getTimestamp().isAfter(intervalStart) && key.getTimestamp().isBefore(intervalEnd)) {
46                 // Packet lies within specified interval after the current UserAction, so we're done.
47                 // Communicate termination to binarySearch by returning 0 which indicates equality.
48                 return 0;
49             }
50             // If packet lies outside inclusion interval of current list item, continue search in lower or upper half of
51             // list depending on whether the timestamp of the current list item is smaller or greater than that of the
52             // packet.
53             return listItem.getTimestamp().compareTo(key.getTimestamp());
54         });
55         if (index >= 0) {
56             // Associate the packet to the its corresponding user action (located during the binary search above).
57             mActionToTrafficMap.get(mActionsSorted.get(index)).add(packet);
58         }
59         // Ignore packet if it is not found to be in temporal proximity of a user action.
60     }
61
62 }